Skip to content

proposal: log/slog: allow implementing slog.Handler and logr.LogSink in the same type #59110

Closed
@pohly

Description

@pohly

https://pkg.go.dev/golang.org/x/exp/slog#Handler and https://pkg.go.dev/github.com/go-logr/logr#LogSink are conceptually similar. If it was possible to implement both interfaces in the same type, then it would be simple to put either slog or logr as user-facing API on top of it.

This is currently not possible because of conflicting parameters for Enabled:

Would it be possible to rename Handler.Enabled? Possible alternatives (just thinking out aloud):

  • EnabledWithContext
  • SlogEnabled
  • LevelEnabled

Would it be useful? I think so - but probably not crucial.

My current workaround for https://github.com/go-logr/zapr/blob/master/zapr.go is a second type:

var _ logr.LogSink = &zapLogger{}
var _ logr.CallDepthLogSink = &zapLogger{}

func (zl *zapLogger) Handle(ctx context.Context, record slog.Record) error {
	return nil // TODO
}

func (zl *zapLogger) WithAttrs(attrs []slog.Attr) slog.Handler {
	return nil // TODO
}

func (zl *zapLogger) WithGroup(name string) slog.Handler {
	return nil // TODO
}

type zapHandler zapLogger

func (zh *zapHandler) Enabled(_ context.Context, slevel slog.Level) bool {
	if slevel >= 0 /* info and higher */ {
		return true
	}
	return (*zapLogger)(zh).Enabled(int(-slevel))
}

func (zh *zapHandler) Handle(ctx context.Context, record slog.Record) error {
	return (*zapLogger)(zh).Handle(ctx, record)
}

func (zh *zapHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
	return (*zapLogger)(zh).WithAttrs(attrs)
}

func (zh *zapHandler) WithGroup(name string) slog.Handler {
	return (*zapLogger)(zh).WithGroup(name)
}

var _ slog.Handler = &zapHandler{}

cc @jba @rsc

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions