[log] logr.Logger and logr.LogSink Support for controller-runtime Compatibility - #200
[log] logr.Logger and logr.LogSink Support for controller-runtime Compatibility#200onelapahead wants to merge 11 commits into
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.
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.
Should we keep the interface consistent with above and instead of a map have keyValuePairs as well?
There was a problem hiding this comment.
Well so this one is meant to feel more logrus native, but did struggle with the names to indicate that...
|
|
||
| // Init initializes the sink | ||
| func (l *Sink) Init(_ logr.RuntimeInfo) { | ||
| // Optional: store callDepth if needed |
There was a problem hiding this comment.
Yeah don't think we need to implement this for now, will leave a different comment
| 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.
Check for negative level?
There was a problem hiding this comment.
shouldn't be possible for logr but it is is int so will be defensive
| } | ||
|
|
||
| // 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.
Confused how with Sink we still allow passing level int ?
There was a problem hiding this comment.
I don't see Debug etc... so maybe this function is actually called Logf ?
There was a problem hiding this comment.
aaah is this implementing just the interface ?? that makes sense then
There was a problem hiding this comment.
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
| @@ -0,0 +1,37 @@ | |||
| // Copyright © 2022 - 2025 Kaleido, Inc. | |||
There was a problem hiding this comment.
| // Copyright © 2022 - 2025 Kaleido, Inc. | |
| // Copyright © 2025 Kaleido, Inc. |
| @@ -0,0 +1,114 @@ | |||
| // Copyright © 2022 - 2025 Kaleido, Inc. | |||
There was a problem hiding this comment.
| // Copyright © 2022 - 2025 Kaleido, Inc. | |
| // Copyright © 2025 Kaleido, Inc. |
| 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.
Do we want to be a bit safer with this cast keysAndValues[i].(string) and throw some error?
| return logr.New(&Sink{ | ||
| name: name, | ||
| ctx: ctx, | ||
| logger: L(ctx), |
There was a problem hiding this comment.
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.
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.