Skip to content

Commit

Permalink
document slog support in logr package
Browse files Browse the repository at this point in the history
The old API isn't going away, so the matching functions cross-reference each
other.
  • Loading branch information
pohly committed Nov 29, 2023
1 parent eea3488 commit 9ac9983
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ logr design but also left out some parts and changed others:
The high-level slog API is explicitly meant to be one of many different APIs
that can be layered on top of a shared `slog.Handler`. logr is one such
alternative API, with [interoperability](#slog-interoperability) provided by the [`slogr`](slogr)
package and (since 1.4.0) by corresponding functionality in the main `logr`
package.

### Inspiration
Expand Down Expand Up @@ -145,11 +146,12 @@ There are implementations for the following logging libraries:
## slog interoperability

Interoperability goes both ways, using the `logr.Logger` API with a `slog.Handler`
and using the `slog.Logger` API with a `logr.LogSink`. [slogr](./slogr) provides `NewLogr` and
`NewSlogHandler` API calls to convert between a `logr.Logger` and a `slog.Handler`.
and using the `slog.Logger` API with a `logr.LogSink`. [slogr](./slogr) provides `NewLogr` (= `logr.NewFromSlogHandler`) and
`NewSlogHandler` (= `logr.NewSlogHandler`) API calls to convert between a `logr.Logger` and a `slog.Handler`.
As usual, `slog.New` can be used to wrap such a `slog.Handler` in the high-level
slog API. `slogr` itself leaves that to the caller.


## Using a `logr.Sink` as backend for slog

Ideally, a logr sink implementation should support both logr and slog by
Expand Down
6 changes: 6 additions & 0 deletions slogr.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
//
// The logr verbosity level is mapped to slog levels such that V(0) becomes
// slog.LevelInfo and V(4) becomes slog.LevelDebug.
//
// NewFromSlogHandler is identical to [slogr.NewLogr]. Either of these can be used.
func NewFromSlogHandler(handler slog.Handler) Logger {
if handler, ok := handler.(*slogHandler); ok {
if handler.sink == nil {
Expand Down Expand Up @@ -56,6 +58,8 @@ func NewFromSlogHandler(handler slog.Handler) Logger {
// slog.New(NewSlogHandler(logger)).Warning(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger)).Info(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger.V(4))).Info(...) -> logger.GetSink().Info(level=4, ...)
//
// NewSlogHandler is identical to [slogr.NewSlogHandler]. Either of these can be used.
func NewSlogHandler(logger Logger) slog.Handler {
if sink, ok := logger.GetSink().(*slogSink); ok && logger.GetV() == 0 {
return sink.handler
Expand Down Expand Up @@ -91,6 +95,8 @@ func NewSlogHandler(logger Logger) slog.Handler {
// An implementation could support both interfaces in two different types, but then
// additional interfaces would be needed to convert between those types in NewLogr
// and NewSlogHandler.
//
// SlogSink is identical to [slogr.SlogSink]. Either of these can be used.
type SlogSink interface {
LogSink

Expand Down
11 changes: 10 additions & 1 deletion slogr/slogr.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ limitations under the License.
// APIs.
//
// See the README in the top-level [./logr] package for a discussion of
// interoperability.
// interoperability. The same functionality is also available through the main
// logr package.
package slogr

import (
Expand All @@ -35,6 +36,9 @@ import (
//
// The logr verbosity level is mapped to slog levels such that V(0) becomes
// slog.LevelInfo and V(4) becomes slog.LevelDebug.
//
// NewLogr is identical to [logr.NewFromSlogHandler]. Either of these can
// be used.
func NewLogr(handler slog.Handler) logr.Logger {
return logr.NewFromSlogHandler(handler)
}
Expand All @@ -57,6 +61,9 @@ func NewLogr(handler slog.Handler) logr.Logger {
// slog.New(NewSlogHandler(logger)).Warning(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger)).Info(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger.V(4))).Info(...) -> logger.GetSink().Info(level=4, ...)
//
// NewSlogHandler is identical to [logr.NewSlogHandler]. Either of these can
// be used.
func NewSlogHandler(logger logr.Logger) slog.Handler {
return logr.NewSlogHandler(logger)
}
Expand Down Expand Up @@ -84,4 +91,6 @@ func NewSlogHandler(logger logr.Logger) slog.Handler {
// An implementation could support both interfaces in two different types, but then
// additional interfaces would be needed to convert between those types in NewLogr
// and NewSlogHandler.
//
// SlogSink is identical to [logr.SlogSink]. Either of these can be used.
type SlogSink = logr.SlogSink

0 comments on commit 9ac9983

Please sign in to comment.