blob: 41e6b012e6f4c7f4987772c2343a21ad8b4c43e7 [file] [log] [blame]
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package log implements event handlers for logging.
package log
import (
"context"
"fmt"
"golang.org/x/exp/slog"
"io"
"os"
"time"
)
type Attrs []slog.Attr
func With(args ...any) Attrs {
var r slog.Record
r.Add(args...)
var as Attrs
r.Attrs(func(a slog.Attr) bool {
as = append(as, a)
return true
})
return as
}
func (as Attrs) Debugf(ctx context.Context, format string, args ...interface{}) {
as.logf(ctx, slog.LevelDebug, format, args...)
}
func (as Attrs) Infof(ctx context.Context, format string, args ...interface{}) {
as.logf(ctx, slog.LevelInfo, format, args...)
}
func (as Attrs) Warningf(ctx context.Context, format string, args ...interface{}) {
as.logf(ctx, slog.LevelWarn, format, args...)
}
func (as Attrs) Errorf(ctx context.Context, format string, args ...interface{}) {
as.logf(ctx, slog.LevelError, format, args...)
}
func Debugf(ctx context.Context, format string, args ...interface{}) {
Attrs{}.logf(ctx, slog.LevelDebug, format, args...)
}
func Infof(ctx context.Context, format string, args ...interface{}) {
Attrs{}.logf(ctx, slog.LevelInfo, format, args...)
}
func Warningf(ctx context.Context, format string, args ...interface{}) {
Attrs{}.logf(ctx, slog.LevelWarn, format, args...)
}
func Errorf(ctx context.Context, format string, args ...interface{}) {
Attrs{}.logf(ctx, slog.LevelError, format, args...)
}
func (as Attrs) logf(ctx context.Context, level slog.Level, format string, args ...interface{}) {
FromContext(ctx).LogAttrs(ctx, level, fmt.Sprintf(format, args...), as...)
}
type key struct{}
func FromContext(ctx context.Context) *slog.Logger {
if l, ok := ctx.Value(key{}).(*slog.Logger); ok {
return l
}
return slog.Default()
}
func NewContext(ctx context.Context, l *slog.Logger) context.Context {
return context.WithValue(ctx, key{}, l)
}
// NewGoogleCloudHandler returns a Handler that outputs JSON for the Google
// Cloud logging service.
// See https://cloud.google.com/logging/docs/agent/logging/configuration#special-fields
// for treatment of special fields.
func NewGoogleCloudHandler(level slog.Leveler) slog.Handler {
return newGoogleCloudHandler(level, os.Stderr)
}
func newGoogleCloudHandler(level slog.Leveler, w io.Writer) slog.Handler {
return slog.NewJSONHandler(w, &slog.HandlerOptions{
Level: level,
ReplaceAttr: gcpReplaceAttr,
})
}
func gcpReplaceAttr(groups []string, a slog.Attr) slog.Attr {
switch a.Key {
case "time":
if a.Value.Kind() == slog.KindTime {
a.Value = slog.StringValue(a.Value.Time().Format(time.RFC3339))
}
case "msg":
a.Key = "message"
case "level":
a.Key = "severity"
case "traceID":
a.Key = "logging.googleapis.com/trace"
}
return a
}