Categorygithub.com/blugnu/ulog
repositorypackage
0.4.3
Repository: https://github.com/blugnu/ulog.git
Documentation: pkg.go.dev

# Packages

No description provided by the author

# README

ulog
build-status go report go version >= 1.14 MIT License coverage docs

blugnu/ulog

A configurable, structured logging library for Go that does not sacrifice (too much) efficiency in exchange for convenience and flexibility.

Features

Features unique to ulog:

  • Automatic Context Enrichment - logs may be enriched with context from the context provided by the caller or from context carried by an error (via support for the blugnu/errorcontext module); automatic contextual enrichment can be embedded by registering ulog.ContextEnricher functions with the logger

  • Multiplexing - (optionally) send logs to multiple destinations simultaneously with independently configured formatting and leveling; for example, full logs could be sent to an aggregator in msgpack or JSON format while logs at error level and above are sent to os.Stderr in in human-readable logfmt format

  • Testable - use the provided mock logger to verify that the logs expected by your observability alerts are actually produced!

Features you'd expect of any logger:

  • Highly Configurable - configure your logger to emit logs in the format you want, with the fields you want, at the level you want, sending them to the destination (or destinations) you want; the default configuration is designed to be sensible and useful out-of-the-box, but can be easily customised to suit your needs

  • Structured Logs - logs are emitted in a structured format (logfmt by default) that can be easily parsed by log aggregators and other tools; a JSON formatter is also provided

  • Efficient - allocations are kept to a minimum and conditional flows eliminated where-ever possible to ensure that the overhead of logging is kept to a minimum

  • Intuitive - a consistent API using Golang idioms that is easy and intuitive to use

Installation

go get github.com/blugnu/ulog

Tech Stack

blugnu/ulog is built on the following main stack:

Full tech stack here

Usage

A logger is created using the ulog.NewLogger factory function.

This function returns a logger, a function to close the logger and an error if the logger could not be created. The close function must be called when the logger is no longer required to release any resources it may have acquired and any batched log entries are flushed.

The logger may be configured using a set of configuration functions that are passed as arguments to the factory function.

A minimal example of using ulog:

package main

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

    // create a new logger
    logger, closelog, err := ulog.NewLogger(ctx)
    if err != nil {
      log.Fatalf("error initialising logger: %s", err)
    }
    defer closelog()

    // log a message
    logger.Info("hello world")
    logger.Error("oops!")
}

This example uses a logger with default configuration that writes log entries at InfoLevel and above to os.Stdout in logfmt format.

Running this code would produce output similar to the following:

time=2023-11-23T12:35:04.789346Z level=INFO  msg="hello world"
time=2023-11-23T12:35:04.789347Z level=ERROR msg="oops!"

Configuration

NOTE: This section deals with configuration of a simple logger sending output to a single io.Writer such as os.Stdout. Configuration of a multiplexing logger is described separately.

The default configuration is designed to be sensible and useful out-of-the-box but can be customised to suit your needs.

The Functional Options Pattern is employed for configuration. To configure the logger pass the required option functions as additional arguments to the NewLogger() factory. All options have sensible defaults.

OptionDescriptionOptionsDefault (if not configured)
LogCallSiteWhether to include the file name and line number of the call-site in the log messagetrue
false
false
LoggerLevelThe minimum log level to emitsee: Log Levelsulog.InfoLevel
LoggerFormatThe formatter to be used when writing logsulog.NewLogfmtFormatter
ulog.NewJSONFormatter
ulog.NewMsgpackFormatter
ulog.NewLogfmtFormatter()
LoggerOutputThe destination to which logs are writtenany io.Writeros.Stdout
MuxUse a multiplexer to send logs to multiple destinations simultaneouslyulog.Mux. See: Mux Configuration-

LoggerLevel

Log Levels

The following levels are supported (in ascending order of significance):

LevelDescription
ulog.TraceLevellow-level diagnostic logs
ulog.DebugLeveldebug messages
ulog.InfoLevelinformational messagesdefault
ulog.WarnLevelwarning messages
ulog.ErrorLevelerror messages
ulog.FatalLevelfatal errors

The default log level may be overridden using the LoggerLevel configuration function to NewLogger, e.g:

ulog.NewLogger(
    ulog.LoggerLevel(ulog.DebugLevel)
)

In this example, the logger is configured to emit logs at DebugLevel and above. TraceLevel logs would not be emitted.

LoggerLevel establishes the minimum log level for the logger.

If the logger is configured with a multiplexer the level for each mux target may be set independently but any target level that is lower than the logger level is effectively ignored.

Mux Target LevelLogger LevelEffective Mux Target Level
ulog.InfoLevelulog.InfoLevelulog.InfoLevel
ulog.DebugLevelulog.InfoLevelulog.InfoLevel
ulog.DebugLevelulog.TraceLevelulog.DebugLevel
ulog.InfoLevelulog.WarnLevelulog.WarnLevel

LoggerFormat

The following formatters are supported:

FormatLoggerFormat OptionDescription
logfmtulog.NewLogfmtFormattera simple, structured format that is easy for both humans and machines to read

This is the default formatter if none is configured
JSONulog.NewJSONFormattera structured format that is easy for machines to parse but can be noisy for humans
msgpackulog.NewMsgpackFormatteran efficient structured, binary format for machine use, unintelligible to (most) humans

Formatters offer a number of configuration options that can be set via functions supplied to their factory function. For example, to configure the name used for the time field by a logfmt formatter:

log, closelog, _ := ulog.NewLogger(ctx,
   ulog.LoggerFormat(ulog.LogfmtFormatter(
      ulog.LogfmtFieldNames(map[ulog.FieldId]string{
         ulog.TimeField: "timestamp",
      }),
   )),
)

LoggerOutput

Logger output may be written to any io.Writer. The default output is os.Stdout.

The output may be configured via the LoggerOutput configuration function when configuring a new logger:

logger, closefn, err := ulog.NewLogger(ctx, ulog.LoggerOutput(io.Stderr))

LogCallsite

If desired, the logger may be configured to emit the file name and line number of the call-site that produced the log message. This is disabled by default.

Call-site logging may be enabled via the LogCallSite configuration function when configuring a new logger:

logger, closelog, err := ulog.NewLogger(ctx, ulog.LogCallSite(true))

If LogCallsite is enabled call site information is added to all log entries, including multiplexed output where configured, regardless of the level.

Mux Configuration

Logs may be sent to multiple destinations simultaneously using a ulog.Mux. For example, full logs could be sent to an aggregator using msgpack format, while logfmt formatted logs at error level and above are also sent to os.Stderr.