diff --git a/main.go b/main.go index ae999a3..87e8221 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,6 @@ import ( "syscall" "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/promlog" @@ -36,6 +35,7 @@ import ( "github.com/prometheus/statsd_exporter/pkg/address" "github.com/prometheus/statsd_exporter/pkg/event" "github.com/prometheus/statsd_exporter/pkg/exporter" + "github.com/prometheus/statsd_exporter/pkg/level" "github.com/prometheus/statsd_exporter/pkg/line" "github.com/prometheus/statsd_exporter/pkg/listener" "github.com/prometheus/statsd_exporter/pkg/mapper" @@ -303,6 +303,10 @@ func main() { kingpin.HelpFlag.Short('h') kingpin.Parse() logger := promlog.New(promlogConfig) + if err := level.SetLogLevel(promlogConfig.Level.String()); err != nil { + level.Error(logger).Log("msg", "failed to set log level", "error", err) + os.Exit(1) + } parser := line.NewParser() if *dogstatsdTagsEnabled { diff --git a/pkg/exporter/exporter.go b/pkg/exporter/exporter.go index 6e5675f..c61ab66 100644 --- a/pkg/exporter/exporter.go +++ b/pkg/exporter/exporter.go @@ -18,11 +18,11 @@ import ( "time" "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/statsd_exporter/pkg/clock" "github.com/prometheus/statsd_exporter/pkg/event" + "github.com/prometheus/statsd_exporter/pkg/level" "github.com/prometheus/statsd_exporter/pkg/mapper" "github.com/prometheus/statsd_exporter/pkg/registry" ) diff --git a/pkg/level/level.go b/pkg/level/level.go new file mode 100644 index 0000000..5b03c6d --- /dev/null +++ b/pkg/level/level.go @@ -0,0 +1,97 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package level + +import ( + "fmt" + + "github.com/go-kit/log" + "github.com/go-kit/log/level" +) + +var logLevel = LevelInfo + +// A Level is a logging priority. Higher levels are more important. +type Level int + +const ( + // LevelDebug logs are typically voluminous, and are usually disabled in + // production. + LevelDebug Level = iota + // LevelInfo is the default logging priority. + LevelInfo + // LevelWarn logs are more important than Info, but don't need individual + // human review. + LevelWarn + // LevelError logs are high-priority. If an application is running smoothly, + // it shouldn't generate any error-level logs. + LevelError +) + +var emptyLogger = &EmptyLogger{} + +type EmptyLogger struct{} + +func (l *EmptyLogger) Log(keyvals ...interface{}) error { + return nil +} + +// SetLogLevel sets the log level. +func SetLogLevel(level string) error { + switch level { + case "debug": + logLevel = LevelDebug + case "info": + logLevel = LevelInfo + case "warn": + logLevel = LevelWarn + case "error": + logLevel = LevelError + default: + return fmt.Errorf("unrecognized log level %s", level) + } + return nil +} + +// Error returns a logger that includes a Key/ErrorValue pair. +func Error(logger log.Logger) log.Logger { + if logLevel <= LevelError { + return level.Error(logger) + } + return emptyLogger +} + +// Warn returns a logger that includes a Key/WarnValue pair. +func Warn(logger log.Logger) log.Logger { + if logLevel <= LevelWarn { + return level.Warn(logger) + } + return emptyLogger +} + +// Info returns a logger that includes a Key/InfoValue pair. +func Info(logger log.Logger) log.Logger { + if logLevel <= LevelInfo { + return level.Info(logger) + } + return emptyLogger +} + +// Debug returns a logger that includes a Key/DebugValue pair. +func Debug(logger log.Logger) log.Logger { + if logLevel <= LevelDebug { + return level.Debug(logger) + } + return emptyLogger +} diff --git a/pkg/level/level_test.go b/pkg/level/level_test.go new file mode 100644 index 0000000..908146f --- /dev/null +++ b/pkg/level/level_test.go @@ -0,0 +1,110 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package level + +import ( + "bytes" + "strings" + "testing" + + "github.com/go-kit/log" +) + +func TestSetLogLevel(t *testing.T) { + tests := []struct { + name string + level string + logLevel Level + wantErr bool + }{ + {"wrong level", "foo", LevelInfo, true}, + {"level debug", "debug", LevelDebug, false}, + {"level info", "info", LevelInfo, false}, + {"level warn", "warn", LevelWarn, false}, + {"level error", "error", LevelError, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := SetLogLevel(tt.level); (err != nil) != tt.wantErr { + t.Fatalf("Expected log level to be set successfully, but got %v", err) + } + if tt.logLevel != logLevel { + t.Fatalf("Expected log level %v, but got %v", tt.logLevel, logLevel) + } + }) + } +} + +func TestVariousLevels(t *testing.T) { + tests := []struct { + name string + level string + want string + }{ + { + "level debug", + "debug", + strings.Join([]string{ + "level=debug log=debug", + "level=info log=info", + "level=warn log=warn", + "level=error log=error", + }, "\n"), + }, + { + "level info", + "info", + strings.Join([]string{ + "level=info log=info", + "level=warn log=warn", + "level=error log=error", + }, "\n"), + }, + { + "level warn", + "warn", + strings.Join([]string{ + "level=warn log=warn", + "level=error log=error", + }, "\n"), + }, + { + "level error", + "error", + strings.Join([]string{ + "level=error log=error", + }, "\n"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + logger := log.NewLogfmtLogger(&buf) + + if err := SetLogLevel(tt.level); err != nil { + t.Fatalf("Expected log level to be set successfully, but got %v", err) + } + + Debug(logger).Log("log", "debug") + Info(logger).Log("log", "info") + Warn(logger).Log("log", "warn") + Error(logger).Log("log", "error") + + got := strings.TrimSpace(buf.String()) + if tt.want != got { + t.Fatalf("Expected log output %v, but got %v", tt.want, got) + } + }) + } +} diff --git a/pkg/line/line.go b/pkg/line/line.go index 4b77473..cd3aac2 100644 --- a/pkg/line/line.go +++ b/pkg/line/line.go @@ -20,10 +20,10 @@ import ( "unicode/utf8" "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/statsd_exporter/pkg/event" + "github.com/prometheus/statsd_exporter/pkg/level" "github.com/prometheus/statsd_exporter/pkg/mapper" ) diff --git a/pkg/listener/listener.go b/pkg/listener/listener.go index 6d07f93..b1a57f5 100644 --- a/pkg/listener/listener.go +++ b/pkg/listener/listener.go @@ -21,10 +21,10 @@ import ( "strings" "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/statsd_exporter/pkg/event" + "github.com/prometheus/statsd_exporter/pkg/level" ) type Parser interface { diff --git a/pkg/mapper/fsm/fsm.go b/pkg/mapper/fsm/fsm.go index 96a162c..85068f7 100644 --- a/pkg/mapper/fsm/fsm.go +++ b/pkg/mapper/fsm/fsm.go @@ -18,7 +18,8 @@ import ( "strings" "github.com/go-kit/log" - "github.com/go-kit/log/level" + + "github.com/prometheus/statsd_exporter/pkg/level" ) type mappingState struct { diff --git a/pkg/mapper/mapper.go b/pkg/mapper/mapper.go index 64be2e2..e213890 100644 --- a/pkg/mapper/mapper.go +++ b/pkg/mapper/mapper.go @@ -21,10 +21,10 @@ import ( "time" "github.com/go-kit/log" - "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" yaml "gopkg.in/yaml.v2" + "github.com/prometheus/statsd_exporter/pkg/level" "github.com/prometheus/statsd_exporter/pkg/mapper/fsm" )