-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Add zapgrpc package #402
Add zapgrpc package #402
Conversation
Generally love this idea. I'm out for a week and won't be able to look until I'm back; try pinging @prashantv or we can pick this up on Wednesday. In the meantime, no harm in integrating it into YARPC as an internal package. |
I updated this to have a |
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.
Love the idea of bundling this package with zap, since it doesn't introduce any new dependencies.
Needs tests, but the general approach lgtm.
zapgrpc/zapgrpc.go
Outdated
fatalfFunc func(*zap.SugaredLogger, string, ...interface{}) | ||
printFunc func(*zap.SugaredLogger, ...interface{}) | ||
printfFunc func(*zap.SugaredLogger, string, ...interface{}) | ||
} |
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.
What's the benefit of keeping these four function pointers instead of
type Logger struct {
sugar *zap.SugaredLogger
development bool
}
and checking development
in Print
and friends? I don't think that the performance impact of a single boolean check will even be measurable relative to the cost of string formatting.
This also lets us get rid of the the loggerOptions
type in favor of type Option func(*Logger)
(or even type Option interface { apply(*Logger) }
).
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.
Talked a little offline, I still prefer this, but I can change to something else
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 could also do debug bool
for now, if that's better for you - it accomplishes the same thing. My biggest issue would be doing WithDevelopment
- I want this to be more specific.
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.
Mind explaining what's attractive about this approach? I'm not necessarily opposed, I'm just not seeing the upside.
There's no reason I can see that changing the internal structure of Logger
requires any changes to the public API - WithDevelopment
can still do exactly what it does now.
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.
Maybe there's a misunderstanding - note this is controlling what happens when you call a grpclog
function such as grpclog.Printf
, not controlling the actual *zap.Logger
given to zapgrpc.SetLogger
, so for example:
grpclog.Print("hello") // if WithDebug was not set, this will call zap.Info
grpclog.Print("hello") // if WithDebug was set, this will call zap.Debug
By setting WithDebug
, if the level of the *zap.Logger
is not debug, this will suppress grpc logging, which might be what someone wants.
Doing this by setting printFunc, printfFunc
versus having a debug
bool to me is cleaner, and the difference is minor, something around a few lines. I think the function style is nicer, and also note how it lets me test grpclog.Fatal*
functions easily - without being able to also set fatalFunc, fatalfFunc
, I wouldn't be really able to test grpclog.Fatal*
functions because the program would exit. Without adding any special boolean to the actual implementation, I am able to add a withWarn
LoggerOption
in the tests that sets the fatal functions to redirect to the warn level, in the same style as the WithDebug
option. This alone might be a good tie breaker.
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.
Fair enough.
zapgrpc/zapgrpc.go
Outdated
import "go.uber.org/zap" | ||
|
||
// LoggerOption is an option for a new Logger. | ||
type LoggerOption func(*loggerOptions) |
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.
See comment on Logger
- if possible, it'd be nice to avoid having exported types reference unexported 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.
Updated to take a *Logger
instead
I've added tests that give 100% coverage on zapgrpc |
Sorry for a late chiming in, but Iet me introduce another way. grpclog.Logger interface says: So you can do this -
|
@flisky you can definitely do that, but it sacrifices quite a bit of performance in some common situations. Since By wrapping the |
Thank you for your elaboration, and I see the point. I'm just not sure whether it should be maintained under
Just my 2 cents. |
I'm not sure if we want this, so feel free to close this otherwise, but I was adding it in yarpc/yarpc-go#863 and thought it might make more sense here.
https://github.com/grpc/grpc-go has a global internal logger it uses, and https://github.com/grpc/grpc-go/tree/master/grpclog defines what logger is used. If a logger is not set, the default golang logger is used, which could mean lost logs for applications that use zap and grpc. This package defines a simple wrapper for a
*zap.Logger
that is compatible withgrpclog.Logger
. To use it, one would do: