File: slogtest.go

package info (click to toggle)
golang-github-chainguard-dev-clog 1.7.0-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 424 kB
  • sloc: makefile: 4
file content (76 lines) | stat: -rw-r--r-- 2,144 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Package slogtest provides utilities for emitting test logs using clog.
//
//	func TestExample(t *testing.T) {
//		ctx := slogtest.Context(t)
//		clog.FromContext(ctx).With("foo", "bar").Info("hello world")
//	}
//
// This produces the following test output:
//
//	=== RUN   TestExample
//		slogtest.go:24: level=INFO source=/path/to/example_test.go:13 msg="hello world" foo=bar
//
// This package is intended to be used in tests only.
package slogtest

import (
	"context"
	"io"
	"log/slog"
	"strings"
	"testing"

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

var _ io.Writer = &logAdapter{}

type logAdapter struct{ l Logger }

func (l *logAdapter) Write(b []byte) (int, error) {
	l.l.Log(strings.TrimSuffix(string(b), "\n"))
	return len(b), nil
}

var _ Logger = (*testing.T)(nil)
var _ Logger = (*testing.B)(nil)
var _ Logger = (*testing.F)(nil)

type Logger interface{ Log(args ...any) }

// TestLogger gets a logger to use in unit and end to end tests.
// This logger is configured to log at debug level.
func TestLogger(t Logger) *clog.Logger {
	return clog.New(slog.NewTextHandler(&logAdapter{l: t}, &slog.HandlerOptions{
		Level:       slog.LevelDebug,
		AddSource:   true,
		ReplaceAttr: RemoveTime,
	}))
}

// TestLoggerWithOptions gets a logger to use in unit and end to end tests.
func TestLoggerWithOptions(t Logger, opts *slog.HandlerOptions) *clog.Logger {
	return clog.New(slog.NewTextHandler(&logAdapter{l: t}, opts))
}

// Context returns a context with a logger to be used in tests.
func Context(t Logger) context.Context {
	return clog.WithLogger(context.Background(), TestLogger(t))
}

// TestContextWithLogger returns a context with a logger to be used in tests
//
// Deprecated: Use Context instead.
func TestContextWithLogger(t Logger) context.Context { return Context(t) }

// RemoveTime removes the top-level time attribute.
// It is intended to be used as a ReplaceAttr function,
// to make example output deterministic.
//
// This is taken from slog/internal/slogtest.RemoveTime.
func RemoveTime(groups []string, a slog.Attr) slog.Attr {
	if a.Key == slog.TimeKey && len(groups) == 0 {
		return slog.Attr{}
	}
	return a
}