Skip to content

Commit

Permalink
Setup Authorino logger
Browse files Browse the repository at this point in the history
  • Loading branch information
grzpiotrowski committed Nov 8, 2023
1 parent d57f130 commit c00955c
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 3 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools v2.2.0+incompatible // indirect
k8s.io/apiextensions-apiserver v0.23.0 // indirect
k8s.io/component-base v0.23.0 // indirect
k8s.io/klog/v2 v2.30.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,8 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
12 changes: 9 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"

"github.com/kuadrant/authorino-operator/pkg/common"
"github.com/kuadrant/authorino-operator/pkg/log"

authorinooperatorv1beta1 "github.com/kuadrant/authorino-operator/api/v1beta1"
"github.com/kuadrant/authorino-operator/controllers"
//+kubebuilder:scaffold:imports
Expand All @@ -39,15 +42,18 @@ import (
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")

version string // value injected in compilation-time
logLevel = common.FetchEnv("LOG_LEVEL", "info")
logMode = common.FetchEnv("LOG_MODE", "production")
logger = log.NewLogger(log.Options{Level: log.ToLogLevel(logLevel), Mode: log.ToLogMode(logMode)}).WithName("authorino-operator").WithName("controller").WithName("Authorino")
version string // value injected in compilation-time
)

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))

utilruntime.Must(authorinooperatorv1beta1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
log.SetLogger(logger)
}

func main() {
Expand Down Expand Up @@ -84,7 +90,7 @@ func main() {

if err = (&controllers.AuthorinoReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("authorino-operator").WithName("controller").WithName("Authorino"),
Log: logger,
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Authorino")
Expand Down
12 changes: 12 additions & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package common

import "os"

func FetchEnv(key string, def string) string {
val, ok := os.LookupEnv(key)
if !ok {
return def
}

return val
}
129 changes: 129 additions & 0 deletions pkg/log/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package log

import (
"context"
"strings"

"github.com/go-logr/logr"
"go.uber.org/zap/zapcore"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

var (
// Log is a singleton base logger that can be used across the system,
// either directly or to create other loggers with name, with values,
// and/or locked to a given log level.
// It is initialized to the promise delegation log provided by
// sigs.k8s.io/controller-runtime, which points to a no-op (null) logger
// until `SetLogger` is called.
// This is also useful for mocking the default logger tests.
Log Logger = ctrl.Log
)

type Logger = logr.Logger

type LogLevel zapcore.Level

func (l *LogLevel) String() string {
return zapcore.Level(*l).String()
}

// ToLogLevel converts a string to a log level.
func ToLogLevel(level string) LogLevel {
var l zapcore.Level
_ = l.UnmarshalText([]byte(level))
return LogLevel(l)
}

// LogMode defines the log output mode.
type LogMode int8

const (
// LogModeProd is the log mode for production.
LogModeProd LogMode = iota
// LogModeDev is for more human-readable outputs, extra stack traces
// and logging info. (aka Zap's "development config".)
LogModeDev
)

func (f *LogMode) String() string {
switch *f {
case LogModeProd:
return "production"
case LogModeDev:
return "development"
default:
return "unknown"
}
}

// ToLogMode converts a string to a log mode.
// Use either 'production' for `LogModeProd` or 'development' for `LogModeDev`.
func ToLogMode(mode string) LogMode {
switch strings.ToLower(mode) {
case "production":
return LogModeProd
case "development":
return LogModeDev
default:
panic("unknown log mode")
}
}

// Options is a set of options for a configured logger.
type Options struct {
Level LogLevel
Mode LogMode
}

// SetLogger sets up a logger.
func SetLogger(logger Logger) {
Log = logger

ctrl.SetLogger(Log) // fulfills `logger` as the de facto logger used by controller-runtime
klog.SetLogger(Log)
}

// WithName uses the singleton logger to create a new logger with the given name.
func WithName(name string) Logger {
return Log.WithName(name)
}

// WithName uses the singleton logger to create a new logger with the given values.
func WithValues(keysAndValues ...interface{}) Logger {
return Log.WithValues(keysAndValues...)
}

// V uses the singleton logger to create a new logger for the given log level.
func V(level int) Logger {
return Log.V(level)
}

// IntoContext takes a context and sets the logger as one of its values.
// Use FromContext function to retrieve the logger.
func IntoContext(ctx context.Context, log Logger) context.Context {
return logr.NewContext(ctx, log)
}

// FromContext returns a logger with predefined values from a context.Context.
func FromContext(ctx context.Context, keysAndValues ...interface{}) Logger {
var l logr.Logger = Log
if ctx != nil {
if logger, err := logr.FromContext(ctx); err == nil {
l = logger
}
}
return l.WithValues(keysAndValues...)
}

// NewLogger returns a new logger with the given options.
// `logger` param is the actual logger implementation; when omitted, a new
// logger based on sigs.k8s.io/controller-runtime/pkg/log/zap is created.
func NewLogger(opts Options) Logger {
return zap.New(
zap.Level(zapcore.Level(opts.Level)),
zap.UseDevMode(opts.Mode == LogModeDev),
)
}
61 changes: 61 additions & 0 deletions pkg/log/logger_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package log

import (
"testing"

"gotest.tools/assert"
)

func TestLogLevelToString(t *testing.T) {
level := LogLevel(-1)
assert.Equal(t, level.String(), "debug")

level = LogLevel(0)
assert.Equal(t, level.String(), "info")

level = LogLevel(1)
assert.Equal(t, level.String(), "warn")

level = LogLevel(2)
assert.Equal(t, level.String(), "error")

level = LogLevel(3)
assert.Equal(t, level.String(), "dpanic")

level = LogLevel(4)
assert.Equal(t, level.String(), "panic")

level = LogLevel(5)
assert.Equal(t, level.String(), "fatal")
}

func TestToLogLevel(t *testing.T) {
assert.Equal(t, int(ToLogLevel("debug")), -1)
assert.Equal(t, int(ToLogLevel("info")), 0)
assert.Equal(t, int(ToLogLevel("warn")), 1)
assert.Equal(t, int(ToLogLevel("error")), 2)
assert.Equal(t, int(ToLogLevel("dpanic")), 3)
assert.Equal(t, int(ToLogLevel("panic")), 4)
assert.Equal(t, int(ToLogLevel("fatal")), 5)
assert.Equal(t, int(ToLogLevel("invalid")), 0) // falls back to default log level (info) without panicking
}

func TestLogModeToString(t *testing.T) {
level := LogMode(0)
assert.Equal(t, level.String(), "production")

level = LogMode(1)
assert.Equal(t, level.String(), "development")
}

func TestToLogMode(t *testing.T) {
assert.Equal(t, int(ToLogMode("production")), 0)
assert.Equal(t, int(ToLogMode("development")), 1)

defer func() {
if r := recover(); r == nil {
t.Errorf(`ToLogMode("invalid") was expected to panic and it did not.`)
}
}()
_ = ToLogMode("invalid")
}

0 comments on commit c00955c

Please sign in to comment.