cslog

package module
v0.0.0-...-275740c Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2024 License: MIT Imports: 10 Imported by: 0

README

cslog

Golang logger using slog with context.

This package is a wrapper for the slog logger, adding any attributes obtained from the context.

Installation

$ go get github.com/kmio11/cslog

Examples

Adding requestId

It is possible to configure the inclusion of any key/value obtained from the context in the logs.
The following is a simple example of an HTTP server, where the loggingMiddleware sets the request ID in the context.
Configure cslog to output this request ID in all logs related to that specific request.

package main

import (
	"context"
	"fmt"
	"log/slog"
	"net/http"
	"net/http/httptest"
	"os"

	"github.com/kmio11/cslog"
)

type requestIdCtxKey struct{}

func loggingMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Set the requestId to the context.
		// All the logs in this request scope includes this requestId.
		ctx := context.WithValue(r.Context(), requestIdCtxKey{}, "6c8b715a-dfe3-40bd-8634-40312fa05897")

		cslog.InfoContext(ctx, "start request")

		next.ServeHTTP(w, r.WithContext(ctx))

		cslog.InfoContext(ctx, "end request", slog.Int("code", 200))
	})
}

func helloWorldHandler(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	cslog.InfoContext(ctx, "start hello")
	fmt.Fprintf(w, "Hello World")
	cslog.InfoContext(ctx, "end hello")
}

func main() {
	// Set up the cslog to output the logs with requestId when the given context has requestId.
	cslog.AddContextAttrs(
		cslog.Context(
			"requestId", nil,
			// When the log handler processes a Record, it call the function you've set here
			// to retrieve a requestId from the context.
			// Alternatively, you can use a utility function and write it as `cslog.GetFn[string](requestIdCtxKey{})`.
			func(ctx context.Context) (value any, ok bool) {
				value, ok = ctx.Value(requestIdCtxKey{}).(string)
				return
			},
			nil,
		),
	)
	// By default, slog.Default().Handler() is used to handle records.
	// You can use any handler with cslog.SetInnerHandler().
	// If you want to use slog.JSONHandler, call cslog.SetJSONHandler.
	cslog.SetJSONHandler(os.Stdout, &slog.HandlerOptions{})

	// Simulate an HTTP request using httptest instead of starting a server.
	httpHandler := loggingMiddleware(http.HandlerFunc(helloWorldHandler))
	req := httptest.NewRequest(http.MethodGet, "http://localhost:8080", nil)
	resp := httptest.NewRecorder()
	httpHandler.ServeHTTP(resp, req)
}

The outputs are:

{"time":"2024-01-01T09:55:54.196341788+09:00","level":"INFO","msg":"start request","requestId":"6c8b715a-dfe3-40bd-8634-40312fa05897"}
{"time":"2024-01-01T09:55:54.196397299+09:00","level":"INFO","msg":"start hello","requestId":"6c8b715a-dfe3-40bd-8634-40312fa05897"}
{"time":"2024-01-01T09:55:54.196407281+09:00","level":"INFO","msg":"end hello","requestId":"6c8b715a-dfe3-40bd-8634-40312fa05897"}
{"time":"2024-01-01T09:55:54.196409716+09:00","level":"INFO","msg":"end request","code":200,"requestId":"6c8b715a-dfe3-40bd-8634-40312fa05897"}
Adding logId / parentLogId
package main

import (
	"context"
	"fmt"

	"github.com/kmio11/cslog"
)

func sub(ctx context.Context, i int) {
	cslog.InfoContext(ctx, fmt.Sprintf("start: sub process %d", i))
	// do something
	cslog.InfoContext(ctx, fmt.Sprintf("end  : sub process %d", i))
}

func main() {
	ctx := cslog.WithLogContext(context.Background())

	cslog.InfoContext(ctx, "start: main")

	for i := 0; i < 3; i++ {
		ctx := cslog.WithChildLogContext(ctx)
		sub(ctx, i)
	}

	cslog.InfoContext(ctx, "end  : main")
}

The outputs are:

2024/01/01 10:01:53 INFO start: main logId=835f149168a5218b
2024/01/01 10:01:53 INFO start: sub process 0 logId=b5fdb8fd38ad42a4 parentLogId=835f149168a5218b
2024/01/01 10:01:53 INFO end  : sub process 0 logId=b5fdb8fd38ad42a4 parentLogId=835f149168a5218b
2024/01/01 10:01:53 INFO start: sub process 1 logId=ec3bbf8fdd12d4d3 parentLogId=835f149168a5218b
2024/01/01 10:01:53 INFO end  : sub process 1 logId=ec3bbf8fdd12d4d3 parentLogId=835f149168a5218b
2024/01/01 10:01:53 INFO start: sub process 2 logId=9ecbb7d29f00cfc9 parentLogId=835f149168a5218b
2024/01/01 10:01:53 INFO end  : sub process 2 logId=9ecbb7d29f00cfc9 parentLogId=835f149168a5218b
2024/01/01 10:01:53 INFO end  : main logId=835f149168a5218b

The outputs include logId and parentLogId.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	// NowFunc returns current time.
	// This function is exported for testing.
	NowFunc = func() time.Time {
		return time.Now()
	}
)

Functions

func AddContextAttrs

func AddContextAttrs(attrs ...ContextAttr)

AddContextAttrs calls LoggerProvider.AddContextAttrs on the default provider.

func Debug

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

Debug calls Logger.Debug on the default logger.

func DebugContext

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

DebugContext calls Logger.DebugContext on the default logger.

func Error

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

Error calls Logger.Error on the default logger.

func ErrorContext

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

ErrorContext calls Logger.ErrorContext on the default logger.

func GetFn

func GetFn[T any](ctxKey any) func(ctx context.Context) (value any, ok bool)

GetFn returns a ContextAttr's getFn for a value with a given key.

func Info

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

Info calls Logger.Info on the default logger.

func InfoContext

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

InfoContext calls Logger.InfoContext on the default logger.

func Log

func Log(ctx context.Context, level slog.Level, msg string, args ...any)

Log calls Logger.Log on the default logger.

func LogAttrs

func LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr)

LogAttrs calls Logger.LogAttrs on the default logger.

func P

func P[T any](v T) *T

P returns a pointer of v.

func SetFn

func SetFn() func(key string, value any) (attr slog.Attr, ok bool)

SetFn returns a ContextAttr's setFn.

func SetInnerHandler

func SetInnerHandler(handler slog.Handler)

SetInnerHandler sets the default logger provider's handler.

func SetJSONHandler

func SetJSONHandler(w io.Writer, opts *slog.HandlerOptions)

SetJSONHandler sets the slog.JSONHandler as the default logger provider's handler.

func SetLogID

func SetLogID(ctx context.Context, logID LogID) context.Context

func SetLogIdGenerator

func SetLogIdGenerator(gen IDGenerator)

SetLogIdGenerator sets the logIdGenerator which generates logId and parentLogId.

func SetParentLogID

func SetParentLogID(ctx context.Context, parentLogID LogID) context.Context

func SetTextHandler

func SetTextHandler(w io.Writer, opts *slog.HandlerOptions)

SetTextHandler sets the slog.TextHandler as the default logger provider's handler.

func Warn

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

Warn calls Logger.Warn on the default logger.

func WarnContext

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

WarnContext calls Logger.WarnContext on the default logger.

func WithChildLogContext

func WithChildLogContext(ctx context.Context) context.Context

WithChildLogContext returns a new context with a newly generated logId. If the given context already contains a logId, it is set as the parentLogId.

func WithLogContext

func WithLogContext(ctx context.Context) context.Context

WithLogContext returns a new context with a newly generated logId. If the given context already contains a logId, it is replaced with the new logId.

Types

type ByteLogID

type ByteLogID [8]byte

func (ByteLogID) IsZero

func (id ByteLogID) IsZero() bool

IsZero reports whether id represents the zero instant,

func (ByteLogID) String

func (id ByteLogID) String() string

type ContextAttr

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

ContextAttr represents an attribute obtained from the context.

  • key: The key to be included in the log output. If key is empty, the key-value pari is omitted from the log.
  • defaultValue: If not nil, defaultValue is used in the log when the valuecannot be obtained from the context using getFn.
  • getFn: A function to retrieve the value from the context. The returned value is included in the log. If ok is false, the defaultValue is used. If defaultValue is nil and ok is false, the key-value pair is omitted from the log by default, or the defaultValue is passed to setFn if setFn is provided.
  • setFn: A function to create slog.Attr. If setFn is nil, slog.Attr is created with key and value (not nil) as-is.

func Context

func Context(
	key string,
	defaultValue any,
	getFn func(ctx context.Context) (value any, ok bool),
	setFn func(key string, value any) (attr slog.Attr, ok bool),
) ContextAttr

Context returns an ContextAttr.

func (ContextAttr) Attr

func (a ContextAttr) Attr(ctx context.Context) (slog.Attr, bool)

Attr retrieves the attribute from the context and returns it as a slog.Attr. If getFn is provided, it attempts to get the value from the context; otherwise, it uses the defaultValue. If setFn is provided, it uses setFn to create the slog.Attr with the obtained or default value.

type ContextHandler

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

func NewContextHandler

func NewContextHandler(sHandler slog.Handler) *ContextHandler

func (*ContextHandler) Enabled

func (h *ContextHandler) Enabled(ctx context.Context, l slog.Level) bool

func (*ContextHandler) Handle

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

Handle processes the given slog.Record within the context. It enhances the Record's attributes with the context attributes obtained from the context.

func (*ContextHandler) SetContextAttrs

func (h *ContextHandler) SetContextAttrs(attrs []ContextAttr) *ContextHandler

SetContextAttrs returns a new Handler with the given context attributes. The receiver's existing context attributes are replaced.

func (*ContextHandler) SetInnerHandler

func (h *ContextHandler) SetInnerHandler(ih slog.Handler)

func (*ContextHandler) WithAttrs

func (h *ContextHandler) WithAttrs(as []slog.Attr) slog.Handler

func (*ContextHandler) WithContextAttrs

func (h *ContextHandler) WithContextAttrs(attrs ...ContextAttr) *ContextHandler

WithContextAttrs returns a new Handler with the given context attributes appended to the receiver's existing context attributes.

func (*ContextHandler) WithGroup

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

type IDGenerator

type IDGenerator interface {
	NewID() LogID
}

type LogID

type LogID interface {
	String() string
	IsZero() bool
}

func GetLogID

func GetLogID(ctx context.Context) LogID

func GetParentLogID

func GetParentLogID(ctx context.Context) LogID

type Logger

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

func DefaultLogger

func DefaultLogger() *Logger

DefaultProvider returns the logger provided by the default logger provider.

func NewLogger

func NewLogger(innerHandler slog.Handler) *Logger

NewLogger returns Logger.

func NewLoggerWithChildContext

func NewLoggerWithChildContext(ctx context.Context) (context.Context, *Logger)

NewContextLogger calls LoggerProvider.NewLoggerWithChildContext on the default provider.

func NewLoggerWithContext

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

NewLoggerWithContext calls LoggerProvider.NewLoggerWithContext on the default provider.

func NewLoggerWithContextAttrs

func NewLoggerWithContextAttrs(attrs ...ContextAttr) *Logger

NewLoggerWithContextAttrs calls LoggerProvider.NewLoggerWithContextAttrs on the default provider.

func (*Logger) Debug

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

func (*Logger) DebugContext

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

func (*Logger) Enabled

func (l *Logger) Enabled(ctx context.Context, level slog.Level) bool

func (*Logger) Error

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

func (*Logger) ErrorContext

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

func (*Logger) HandleLog

func (l *Logger) HandleLog(ctx context.Context, level slog.Level, callDepth int, msg string, args ...any)

HandleLog is the low-level logging method for methods that take ...any. When it is called directly by a logging method or function, set callDepth is 0. If you create a wrapped logging function and want to include source code locations in the log, set the appropriate callDepth.

func (*Logger) HandleLogAttrs

func (l *Logger) HandleLogAttrs(ctx context.Context, level slog.Level, callDepth int, msg string, attrs ...slog.Attr)

HandleLogAttrs is like [Logger.log], but for methods that take ...Attr.

func (*Logger) Handler

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

func (*Logger) Info

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

func (*Logger) InfoContext

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

func (*Logger) Log

func (l *Logger) Log(ctx context.Context, level slog.Level, msg string, args ...any)

func (*Logger) LogAttrs

func (l *Logger) LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr)

func (*Logger) Warn

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

func (*Logger) WarnContext

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

func (*Logger) With

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

func (*Logger) WithChildContext

func (l *Logger) WithChildContext(ctx context.Context) (context.Context, *Logger)

NewLoggerWithChildContext creates a new child context and a corresponding logger. If the provided context (ctx) has an existing logId, the parentLogId is set to the logId, and it generates a new logId. The child context includes both parentLogId and logId, and a new logger is created based on this child context.

func (*Logger) WithContext

func (l *Logger) WithContext(ctx context.Context) (context.Context, *Logger)

NewLoggerWithContext creates a new context and a corresponding logger. If the provided context (ctx) does not have a logId, a new logId is generated, and it is set to the context. The created logger includes the logId, parentLogId, and other context attributes set in the provider based on the context. The context attributes' default values are set to the values found in the given context, if they exist.

func (*Logger) WithContextAttrs

func (l *Logger) WithContextAttrs(attrs ...ContextAttr) *Logger

WithContextAttrs returns a Logger that includes the given context attributes in each output operation.

func (*Logger) WithGroup

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

type LoggerProvider

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

func DefaultProvider

func DefaultProvider() *LoggerProvider

DefaultProvider returns the default logger provider.

func NewLoggerProvider

func NewLoggerProvider(innerHandler slog.Handler) *LoggerProvider

NewLoggerProvider returns LoggerProvider.

func (*LoggerProvider) AddContextAttrs

func (p *LoggerProvider) AddContextAttrs(attrs ...ContextAttr)

AddContextAttrs sets the attr (key-value pair) obtained from context to be output to the log. See also ContextAttr.

func (*LoggerProvider) NewLogger

func (p *LoggerProvider) NewLogger() *Logger

NewLogger returns Logger.

func (*LoggerProvider) NewLoggerWithChildContext

func (p *LoggerProvider) NewLoggerWithChildContext(ctx context.Context) (context.Context, *Logger)

NewLoggerWithChildContext returns a context and a logger by Logger.WithChildContext

func (*LoggerProvider) NewLoggerWithContext

func (p *LoggerProvider) NewLoggerWithContext(ctx context.Context) (context.Context, *Logger)

NewLoggerWithContextAttrs returns a context and a logger by Logger.WithContextAttrs

func (*LoggerProvider) NewLoggerWithContextAttrs

func (p *LoggerProvider) NewLoggerWithContextAttrs(attrs ...ContextAttr) *Logger

NewLoggerWithContext returns a context and a logger by Logger.WithContext

func (*LoggerProvider) SetInnerHandler

func (p *LoggerProvider) SetInnerHandler(handler slog.Handler)

SetInnerHandler sets the inner handler.

func (*LoggerProvider) SetJSONHandler

func (p *LoggerProvider) SetJSONHandler(w io.Writer, opts *slog.HandlerOptions)

SetJSONHandler sets the slog.JSONHandler as the inner handler.

func (*LoggerProvider) SetTextHandler

func (p *LoggerProvider) SetTextHandler(w io.Writer, opts *slog.HandlerOptions)

SetTextHandler sets the slog.TextHandler as the inner handler.

type StringLogID

type StringLogID string

func (StringLogID) IsZero

func (s StringLogID) IsZero() bool

func (StringLogID) String

func (s StringLogID) String() string

Directories

Path Synopsis
_example

Jump to

Keyboard shortcuts

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