Tools and testing for log/slog (hereafter just slog) handlers.
📝 Author has brain cancer and will archive this project pretty soon. -- 2025-01-28
Recent benchmark data is available via GitHub Pages.
See the source or documentation for more detailed documentation.
- Test harness for benchmarking
sloghandler performance - Test harness for verifying
sloghandler functionality - Web Server that processes output of previous two steps and provides access to result.
- Static copies of server pages provided via GitHub Pages.
- Functions for use with
slog.HandlerOptions.ReplaceAttr - Utility to redirect internal
ginlogging toslog - Demo Handlers
- Template for repository use
- Test handler
trace.Handler
Benchmarks of slog handlers can be done by creating
simple _test.go files that utilize the bench/test.SlogBenchmarkSuite
located in this repository.
Usage details for this facility are provided in
the README file
located in the bench package directory.
Benchmarks are intended to compare multiple handlers.
This repository is configured to test all known, functional slog handlers that generate JSON.
The benchmark data generated can be processed by two applications:
tabular
generates a set of tables, each of which compares handlers for a given benchmark test.server
runs a simple web server showing the same tables plus bar charts and handler verification warnings.
Verification of slog handlers can be done by creating
simple _test.go files that utilize the verify/test.SlogTestSuite
located in this repository.
Usage details for this facility are provided in
the README file
located in the verify package directory.
Verification testing is intended to test a single handler or to compare multiple handlers.
This repository is configured to test all known, functional slog handlers that generate JSON.
The tests implemented herein were inspired by:
- the
slogtestapplication, - rules specified in
the
log/slog.Handerand handler writing guide documentation, - issues I noticed while exploring
go-logging-benchmark - as well as some other test cases that seemed useful.
The cmd/server
application is intended to process the benchmark and verification output and
display it on a series of web pages.
The pages display:
- handler data: benchmarks and warnings
- bench test data: benchmarks and warnings
- verification test data: warnings
- warning definitions and coverage
The benchmark data is displayed as a table
(similar to cmd/tabular) and
as a series of bar charts comparing tests for a handler or handlers for a test.
Server pages are generated on a weekly basis using GitHub Actions and Pages. The GitHub Action:
- updates libraries used by this repository
- builds and runs:
- handler benchmarks,
- handler verifications, and
- the
cmd/serverapplication
- at which point the
wgettool is used to copy the server pages into thedocssubdirectory.
The pages in the docs subdirectory are then
vended by GitHub Pages.
A small collection of functions in the
replace package
can be used with slog.HandlerOptions.ReplaceAttr.
These functions are intended to "fix" some of the verification issues with various handlers.
Package gin contains utilities for using slog with
gin-gonic/gin.
In particular, this package provides
gin.NewWriter
which can be used to redirect Gin-internal logging.
Several new slog handlers are available.
The sloggy package defines a feature-complete, green field slog.Handler implementation.
This can be used as is, though it is admittedly slower than slog.JSONHandler
(also feature-complete and generally used as the model for correct functionality).
It might be useful as a starting point for other, better implementations.
The flash package is a copy of sloggy with subsequent performance-enhancing edits.
It is just as feature-compliant and much faster, now in the group of "fastest" handlers
(slog/JSONHandler, phsym/zeroslog, and chanchal/zaphandler,
though only the first of these is feature-complete).
Profiling of the verification and benchmark code shows almost all CPU cycles
used for formatting various data items into []byte buffers.
It is possible that the slog/JSONHandler and madkins/flash handlers
have reached something like the theoretical speed limit for fully functional slog handlers.
At this point flash may be as usable as slog.JSONHandler,
though the latter may be a smarter choice as it is supported by the core Go team.
The flash handler also supports
flash.Extras options.
The documented slog.HandlerOptions continue to be supported.
The optional flash.Extras options can be used to adjust output somewhat
in order to achieve compatability with previous logging solutions.
The "trace" handler trace.Handler doesn't log anything,
it just prints out the slog.Handler interface calls it receives.
These test suites can be linked into any slog.Handler repository.
The advantage would be quicker feedback on changes in progress in your code.
A template package
is provided to make installation and usage as simple as possible.
The tests in this repository only apply to slog JSON output.
Console output can come in a variety of formats and
generally doesn't have a performance issue as only humans will look at it.
Your response to this repository, especially if you are a slog handler author,
may well be one or more of:
- "Why does this exist?"
- "Who are you to make these rules?"
These are reasonable questions.
The genesis of this repository was the author noticing that different
slog handlers had varying outputs.
The author wanted to provide a way to compare the outputs,
because it seemed important (or at least personally interesting).
Over time the project grew to include handler benchmarks and a lot of other stuff.
The author has no authority to dictate slog handler behavior.
The intent of this project was to measure handlers against each other and
published documentation.
Benchmark and verification tests come from slog documentation,
the slogtest test harness, and tests embedded in
betterstack-community/go-logging-benchmarks.
Warnings generated by these tests pretty much defined themselves (with the author's help, of course).
Each test and/or warning is based on some sort of justification. This justification is reflected in documentation and comments throughout the code. It should be possible to follow this trail of bread crumbs to justify each test or warning. Whether the reader agrees with this justification is subjective.
The several levels of verification tests are defined based on the strength of justification:
- Required
Justified from requirements in theslog.Handlerdocumentation. - Implied
Implied by documentation but can't be considered required. - Suggested
Not mandated by any documentation or requirements. These are the ones that the author just made up because they seemed appropriate. - Administrative
Information about the tests or conflicts with other warnings.
- You don't have to pay attention to any of this. Really.
- If you do pay attention, you should probably work down from
Requiredwarnings. - Consider your users' viewpoint...
- Are you confident that the
sloghandler you choose will be fine forever? - If you need to swap out
sloghandlers will the new one support your usage of the old one?- Should your code use only generally supported features even if more useful ones are available?
- Are you prepared to change logging statements to use a less functional handler?
- Consider the trade-off between performance and functionality.
- Do you need faster logging without support for picky warnings?
- Do you need full support of all verification tests at the cost of performance?
The author considers the interoperability of logging via slog to be very important,
and possibly the best aspect of slog logging.
Editing every log statement in a large project can be a real pain.
Slog Documentation
Slog Handlers
The following handlers are currently under test in this repository:
chanchal/zaphandlermadkins/flashmadkins/replattrmadkins/sloggyphsym/zeroslogphuslu/slogsamber/slog-logrussamber/slog-zapsamber/slog-zerologslog/JSONHandler
Handlers that have been investigated and found wanting:
-
darvazahandlers are based on a different definition oflog/slogas an interface that is not compatible with the "real"log/slog/Logger. Since the latter is not an interface there is no way to build a shim. In addition, there is no separateHandlerobject. -
Some handlers are still using
golang.org/x/exp/sloginstead of the standard librarylog/slog: -
The
trim21/sloghandler is documented as "immature". -
The
go-logr/zerologrhandler presents some challenges:- Wraps
go-logr/lograround ars/zerologlogger (not a handler),
then wraps another layer (zerologr.LogSink) around that to return aslog.Handler. - Doesn't support
slog.HandlerOptionsdirectly. - Configuring a default
slog.Levelper handler is difficult.- Negative integers are unsupported so levels must be "fixed" in use.
- Higher numbers are less important, whereas in
sloglower numbers (including negative numbers) are less important so everything must be reversed. - The
Enabled()implementation uses both local level value and
the globalzerologlevel so the per-handler/logger level isn't truly local.
- Wraps
Console handlers are not tested in this repository,
but the author likes this one (and uses it in cmd/server):
Miscellaneous
- Awesome
sloglist of link to variousslog-related projects and resources. - Go Logging Benchmarks
- Benchmarks of various Go logging packages (not just
slogloggers). - Used GitHub Action in this project as template for generating GitHub Pages for the current repository.
- Benchmarks of various Go logging packages (not just