slog-helpers

module
v0.0.0-...-05acd2d Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2024 License: MIT

README

slog-helpers

Golang slog structured logging library added in Go 1.21 is a great library. However, it lacks some helpers that are useful in practice. This library provides some of those helpers.

Principles

  • we want to stick as closely as possible to slog standards and objects without creating new concepts, types or interfaces
  • we want to provide a kind of duality:
    • some generic and configurable handlers you can use in plenty of contexts
    • an opinionated twelve-factor app inspired "setup helper" that will make a full-featured slog.Logger with a minimal amount of boilerplate code (by using environment variables and opinionated choices).

Features

  • 1️⃣ a ready-to-use slog.Handler that prints (or embeds in a slog.Attr for JSON output for example) a stacktrace when an error is logged with ERROR level or with a stacktrace=true attribute
  • 2️⃣ a ready-to-use slog.Handler that prints logs in console for humans (with a readable format and colors)
  • 3️⃣ a utility slog.Handler that doesn't print or write something by itself but calls external function callbacks with 3 different types of API:
    • a full-featured one with all the richness (but also complexity) of slog.Attr (different kinds of values, recursive groups...)
    • a simplified one (with stringified and flattened slog.Attr)
    • and a compromise between the two
  • 4️⃣ an opinionated twelve-factor app inspired "setup helper" that will make a full-featured slog.Logger with a minimal amount of boilerplate code (by using environment variables and opinionated choices)

Quickstart

Installation

go get github.com/fabien-marty/slog-helpers

Usage (1️⃣ StackTracer handler)
Source
package main

import (
	"log/slog"
	"os"

	"github.com/fabien-marty/slog-helpers/pkg/stacktrace"
)

func main() {
	// Create a first handler
	textHandler := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{})

	// Create a new StackTrace handler by decorating the first one
	stackTraceHandler := stacktrace.New(textHandler, &stacktrace.Options{
		HandlerOptions: slog.HandlerOptions{
			AddSource: true,
		},
		Mode: stacktrace.ModePrintWithColors,
	})

	// Create a logger with the StackTrace handler
	logger := slog.New(stackTraceHandler)

	logger.Warn("this is a standard warning")
	funcToShowcaseTheStackTrace(logger)
}

func funcToShowcaseTheStackTrace(logger *slog.Logger) {
	logger.Warn("this is a warning but with a stack trace",
		slog.Bool("add-stacktrace", true), // force stacktrace add/dump for this message
	)
}

Output

stracktrace handler output

To go further with this handler

To go further with this stacktrace handler and have a look at all available features, please read the reference documentation.

Usage (2️⃣ Human handler)
Source
package main

import (
	"log/slog"
	"os"

	"github.com/fabien-marty/slog-helpers/pkg/human"
)

func main() {
	// Create a new human handler
	humanHandler := human.New(os.Stderr, &human.Options{
		HandlerOptions: slog.HandlerOptions{
			AddSource: true,
			Level:     slog.LevelDebug,
		},
		UseColors: true, // force the usage of colors (the default behavior is to detect if the output is a terminal)
	})

	// Create a logger with this handler
	logger := slog.New(humanHandler)

	// Create a sub-logger with some default group/key
	logger = logger.With(slog.Group("common", slog.String("rootkey", "rootvalue")))

	// Log some messages
	logger.Debug("this is a debug message", slog.String("key", "value"))
	logger.Info("this is an info message")
	logger.Warn("this is a warning message", slog.Int("intkey", 123))
	logger.Error("this is an error message")
}

Output

human handler output

To go further with this handler

To go further with this stacktrace handler and have a look at all available features, please read the reference documentation.

Usage (3️⃣ External handler)
Source
package main

import (
	"fmt"
	"log/slog"
	"time"

	"github.com/fabien-marty/slog-helpers/pkg/external"
)

// callback is called for each message logged
//
// attrs is a list of key/value pairs (as flattened strings)
func callback(t time.Time, level slog.Level, message string, attrs []external.StringifiedAttr) error {
	fmt.Println("time   :", t.Format(time.RFC3339))
	fmt.Println("level  :", level)
	fmt.Println("message:", message)
	for _, attr := range attrs {
		fmt.Printf("attr   : %s => %s\n", attr.Key, attr.Value)
	}
	return nil
}

func main() {
	// Create a new external handler
	handler := external.New(&external.Options{
		StringifiedCallback: callback, // use the simplified callback form (2 other forms are available)
	})

	// Create a logger with this handler
	logger := slog.New(handler)

	// Create a sub-logger with some default group/key
	logger = logger.With(slog.Group("common", slog.String("rootkey", "rootvalue")))

	// Log a message
	logger.Info("this is an info message", slog.String("key", "value"))
}

Output

external handler output

To go further with this handler

To go further with this stacktrace handler and have a look at all available features, please read the reference documentation.

Usage (4️⃣ All in one with the setup helper)
Source
package main

import (
	"log/slog"

	"github.com/fabien-marty/slog-helpers/pkg/slogc"
)

func main() {

	// Create a new slog.Logger automatically configured from environment variables and given options
	logger := slogc.GetLogger(
		slogc.WithLevel(slog.LevelDebug),
		slogc.WithStackTrace(true),
		slogc.WithColors(true),
	)

	// Create a sub-logger with some default group/key
	logger = logger.With(slog.Group("common", slog.String("rootkey", "rootvalue")))

	// Log some messages
	logger.Debug("this is a debug message", slog.String("key", "value"))
	logger.Info("this is an info message")
	logger.Warn("this is a warning message", slog.Int("intkey", 123))
	funcToShowcaseTheStackTrace(logger)

}

func funcToShowcaseTheStackTrace(lgr *slog.Logger) {
	lgr.Warn("this is a warning but with a stack trace", slog.Bool("add-stacktrace", true))
}

Output (without particular env (default) or with env var LOG_FORMAT=text-human)

slogc handler output

Output (same code but with env var LOG_FORMAT=json-gcp)

[!TIP]
Use LOG_FORMAT=json-gcp env var of WithFormat("json-gcp") in code to have a JSON output compatible with Google Cloud Platform Logging

{
    "time": "2024-06-24T07:06:32.218354885+02:00",
    "severity": "DEBUG",
    "logging.googleapis.com/sourceLocation": {
        "function": "main.main",
        "file": "/home/fab/src/slog-helpers/cmd/slogc-demo1/main.go",
        "line": 22
    },
    "message": "this is a debug message",
    "common": {
        "rootkey": "rootvalue"
    },
    "key": "value"
}
{
    "time": "2024-06-24T07:06:32.218453437+02:00",
    "severity": "INFO",
    "logging.googleapis.com/sourceLocation": {
        "function": "main.main",
        "file": "/home/fab/src/slog-helpers/cmd/slogc-demo1/main.go",
        "line": 23
    },
    "message": "this is an info message",
    "common": {
        "rootkey": "rootvalue"
    }
}
{
    "time": "2024-06-24T07:06:32.218459373+02:00",
    "severity": "WARNING",
    "logging.googleapis.com/sourceLocation": {
        "function": "main.main",
        "file": "/home/fab/src/slog-helpers/cmd/slogc-demo1/main.go",
        "line": 24
    },
    "message": "this is a warning message",
    "common": {
        "rootkey": "rootvalue"
    },
    "intkey": 123
}
{
    "time": "2024-06-24T07:06:32.218466498+02:00",
    "severity": "WARNING",
    "logging.googleapis.com/sourceLocation": {
        "function": "main.funcToShowcaseTheStackTrace",
        "file": "/home/fab/src/slog-helpers/cmd/slogc-demo1/main.go",
        "line": 30
    },
    "message": "this is a warning but with a stack trace",
    "common": {
        "rootkey": "rootvalue"
    },
    "stacktrace": "stack trace\n/home/fab/src/slog-helpers/cmd/slogc-demo1/main.go:30 main.funcToShowcaseTheStackTrace()\n/home/fab/src/slog-helpers/cmd/slogc-demo1/main.go:25 main.main()"
}

Directories

Path Synopsis
cmd
internal
pkg
stacktrace
stacktrace.Handler is a slog handler that adds a stack trace to the record (add attribute or print/write).
stacktrace.Handler is a slog handler that adds a stack trace to the record (add attribute or print/write).

Jump to

Keyboard shortcuts

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