diff --git a/go.mod b/go.mod index 8a654f8c..22c475b6 100644 --- a/go.mod +++ b/go.mod @@ -37,4 +37,5 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/square/go-jose.v2 v2.5.1 k8s.io/apimachinery v0.19.3 + k8s.io/klog/v2 v2.8.0 // indirect ) diff --git a/go.sum b/go.sum index a0940db2..2a5b1e0f 100644 --- a/go.sum +++ b/go.sum @@ -120,6 +120,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= @@ -663,6 +665,8 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/main.go b/main.go index 97f2c5a0..9703c657 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" "math/rand" "os" @@ -12,6 +13,7 @@ import ( "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger" "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation" "github.com/spf13/pflag" + "k8s.io/klog/v2" ) func main() { @@ -27,8 +29,11 @@ func main() { alphaConfig := configFlagSet.String("alpha-config", "", "path to alpha config file (use at your own risk - the structure in this config file may change between minor releases)") convertConfig := configFlagSet.Bool("convert-config-to-alpha", false, "if true, the proxy will load configuration as normal and convert existing configuration to the alpha config structure, and print it to stdout") showVersion := configFlagSet.Bool("version", false, "print version string") + logLevel := configFlagSet.Int("log-level", 0, "standard logging level (higher numbers will be more verbose)") configFlagSet.Parse(os.Args[1:]) + configureKlog(*logLevel) + if *showVersion { fmt.Printf("oauth2-proxy %s (built with %s)\n", VERSION, runtime.Version()) return @@ -154,3 +159,29 @@ func printConvertedConfig(opts *options.Options) error { return nil } + +// configureKlog congiures the klog library to write its output to the OAuth2 +// Proxy logger package. This allows us to use the interfaces but retain the +// formatting configured by our built in logger library. +func configureKlog(logLevel int) { + klogFlags := flag.NewFlagSet("klog", flag.ExitOnError) + klog.InitFlags(klogFlags) + + // If any of the following fail, this is a programming error + if err := klogFlags.Lookup("logtostderr").Value.Set("false"); err != nil { + panic(err) + } + if err := klogFlags.Lookup("one_output").Value.Set("true"); err != nil { + panic(err) + } + if err := klogFlags.Lookup("skip_headers").Value.Set("true"); err != nil { + panic(err) + } + + // If this fails, it's a user input error + if err := klogFlags.Lookup("v").Value.Set(fmt.Sprintf("%d", logLevel)); err != nil { + logger.Fatalf("ERROR: could not set log level: %v", err) + } + klog.SetOutput(logger.StdKlogErrorLogger) + klog.SetOutputBySeverity("INFO", logger.StdKlogInfoLogger) +} diff --git a/pkg/logger/klog.go b/pkg/logger/klog.go new file mode 100644 index 00000000..7aaade1b --- /dev/null +++ b/pkg/logger/klog.go @@ -0,0 +1,29 @@ +package logger + +// KlogInfoLogger is used for info level log output in Klog +type KlogInfoLogger struct { + logger *Logger +} + +// Write is used to output klog log lines +func (l *KlogInfoLogger) Write(data []byte) (int, error) { + l.logger.Output(DEFAULT, 6, string(data)) + return len(data), nil +} + +// KlogInfoLogger is used for error level log output in Klog +type KlogErrorLogger struct { + logger *Logger +} + +// Write is used to output klog log lines +func (l *KlogErrorLogger) Write(data []byte) (int, error) { + l.logger.Output(ERROR, 6, string(data)) + return len(data), nil +} + +// StdKlogInfoLogger is an info logger using the standard logger +var StdKlogInfoLogger = &KlogInfoLogger{logger: std} + +// StdKlogErrorLogger is an info logger using the standard logger +var StdKlogErrorLogger = &KlogErrorLogger{logger: std} diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index cb1da0a4..003a9e8f 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -149,9 +149,12 @@ func (l *Logger) formatLogMessage(calldepth int, message string) []byte { panic(err) } - _, err = logBuff.Write([]byte("\n")) - if err != nil { - panic(err) + // If the output doesn't end with a new line, add one + if string(logBuff.Bytes()[logBuff.Len()-1]) != "\n" { + _, err = logBuff.Write([]byte("\n")) + if err != nil { + panic(err) + } } return logBuff.Bytes()