Skip to content

Commit

Permalink
Added support for overriding color and name for level along with cust…
Browse files Browse the repository at this point in the history
…om levels.
  • Loading branch information
iamsumit committed May 15, 2024
1 parent c4b4292 commit 4816575
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
33 changes: 33 additions & 0 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ var (
defaultTimeFormat = time.StampMilli
)

// LevelMeta contains the name and color of a level.
type LevelMeta struct {
Name string
Color string
}

// Options for a slog.Handler that writes tinted logs. A zero Options consists
// entirely of default values.
//
Expand All @@ -95,6 +101,10 @@ type Options struct {
// Minimum level to log (Default: slog.LevelInfo)
Level slog.Leveler

// LevelMeta is a map of level to its name and color. If set, it overrides
// the default level names and colors.
LevelMeta map[slog.Level]LevelMeta

// ReplaceAttr is called to rewrite each non-group attribute before it is logged.
// See https://pkg.go.dev/log/slog#HandlerOptions for details.
ReplaceAttr func(groups []string, attr slog.Attr) slog.Attr
Expand Down Expand Up @@ -122,6 +132,11 @@ func NewHandler(w io.Writer, opts *Options) slog.Handler {
if opts.Level != nil {
h.level = opts.Level
}

if len(opts.LevelMeta) > 0 {
h.levelMeta = opts.LevelMeta
}

h.replaceAttr = opts.ReplaceAttr
if opts.TimeFormat != "" {
h.timeFormat = opts.TimeFormat
Expand All @@ -141,6 +156,7 @@ type handler struct {

addSource bool
level slog.Leveler
levelMeta map[slog.Level]LevelMeta
replaceAttr func([]string, slog.Attr) slog.Attr
timeFormat string
noColor bool
Expand Down Expand Up @@ -283,6 +299,10 @@ func (h *handler) appendTime(buf *buffer, t time.Time) {
}

func (h *handler) appendLevel(buf *buffer, level slog.Level) {
if h.applyMeta(buf, level) {
return
}

switch {
case level < slog.LevelInfo:
buf.WriteString("DBG")
Expand All @@ -305,6 +325,19 @@ func (h *handler) appendLevel(buf *buffer, level slog.Level) {
}
}

func (h *handler) applyMeta(buf *buffer, level slog.Level) bool {
lvlMeta, ok := h.levelMeta[level]
if !ok {
return false
}

buf.WriteStringIf(!h.noColor, lvlMeta.Color)
buf.WriteString(lvlMeta.Name)
buf.WriteStringIf(!h.noColor, ansiReset)

return true
}

func appendLevelDelta(buf *buffer, delta slog.Level) {
if delta == 0 {
return
Expand Down
32 changes: 31 additions & 1 deletion handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,31 @@ import (

var faketime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)

const CustomLevel slog.Level = -6

func Example() {
lvlMeta := map[slog.Level]tint.LevelMeta{
CustomLevel: {
Name: "TEST",
Color: "\033[95m",
},
slog.LevelDebug: {
Name: "DBG",
Color: "\033[94m",
},
}

slog.SetDefault(slog.New(tint.NewHandler(os.Stderr, &tint.Options{
Level: slog.LevelDebug,
Level: CustomLevel,
LevelMeta: lvlMeta,
TimeFormat: time.Kitchen,
})))

slog.Info("Starting server", "addr", ":8080", "env", "production")
slog.Debug("Connected to DB", "db", "myapp", "host", "localhost:5432")
slog.Warn("Slow request", "method", "GET", "path", "/users", "duration", 497*time.Millisecond)
slog.Error("DB connection lost", tint.Err(errors.New("connection reset")), "db", "myapp")
slog.Log(context.Background(), CustomLevel, "Custom level message")
// Output:
}

Expand Down Expand Up @@ -344,6 +359,21 @@ func TestHandler(t *testing.T) {
},
Want: `Nov 10 23:00:00.000 INF test key="{A:123 B:<nil>}"`,
},
{ // https://github.com/lmittmann/tint/issues/37
Opts: &tint.Options{
Level: slog.LevelDebug,
LevelMeta: map[slog.Level]tint.LevelMeta{
slog.LevelDebug: {
Name: "MyDebug",
Color: "\033[32m",
},
},
},
F: func(l *slog.Logger) {
l.Debug("test")
},
Want: `Nov 10 23:00:00.000 MyDebug test`,
},
}

for i, test := range tests {
Expand Down

0 comments on commit 4816575

Please sign in to comment.