-
Notifications
You must be signed in to change notification settings - Fork 297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow fx.Module-specific custom loggers #947
Conversation
Currently passing fx.WithLogger option to fx.Module does not work because fx currently does not support specifying module-level custom loggers. Now fx.WithLogger can be passed to fx.Modules for specifying custom loggers for fx.Modules Fixes uber-go#894
Codecov Report
@@ Coverage Diff @@
## master #947 +/- ##
==========================================
+ Coverage 98.72% 98.89% +0.17%
==========================================
Files 30 30
Lines 1332 1360 +28
==========================================
+ Hits 1315 1345 +30
+ Misses 11 10 -1
+ Partials 6 5 -1
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
- added another failure case for WithLogger in fx.Module - updated existing failure cases to expect any fx.Invokes to be not called
m.log.LogEvent(ev) | ||
} | ||
|
||
func (m *module) constructAllCustomLoggers() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add a comment here clarifying that this will build the custom loggers for all the modules in the tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment
module.go
Outdated
buffer, ok := m.log.(*logBuffer) | ||
if ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can inline this:
buffer, ok := m.log.(*logBuffer) | |
if ok { | |
if buffer, ok := m.log.(*logBuffer); ok { |
See also: https://github.com/uber-go/guide/blob/master/style.md#reduce-scope-of-variables
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 👍
module.go
Outdated
if err := m.scope.Provide(p.Target); err != nil { | ||
return fmt.Errorf("fx.WithLogger(%v) from:\n%+vFailed: %v", | ||
fname, p.Stack, err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add the module name in this error. Also, use the %w
modifier to format the error type to make it print nicely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the error message to include module name
module_test.go
Outdated
|
||
require.NoError(t, app.Err()) | ||
|
||
assert.Equal(t, []string{"Started", "Stopped"}, spy.EventTypes()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests may actually be better off written as a table test.
See: https://github.com/uber-go/guide/blob/master/style.md#test-tables
module_test.go
Outdated
var buff bytes.Buffer | ||
app := fx.New( | ||
redis, | ||
fx.Logger(log.New(&buff, "", 0)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is deprecated - can you change these with WithLogger
and use spy like the other tests?
- added comments on module.constructAllCustomLoggers - made module's parent logger the default logger for any given module - coding style changes per style guide - added more test cases for module-specific logger
module_test.go
Outdated
fx.Invoke(func(s string) { | ||
assert.Fail(t, "this should never run") | ||
}), | ||
)..., |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collect the default options into fx.Options
instead of appending and exploding it like this.
module_test.go
Outdated
}, | ||
{ | ||
desc: "logger dependency in module failed to build", | ||
giveModuleOpts: []fx.Option{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
giveModuleOpts: []fx.Option{ | |
giveModuleOpts: fx.Options( |
module.go
Outdated
}() | ||
|
||
if err := m.scope.Provide(p.Target); err != nil { | ||
return fmt.Errorf("fx.WithLogger(%v) from:\n%+v\nin Module: %v\nFailed: %w", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use %q
to put the module's name in quotes in the error string.
return fmt.Errorf("fx.WithLogger(%v) from:\n%+v\nin Module: %v\nFailed: %w", | |
return fmt.Errorf("fx.WithLogger(%v) from:\n%+v\nin Module: %q\nFailed: %w", |
module.go
Outdated
// TODO: Use dig.FillProvideInfo to inspect the provided constructor | ||
// and fail the application if its signature didn't match. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this comment is misplaced. It should be placed above the m.scope.Provide
, not here.
module_test.go
Outdated
fx.Provide(func() *Logger { | ||
return &Logger{Name: "grandchild"} | ||
}), | ||
fx.Invoke(func(r *Logger) { | ||
assert.Equal(t, "grandchild", r.Name) | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to stare at this test for a while because it wasn't clear what this Logger thing was. Looks like this is just a random dependency that gets Provided to make sure that the "Provided" event gets logged by the loggers you supply, which are appSpy
and childSupply
.
Can you change this so that it uses some other naive looking type, and not something that looks like an actual logger that gets passed to fx.WithLogger?
module_test.go
Outdated
giveModuleOpts fx.Option | ||
giveAppOpts fx.Option | ||
wantErrContains []string | ||
wantEventTypes []string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: :%s/wantEventTypes/wantEvents/g
module_test.go
Outdated
assert.Contains(t, | ||
err.Error(), | ||
contains, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert.Contains(t, | |
err.Error(), | |
contains, | |
) | |
assert.Contains(t, err.Error(), contains) |
module_test.go
Outdated
// events from modules do not appear in app logger | ||
assert.Equal(t, []string{ | ||
"Provided", "Provided", "Provided", | ||
"LoggerInitialized", "Invoking", "Invoked", | ||
}, appSpy.EventTypes()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add what you have as a comment as the last parameter of assert.Equal and it'll show up in the test failure message if it passes. i.e.
// events from modules do not appear in app logger | |
assert.Equal(t, []string{ | |
"Provided", "Provided", "Provided", | |
"LoggerInitialized", "Invoking", "Invoked", | |
}, appSpy.EventTypes()) | |
// events from modules do not appear in app logger | |
assert.Equal(t, []string{ | |
"Provided", "Provided", "Provided", | |
"LoggerInitialized", "Invoking", "Invoked", | |
}, appSpy.EventTypes(), "events from modules should not appear in app logger") |
- Logger switched to another type for WithLogger test cases - used %q for module name in error message - comments updated to be clearer - more test case cleanup
} | ||
} | ||
|
||
// Mirroring the behavior of app.constructCustomLogger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're copy-pasting a lot of code here. Looking at app.constructCustomLogger, we can reuse this method and remove the duplication.
i.e. the App
struct already has a "root" scope module. You should be able to just use that module to construct the custom loggers using this method and remove the app.constructCustomLogger method, rather than duplicating the feature across the two types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To do this, I would need to refactor the whole initialization process of app.log
to be handled by module instead of fx.New. Is it reasonable to include this type of change in this PR's scope?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can file a follow-up task to refactor it if you believe this PR is getting too large.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GO-1690 created
* Allow fx.Module-specific custom loggers Currently passing fx.WithLogger option to fx.Module does not work because fx currently does not support specifying module-level custom loggers. Now fx.WithLogger can be passed to fx.Modules for specifying custom loggers for fx.Modules Fixes uber-go#894 * Adding more test cases for module-level logger * More test case cleanups: - added another failure case for WithLogger in fx.Module - updated existing failure cases to expect any fx.Invokes to be not called * Addressing comments from PR review - added comments on module.constructAllCustomLoggers - made module's parent logger the default logger for any given module - coding style changes per style guide - added more test cases for module-specific logger * More test code refactoring * Made more modifications per review comments: - Logger switched to another type for WithLogger test cases - used %q for module name in error message - comments updated to be clearer - more test case cleanup * Added asserts to ensure module logger is not logging app start/stop events * Update module_test.go * Apply suggestions from code review Co-authored-by: Sung Yoon Whang <sungyoonwhang@gmail.com>
Currently passing fx.WithLogger option to fx.Module does not work because fx currently does not support specifying module-level custom loggers.
Now fx.WithLogger can be passed to fx.Modules for specifying custom loggers for fx.Modules. Also added some test cases to test fx.Module-specific loggers.
Fixes #894