Skip to content

Commit ceef6d7

Browse files
committed
addressed PR comments
1 parent ecd81f8 commit ceef6d7

File tree

8 files changed

+551
-134
lines changed

8 files changed

+551
-134
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package main
2+
3+
import (
4+
grlog "code.cloudfoundry.org/gorouter/logger"
5+
"code.cloudfoundry.org/lager/v3"
6+
"go.uber.org/zap"
7+
"go.uber.org/zap/zapcore"
8+
"log/slog"
9+
"os"
10+
"strings"
11+
"time"
12+
)
13+
14+
// zapLevelSink is a lager sink that uses a slog.Logger for logging.
15+
// It implements the lager.Sink interface, allowing it to be used with
16+
// lager's logging system. The Log method logs the message and source
17+
// using the slog.Logger, and the LogLevel method returns the current
18+
// logging level.
19+
type zapLevelSink struct {
20+
logger *slog.Logger
21+
}
22+
23+
func (z *zapLevelSink) Log(lf lager.LogFormat) {
24+
z.logger.Info("zapLevelSink Log()", slog.String("Zap Level Sink log invoked", lf.Message),
25+
slog.String("source", lf.Source))
26+
}
27+
28+
func (z *zapLevelSink) LogLevel() lager.LogLevel {
29+
switch strings.ToLower(grlog.GetLoggingLevel()) {
30+
case "debug":
31+
return lager.DEBUG
32+
case "info":
33+
return lager.INFO
34+
case "error":
35+
return lager.ERROR
36+
case "warn":
37+
// lager does not have a separate WARN level, it uses INFO for warnings.
38+
return lager.INFO
39+
case "fatal":
40+
return lager.FATAL
41+
default:
42+
return lager.INFO
43+
}
44+
}
45+
46+
// The SetMinLevel method updates the logging level of the
47+
// zapLevelSink based on the provided lager.LogLevel, mapping it to
48+
// the corresponding zapcore.Level. The logger is expected to be set
49+
// before using this sink, and it will log an info message when the
50+
// logging level is updated.
51+
func (z *zapLevelSink) SetMinLevel(level lager.LogLevel) {
52+
var zapLevel zapcore.Level
53+
switch level {
54+
case lager.DEBUG:
55+
zapLevel = zapcore.DebugLevel
56+
case lager.INFO:
57+
zapLevel = zapcore.InfoLevel
58+
case lager.ERROR:
59+
zapLevel = zapcore.ErrorLevel
60+
case lager.FATAL:
61+
zapLevel = zapcore.FatalLevel
62+
default:
63+
// There is no lager.WARN level, so mapping it to zapcore.WarnLevel in default case.
64+
zapLevel = zapcore.WarnLevel
65+
}
66+
67+
grlog.SetLoggingLevel(zapLevel.String())
68+
69+
// Print the new log level to the logger to confirm the change.
70+
// This is useful for debugging and confirming that the log level has been updated.
71+
if z.logger != nil {
72+
// We cannot use z.logger.Info() directly here because it won't print the
73+
// log level when it is set to zapcore.ErrorLevel or zapcore.FatalLevel.
74+
// Instead, we use slog.New() to log the message. This ensures that the
75+
// log level change is always logged, regardless of the current log level.
76+
tmpLogger := NewZapLoggerWithTimestamp()
77+
tmpLogger.Info("Gorouter logger -> zapcore log level updated.",
78+
zap.String("new log_level", zapLevel.String()))
79+
}
80+
}
81+
82+
// NewZapLoggerWithTimestamp creates a new zap.Logger with a custom
83+
// timestamp encoder that outputs the timestamp as a float64 representing
84+
// the number of seconds since the Unix epoch.
85+
func NewZapLoggerWithTimestamp() *zap.Logger {
86+
cfg := zap.NewProductionEncoderConfig()
87+
// customized keys for the JSON encoder
88+
cfg.TimeKey = "timestamp"
89+
cfg.LevelKey = "log_level"
90+
cfg.MessageKey = "message"
91+
// time encoded as float64
92+
cfg.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
93+
enc.AppendFloat64(float64(t.UnixNano()) / 1e9)
94+
}
95+
// Encode log level as int. zapcore.Level is 0-indexed,
96+
// so add 1 to the level to match the gorouter's expected level.
97+
cfg.EncodeLevel = func(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
98+
enc.AppendInt(int(l + 1))
99+
}
100+
core := zapcore.NewCore(zapcore.NewJSONEncoder(cfg), zapcore.AddSync(os.Stdout), zap.InfoLevel)
101+
return zap.New(core)
102+
}

src/code.cloudfoundry.org/gorouter/cmd/gorouter/main.go

Lines changed: 1 addition & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,13 @@ import (
88
"log/slog"
99
"os"
1010
"runtime"
11-
"strings"
1211
"syscall"
1312
"time"
1413

1514
"code.cloudfoundry.org/gorouter/metrics_prometheus"
16-
"go.uber.org/zap/zapcore"
1715

1816
"code.cloudfoundry.org/clock"
1917
"code.cloudfoundry.org/debugserver"
20-
"code.cloudfoundry.org/lager/v3"
2118
"code.cloudfoundry.org/tlsconfig"
2219
"github.com/cloudfoundry/dropsonde"
2320
"github.com/cloudfoundry/dropsonde/metric_sender"
@@ -52,81 +49,13 @@ var (
5249
h *health.Health
5350
)
5451

55-
// zapLevelSink is a lager sink that uses a slog.Logger for logging.
56-
// It implements the lager.Sink interface, allowing it to be used with
57-
// lager's logging system. The Log method logs the message and source
58-
// using the slog.Logger, and the LogLevel method returns the current
59-
// logging level.
60-
61-
type zapLevelSink struct {
62-
logger *slog.Logger
63-
}
64-
65-
func (z *zapLevelSink) Log(lf lager.LogFormat) {
66-
z.logger.Info("zapLevelSink Log()", slog.String("Zap Level Sink log invoked", lf.Message),
67-
slog.String("source", lf.Source))
68-
}
69-
70-
func (z *zapLevelSink) LogLevel() lager.LogLevel {
71-
switch strings.ToLower(grlog.GetLoggingLevel()) {
72-
case "debug":
73-
return lager.DEBUG
74-
case "info":
75-
return lager.INFO
76-
case "error":
77-
return lager.ERROR
78-
case "fatal":
79-
return lager.FATAL
80-
default:
81-
return lager.INFO
82-
}
83-
}
84-
85-
// The SetMinLevel method updates the logging level of the
86-
// zapLevelSink based on the provided lager.LogLevel, mapping it to
87-
// the corresponding zapcore.Level. The logger is expected to be set
88-
// before using this sink, and it will log an info message when the
89-
// logging level is updated.
90-
91-
func (z *zapLevelSink) SetMinLevel(level lager.LogLevel) {
92-
var zapLevel zapcore.Level
93-
switch level {
94-
case lager.DEBUG:
95-
zapLevel = zapcore.DebugLevel
96-
case lager.INFO:
97-
zapLevel = zapcore.InfoLevel
98-
case lager.ERROR, lager.FATAL:
99-
// For lager.ERROR and lager.FATAL, we use zapcore.ErrorLevel.
100-
// This is because zapcore.ErrorLevel captures both error and fatal logs.
101-
// Using zapcore.FatalLevel would cause the application to exit immediately.
102-
// Because zapcore.FatalLevel calls os.Exit(1) after logging the message.
103-
zapLevel = zapcore.ErrorLevel
104-
default:
105-
zapLevel = zapcore.InfoLevel
106-
}
107-
108-
grlog.SetLoggingLevel(zapLevel.String())
109-
110-
// Print the new log level to the logger to confirm the change.
111-
// This is useful for debugging and confirming that the log level has been updated.
112-
if z.logger != nil {
113-
// We cannot use z.logger.Info() directly here because it won't print the
114-
// log level when it is set to zapcore.ErrorLevel or zapcore.FatalLevel.
115-
// Instead, we use slog.New() to log the message. This ensures that the
116-
// log level change is always logged, regardless of the current log level.
117-
tmpLogger := slog.New(slog.NewTextHandler(os.Stdout, nil))
118-
tmpLogger.Info("Gorouter logger -> zapcore log level updated.", slog.String("new-level", z.LogLevel().String()))
119-
}
120-
}
121-
12252
func main() {
12353
flag.StringVar(&configFile, "c", "", "Configuration File")
12454
flag.Parse()
12555

12656
prefix := "gorouter.stdout"
12757
coreLogger := grlog.CreateLogger()
12858
grlog.SetLoggingLevel("INFO")
129-
coreLogger.Info("gorouter-startup-test-log", slog.String("test", "true"))
13059

13160
c, err := config.DefaultConfig()
13261
if err != nil {
@@ -173,28 +102,17 @@ func main() {
173102

174103
// start the debugserver
175104
if c.DebugAddr != "" {
176-
logLevel, logErr := lager.LogLevelFromString(c.Logging.Level)
177-
if logErr != nil {
178-
logger.Error("invalid-log-level", grlog.ErrAttr(logErr))
179-
}
180-
181105
// create a zapLevelSink that uses the logger
182106
sink := &zapLevelSink{logger: logger}
183-
184-
// create a reconfigurable sink that can change log levels at runtime
185-
reconfigurableSink := lager.NewReconfigurableSink(sink, logLevel)
186-
187-
// start the debugserver with the reconfigurable sink
107+
// create a new debugserver with the address and the sink and run it
188108
_, err = debugserver.Run(c.DebugAddr, sink)
189109
if err != nil {
190110
logger.Error("failed-to-start-debug-server", grlog.ErrAttr(err))
191111
}
192-
193112
logger.Info("debugserver-started",
194113
slog.String("address", c.DebugAddr),
195114
slog.String("log_level", c.Logging.Level),
196115
slog.String("log_format", c.Logging.Format.Timestamp),
197-
slog.String("log_level_from_sink", reconfigurableSink.GetMinLevel().String()),
198116
)
199117
}
200118

0 commit comments

Comments
 (0)