Add an exported func to be able to set a new level color for Development mode#3
Merged
icefed merged 1 commit intoicefed:masterfrom Oct 3, 2025
Merged
Conversation
d93cf0e to
9a8ba56
Compare
…ent mode
I also added a `UseDefaultLevelColors` function to reset it back to the stock
list, mostly for being able to reset it back to stock in the unit tests.
This is _fractionally_ less efficient as it's now a loop rather
than a switch statement that can be unrolledm, but this is unavoidable if we
want it to be controllable by the developer at runtime.
Benchmark results:
```
BenchmarkLevelFormat/ERROR+5/new-12 12287250 94.46 ns/op
BenchmarkLevelFormat/ERROR+5/old-12 13530858 89.57 ns/op
BenchmarkLevelFormat/ERROR/new-12 100000000 12.95 ns/op
BenchmarkLevelFormat/ERROR/old-12 131831570 10.26 ns/op
BenchmarkLevelFormat/INFO/new-12 100000000 10.07 ns/op
BenchmarkLevelFormat/INFO/old-12 146790718 8.549 ns/op
BenchmarkLevelFormat/INFO+2/new-12 13149951 88.20 ns/op
BenchmarkLevelFormat/INFO+2/old-12 13251370 86.32 ns/op
BenchmarkLevelFormat/DEBUG/new-12 93846536 11.90 ns/op
BenchmarkLevelFormat/DEBUG/old-12 149301160 8.671 ns/op
BenchmarkLevelFormat/DEBUG-4/new-12 12009832 94.50 ns/op
BenchmarkLevelFormat/DEBUG-4/old-12 12207226 92.35 ns/op
```
(Note that the non-"Pure" levels are much slower anyway as `l.String()` hits a
fmt.Sprintf path inside slog package)
Here "old" is the current version on main using switch and "new" is the
version in this PR.
The benchmark code (not committed) was this:
```go
func BenchmarkLevelFormat(b *testing.B) {
for _, lvl := range []slog.Level{
slog.LevelError + 5,
slog.LevelError,
slog.LevelInfo,
slog.LevelInfo + 2,
slog.LevelDebug,
slog.LevelDebug - 4,
} {
b.Run(lvl.String(), func(b *testing.B) {
for _, fn := range []struct {
name string
fn func(buf *buffer.Buffer, l slog.Level)
}{
{"new", formatColorLevelValue}, {"old", old},
} {
b.Run(fn.name, func(b *testing.B) {
b.ResetTimer()
buf := buffer.New()
defer buf.Free()
b.ResetTimer()
for b.Loop() {
fn.fn(buf, lvl)
}
})
}
})
}
}
func old(buf *buffer.Buffer, l slog.Level) {
switch {
case l < slog.LevelInfo: // LevelDebug
buf.WriteString(magenta)
case l < slog.LevelWarn: // LevelInfo
buf.WriteString(blue)
case l < slog.LevelError: // LevelWarn
buf.WriteString(yellow)
default: // LevelError
buf.WriteString(red)
}
buf.WriteString(l.String())
buf.WriteString(reset)
}
```
9a8ba56 to
ab6ef1e
Compare
Owner
|
@ashb Thank you. A little performance reduction is acceptable in development mode. |
Owner
|
Have you considered adding trace level that you need? a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add an exported func to be able to set a new level color for Development mode
I also added a
UseDefaultLevelColorsfunction to reset it back to the stocklist, mostly for being able to reset it back to stock in the unit tests.
This is fractionally less efficient as it's now a loop rather
than a switch statement that can be unrolledm, but this is unavoidable if we
want it to be controllable by the developer at runtime.
Benchmark results:
(Note that the non-"Pure" levels are much slower anyway as
l.String()hits afmt.Sprintf path inside slog package)
Here "old" is the current version on main using switch and "new" is the
version in this PR.
The benchmark code (not committed) was this: