Repository: prometheus/statsd_exporter
Pull request #390 (2021-09-01 11:01:42)

refactor: replace level pkg


Patch:
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/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"
 )
 


Test patch:
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)
+			}
+		})
+	}
+}