Categorygithub.com/big-squid/go-logging
modulepackage
0.1.0-rework-api.0
Repository: https://github.com/big-squid/go-logging.git
Documentation: pkg.go.dev

# README

Installation

As outlined in https://blog.golang.org/using-go-modules add

import (
  ...
  "github.com/big-squid/go-logging"
  ...
)

to your project and run go mod tidy or a build.

Usage

Hard-coded Log Configuration
package main

import (
  logging "github.com/big-squid/go-logging"
)

var logger logging.Logger

func init() {
  logger = logging.New(logging.RootLogConfig{
		Label: "main",
    Level: logging.Debug,
    Loggers: {
      "counter": &LogConfig{
        Level: logging.Info
      },
    }
	}
}

func counter() {
  log := logger.ChildLogger("counter")
  for i := 0; i < 5; i++ {
    log.Warn("Loop %v", i)
  }
  log.Fatal("done")
}

func main() {
  log := logger
  log.Trace("This will only appear if the level is TRACE")
  log.Debug("Debug msg")
  log.Info("Info msg")

  counter()
}

This example demonstrates the basic usage of a go-logging logger:

  1. A Logger is created using logger.New()
  2. logger.New() takes a *RootLogConfig{} that specifies
  • a log Level indicating which log messages should be written to the logs
  • an optional Label to include in all log messages
  • optional child logger configuration Loggers in a map[string]*LogConfig
  1. Child loggers may be created using logger.ChildLogger(), which requires a name. The name will be used to:
  • create a label, by appending it to the parent logger's label
  • find the child logger's configuration in it's parent logger's Logger's map. The logger's Level may be supplied in this configuration. If not, the parent logger's level will be used.
  1. Loggers export log level functions for logging at a particular level. Log level functions exist for Trace(), Debug(), Info(), Warn(), Error(), and Fatal(). Each of these will generate a log message at the log level that matches their name if the logger's level is less than or equal to that level.

NOTE: There is no exported generic Log() method. You must use a log level. NOTE: Fatal() will call panic("FATAL") after logging it's message. This is an extreme measure - though it can be caught and does allow deferred code to run. It's use is generally discouraged.

Config-only Log Levels

Astute observes will notice 3 LogLevel constants that do not map to a log level function. These are use only for configuration. They are:

  1. logging.All - this indicates that all log messages should be written to the logs
  2. logging.Off - this indicates that no log messages should be written to the logs
  3. logging.NotSet - this indicates that a log level has not been set for a given logger and the logger should inherit it's parent's log level or use the default logging.Info if no parent exists. This log level is the "zero value" for the LogLevel constants.

Ways to get a RootLogConfig

It's very unlikely that you actually want to hard code your log configuration. go-logging provides several methods for retrieving a configuration from outside the code. Log levels should be set using the case insensitive string equivalent of the constant name.

JsonConfig

cfg, err := logging.JsonConfig([]byte(`
	{ "level": "ERROR",
      "loggers": {
        "main": {
          "level": "INFO",
          "loggers": {
            "child": {
              "level": "DEBUG"
            }
          }
        }
      }
    }
`))

if nil != err {
  panic(err)
}

logger := logging.New(cfg)

JsonConfig() takes JSON as a []byte and Marshalls it in to a *RootLogConfig. It is used by the other configuration functions.

FileConfig

FileConfig() reads a file path and creates a *RootLogConfig{} from it's json data

cfg, err := logging.FileConfig("./log-config.json")
if nil != err {
  panic(err)
}

logger := logging.New(cfg)

PathEnvConfig

PathEnvConfig() gets a file path from the specified environment variable, reads it's contents and creates a *RootLogConfig from it's json data

cfg, err := logging.PathEnvConfig("LOG_CONFIG_PATH")
if nil != err {
  panic(err)
}

logger := logging.New(cfg)

EnvPrefixConfig

EnvPrefixConfig() finds all of the environment variables that start with a specified prefix and uses them to build a *RootLogConfig{}. After the prefix, a single underscore ("_") is treated as a word separator. Two successive underscores ("__") are treated as a struct separator - the left side is the name of the parent struct, the right is a field name. Environment variables that appear to be JSON (because they start with a curly brace - "{") will attempt to be parsed as JSON.

// LOG_CONFIG_LEVEL="ERROR"
// LOG_CONFIG_LABEL="_root_"
// LOG_CONFIG_LOGGERS__CHILD__LEVEL="DEBUG"
// LOG_CONFIG_LOGGERS__CHILD__GRANDCHILD__LEVEL="TRACE"
// LOG_CONFIG_LOGGERS__JSON_CHILD="{\"level\": \"WARN\", \"loggers\": {\"grandchild\": {\"level\": \"ERROR\"}}}"
  
cfg, err := logging.EnvPrefixConfig("LOG_CONFIG")
if nil != err {
  panic(err)
}

logger := logging.New(cfg)

Advanced Usage

It is possible to further customize the logs written by a go-logging logger as well as where and how they are written by specifying a LogHandler function. For now, interested parties should review the implementation of the DefaultLogHandler in the source code.

Shhh! Don't tell anyone!

Of particular note, the DefaultLogHandler uses log.PrintLn() to write log messages. (This is how our log output contains timestamps without them being included in the LogMessage struct.) Using the base "log" package in this way allows the user to make use of log.SetOutput() and log.SetFlags() if desired - though this is considered a private implementation detail. Users who want backward compatibility guarantees should implement their own LogHandler instead.

# Functions

DefaultLogHandler is a LogHandler that writes color coded log messages to stdout with UTC timestamps.
EnvPrefixConfig finds all the environment variables that start with a specified prefix and uses them to build a RootLogConfig.
FileConfig reads a file path and creates a RootLogConfig from it's JSON data.
JsonConfig creates a RootLogConfig from JSON data.
New returns a new root Logger.
PathEnvConfig gets a file path from the specified environment variable, reads it's contents and creates a RootLogConfig from it's JSON data.

# Constants

Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).
Log Constants NotSet is literally our "zero value" NOTE: go does _not_ recommend using ALL_CAPS for constants, as these would always be exported (see https://stackoverflow.com/questions/22688906/go-naming-conventions-for-const).

# Variables

No description provided by the author

# Structs

No description provided by the author
No description provided by the author
Logger is the primary structure in this package.
LogMessage structs will be passed by the logger to the configured LogHandler each time a logging function (`.Trace()`, `.Debug()`,`.Info()`,`.Warn()`, `.Error()`) is called.
No description provided by the author

# Type aliases

No description provided by the author
LogHandler receives a LogMessage and ensures it is properly written to the logs.
No description provided by the author