Skip to content
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

Enhanced logging #172

Merged
merged 11 commits into from
Oct 21, 2021
Merged

Enhanced logging #172

merged 11 commits into from
Oct 21, 2021

Conversation

guicassolato
Copy link
Collaborator

@guicassolato guicassolato commented Oct 18, 2021

Adds better log levels and log configuration.

  • Support for log levels (debuginfoerror)
  • Configurable log modes: production, development
  • No sensitive data output to info log messages
  • Log tracing ID
  • Documentation: descriptions of log messages, extra values included and samples
  • Logging guidelines for developers

Check the added docs page for details about how the log messages look like, limitations regarding sensitive data obfuscating, and log configuration options.


Closes #12 and #161

@guicassolato guicassolato self-assigned this Oct 18, 2021
@guicassolato guicassolato requested a review from a team October 18, 2021 12:08
pkg/common/log/log.go Outdated Show resolved Hide resolved
pkg/common/log/log.go Outdated Show resolved Hide resolved
pkg/config/authorization/kubernetes_authz.go Outdated Show resolved Hide resolved
@eguzki
Copy link
Collaborator

eguzki commented Oct 19, 2021

This is looking good, aligns with logging options offered by controller runtime loggers.

I think whatever it comes out of this, it should be used as pattern for other kuadrant controllers.

This is useful so parsers can focus in either one log level or the other, without missing info when switching levels.
Debug version of these log messages continue to include extra info, both about the request and response.
return ctrl.Result{}, nil
}

func (r *AuthConfigReconciler) translateAuthConfig(ctx context.Context, authConfig *configv1beta1.AuthConfig) (map[string]authorinoService.APIConfig, error) {
func (r *AuthConfigReconciler) translateAuthConfig(ctx context.Context, authConfig *configv1beta1.AuthConfig, logger log.Logger) (map[string]authorinoService.APIConfig, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be logr.Logger type?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using ours instead. Again, the same pattern of abstraction under a layer we control. "github.com/kuadrant/authorino/pkg/common/log".Logger == "github.com/go-logr/logr".Logger

@@ -62,13 +63,17 @@ var (
oidcHTTPPort = common.FetchEnv("OIDC_HTTP_PORT", "8083")
oidcTLSCertPath = common.FetchEnv("OIDC_TLS_CERT", "")
oidcTLSCertKeyPath = common.FetchEnv("OIDC_TLS_CERT_KEY", "")

logger = log.NewLogger(log.Options{Level: log.ToLogLevel(logLevel), Mode: log.ToLogMode(logMode)}, nil).WithName("authorino")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while I think it is ok, it is not needed to have a global var used for the main package. It is being set in the init, so any function in this package is safe to get the logger as

log.Log.Error(...)

pkg/common/log/log.go Show resolved Hide resolved
Log = logger
Level = opts.Level

ctrl.SetLogger(logger) // fulfills `logger` as the de facto logger used by controller-runtime
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I am not sure about this, but let's give it a try.

Copy link
Collaborator Author

@guicassolato guicassolato Oct 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"SetLogger" means:

  • to set the singleton (which is used, as a base logger, in a few places where I chose not to inject a previously configured logger in the stack call)
  • to set whatever delegation logger being used by any dependency that we know of (controller-runtime and klog in our case)

If we don't ctrl.SetLogger(logger), some log entries generated deep down by controlller-runtime would either be skipped (due to null logger set by default) or be printed on a different format (not as JSON, missing "authorino." in the logger's name, etc).

I actually ran into this with klog, that prints leader election-related logs. While most entries were being formatted as configured, klog's ones were leaking completely unformatted.

}

// configuredLogger is a delegation logger that holds information about the log options.
type configuredLogger struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that the purpose of this new configuredLogger struct is to keep the options for later use. Is it being used?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Other than that, it's just a delegation logger.

// It is useful for checking the log level in the code and avoid expensive
// tasks only required for some specific levels.
// It is setup by the `SetLogger` function.
Level LogLevel
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this is even needed.

As you know, the logr.Logger interface, has this Enabled() method. It is not useful to get the actual log level option of a logger instance, but can tell if a logger instance is being enabled or not.

myLogger = log.Log
fmt.Println(myLogger.Enabled()) // true when log level set to debug or info

myDebugLogger = myLogger.V(1)
fmt.Println(myDebugLogger.Enabled()) // true when log level set to debug 

we are using in the kuadrant controller:
https://github.com/Kuadrant/kuadrant-controller/blob/145657005a3a64676281a3799e118c24d47bea83/controllers/apiproduct_controller.go#L70

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are totally right. Good catch!

Added 4f0fe1c.

pkg/config/metadata/generic_http.go Outdated Show resolved Hide resolved
No need to store log level. We can use `logr.Enabled()`.
@guicassolato guicassolato requested a review from a team October 20, 2021 16:43
eguzki
eguzki previously approved these changes Oct 21, 2021
switch {
case config.OPA != nil:
return config.OPA.Call(pipeline, ctx)
return config.OPA.Call(pipeline, ctx, logger)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guicassolato another option would be to inject the logger in the context.

Check https://github.com/kubernetes-sigs/controller-runtime/blob/1462c6e3a5dbe3b04d11286b190253c845c8e338/pkg/log/log.go#L85

func FromContext(ctx context.Context, keysAndValues ...interface{}) logr.Logger

and

func IntoContext(ctx context.Context, log logr.Logger) context.Context

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eguzki , please tell me if it's better now. 9eb2fa5

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

eguzki
eguzki previously approved these changes Oct 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Level-based logging
2 participants