@@ -28,15 +28,54 @@ func (d *Discovery) Discover(
2828) (component.Components , error ) {
2929 d .classifier = filter .NewClassifier (d .filters )
3030
31- results , err := d .runFilesystemPhase (ctx , l , opts )
31+ var (
32+ results * PhaseResults
33+ err error
34+ )
35+
36+ withWorktree := len (d .gitExpressions ) > 0 && d .worktrees != nil
37+
38+ l .Debugf ("Discovery: starting filesystem phase (workers=%d, with_worktree=%t)" , d .numWorkers , withWorktree )
39+
40+ err = telemetry .TelemeterFromContext (ctx ).Collect (ctx , "discovery_phase_filesystem" , map [string ]any {
41+ "num_workers" : d .numWorkers ,
42+ "with_worktree" : withWorktree ,
43+ }, func (childCtx context.Context ) error {
44+ var phaseErr error
45+
46+ results , phaseErr = d .runFilesystemPhase (childCtx , l , opts )
47+
48+ return phaseErr
49+ })
50+
51+ logPhaseComplete (l , "filesystem" , results , err )
52+
3253 if err != nil && (! d .suppressParseErrors || errors .As (err , new (CoexistenceError ))) {
3354 return nil , err
3455 }
3556
3657 discovered , candidates := results .Discovered , results .Candidates
3758
3859 if d .requiresParse || d .classifier .HasParseRequiredFilters () {
39- results , err = d .runParsePhase (ctx , l , opts , discovered , candidates )
60+ l .Debugf ("Discovery: starting parse phase (discovered=%d, candidates=%d)" , len (discovered ), len (candidates ))
61+
62+ err = telemetry .TelemeterFromContext (ctx ).Collect (ctx , "discovery_phase_parse" , map [string ]any {
63+ "num_workers" : d .numWorkers ,
64+ "discovered_in" : len (discovered ),
65+ "candidates_in" : len (candidates ),
66+ "parse_includes" : d .parseIncludes ,
67+ "parse_exclude" : d .parseExclude ,
68+ "read_files" : d .readFiles ,
69+ }, func (childCtx context.Context ) error {
70+ var phaseErr error
71+
72+ results , phaseErr = d .runParsePhase (childCtx , l , opts , discovered , candidates )
73+
74+ return phaseErr
75+ })
76+
77+ logPhaseComplete (l , "parse" , results , err )
78+
4079 if err != nil && ! d .suppressParseErrors {
4180 return nil , err
4281 }
@@ -52,7 +91,25 @@ func (d *Discovery) Discover(
5291 }
5392 }
5493
55- results , err = d .runGraphPhase (ctx , l , opts , discovered , candidates )
94+ l .Debugf ("Discovery: starting graph phase (discovered=%d, candidates=%d, max_depth=%d, has_dependent_filters=%t)" ,
95+ len (discovered ), len (candidates ), d .maxDependencyDepth , d .classifier .HasDependentFilters ())
96+
97+ err = telemetry .TelemeterFromContext (ctx ).Collect (ctx , "discovery_phase_graph" , map [string ]any {
98+ "num_workers" : d .numWorkers ,
99+ "max_dependency_depth" : d .maxDependencyDepth ,
100+ "discovered_in" : len (discovered ),
101+ "candidates_in" : len (candidates ),
102+ "has_dependent_filters" : d .classifier .HasDependentFilters (),
103+ }, func (childCtx context.Context ) error {
104+ var phaseErr error
105+
106+ results , phaseErr = d .runGraphPhase (childCtx , l , opts , discovered , candidates )
107+
108+ return phaseErr
109+ })
110+
111+ logPhaseComplete (l , "graph" , results , err )
112+
56113 if err != nil && ! d .suppressParseErrors {
57114 return nil , err
58115 }
@@ -63,7 +120,23 @@ func (d *Discovery) Discover(
63120 components := resultsToComponents (discovered )
64121
65122 if d .discoverRelationships {
66- components , err = d .runRelationshipPhase (ctx , l , opts , components )
123+ l .Debugf ("Discovery: starting relationship phase (components=%d, max_depth=%d)" ,
124+ len (components ), d .maxDependencyDepth )
125+
126+ err = telemetry .TelemeterFromContext (ctx ).Collect (ctx , "discovery_phase_relationship" , map [string ]any {
127+ "num_workers" : d .numWorkers ,
128+ "max_dependency_depth" : d .maxDependencyDepth ,
129+ "components_in" : len (components ),
130+ }, func (childCtx context.Context ) error {
131+ var phaseErr error
132+
133+ components , phaseErr = d .runRelationshipPhase (childCtx , l , opts , components )
134+
135+ return phaseErr
136+ })
137+
138+ l .Debugf ("Discovery: relationship phase complete (components=%d, err=%v)" , len (components ), err )
139+
67140 if err != nil && ! d .suppressParseErrors {
68141 return components , err
69142 }
@@ -110,6 +183,17 @@ func (d *Discovery) Discover(
110183 return components , nil
111184}
112185
186+ // logPhaseComplete emits a debug log summarizing a discovery phase's outcome.
187+ func logPhaseComplete (l log.Logger , name string , results * PhaseResults , err error ) {
188+ var discovered , candidates int
189+ if results != nil {
190+ discovered = len (results .Discovered )
191+ candidates = len (results .Candidates )
192+ }
193+
194+ l .Debugf ("Discovery: %s phase complete (discovered=%d, candidates=%d, err=%v)" , name , discovered , candidates , err )
195+ }
196+
113197// runFilesystemPhase runs the filesystem and worktree phases concurrently.
114198func (d * Discovery ) runFilesystemPhase (
115199 ctx context.Context ,
@@ -131,13 +215,29 @@ func (d *Discovery) runFilesystemPhase(
131215 g .SetLimit (maxPhases )
132216
133217 g .Go (func () error {
134- phase := NewFilesystemPhase (d .numWorkers )
135- result , err := phase .Run (ctx , l , & PhaseInput {
136- Opts : opts ,
137- Classifier : d .classifier ,
138- Discovery : d ,
218+ var result * PhaseResults
219+
220+ l .Debugf ("Discovery: starting filesystem walk at %s" , d .workingDir )
221+
222+ err := telemetry .TelemeterFromContext (ctx ).Collect (ctx , "discovery_filesystem_walk" , map [string ]any {
223+ "num_workers" : d .numWorkers ,
224+ "working_dir" : d .workingDir ,
225+ }, func (childCtx context.Context ) error {
226+ phase := NewFilesystemPhase (d .numWorkers )
227+
228+ var phaseErr error
229+
230+ result , phaseErr = phase .Run (childCtx , l , & PhaseInput {
231+ Opts : opts ,
232+ Classifier : d .classifier ,
233+ Discovery : d ,
234+ })
235+
236+ return phaseErr
139237 })
140238
239+ logPhaseComplete (l , "filesystem walk" , result , err )
240+
141241 mu .Lock ()
142242
143243 if result != nil {
@@ -156,13 +256,29 @@ func (d *Discovery) runFilesystemPhase(
156256
157257 if len (d .gitExpressions ) > 0 && d .worktrees != nil {
158258 g .Go (func () error {
159- phase := NewWorktreePhase (d .gitExpressions , d .numWorkers )
160- result , err := phase .Run (ctx , l , & PhaseInput {
161- Opts : opts ,
162- Classifier : d .classifier ,
163- Discovery : d ,
259+ var result * PhaseResults
260+
261+ l .Debugf ("Discovery: starting worktree walk (git_expressions=%d)" , len (d .gitExpressions ))
262+
263+ err := telemetry .TelemeterFromContext (ctx ).Collect (ctx , "discovery_worktree_walk" , map [string ]any {
264+ "num_workers" : d .numWorkers ,
265+ "git_expression_count" : len (d .gitExpressions ),
266+ }, func (childCtx context.Context ) error {
267+ phase := NewWorktreePhase (d .gitExpressions , d .numWorkers )
268+
269+ var phaseErr error
270+
271+ result , phaseErr = phase .Run (childCtx , l , & PhaseInput {
272+ Opts : opts ,
273+ Classifier : d .classifier ,
274+ Discovery : d ,
275+ })
276+
277+ return phaseErr
164278 })
165279
280+ logPhaseComplete (l , "worktree walk" , result , err )
281+
166282 mu .Lock ()
167283
168284 if result != nil {
@@ -372,21 +488,19 @@ func (d *Discovery) buildComponentDependencies(
372488 return nil
373489 }
374490
375- cfg := unit .Config ()
376- if cfg == nil {
377- err := parseComponent (ctx , l , c , opts , d )
378- if err != nil {
379- if d .suppressParseErrors {
380- l .Debugf ("Suppressed parse error for %s: %v" , c .Path (), err )
381- return nil
382- }
491+ ctx = contextWithParsePhase (ctx , parsePhaseTagDependencyGraph )
383492
384- return err
493+ if err := ensureParsed (ctx , l , c , opts , d ); err != nil {
494+ if d .suppressParseErrors {
495+ l .Debugf ("Suppressed parse error for %s: %v" , c .Path (), err )
496+ return nil
385497 }
386498
387- cfg = unit . Config ()
499+ return err
388500 }
389501
502+ cfg := unit .Config ()
503+
390504 depPaths , err := extractDependencyPaths (cfg , c )
391505 if err != nil {
392506 return err
0 commit comments