Skip to content

Commit a87bfd3

Browse files
committed
logs.go: LogToSlogWriter wasn't setting the right logs as ERROR
1 parent f773c6a commit a87bfd3

File tree

2 files changed

+89
-14
lines changed

2 files changed

+89
-14
lines changed

pkg/logs/logs.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,38 +116,39 @@ func Initialize() {
116116
slog := slog.Default()
117117

118118
Log = &log.Logger{}
119-
Log.SetOutput(logToSlogWriter{slog: slog, source: "agent"})
119+
Log.SetOutput(LogToSlogWriter{Slog: slog, Source: "agent"})
120120

121121
// Let's make sure the VCert library, which is the only library we import to
122122
// be using the global log.Default, also uses the common slog logger.
123123
vcertLog := log.Default()
124-
vcertLog.SetOutput(logToSlogWriter{slog: slog, source: "vcert"})
124+
vcertLog.SetOutput(LogToSlogWriter{Slog: slog, Source: "vcert"})
125125
// This is a work around for a bug in vcert where it adds a `vCert: ` prefix
126126
// to the global log logger. It can be removed when this is fixed upstream
127127
// in vcert: https://github.com/Venafi/vcert/pull/512
128128
vcertLog.SetPrefix("")
129129
}
130130

131-
type logToSlogWriter struct {
132-
slog *slog.Logger
133-
source string
131+
type LogToSlogWriter struct {
132+
Slog *slog.Logger
133+
Source string
134134
}
135135

136-
func (w logToSlogWriter) Write(p []byte) (n int, err error) {
136+
func (w LogToSlogWriter) Write(p []byte) (n int, err error) {
137137
// log.Printf writes a newline at the end of the message, so we need to trim
138138
// it.
139139
p = bytes.TrimSuffix(p, []byte("\n"))
140140

141141
message := string(p)
142-
if isCritical(message) {
143-
w.slog.With("source", w.source).Error(message)
142+
if strings.Contains(message, "error") ||
143+
strings.Contains(message, "failed") ||
144+
strings.Contains(message, "fatal") ||
145+
strings.Contains(message, "Failed") ||
146+
strings.Contains(message, "While evaluating configuration") ||
147+
strings.Contains(message, "data-path override present") ||
148+
strings.Contains(message, "Cannot marshal readings") {
149+
w.Slog.With("source", w.Source).Error(message)
144150
} else {
145-
w.slog.With("source", w.source).Info(message)
151+
w.Slog.With("source", w.Source).Info(message)
146152
}
147153
return len(p), nil
148154
}
149-
150-
func isCritical(msg string) bool {
151-
// You can implement more robust logic to detect critical log messages
152-
return strings.Contains(msg, "FATAL") || strings.Contains(msg, "ERROR")
153-
}

pkg/logs/logs_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
_ "github.com/Venafi/vcert/v5"
1717
"github.com/spf13/pflag"
18+
"github.com/stretchr/testify/assert"
1819
"github.com/stretchr/testify/require"
1920
"k8s.io/klog/v2"
2021

@@ -316,3 +317,76 @@ func replaceWithStaticTimestamps(input string) string {
316317
input = fileAndLineRegexpKlog.ReplaceAllString(input, " $1.go:000")
317318
return input
318319
}
320+
321+
func TestLogToSlogWriter(t *testing.T) {
322+
// This test makes sure that all the agent's Log.Fatalf calls are correctly
323+
// translated to slog.Error calls.
324+
//
325+
// This list was generated using:
326+
// grep -r "Log\.Fatalf" ./cmd ./pkg
327+
given := strings.TrimPrefix(`
328+
Failed to load config file for agent from
329+
Failed to read config file
330+
Failed to parse config file
331+
While evaluating configuration
332+
failed to run pprof profiler
333+
failed to run the health check server
334+
failed to start a controller-runtime component
335+
failed to wait for controller-runtime component to stop
336+
running data gatherer %s of type %s as Local, data-path override present
337+
failed to instantiate %q data gatherer
338+
failed to read local data file
339+
failed to unmarshal local data file
340+
failed to output to local file
341+
Exiting due to fatal error uploading
342+
halting datagathering in strict mode due to error
343+
Cannot marshal readings
344+
Failed to read config file
345+
Failed to parse config file
346+
Failed to validate data gatherers
347+
this is a happy log that should show as INFO`, "\n")
348+
expect := strings.TrimPrefix(`
349+
level=ERROR msg="Failed to load config file for agent from" source=agent
350+
level=ERROR msg="Failed to read config file" source=agent
351+
level=ERROR msg="Failed to parse config file" source=agent
352+
level=ERROR msg="While evaluating configuration" source=agent
353+
level=ERROR msg="failed to run pprof profiler" source=agent
354+
level=ERROR msg="failed to run the health check server" source=agent
355+
level=ERROR msg="failed to start a controller-runtime component" source=agent
356+
level=ERROR msg="failed to wait for controller-runtime component to stop" source=agent
357+
level=ERROR msg="running data gatherer %!s(MISSING) of type %!s(MISSING) as Local, data-path override present" source=agent
358+
level=ERROR msg="failed to instantiate %!q(MISSING) data gatherer" source=agent
359+
level=ERROR msg="failed to read local data file" source=agent
360+
level=ERROR msg="failed to unmarshal local data file" source=agent
361+
level=ERROR msg="failed to output to local file" source=agent
362+
level=ERROR msg="Exiting due to fatal error uploading" source=agent
363+
level=ERROR msg="halting datagathering in strict mode due to error" source=agent
364+
level=ERROR msg="Cannot marshal readings" source=agent
365+
level=ERROR msg="Failed to read config file" source=agent
366+
level=ERROR msg="Failed to parse config file" source=agent
367+
level=ERROR msg="Failed to validate data gatherers" source=agent
368+
level=INFO msg="this is a happy log that should show as INFO" source=agent
369+
`, "\n")
370+
371+
gotBuf := &bytes.Buffer{}
372+
slogHandler := slog.NewTextHandler(gotBuf, &slog.HandlerOptions{
373+
// Remove the timestamp from the logs so that we can compare them.
374+
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
375+
if a.Key == "time" {
376+
return slog.Attr{}
377+
}
378+
return a
379+
},
380+
})
381+
slogLogger := slog.New(slogHandler)
382+
383+
logger := log.New(&bytes.Buffer{}, "", 0)
384+
logger.SetOutput(logs.LogToSlogWriter{Slog: slogLogger, Source: "agent"})
385+
386+
for _, line := range strings.Split(given, "\n") {
387+
// Simulate the current agent's logs.
388+
logger.Printf(line)
389+
}
390+
391+
assert.Equal(t, expect, gotBuf.String())
392+
}

0 commit comments

Comments
 (0)