slogtfmt

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2024 License: MIT Imports: 6 Imported by: 0

README

slogtfmt

slogtfmt is a handler for slog that allows you to customize timestamp formats for both log timestamps and time attributes. This package also provides a helper function to add tags to log entries.

Features

  • Customizable time value formatting for both log timestamps and time attributes
  • Support for log record tagging, tags are shown in square brackets before the message
  • Optional inclusion of source code information (file and line number)

Installation

To install slogtfmt, use go get:

go get github.com/corvax/slogtfmt

Usage

Creating a New Handler

To create a new slog handler, use the NewHandler function. This function requires an io.Writer where the logs will be written and an Options struct to configure the handler.

package main

import (
	"time"
	"os"
	"github.com/corvax/slogtfmt"
)

func main() {
	opts := &slogtfmt.Options{
		Level:               slog.LevelInfo,
		AddSource:           false,
		TimeFormat:          "2006-01-02T15:04:05.999Z07:00",
		TimeInUTC:           true,
		TimeAttributeFormat: time.RFC3339,
		TimeAttributeInUTC:  true,
	}

	logger := slog.New(slogtfmt.NewHandler(os.Stdout, opts))
	slog.SetDefault(logger)
	slog.Info("Started", slog.Time("time", time.Now()))

	// To create a logger with an added tag, use With(slogtfmt.Tag("tag_name")
	serviceLogger := logger.With(slogtfmt.Tag("service"))
	serviceLogger.Info("Started")
}
Sample output

The output of the sample code above would be as following:

2024-07-01T04:23:30.557Z    INFO    Started time=2024-07-01T03:41:05Z
2024-07-01T04:23:30.557Z    INFO    [service]     Started
Without a timestamp

In order to omit the log timestamp, set TimeFormat to an empty string.

	opts := &slogtfmt.Options{
		Level:      slog.LevelDebug,
		TimeFormat: "",
	}

	slog.SetDefault(slog.New(slogtfmt.NewHandler(os.Stdout, opts)))

	slog.Info("Started", slog.Time("time", time.Now())
	slog.Debug("User connected", slog.String("user", "username"))
	slog.Warn("Access denied", slog.String("role", "readOnly"))
 	slog.Error("Service is unavailable")
 	slog.Info("Finished")
Output:

Note that the time attribute format is not affected and uses the default formatting slogtfmt.RFC3339Milli.

INFO	Started time=2024-07-01T15:02:50.720+10:00
DEBUG	User connected user="username"
WARN	Access denied role="readOnly"
ERROR	Service is unavailable
INFO	Finished
Using With Option functions

You can also use the slogtfmt.NewHandlerWithOptions() constructor with Option functions.

To achieve the same log formatting as shown above, you can use the following snippet:

slog.SetDefault(slog.New(slogtfmt.NewHandlerWithOptions(
	os.Stdout,
	slogtfmt.WithLevel(slog.LevelDebug),
	slogtfmt.WithTimeFormat(""),
)))

With functions are available for all Options.

Default options

The constructor slogtfmt.NewHandlerWithOptions() creates the handler with the default Options and then updates them using the provided With option functions.

If nil as Options is passed to slogtfmt.NewHandler(), the handler will be created with the default options.

Default options
defaultOptions := &Options{
	Level:               slog.LevelInfo,
	AddSource:           false,
	TimeFormat:          slogtfmt.RFC3339Milli,
	TimeInUTC:           false,
	TimeAttributeFormat: slogtfmt.RFC3339Milli,
	TimeAttributeInUTC:  false,
}

Time formats

In addition to the standard time format, there are some additional time formats available in the package that can be used for formatting timestamps.

const (
	RFC3339Milli = "2006-01-02T15:04:05.000Z07:00"
	RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
)

Options

The Options struct allows you to customize the behavior of the handler. Below is a detailed explanation of each field in the Options struct:

  • Level: Specifies the minimum level to log. Logs with a lower level are discarded. If nil, the handler uses slog.LevelInfo.
  • AddSource: If set to true, the handler computes the source code position of the log statement and adds the file name and the position to the output.
  • TimeFormat: The format used for log timestamps in the output. If empty, the handler will omit the timestamps.
  • TimeInUTC: Specifies whether the time format should use UTC instead of the local time zone.
  • TimeAttributeFormat: Specifies the time format used for the time attribute in the log record. If empty, the default time format of time.RFC3339 is used.
  • TimeAttributeInUTC: Specifies whether the time attribute in the log record should use UTC instead of the local time zone.

loggerf.Logger

The loggerf.Logger is a wrapper around the standard slog.Logger structure that provides additional functions to format log messages. These functions allow you to log messages with formatted strings, similar to fmt.Printf.

Formatting functions

The loggerf.Logger provides the following functions to format the log message:

  • Debugf(format string, args ...any): Log a debug message with formatting.
  • Infof(format string, args ...any): Log an info message with formatting.
  • Warnf(format string, args ...any): Log a warning message with formatting.
  • Errorf(format string, args ...any): Log an error message with formatting.
  • Logf(ctx context.Context, level slog.Level, format string, args ...any): Log a formatted message at the specified log level.
Usage

To use the loggerf.Logger, add the loggerf import to your code:

go get github.com/corvax/slogtfmt/loggerf

Create a new instance of loggerf.Logger based on any slog.Logger:

import (
	"errors"
	"log/slog"
	"os"

	"github.com/corvax/slogtfmt"
	"github.com/corvax/slogtfmt/loggerf"
)

func main() {
	handler := slogtfmt.NewHandler(os.Stdout, &slogtfmt.Options{
		Level:      slog.LevelDebug,
		TimeFormat: "",
	})
	slogger := slog.New(handler)
	logger := loggerf.NewLogger(slogger)

	// Now you can use the functions to format the log messages.
	// For example:
	username := "user"
	ipAddress := "localhost"
	diskUsage := 98
	err := errors.New("test error")

	logger.Debugf("Debug message: %s", "Hello, World!")
	logger.Infof("User %s logged in from %s", username, ipAddress)
	logger.Warnf("Warning: disk usage is at %d%%", diskUsage)
	logger.Errorf("Error occurred: %v", err)
}

Output:

DEBUG   Debug message: Hello, World!
INFO    User user logged in from localhost
WARN    Warning: disk usage is at 98%
ERROR   Error occured: test error
With context

You can also create a new logger with additional context using the With method:

import (
	"errors"
	"log/slog"
	"os"

	"github.com/corvax/slogtfmt"
	"github.com/corvax/slogtfmt/loggerf"
)

func main() {
	handler := slogtfmt.NewHandler(os.Stdout, &slogtfmt.Options{
		Level:      slog.LevelDebug,
		TimeFormat: "",
	})
	slogger := slog.New(handler)
	logger := loggerf.NewLogger(slogger.With(slogtfmt.Tag("service")))

	// Now you can use the functions to format the log message.
	// For example:
	username := "user"
	ipAddress := "localhost"
	diskUsage := 98
	err := errors.New("test error")

	logger.Debugf("Debug message: %s", "Hello, World!")
	logger.Infof("User %s logged in from %s", username, ipAddress)
	logger.Warnf("Warning: disk usage is at %d%%", diskUsage)
	logger.Errorf("Error occurred: %v", err)
}

Output:

DEBUG   [service]	Debug message: Hello, World!
INFO    [service]	User user logged in from localhost
WARN    [service]	Warning: disk usage is at 98%
ERROR   [service]	Error occured: test error

WithGroup can also be used to create a new logger with additional context and a group name.

Notes

Please be aware that the formatting log message functions use args to format the message. args values are not used to build slog.Attr.

If you want to add additional attributes to your log message, you can still use the slog.Logger methods, for example:

logger.Info("User is logged in", "username", username, "host", ipAddress)

Output:

INFO    User is logged in username="user" host="localhost"

loggerf.Logger embeds the slog.Logger structure, so you can use any of the slog.Logger methods.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	RFC3339Milli = "2006-01-02T15:04:05.000Z07:00"
	RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
)

Variables

This section is empty.

Functions

func Tag

func Tag(name string) slog.Attr

Tag returns an slog.Attr that can be used to set the tag for a log record. The tag value will be put in square brackets before the log message.

Types

type Handler

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

Handler is a custom implementation of slog.Handler that provides advanced formatting capabilities for log records. It offers the following features:

  • Customizable time value formatting for both log timestamps and time attributes
  • Support for log record tagging using square brackets before the message
  • Optional inclusion of source code information (file and line number)

func NewHandler

func NewHandler(out io.Writer, opts *Options) *Handler

NewHandler creates a new Handler with the provided io.Writer and Options. If no Options are provided, it will use the default Options. The default Options include:

  • Level set to slog.LevelInfo
  • Time formats are set to RFC3339Milli
  • Time values are in local time zone

If Level is not set in opts, it will default to slog.LevelInfo.

func NewHandlerWithOptions added in v0.2.0

func NewHandlerWithOptions(out io.Writer, opts ...Option) *Handler

NewHandlerWithOptions creates a new Handler with the provided io.Writer and a set of configurable options. The options allow customizing the log level, whether to include source location, the time format, and whether to use UTC time. If no options are provided, it will use the default options with the time format set to RFC3339Milli.

func (*Handler) Enabled

func (h *Handler) Enabled(_ context.Context, level slog.Level) bool

Enabled returns whether the given log level is enabled for this Handler. The Handler will only log records with a level greater than or equal to the configured level.

func (*Handler) Handle

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

Handle processes a log record and writes it to the configured io.Writer. It appends the time, level, tag (if set), source location (if configured), message, and attributes to the output. The output is formatted according to the configured Options.

func (*Handler) WithAttrs

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

WithAttrs returns a new Handler that will log all records with the given attributes. If the list of attributes is empty, the original Handler is returned.

func (*Handler) WithGroup

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

WithGroup returns a new Handler that will log all records with the given group name. If the group name is empty, the original Handler is returned.

type Option added in v0.2.0

type Option = func(*Options)

func WithAddSource added in v0.2.0

func WithAddSource(addSource bool) Option

WithAddSource returns an Option that sets whether to include the source code location (file and line number) in the log record.

func WithLevel added in v0.2.0

func WithLevel(level slog.Leveler) Option

WithLevel returns an Option that sets the log level for the Handler. The provided level will be used to filter log records, only records at or above the specified level will be logged.

func WithTimeAttributeFormat added in v0.2.0

func WithTimeAttributeFormat(timeAttributeFormat string) Option

WithTimeAttributeFormat returns an Option that sets the time format for the time attribute in the log record. The provided timeAttributeFormat string should be a valid time.Format layout string.

func WithTimeAttributeInUTC added in v0.2.0

func WithTimeAttributeInUTC(timeAttributeInUTC bool) Option

WithTimeAttributeInUTC returns an Option that sets whether to use UTC time for the time attribute in the log record. If timeAttributeInUTC is true, the time attribute will be in UTC time, otherwise it will be in the local time zone.

func WithTimeFormat added in v0.2.0

func WithTimeFormat(timeFormat string) Option

WithTimeFormat returns an Option that sets the time format for the log record timestamp. The provided timeFormat string should be a valid time.Format layout string.

func WithTimeInUTC added in v0.2.0

func WithTimeInUTC(timeInUTC bool) Option

WithTimeInUTC returns an Option that sets whether to use UTC time for the log record timestamp. If timeInUTC is true, the timestamp will be in UTC time, otherwise it will be in the local time zone.

type Options

type Options struct {
	// Level reports the minimum level to log.
	// Levels with lower levels are discarded.
	// If nil, the Handler uses [slog.LevelInfo].
	Level slog.Leveler

	// AddSource causes the handler to compute the source code position
	// of the log statement and add a SourceKey attribute to the output.
	AddSource bool

	// TimeFormat is the format used for timestamps in the output.
	// If empty, the Handler will omit the timestamps.
	TimeFormat string

	// TimeInUTC specifies whether the time format should use UTC instead of the local time zone.
	TimeInUTC bool

	// TimeAttributeFormat specifies the time format used for the time attribute
	// in the log record. If empty, the default time format of time.RFC3339 is used.
	TimeAttributeFormat string

	// TimeAttributeInUTC specifies whether the time attribute in the log record
	// should use UTC instead of the local time zone.
	TimeAttributeInUTC bool
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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