Documentation
¶
Overview ¶
Package ctxslog provides helpers around slog.
Example ¶
package main
import (
"context"
"log/slog"
"net/http"
"os"
"go.yhsif.com/ctxslog"
)
func EndpointHandler(ctx context.Context, traceID string) {
// Inside an endpoint handler, attach trace id for all logs in this context
ctx = ctxslog.Attach(ctx, "trace", traceID)
// Now slog's global log functions with ctx will also have trace info
slog.ErrorContext(ctx, "Not implemented")
thirdPartyLibCall := func(ctx context.Context) {
// Some third party library that uses slog and spams logs a lot.
slog.ErrorContext(ctx, "not really an error")
}
thirdPartyLibCall(
ctxslog.AttachLogLevel(ctx, ctxslog.MaxLevel), // now even if it logs at error level it won't shown
)
}
func HttpHandler(w http.ResponseWriter, r *http.Request) {
ctx := ctxslog.Attach(
r.Context(),
// Add httpRequest group to every log within this context
"httpRequest", ctxslog.HTTPRequest(r, ctxslog.RemoteAddrIP),
)
// Enable callstack even at debug level for this context
ctx = ctxslog.AttachCallstackLevel(ctx, slog.LevelDebug)
slog.DebugContext(ctx, "foo") // this log will contain httpRequest group and callstack.
}
func main() {
// Sets the global slog logger
slog.SetDefault(ctxslog.New(
ctxslog.WithWriter(os.Stderr), // This is the default and can be omitted
ctxslog.WithJSON, // This is the default, use ctxslog.WithText instead if you want non-json logs
ctxslog.WithAddSource(true), // Add source info
ctxslog.WithLevel(slog.LevelDebug), // Keep debug level logs
ctxslog.WithCallstack(slog.LevelError), // For error and above levels, also add callstack info
ctxslog.WithGlobalKVs("version", os.Getenv("VERSION_TAG")), // Add version info to every log
ctxslog.WithReplaceAttr(ctxslog.ChainReplaceAttr(
ctxslog.GCPKeys, // Use Google Cloud Structured logging friendly log keys
ctxslog.StringDuration, // Log time durations as strings
)),
))
// Now you can just use slog's global log functions
slog.Info("Hello, world!", "key", "value")
}
Output:
Index ¶
- Constants
- func Attach(ctx context.Context, args ...any) context.Context
- func AttachCallstackLevel(ctx context.Context, level slog.Leveler) context.Context
- func AttachLogLevel(ctx context.Context, level slog.Leveler) context.Context
- func CallstackHandler(h slog.Handler, min slog.Leveler) slog.Handler
- func ContextHandler(h slog.Handler) slog.Handler
- func GCPKeys(groups []string, a slog.Attr) slog.Attr
- func GCPRealIP(r *http.Request) netip.Addr
- func HTTPRequest(r *http.Request, ip func(*http.Request) netip.Addr) slog.Value
- func New(opts ...Option) *slog.Logger
- func RemoteAddrIP(r *http.Request) netip.Addr
- func StringDuration(groups []string, a slog.Attr) slog.Attr
- func StringInt(groups []string, a slog.Attr) slog.Attr
- func WithJSON(o *options)
- func WithText(o *options)
- type Option
- type ReplaceAttrFunc
Examples ¶
Constants ¶
Minimal and maximal possible log levels.
You can use MinLevel as the log level or callstack level in context/logger to include all logs, or use MaxLevel to exclude all logs (except logs logged explicitly at MaxLevel).
Variables ¶
This section is empty.
Functions ¶
func Attach ¶
Attaches logger args into context.
NOTE: This does in most cases require that you already called slog.SetDefault on a logger retruend by New.
func AttachCallstackLevel ¶
AttachCallstackLevel attaches min callstack level (inclusive) to the context, overriding the global one set on the logger.
func AttachLogLevel ¶
AttachLogLevel attaches min log level (inclusive) to the context, overriding the global one set on the logger.
func CallstackHandler ¶
CallstackHandler wraps handler to print out full callstack at minimal level (inclusive).
If h is already a CallstackHandler, its configured min level will be modified instead.
func ContextHandler ¶
ContextHandler wraps handler to handle contexts from Attach and AttachLogLevel.
func GCPKeys ¶
GCPKeys is a ReplaceAttrFunc that replaces certain keys from Attr to meet Google Cloud Structured logging's expectations.
func GCPRealIP ¶
GCPRealIP gets the real IP form an GCP request (cloud run or app engine).
It picks the last non-local IP from X-Forwarded-For header, fallback to RemoteAddrIP if none found.
func HTTPRequest ¶
HTTPRequest returns a group value for some common HTTP request data.
The ip lambda is used to determine the real ip of the request. If it's nil, RemoteAddrIP will be used.
func New ¶
New creates a *slog.Logger that can handle contexts.
You usually want to call slog.SetDefault with the Logger returned, like:
slog.SetDefault(ctxslog.New(...))
func RemoteAddrIP ¶
RemoteAddrIP returns the ip parsed from r.RemoteAddr.
func StringDuration ¶
StringDuration is a ReplaceAttrFunc that renders duration values as strings.
func StringInt ¶
StringInt is a ReplaceAttrFunc that renders int64 and uint64 values as strings.
It's useful in cases that your log ingester parses all number values as float64 and cause loss of precision.
func WithJSON ¶
func WithJSON(o *options)
WithJSON sets the logger to be json logger.
This is the default behavior.
Types ¶
type Option ¶
type Option func(*options)
Option define logger options for New.
func WithCallstack ¶
WithCallstack adds callstack at min level (inclusive).
Set it to MaxLevel to disable callstack at all levels (except logs logged explicitly at MaxLevel). To add callstack at all levels, use MinLevel.
Default: MaxLevel.
func WithGlobalKVs ¶
WithGlobalKVs sets global key-value pairs.
func WithReplaceAttr ¶
func WithReplaceAttr(f ReplaceAttrFunc) Option
WithReplaceAttr sets the ReplaceAttr option.
Note that this option is overwriting not cumulative. To chain several ReplaceAttr functions, use ChainReplaceAttr.
type ReplaceAttrFunc ¶
Type alias for slog.HandlerOptions.ReplaceAttr.
func ChainReplaceAttr ¶
func ChainReplaceAttr(fs ...ReplaceAttrFunc) ReplaceAttrFunc
ChainReplaceAttr chains multiple ReplaceAttrFunc together.
Source Files
¶
- attr.go
- doc.go
- handler.go
- http.go
- logger.go