Skip to content

Commit 57f8ff4

Browse files
authored
feat: add runtime to fxevent.Run events (#1240)
This PR adds runtime info of constructors and decorators to Run events, and the runtime of every constructor and decorator (including ones created by fx.Supply and fx.Replace) will be logged when logging Run events. This will help us identify which part of the dependency graph takes long to construct. Closes #1213
1 parent 99eee83 commit 57f8ff4

8 files changed

Lines changed: 37 additions & 20 deletions

File tree

fxevent/console.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func (l *ConsoleLogger) LogEvent(event Event) {
109109
if e.ModuleName != "" {
110110
moduleStr = fmt.Sprintf(" from module %q", e.ModuleName)
111111
}
112-
l.logf("RUN\t%v: %v%v", e.Kind, e.Name, moduleStr)
112+
l.logf("RUN\t%v: %v in %s%v", e.Kind, e.Name, e.Runtime, moduleStr)
113113
if e.Err != nil {
114114
l.logf("Error returned: %+v", e.Err)
115115
}

fxevent/console_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -267,27 +267,29 @@ func TestConsoleLogger(t *testing.T) {
267267
},
268268
{
269269
name: "Run",
270-
give: &Run{Name: "bytes.NewBuffer()", Kind: "constructor"},
271-
want: "[Fx] RUN\tconstructor: bytes.NewBuffer()\n",
270+
give: &Run{Name: "bytes.NewBuffer()", Kind: "constructor", Runtime: 10 * time.Nanosecond},
271+
want: "[Fx] RUN\tconstructor: bytes.NewBuffer() in 10ns\n",
272272
},
273273
{
274274
name: "Run with module",
275275
give: &Run{
276276
Name: "bytes.NewBuffer()",
277277
Kind: "constructor",
278+
Runtime: 50 * time.Millisecond,
278279
ModuleName: "myModule",
279280
},
280-
want: "[Fx] RUN\tconstructor: bytes.NewBuffer() from module \"myModule\"\n",
281+
want: "[Fx] RUN\tconstructor: bytes.NewBuffer() in 50ms from module \"myModule\"\n",
281282
},
282283
{
283284
name: "RunError",
284285
give: &Run{
285-
Name: "bytes.NewBuffer()",
286-
Kind: "constructor",
287-
Err: errors.New("terrible constructor error"),
286+
Name: "bytes.NewBuffer()",
287+
Kind: "constructor",
288+
Runtime: 5 * time.Second,
289+
Err: errors.New("terrible constructor error"),
288290
},
289291
want: joinLines(
290-
"[Fx] RUN\tconstructor: bytes.NewBuffer()",
292+
"[Fx] RUN\tconstructor: bytes.NewBuffer() in 5s",
291293
"[Fx] Error returned: terrible constructor error",
292294
),
293295
},

fxevent/event.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ type Run struct {
203203
// ModuleName is the name of the module in which the function belongs.
204204
ModuleName string
205205

206+
// Runtime specifies how long it took to run this function.
207+
Runtime time.Duration
208+
206209
// Err is non-nil if the function returned an error.
207210
// If fx.RecoverFromPanics is used, this will include panics.
208211
Err error

fxevent/slog.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ func (l *SlogLogger) LogEvent(event Event) {
204204
l.logEvent("run",
205205
slog.String("name", e.Name),
206206
slog.String("kind", e.Kind),
207+
slog.String("runtime", e.Runtime.String()),
207208
slogMaybeModuleField(e.ModuleName),
208209
)
209210
}

fxevent/slog_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,12 @@ func TestSlogLogger(t *testing.T) {
342342
},
343343
{
344344
name: "Run",
345-
give: &Run{Name: "bytes.NewBuffer()", Kind: "constructor"},
345+
give: &Run{Name: "bytes.NewBuffer()", Kind: "constructor", Runtime: 3 * time.Millisecond},
346346
wantMessage: "run",
347347
wantFields: map[string]interface{}{
348-
"name": "bytes.NewBuffer()",
349-
"kind": "constructor",
348+
"name": "bytes.NewBuffer()",
349+
"kind": "constructor",
350+
"runtime": "3ms",
350351
},
351352
},
352353
{
@@ -355,12 +356,14 @@ func TestSlogLogger(t *testing.T) {
355356
Name: "bytes.NewBuffer()",
356357
Kind: "constructor",
357358
ModuleName: "myModule",
359+
Runtime: 3 * time.Millisecond,
358360
},
359361
wantMessage: "run",
360362
wantFields: map[string]interface{}{
361-
"name": "bytes.NewBuffer()",
362-
"kind": "constructor",
363-
"module": "myModule",
363+
"name": "bytes.NewBuffer()",
364+
"kind": "constructor",
365+
"module": "myModule",
366+
"runtime": "3ms",
364367
},
365368
},
366369
{

fxevent/zap.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ func (l *ZapLogger) LogEvent(event Event) {
179179
l.logEvent("run",
180180
zap.String("name", e.Name),
181181
zap.String("kind", e.Kind),
182+
zap.String("runtime", e.Runtime.String()),
182183
moduleField(e.ModuleName),
183184
)
184185
}

fxevent/zap_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,12 @@ func TestZapLogger(t *testing.T) {
274274
},
275275
{
276276
name: "Run",
277-
give: &Run{Name: "bytes.NewBuffer()", Kind: "constructor"},
277+
give: &Run{Name: "bytes.NewBuffer()", Kind: "constructor", Runtime: time.Second},
278278
wantMessage: "run",
279279
wantFields: map[string]interface{}{
280-
"name": "bytes.NewBuffer()",
281-
"kind": "constructor",
280+
"name": "bytes.NewBuffer()",
281+
"kind": "constructor",
282+
"runtime": "1s",
282283
},
283284
},
284285
{
@@ -287,12 +288,14 @@ func TestZapLogger(t *testing.T) {
287288
Name: "bytes.NewBuffer()",
288289
Kind: "constructor",
289290
ModuleName: "myModule",
291+
Runtime: time.Millisecond,
290292
},
291293
wantMessage: "run",
292294
wantFields: map[string]interface{}{
293-
"name": "bytes.NewBuffer()",
294-
"kind": "constructor",
295-
"module": "myModule",
295+
"name": "bytes.NewBuffer()",
296+
"kind": "constructor",
297+
"module": "myModule",
298+
"runtime": "1ms",
296299
},
297300
},
298301
{

module.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ func (m *module) provide(p provide) {
200200
Name: funcName,
201201
Kind: "provide",
202202
ModuleName: m.name,
203+
Runtime: ci.Runtime,
203204
Err: ci.Error,
204205
})
205206
}),
@@ -232,6 +233,7 @@ func (m *module) supply(p provide) {
232233
m.log.LogEvent(&fxevent.Run{
233234
Name: fmt.Sprintf("stub(%v)", typeName),
234235
Kind: "supply",
236+
Runtime: ci.Runtime,
235237
ModuleName: m.name,
236238
})
237239
}),
@@ -356,6 +358,7 @@ func (m *module) decorate(d decorator) (err error) {
356358
Name: funcName,
357359
Kind: "decorate",
358360
ModuleName: m.name,
361+
Runtime: ci.Runtime,
359362
Err: ci.Error,
360363
})
361364
}),
@@ -387,6 +390,7 @@ func (m *module) replace(d decorator) error {
387390
Name: fmt.Sprintf("stub(%v)", typeName),
388391
Kind: "replace",
389392
ModuleName: m.name,
393+
Runtime: ci.Runtime,
390394
Err: ci.Error,
391395
})
392396
}),

0 commit comments

Comments
 (0)