httplog

package module
v2.0.6 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2023 License: MIT Imports: 13 Imported by: 126

README

httplog

Small but powerful structured logging package for HTTP request logging built on the Go 1.21+ stdlib slog package.

go get -u github.com/go-chi/httplog/v2

Example

(see _example/)

package main

import (
  "log/slog"
  "net/http"
  "github.com/go-chi/chi/v5"
  "github.com/go-chi/chi/v5/middleware"
  "github.com/go-chi/httplog/v2"
)

func main() {
  // Logger
  logger := httplog.NewLogger("httplog-example", httplog.Options{
    // JSON:             true,
    LogLevel:         slog.LevelDebug,
    Concise:          true,
    RequestHeaders:   true,
    MessageFieldName: "message",
    // TimeFieldFormat: time.RFC850,
    Tags: map[string]string{
      "version": "v1.0-81aa4244d9fc8076a",
      "env":     "dev",
    },
    QuietDownRoutes: []string{
      "/",
      "/ping",
    },
    QuietDownPeriod: 10 * time.Second,
    // SourceFieldName: "source",
  })

  // Service
  r := chi.NewRouter()
  r.Use(httplog.RequestLogger(logger))
  r.Use(middleware.Heartbeat("/ping"))

  r.Use(func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
      ctx := r.Context()
      httplog.LogEntrySetField(ctx, "user", slog.StringValue("user1"))
      next.ServeHTTP(w, r.WithContext(ctx))
    })
  })

  r.Get("/", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("hello world"))
  })

  r.Get("/panic", func(w http.ResponseWriter, r *http.Request) {
    panic("oh no")
  })

  r.Get("/info", func(w http.ResponseWriter, r *http.Request) {
    oplog := httplog.LogEntry(r.Context())
    w.Header().Add("Content-Type", "text/plain")
    oplog.Info("info here")
    w.Write([]byte("info here"))
  })

  r.Get("/warn", func(w http.ResponseWriter, r *http.Request) {
    oplog := httplog.LogEntry(r.Context())
    oplog.Warn("warn here")
    w.WriteHeader(400)
    w.Write([]byte("warn here"))
  })

  r.Get("/err", func(w http.ResponseWriter, r *http.Request) {
    oplog := httplog.LogEntry(r.Context())
    oplog.Error("msg here", "err", errors.New("err here"))
    w.WriteHeader(500)
    w.Write([]byte("oops, err"))
  })

  http.ListenAndServe("localhost:8000", r)
}

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultHandlerConfig = &slog.HandlerOptions{
	Level:     slog.LevelInfo,
	AddSource: true,
}
View Source
var IsTTY bool

Functions

func ErrAttr added in v2.0.5

func ErrAttr(err error) slog.Attr

func Handler

func Handler(logger *Logger, optSkipPaths ...[]string) func(next http.Handler) http.Handler

func LevelByName added in v2.0.6

func LevelByName(name string) slog.Level

func LogEntry

func LogEntry(ctx context.Context) slog.Logger

func LogEntrySetField

func LogEntrySetField(ctx context.Context, key string, value slog.Value)

func LogEntrySetFields

func LogEntrySetFields(ctx context.Context, fields map[string]interface{})

func RequestLogger

func RequestLogger(logger *Logger, skipPaths ...[]string) func(next http.Handler) http.Handler

RequestLogger is an http middleware to log http requests and responses.

NOTE: for simplicity, RequestLogger automatically makes use of the chi RequestID and Recoverer middleware.

Types

type Logger

type Logger struct {
	*slog.Logger
	Options Options
}

func NewLogger

func NewLogger(serviceName string, options ...Options) *Logger

func (*Logger) Configure

func (l *Logger) Configure(opts Options)

Configure will set new options for the httplog instance and behaviour of underlying slog pkg and its global logger.

type Options

type Options struct {
	// LogLevel defines the minimum level of severity that app should log.
	// Must be one of:
	// slog.LevelDebug, slog.LevelInfo, slog.LevelWarn, slog.LevelError
	LogLevel slog.Level

	// LevelFieldName sets the field name for the log level or severity.
	// Some providers parse and search for different field names.
	LevelFieldName string

	// MessageFieldName sets the field name for the message.
	// Default is "msg".
	MessageFieldName string

	// JSON enables structured logging output in json. Make sure to enable this
	// in production mode so log aggregators can receive data in parsable format.
	//
	// In local development mode, its appropriate to set this value to false to
	// receive pretty output and stacktraces to stdout.
	JSON bool

	// Concise mode includes fewer log details during the request flow. For example
	// excluding details like request content length, user-agent and other details.
	// This is useful if during development your console is too noisy.
	Concise bool

	// Tags are additional fields included at the root level of all logs.
	// These can be useful for example the commit hash of a build, or an environment
	// name like prod/stg/dev
	Tags map[string]string

	// RequestHeaders enables logging of all request headers, however sensitive
	// headers like authorization, cookie and set-cookie are hidden.
	RequestHeaders bool

	// HideRequestHeaders are additional requests headers which are redacted from the logs
	HideRequestHeaders []string

	// ResponseHeaders enables logging of all response headers.
	ResponseHeaders bool

	// QuietDownRoutes are routes which are temporarily excluded from logging for a QuietDownPeriod after it occurs
	// for the first time
	// to cancel noise from logging for routes that are known to be noisy.
	QuietDownRoutes []string

	// QuietDownPeriod is the duration for which a route is excluded from logging after it occurs for the first time
	// if the route is in QuietDownRoutes
	QuietDownPeriod time.Duration

	// TimeFieldFormat defines the time format of the Time field, defaulting to "time.RFC3339Nano" see options at:
	// https://pkg.go.dev/time#pkg-constants
	TimeFieldFormat string

	// TimeFieldName sets the field name for the time field.
	// Some providers parse and search for different field names.
	TimeFieldName string

	// SourceFieldName sets the field name for the source field which logs
	// the location in the program source code where the logger was called.
	// If set to "" then it'll be disabled.
	SourceFieldName string

	// Writer is the log writer, default is os.Stdout
	Writer io.Writer

	// ReplaceAttrsOverride allows to add custom logic to replace attributes
	// in addition to the default logic set in this package.
	ReplaceAttrsOverride func(groups []string, a slog.Attr) slog.Attr
}

type PrettyHandler

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

func NewPrettyHandler

func NewPrettyHandler(w io.Writer, options ...*slog.HandlerOptions) *PrettyHandler

func (*PrettyHandler) Enabled

func (h *PrettyHandler) Enabled(ctx context.Context, level slog.Level) bool

func (*PrettyHandler) Handle

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

func (*PrettyHandler) WithAttrs

func (h *PrettyHandler) WithAttrs(attrs []slog.Attr) slog.Handler

func (*PrettyHandler) WithGroup

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

type RequestLoggerEntry

type RequestLoggerEntry struct {
	Logger  slog.Logger
	Options Options
	// contains filtered or unexported fields
}

func (*RequestLoggerEntry) Panic

func (l *RequestLoggerEntry) Panic(v interface{}, stack []byte)

func (*RequestLoggerEntry) Write

func (l *RequestLoggerEntry) Write(status, bytes int, header http.Header, elapsed time.Duration, extra interface{})

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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