Documentation
¶
Overview ¶
Package log provides small constructors for composing standard log/slog loggers and handlers without introducing a replacement logger interface.
Example (BoundedAsync) ¶
package main
import (
"context"
"fmt"
"log/slog"
"time"
"github.com/faustbrian/go-log/handler/async"
"github.com/faustbrian/go-log/handler/capture"
)
func main() {
sink := capture.New()
handler, err := async.New(sink, async.Options{
Capacity: 16,
Overflow: async.Block,
})
if err != nil {
panic(err)
}
slog.New(handler).Info("queued")
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := handler.Shutdown(ctx); err != nil {
panic(err)
}
fmt.Println(sink.Len(), handler.Stats().Delivered)
}
Output: 1 1
Example (RotatingStandardJSON) ¶
package main
import (
"fmt"
"log/slog"
"os"
"github.com/faustbrian/go-log/handler/rotate"
)
func main() {
directory, err := os.MkdirTemp("", "log-example")
if err != nil {
panic(err)
}
defer func() {
_ = os.RemoveAll(directory)
}()
writer, err := rotate.New(rotate.Options{
Path: directory + "/service.log",
MaxBytes: 1 << 20,
Backups: 2,
})
if err != nil {
panic(err)
}
logger := slog.New(slog.NewJSONHandler(writer, &slog.HandlerOptions{ReplaceAttr: removeTime}))
logger.Info("local")
if err := writer.Close(); err != nil {
panic(err)
}
contents, err := os.ReadFile(directory + "/service.log")
if err != nil {
panic(err)
}
fmt.Print(string(contents))
}
func removeTime(_ []string, attr slog.Attr) slog.Attr {
if attr.Key == slog.TimeKey {
return slog.Attr{}
}
return attr
}
Output: {"level":"INFO","msg":"local"}
Example (StackRouting) ¶
package main
import (
"bytes"
"fmt"
"log/slog"
"strings"
"github.com/faustbrian/go-log/handler/stack"
)
func main() {
var application bytes.Buffer
var failures bytes.Buffer
options := &slog.HandlerOptions{ReplaceAttr: removeTime}
handler, err := stack.New(
stack.Route{
Handler: slog.NewTextHandler(&application, options),
MinLevel: slog.LevelInfo,
},
stack.Route{
Handler: slog.NewTextHandler(&failures, options),
MinLevel: slog.LevelError,
},
)
if err != nil {
panic(err)
}
logger := slog.New(handler)
logger.Info("accepted")
logger.Error("failed")
fmt.Println(strings.TrimSpace(application.String()))
fmt.Println(strings.TrimSpace(failures.String()))
}
func removeTime(_ []string, attr slog.Attr) slog.Attr {
if attr.Key == slog.TimeKey {
return slog.Attr{}
}
return attr
}
Output: level=INFO msg=accepted level=ERROR msg=failed level=ERROR msg=failed
Example (StructuralRedaction) ¶
package main
import (
"bytes"
"fmt"
"log/slog"
"github.com/faustbrian/go-log/handler/redact"
)
func main() {
var output bytes.Buffer
next := slog.NewJSONHandler(&output, &slog.HandlerOptions{ReplaceAttr: removeTime})
handler, err := redact.New(next, &redact.Options{
Rules: []redact.Rule{redact.Keys("password", "authorization")},
})
if err != nil {
panic(err)
}
slog.New(handler).Info("login",
slog.String("user", "alice"),
slog.String("password", "secret"),
)
fmt.Print(output.String())
}
func removeTime(_ []string, attr slog.Attr) slog.Attr {
if attr.Key == slog.TimeKey {
return slog.Attr{}
}
return attr
}
Output: {"level":"INFO","msg":"login","user":"alice","password":"[REDACTED]"}
Example (TraceCorrelation) ¶
package main
import (
"context"
"fmt"
"log/slog"
"github.com/faustbrian/go-log/handler/capture"
logotel "github.com/faustbrian/go-log/otel"
"go.opentelemetry.io/otel/trace"
)
func main() {
sink := capture.New()
handler, err := logotel.New(sink, logotel.Options{})
if err != nil {
panic(err)
}
spanContext := trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
SpanID: trace.SpanID{1, 0, 0, 0, 0, 0, 0, 1},
})
ctx := trace.ContextWithSpanContext(context.Background(), spanContext)
slog.New(handler).InfoContext(ctx, "correlated")
record, _ := sink.Last()
record.Attrs(func(attr slog.Attr) bool {
fmt.Printf("%s=%s\n", attr.Key, attr.Value.String())
return true
})
}
Output: trace_id=01000000000000000000000000000001 span_id=0100000000000001
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ErrNilHandler = errors.New("log: nil handler")
ErrNilHandler is returned when New is called without a handler.
Functions ¶
func New ¶
New constructs a standard slog.Logger from handler.
New keeps *slog.Logger as the application-facing type. It returns the first option error and never constructs a logger around a nil handler.
Example ¶
package main
import (
"log/slog"
"os"
log "github.com/faustbrian/go-log"
)
func main() {
options := &slog.HandlerOptions{ReplaceAttr: removeTime}
logger, err := log.New(
slog.NewTextHandler(os.Stdout, options),
log.WithAttrs(slog.String("service", "orders")),
)
if err != nil {
panic(err)
}
logger.Info("ready")
}
func removeTime(_ []string, attr slog.Attr) slog.Attr {
if attr.Key == slog.TimeKey {
return slog.Attr{}
}
return attr
}
Output: level=INFO msg=ready service=orders
Types ¶
Directories
¶
| Path | Synopsis |
|---|---|
|
handler
|
|
|
async
Package async provides bounded asynchronous delivery for standard log/slog handlers.
|
Package async provides bounded asynchronous delivery for standard log/slog handlers. |
|
capture
Package capture provides an in-memory slog handler and lightweight test assertions.
|
Package capture provides an in-memory slog handler and lightweight test assertions. |
|
redact
Package redact provides structural attribute redaction for standard log/slog handlers.
|
Package redact provides structural attribute redaction for standard log/slog handlers. |
|
rotate
Package rotate provides an optional bounded local-file writer for use with the standard log/slog JSON and text handlers.
|
Package rotate provides an optional bounded local-file writer for use with the standard log/slog JSON and text handlers. |
|
sample
Package sample provides deterministic and rate-based sampling decorators for standard log/slog handlers.
|
Package sample provides deterministic and rate-based sampling decorators for standard log/slog handlers. |
|
stack
Package stack provides synchronous fan-out and per-sink level routing for standard log/slog handlers.
|
Package stack provides synchronous fan-out and per-sink level routing for standard log/slog handlers. |
|
Package otel correlates slog records with the standard OpenTelemetry span context produced by telemetry.
|
Package otel correlates slog records with the standard OpenTelemetry span context produced by telemetry. |
Click to show internal directories.
Click to hide internal directories.