Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Headers, error formatting, multiline attr value handling, dim theme, and ReplaceAttr support #15

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

ansel1
Copy link

@ansel1 ansel1 commented Jan 11, 2025

This PR combines the other PRs:

  • Headers: Configurable list of attrs which are moved into the header section of the log line, between the source and message fields Support for configurable headers... #6
  • ReplaceAttr support: Just like slog.HandlerOptions.ReplaceAttr. Will work with all the builtin attrs and with headers as well. ReplaceAttr support #5
  • Attr values with newlines: moves any attributes with newlines in their values to the end of the log line. Makes it easier to scan log output when newlines are mixed in with other attribute values. Multiline values #8
  • Error formatting: if error attr values also implement fmt.Formatter, then print the error using fmt.Printf("%+v"). Several error packages use this convention for printing stack traces. Formatting errors #7
  • New "Dim" theme, but with cyan attrs keys. The "Dim" theme in Adds a new "Dim" theme #10 changes two things from the Default theme: the attr key color goes from Cyan to Blue, and the attr value goes from default to Gray. I tested that on several terminals, using common themes. The Blue doesn't work well with some common themes. It's two dark and vivid. So the Dim theme in this PR only changes the attr value color to Gray. It's such a subtle change that maybe you'd consider just changing the Default theme? New dimmer theme #9

I've benchmarked this against the main branch. Even when the features are used, there are still zero allocations. The only feature which introduces some performance overhead is the multiline value handling, which increased processing by about 75ns on my system (from about 825ns to 900ns). The other features have no impact when not used.

As an example, given this:

h := console.NewHandler(os.Stdout, &console.HandlerOptions{
				AddSource:  true,
				Theme:      console.NewDimTheme(),
				Headers:    []string{"logger"},
				TimeFormat: time.Kitchen,
				ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
					if a.Key == "size"  && a.Value.Int64() > 100 {
						a.Value = slog.StringValue("huge")
					}
					return a
				},
			})

slog.New(v.handler).With("logger", "main").Info("hello world", "err", merry.New("boom"), "color", "red", "err2", merry.New("bang"), "size", 101)

Output looks like:
image

Here's another sample, from macos Terminal.app, Basic Theme:
image

Note:

  • The "Dim" theme: Exactly the same is the "Default" theme, except attr values are Gray instead of default color
  • The "logger" attr has been extracted and placed in the header section, after the source.
  • ReplaceAttr was used to replace the value of the "size" attr: 101 -> "huge"
  • The error value was pretty printed with a full stacktrace
  • Both of the multiline values were moved to the end of the log line

More work could be considered on multiline values, like placing the entire value on its own lines. Still playing with different options.

Russ Egan and others added 13 commits January 7, 2025 20:53
Makes attribute values and keys a little darker to make the messages pop more.  Addresses issue phsym#9.
Uses fmt.Fprintf with "%+v" to print errors.  Useful with some error packages which render additional information like stacktraces.  Addresses phsym#7
Sort multiline values to the end, and print the key on a separate line
HandlerOptions.ReplaceAttr support.

When ReplaceAttr is set, there will be more allocations.

There is one allocation happening even when ReplaceAttr is nil, around passing the slice of groups to ReplaceAttr.  Still needs to be optimized away.
Encoders are now the disposable state struct for each Handle call.  A sync pool of encoders replaces the sync pool of buffers.

This allows the encoder to store additional state per Handle() call, including a slice of currently open groups, which is needed to call ReplaceAttr.

Benchmarking shows 0 allocations, regardless of whether ReplaceAttr is set or not.  Setting a ReplaceAttr does add some overhead, similar to the slog.TextHandler.

Benchmarking also shows a slight performance improvement over the original code (using the buf pool), when ReplaceAttrs is not set.
If the error doesn't implement fmt.Formatter, as most won't, its faster to use err.Error() than always use fmt to print the error.
Only the caller knows the appropriate style to use for the current context in the log line.
Add support for adding headers

    Headers are optional attributes removed from the end of the line, and injected (values only) into the header of the line, after the level/source, and before the message.
Blue looks good with some terminal themes, but not with the default macos theme.  Cyan generally looks fine on more themes I think.
@ansel1 ansel1 mentioned this pull request Jan 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant