Skip to content

Commit cb1839e

Browse files
committed
Add support for using slog for log output
Allows containerd logs to use the default slog logger if configured. Ensures that when formatting is set, such as through a default configuration, if the slog format as well previously set. Signed-off-by: Derek McGowan <derek@mcg.dev>
1 parent 909c7de commit cb1839e

3 files changed

Lines changed: 374 additions & 2 deletions

File tree

context.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ package log
4040
import (
4141
"context"
4242
"fmt"
43+
"log/slog"
4344

4445
"github.com/sirupsen/logrus"
4546
)
@@ -127,6 +128,9 @@ func SetLevel(level string) error {
127128
}
128129

129130
L.Logger.SetLevel(lvl)
131+
if slogOut != nil {
132+
slogLevel.Set(logrusToSlogLevel(lvl))
133+
}
130134
return nil
131135
}
132136

@@ -155,15 +159,26 @@ func SetFormat(format OutputFormat) error {
155159
TimestampFormat: RFC3339NanoFixed,
156160
FullTimestamp: true,
157161
})
158-
return nil
159162
case JSONFormat:
160163
L.Logger.SetFormatter(&logrus.JSONFormatter{
161164
TimestampFormat: RFC3339NanoFixed,
162165
})
163-
return nil
164166
default:
165167
return fmt.Errorf("unknown log format: %s", format)
166168
}
169+
170+
if slogOut != nil {
171+
var handler slog.Handler
172+
switch format {
173+
case TextFormat:
174+
handler = slog.NewTextHandler(slogOut, &slog.HandlerOptions{Level: slogLevel})
175+
case JSONFormat:
176+
handler = slog.NewJSONHandler(slogOut, &slog.HandlerOptions{Level: slogLevel})
177+
}
178+
slog.SetDefault(slog.New(handler))
179+
}
180+
181+
return nil
167182
}
168183

169184
// WithLogger returns a new context with the provided logger. Use in

slog.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package log
18+
19+
import (
20+
"context"
21+
"io"
22+
"log/slog"
23+
24+
"github.com/sirupsen/logrus"
25+
)
26+
27+
// slogOut is used to set the slog logger when setting output format.
28+
var slogOut io.Writer
29+
30+
// slogLevel is used to control the slog handler's level when slog output is active.
31+
var slogLevel = &slog.LevelVar{}
32+
33+
func UseSlog() {
34+
L.Logger.SetNoLock()
35+
L.Logger.AddHook(slogHook{})
36+
slogOut = L.Logger.Out
37+
L.Logger.SetOutput(io.Discard)
38+
}
39+
40+
type slogHook struct{}
41+
42+
func (hook slogHook) Levels() []logrus.Level {
43+
return logrus.AllLevels
44+
}
45+
46+
func logrusToSlogLevel(l logrus.Level) slog.Level {
47+
switch l {
48+
case logrus.PanicLevel:
49+
return slog.LevelError + 4
50+
case logrus.FatalLevel:
51+
return slog.LevelError + 2
52+
case logrus.ErrorLevel:
53+
return slog.LevelError
54+
case logrus.WarnLevel:
55+
return slog.LevelWarn
56+
case logrus.DebugLevel:
57+
return slog.LevelDebug
58+
case logrus.TraceLevel:
59+
return slog.LevelDebug - 4
60+
default:
61+
return slog.LevelInfo
62+
}
63+
}
64+
65+
func (hook slogHook) Fire(entry *logrus.Entry) error {
66+
level := logrusToSlogLevel(entry.Level)
67+
68+
handler := slog.Default().Handler()
69+
70+
ctx := entry.Context
71+
if ctx == nil {
72+
ctx = context.Background()
73+
}
74+
75+
if !handler.Enabled(ctx, level) {
76+
return nil
77+
}
78+
79+
record := slog.NewRecord(entry.Time, level, entry.Message, 0)
80+
81+
// Convert logrus fields to slog attributes.
82+
for k, v := range entry.Data {
83+
record.AddAttrs(slog.Any(k, v))
84+
}
85+
86+
return handler.Handle(ctx, record)
87+
}

0 commit comments

Comments
 (0)