-
Notifications
You must be signed in to change notification settings - Fork 14
[log] logr.Logger and logr.LogSink Support for controller-runtime Compatibility #200
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
Conversation
…patibility Signed-off-by: hfuss <hayden.fuss@kaleido.io>
|
In a controller-runtime / kubebuilder base operator you can then easily do: func main() {
// ... flag parsing ...
// Initialize ff-common logging instead of zapr
ctx := context.Background()
log.SetLevel(opts.LogLevel) // or read from flag
// Set the controller-runtime logger to use our ff-common adapter
ctrl.SetLogger(log.NewLogr(ctx, "firefly-operator"))
// ... rest of setup ...
}and use |
…for logging Signed-off-by: hfuss <hayden.fuss@kaleido.io>
…lementation Signed-off-by: hfuss <hayden.fuss@kaleido.io>
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
EnriqueL8
left a comment
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.
Thanks @onelapahead - this is awesome 🙇🏼
Left a few comments/things I don't understand
| } | ||
|
|
||
| // WithFields adds the specified, structured fields to the logger in the context | ||
| func WithFields(ctx context.Context, fields map[string]string) context.Context { |
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.
Should we keep the interface consistent with above and instead of a map have keyValuePairs as well?
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.
Well so this one is meant to feel more logrus native, but did struggle with the names to indicate that...
pkg/log/logr.go
Outdated
|
|
||
| // Init initializes the sink | ||
| func (l *Sink) Init(_ logr.RuntimeInfo) { | ||
| // Optional: store callDepth if needed |
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.
???
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.
Yeah don't think we need to implement this for now, will leave a different comment
pkg/log/logr.go
Outdated
| func (l *Sink) Enabled(level int) bool { | ||
| // Map logr V-levels to ff-common levels | ||
| // logr: V(0)=info, V(1)=debug, V(2+)=trace | ||
| switch level { |
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.
Check for negative level?
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.
shouldn't be possible for logr but it is is int so will be defensive
pkg/log/logr.go
Outdated
| } | ||
|
|
||
| // Info logs an info message with the given keys and values. keysAndValues is not efficiently implemented, use WithValues instead | ||
| func (l *Sink) Info(level int, msg string, keysAndValues ...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.
Confused how with Sink we still allow passing level int ?
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 don't see Debug etc... so maybe this function is actually called Logf ?
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.
aaah is this implementing just the interface ?? that makes sense then
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.
yeah this is all the logr interface - which doesn't have log levels just ints lol - its quite terse.
This is just so k8s libs log through our logging, so we can use our logging in k8s controllers w/o having two different loggers going
pkg/log/logr_test.go
Outdated
| @@ -0,0 +1,37 @@ | |||
| // Copyright © 2022 - 2025 Kaleido, Inc. | |||
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.
| // Copyright © 2022 - 2025 Kaleido, Inc. | |
| // Copyright © 2025 Kaleido, Inc. |
pkg/log/logr.go
Outdated
| @@ -0,0 +1,114 @@ | |||
| // Copyright © 2022 - 2025 Kaleido, Inc. | |||
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.
| // Copyright © 2022 - 2025 Kaleido, Inc. | |
| // Copyright © 2025 Kaleido, Inc. |
pkg/log/logr.go
Outdated
| func (l *Sink) buildContext(keysAndValues []interface{}) context.Context { | ||
| fields := make(map[string]string) | ||
| for i := 0; i < len(keysAndValues); i += 2 { | ||
| fields[keysAndValues[i].(string)] = keysAndValues[i+1].(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.
Do we want to be a bit safer with this cast keysAndValues[i].(string) and throw some error?
pkg/log/logr.go
Outdated
| return logr.New(&Sink{ | ||
| name: name, | ||
| ctx: ctx, | ||
| logger: L(ctx), |
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 L( is so miss leading, it's actually getting the logger from context - it was already there so no worries just annoying
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 I should be using the private impl that L is pointed to ? That would read better
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
…amically via monitoring server; all dbsql logs to trace Signed-off-by: hfuss <hayden.fuss@kaleido.io>
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
|
Likely need to break out the dynamic logging changes into a separate PR... will do that once I'm done testing |
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
Signed-off-by: hfuss <hayden.fuss@kaleido.io>
|
After testing - this PR is working great for a few different use cases, but I think until ff-common migrates to a newer framework like zap instead of logrus - its best to avoid |
Kubernetes controllers love
logras an interface for logging.FireFly loves
logrus(log levels are so much better than-vvvvv).🍅 🥔
In our Kubernetes operators - we'd prefer to provide the controller-runtime / K8s libraries with an ff-common like logger, so that we can then use
log.L(ctx)semantics w/ proper log levels to create a smoother logging experience for our developers vs our users.These wrapper implementations would help achieve that.