Skip to content

madkins23/go-slog

Repository files navigation

go-slog

Tools and testing for log/slog (hereafter just slog) handlers.

Recent benchmark data is available via GitHub Pages.

See the source or documentation for more detailed documentation.

GitHub release (latest by date) Go Reference GitHub Go Report Card

Repository Contents

Handler Benchmarks

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.

Handler Verification

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:

Web Server

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.

Generating GitHub Pages

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/server application
  • at which point the wget tool is used to copy the server pages into the docs subdirectory.

The pages in the docs subdirectory are then vended by GitHub Pages.

Replace Attributes Functions

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.

Gin Integration

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.

Demo Handlers

Several new slog handlers are available.

sloggy Handler

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.

flash Handler

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.

trace Handler

The "trace" handler trace.Handler doesn't log anything, it just prints out the slog.Handler interface calls it receives.

Template for Repository Usage

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.

Caveats

JSON Only

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.

WTF?

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 the slog.Handler documentation.
  • 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.

As a slog Author

  • You don't have to pay attention to any of this. Really.
  • If you do pay attention, you should probably work down from Required warnings.
  • Consider your users' viewpoint...

As a slog User

  • Are you confident that the slog handler you choose will be fine forever?
  • If you need to swap out slog handlers 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?

IMHO

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.

Links

Slog Documentation

Slog Handlers

The following handlers are currently under test in this repository:

Handlers that have been investigated and found wanting:

  • darvaza handlers are based on a different definition of log/slog as 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 separate Handler object.

  • Some handlers are still using golang.org/x/exp/slog instead of the standard library log/slog:

  • The trim21/slog handler is documented as "immature".

  • The go-logr/zerologr handler presents some challenges:

    • Wraps go-logr/logr around a rs/zerolog logger (not a handler),
      then wraps another layer (zerologr.LogSink) around that to return a slog.Handler.
    • Doesn't support slog.HandlerOptions directly.
    • Configuring a default slog.Level per handler is difficult.
      • Negative integers are unsupported so levels must be "fixed" in use.
      • Higher numbers are less important, whereas in slog lower numbers (including negative numbers) are less important so everything must be reversed.
      • The Enabled() implementation uses both local level value and
        the global zerolog level so the per-handler/logger level isn't truly local.

Console handlers are not tested in this repository, but the author likes this one (and uses it in cmd/server):

Miscellaneous

  • Awesome slog list of link to various slog-related projects and resources.
  • Go Logging Benchmarks
    • Benchmarks of various Go logging packages (not just slog loggers).
    • Used GitHub Action in this project as template for generating GitHub Pages for the current repository.

About

Testing and tools for log/slog handlers

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages