clog

package module
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 6, 2024 License: Apache-2.0 Imports: 6 Imported by: 78

README

👞 clog

Go Reference

Context-aware slog

slog was added in Go 1.21, so using this requires Go 1.21 or later.

Usage

Context Logger

The context Logger can be used to use Loggers from the context. This is sometimes preferred over the Context Handler, since this can make it easier to use different loggers in different contexts (e.g. testing).

This approach is heavily inspired by knative.dev/pkg/logging, but with zero dependencies outside the standard library (compare with pkg/logging's deps).

package main

import (
	"context"
	"log/slog"

	"github.com/chainguard-dev/clog"
)

func main() {
	// One-time setup
	log := clog.New(slog.Default().Handler()).With("a", "b")
	ctx := clog.WithLogger(context.Background(), log)

	f(ctx)
}

func f(ctx context.Context) {
	// Grab logger from context and use.
	log := clog.FromContext(ctx)
	log.Info("in f")

	// Add logging context and pass on.
	ctx = clog.WithLogger(ctx, log.With("f", "hello"))
	g(ctx)
}

func g(ctx context.Context) {
	// Grab logger from context and use.
	log := clog.FromContext(ctx)
	log.Info("in g")

	// Package level context loggers are also aware
	clog.ErrorContext(ctx, "asdf")
}

$ go run .
2009/11/10 23:00:00 INFO in f a=b
2009/11/10 23:00:00 INFO in g a=b f=hello
2009/11/10 23:00:00 ERROR asdf a=b f=hello
Testing

The slogtest package provides utilities to make it easy to create loggers that will use the native testing logging.

func TestFoo(t *testing.T) {
	ctx := slogtest.TestContextWithLogger(t)

	for _, tc := range []string{"a", "b"} {
		t.Run(tc, func(t *testing.T) {
			clog.FromContext(ctx).Infof("hello world")
		})
	}
}
$ go test -v ./examples/logger
=== RUN   TestLog
=== RUN   TestLog/a
=== NAME  TestLog
    slogtest.go:20: time=2023-12-12T18:42:53.020-05:00 level=INFO msg="hello world"

=== RUN   TestLog/b
=== NAME  TestLog
    slogtest.go:20: time=2023-12-12T18:42:53.020-05:00 level=INFO msg="hello world"

--- PASS: TestLog (0.00s)
    --- PASS: TestLog/a (0.00s)
    --- PASS: TestLog/b (0.00s)
PASS
ok      github.com/chainguard-dev/clog/examples/logger
Context Handler

The context Handler can be used to insert values from the context.

func init() {
	slog.SetDefault(slog.New(clog.NewHandler(slog.NewTextHandler(os.Stdout, nil))))
}

func main() {
	ctx := context.Background()
	ctx = clog.WithValues(ctx, "foo", "bar")

	// Use slog package directly
	slog.InfoContext(ctx, "hello world", slog.Bool("baz", true))

	// glog / zap style (note: can't pass additional attributes)
	clog.ErrorContextf(ctx, "hello %s", "world")
}
$ go run .
time=2009-11-10T23:00:00.000Z level=INFO msg="hello world" baz=true foo=bar
time=2009-11-10T23:00:00.000Z level=ERROR msg="hello world" foo=bar
Google Cloud Platform support

This package also provides a GCP-optimized JSON handler for structured logging and trace attribution.

See ./gcp/README.md for details.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Debug

func Debug(msg string, args ...any)

Debug calls Debug on the default logger.

func DebugContext

func DebugContext(ctx context.Context, msg string, args ...any)

DebugContext calls DebugContext on the context logger.

func DebugContextf

func DebugContextf(ctx context.Context, format string, args ...any)

DebugContextf calls DebugContextf on the context logger. If a Logger is found in the context, it will be used.

func Debugf

func Debugf(format string, args ...any)

Debugf calls Debugf on the default logger.

func Error

func Error(msg string, args ...any)

Error calls Error on the default logger.

func ErrorContext

func ErrorContext(ctx context.Context, msg string, args ...any)

ErrorContext calls ErrorContext on the context logger.

func ErrorContextf

func ErrorContextf(ctx context.Context, format string, args ...any)

ErrorContextf calls ErrorContextf on the context logger.

func Errorf

func Errorf(format string, args ...any)

Errorf calls Errorf on the default logger.

func Fatal added in v1.3.1

func Fatal(msg string, args ...any)

Fatal calls Error on the default logger, then exits.

func FatalContext added in v1.3.1

func FatalContext(ctx context.Context, msg string, args ...any)

FatalContext calls ErrorContext on the context logger, then exits.

func FatalContextf added in v1.3.1

func FatalContextf(ctx context.Context, format string, args ...any)

FatalContextf calls ErrorContextf on the context logger, then exits.

func Fatalf added in v1.3.1

func Fatalf(format string, args ...any)

Fatalf calls Errorf on the default logger, then exits.

func Info

func Info(msg string, args ...any)

Info calls Info on the default logger.

func InfoContext

func InfoContext(ctx context.Context, msg string, args ...any)

InfoContext calls InfoContext on the context logger. If a Logger is found in the context, it will be used.

func InfoContextf

func InfoContextf(ctx context.Context, format string, args ...any)

InfoContextf calls InfoContextf on the context logger. If a Logger is found in the context, it will be used.

func Infof

func Infof(format string, args ...any)

Infof calls Infof on the default logger.

func Warn

func Warn(msg string, args ...any)

Warn calls Warn on the default logger.

func WarnContext

func WarnContext(ctx context.Context, msg string, args ...any)

WarnContext calls WarnContext on the context logger. If a Logger is found in the context, it will be used.

func WarnContextf

func WarnContextf(ctx context.Context, format string, args ...any)

WarnContextf calls WarnContextf on the context logger. If a Logger is found in the context, it will be used.

func Warnf

func Warnf(format string, args ...any)

Warnf calls Warnf on the default logger.

func WithLogger

func WithLogger(ctx context.Context, logger *Logger) context.Context

func WithValues

func WithValues(ctx context.Context, args ...any) context.Context

With returns a new context with the given values. Values are expected to be key-value pairs, where the key is a string. e.g. WithValues(ctx, "foo", "bar", "baz", 1) If a value already exists, it is overwritten. If an odd number of arguments are provided, With panics.

Types

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler is a slog.Handler that adds context values to the log record. Values are added via WithValues.

Example
package main

import (
	"context"
	"log/slog"
	"os"

	"github.com/chainguard-dev/clog"
	"github.com/chainguard-dev/clog/slogtest"
)

func main() {
	log := slog.New(clog.NewHandler(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		// Remove time for repeatable results
		ReplaceAttr: slogtest.RemoveTime,
	})))

	ctx := context.Background()
	ctx = clog.WithValues(ctx, "foo", "bar")
	log.InfoContext(ctx, "hello world", slog.Bool("baz", true))

}
Output:

level=INFO msg="hello world" baz=true foo=bar

func NewHandler

func NewHandler(h slog.Handler) Handler

NewHandler configures a new context aware slog handler. If h is nil, the default slog handler is used.

func (Handler) Enabled

func (h Handler) Enabled(ctx context.Context, level slog.Level) bool

func (Handler) Handle

func (h Handler) Handle(ctx context.Context, r slog.Record) error

func (Handler) WithAttrs

func (h Handler) WithAttrs(attrs []slog.Attr) slog.Handler

func (Handler) WithGroup

func (h Handler) WithGroup(name string) slog.Handler

type Logger

type Logger struct {
	slog.Logger
	// contains filtered or unexported fields
}

Logger implements a wrapper around slog.Logger that adds formatter functions (e.g. Infof, Errorf)

Example
package main

import (
	"context"
	"log/slog"
	"os"

	"github.com/chainguard-dev/clog"
	"github.com/chainguard-dev/clog/slogtest"
)

func main() {
	log := clog.NewLogger(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		// Remove time for repeatable results
		ReplaceAttr: slogtest.RemoveTime,
	})))
	log = log.With("a", "b")
	ctx := clog.WithLogger(context.Background(), log)

	// Grab logger from context and use
	// Note: this is a formatter aware method, not an slog.Attr method.
	clog.FromContext(ctx).With("foo", "bar").Infof("hello %s", "world")

	// Package level context loggers are also aware
	clog.ErrorContext(ctx, "asdf", slog.Bool("baz", true))

}
Output:

level=INFO msg="hello world" a=b foo=bar
level=ERROR msg=asdf a=b baz=true

func DefaultLogger

func DefaultLogger() *Logger

DefaultLogger returns a new logger that uses the default slog.Logger.

func FromContext

func FromContext(ctx context.Context) *Logger
Example (PreserveContext)
package main

import (
	"context"
	"log/slog"
	"os"

	"github.com/chainguard-dev/clog"
	"github.com/chainguard-dev/clog/slogtest"
)

func main() {
	log := clog.NewLogger(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		// Remove time for repeatable results
		ReplaceAttr: slogtest.RemoveTime,
	}))).With("foo", "bar")
	ctx := clog.WithLogger(context.Background(), log)

	// Previous context values are preserved when using FromContext
	clog.FromContext(ctx).Info("hello world")

}
Output:

level=INFO msg="hello world" foo=bar

func New

func New(h slog.Handler) *Logger

New returns a new logger that wraps the given slog.Handler.

func NewLogger

func NewLogger(l *slog.Logger) *Logger

NewLogger returns a new logger that wraps the given slog.Logger with the default context.

func NewLoggerWithContext added in v1.3.1

func NewLoggerWithContext(ctx context.Context, l *slog.Logger) *Logger

NewLoggerWithContext returns a new logger that wraps the given slog.Logger.

func NewWithContext added in v1.3.1

func NewWithContext(ctx context.Context, h slog.Handler) *Logger

New returns a new logger that wraps the given slog.Handler.

func With

func With(args ...any) *Logger

With calls Logger.With on the default logger.

func (*Logger) Base

func (l *Logger) Base() *slog.Logger

Base returns the underlying slog.Logger.

func (*Logger) DebugContextf

func (l *Logger) DebugContextf(ctx context.Context, format string, args ...any)

DebugContextf logs at LevelDebug with the given context, format and arguments.

func (*Logger) Debugf

func (l *Logger) Debugf(format string, args ...any)

Debugf logs at LevelDebug with the given format and arguments.

func (*Logger) ErrorContextf

func (l *Logger) ErrorContextf(ctx context.Context, format string, args ...any)

ErrorContextf logs at LevelError with the given context, format and arguments.

func (*Logger) Errorf

func (l *Logger) Errorf(format string, args ...any)

Errorf logs at LevelError with the given format and arguments.

func (*Logger) Fatal added in v1.3.1

func (l *Logger) Fatal(msg string, args ...any)

Fatal logs at LevelError with the given message, then exits.

func (*Logger) FatalContext added in v1.3.1

func (l *Logger) FatalContext(ctx context.Context, msg string, args ...any)

FatalfContext logs at LevelError with the given context and message, then exits.

func (*Logger) FatalContextf added in v1.3.1

func (l *Logger) FatalContextf(ctx context.Context, format string, args ...any)

FatalfContextf logs at LevelError with the given context, format and arguments, then exits.

func (*Logger) Fatalf added in v1.3.1

func (l *Logger) Fatalf(format string, args ...any)

Fatalf logs at LevelError with the given format and arguments, then exits.

func (*Logger) Handler

func (l *Logger) Handler() slog.Handler

Handler returns the underlying slog.Handler.

func (*Logger) InfoContextf

func (l *Logger) InfoContextf(ctx context.Context, format string, args ...any)

InfoContextf logs at LevelInfo with the given context, format and arguments.

func (*Logger) Infof

func (l *Logger) Infof(format string, args ...any)

Infof logs at LevelInfo with the given format and arguments.

func (*Logger) WarnContextf

func (l *Logger) WarnContextf(ctx context.Context, format string, args ...any)

WarnContextf logs at LevelWarn with the given context, format and arguments.

func (*Logger) Warnf

func (l *Logger) Warnf(format string, args ...any)

Warnf logs at LevelWarn with the given format and arguments.

func (*Logger) With

func (l *Logger) With(args ...any) *Logger

With calls Logger.With on the logger.

func (*Logger) WithGroup

func (l *Logger) WithGroup(name string) *Logger

WithGroup calls Logger.WithGroup on the default logger.

Directories

Path Synopsis
examples
gcp

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL