log

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jan 2, 2024 License: MIT Imports: 8 Imported by: 7

README

go-log

Simple logger wrapper allowing for log levels and runtime level setup.

Usage

The log usage is pretty much the same as the default log package from go.

The main difference is the addition of a level variable that allows a decision to be made if the log will be printed based on the current log level.

The package initializes a default log which can be called directly from package functions. The log is initialized in WARNING level.

package main

import "github.com/gomatbase/go-log"

func main() {
    log.Println(log.ERROR,"This log entry will be printed")
    log.Println(log.TRACE,"This log entry will be ignored")

    // output:
    // This log entry will be printed
}

The Println function has the counterpart Printf function allowing for formatted output.

package main

import "github.com/gomatbase/go-log"

func main() {
    log.Printf(log.ERROR,"This %v entry will be printed","log")
    log.Printf(log.TRACE,"This %v entry will be ignored","log")
    
    // output:
    // This log entry will be printed
}
Custom Loggers

The package will create a default logger which can be used for out-of-the-box logging.

The default logger will be initialized in level WARNING, it will output entries to stdout without timestamps and a critical log will not result in a panic.

These are options that can be customized for custom loggers.

To create a new custom logger the function Get(name string) will create a new logger with the default options (same as the default logger) or return an existing logger.

Any custom logger will output its name as a prefix of the log entry (more precisely it will output the name followed by " - " and then the log entry). The name of the logger will typically identify the source it is logging from, like the package name, a filename or some other identifier the developer may find useful.

package main

import (
    "os"

    "github.com/gomatbase/go-log"
)

func main() {
    // First time getting a logger named "TESTER", logger will be created
    logger, e := log.Get("TESTER")
    if e != nil {
        log.Critical("Unable to create custom logger : ", e)
        os.Exit(1)
    }
    logger.Warning("Logging a warning with custom logger")
    logger.Info("Logging information with custom logger")
    logger.SetLevel(log.INFO)
    
    // Getting the logger will return the same logger as it already exists
    customLogger, e := log.Get("TESTER")
    if e != nil {
        log.Critical("Unable to get custom logger TESTER : ", e)
        os.Exit(1)
    }
    customLogger.Warning("Logging a warning with custom logger")
    customLogger.Info("Logging information with custom logger")

    // output:
    // TESTER - Logging a warning with custom logger
    // TESTER - Logging a warning with custom logger
    // TESTER - Logging information with custom logger
}
Configuring a custom logger

To set specific options for a logger (like changing the output stream, adding log flags or ending fatally when logging criticals), Get(name string, options log.Options) can be used instead.

To create the logger options, you may either create a new log.Options object or use the syntax-candy functions WithOptions() or WithoutOptions(). Both these functions will return a log.Options object initialized with the default values (the difference is only to make it more readable the intention of the options object).

log.Options has several methods which allow setting the options values effectively acting as a simplistic builder.

After creating a logger, using Get(name string, options log.Options) with different options than the ones used to create the logger will result in error. Using the same options will be the same as using Get(name string) for an existing logger.

If for some reason there is a need to change the initial configurations of an existing logger, OverrideLogWithOptions(name string, options log.Options) must be used instead. This function will result in error if overriding options for a non-existing logger. The function is also not thread safe, so if a logger is already in use in another running thread, the operation may result in unexpected results. The method is provided for completeness, but it's not recommended. Typically, a logger should be created and used unchanged throughout a process life-cycle eventually changing its log level.

package main

import (
    "os"

    "github.com/gomatbase/go-log"
)

func main() {
    // First time getting a logger named "TESTER", logger will be created
    logger, e := log.GetWithOptions("TESTER",
        log.WithOptions().
            DateFlags(log.Ldate).        // Set the log flags following the same options as the standard log package
            WithWriter(os.Stderr).       // Write logs to another writer (stderr in this case)
            WithoutFailingCriticals().   // Write a critical log as a failure, panicking
            WithFailingCriticals().      // Write a critical log as a plain log entry, not causing the process to exit
            WithStartingLevel(log.INFO)) // Set the starting log level to INFO
    if e != nil {
        log.Critical("Unable to create custom logger TESTER : ", e)
        os.Exit(1)
    }
    
    logger.Critical("A critical, non-failing error entry")
    logger.Info("Logging information")

    logger, _ = log.Get("TESTER")
    logger.Error("Logging an error")
    logger.Info("Logging information")
    
    _, _ = log.OverrideLogWithOptions("TESTER",
        log.WithOptions().
            DateFlags(0).
            WithFailingCriticals().
            WithStartingLevel(log.ERROR))

    logger.Info("Logging some more info")
    logger.Critical("Fatal critical, exiting...")

    // output (assuming date 15/06/2021) :
    // TESTER - 2021/06/15 A critical, non-failing error entry
    // TESTER - 2021/06/15 Logging information
    // TESTER - 2021/06/15 Logging an error
    // TESTER - 2021/06/15 Logging information
    // TESTER - Fatal critical, exiting...
}
Log Levels

The log level is a simple uint which the logger uses to compare with the level of a log entry and will print any log entry whose level is less or equal than the logger level.

Constants are provided with names for the severity of the intended log. Some namesake functions are also provided to allow logging for the level without explicitly stating the log level in every call. The provided constants by decreasing order of severity are:

  1. CRITICAL (it will always log the entry)
    • log.Critical(log ...interface{})
    • log.Criticalf(format string, variables ...interface{})
  2. ERROR
    • log.Error(log ...interface{})
    • log.Errorf(format string, variables ...interface{})
  3. WARNING (default value for any newly created logger unless specified otherwise)
    • log.Warning(log ...interface{})
    • log.Warningf(log string, variables ...interface{})
  4. INFO
    • log.Info(log ...interface{})
    • log.Infof(format string, variables ...interface{})
  5. DEBUG
    • log.Debug(log ...interface{})
    • log.Debugf(format string, variables ...interface{})
  6. TRACE
    • log.Trace(log ...interface{})
    • log.Tracef(format string, variables ...interface{})

These constants and methods are provided for convenience but the level can be specified as any unsigned integer, and using log.Println(level uint, log ...interface{}) and log.Printf(level uint, format string, variables ...interface{}) any kind of level range may be used.

Documentation

Overview

Package log is a simple logging framework with severity levels

Index

Examples

Constants

View Source
const (

	// ErrEmptyLoggerName Error raised when trying to refer to a logger with an empty name
	ErrEmptyLoggerName = err.Error("logger name may not be empty")

	// ErrReinitializingExistingLogger Error raised when trying to initialize an existing logger with different options
	ErrReinitializingExistingLogger = err.Error("trying to initialize an already initialized logger with different options")

	// ErrLoggerDoesNotExist Error raised when referring to a non-existing logger
	ErrLoggerDoesNotExist = err.Error("logger with given name doesn't exist")

	// ErrUnknownLoggerType Error raised when creating a new logger of an unknown type (shouldn't happen)
	ErrUnknownLoggerType = err.Error("logger type is not known")
)
View Source
const (
	CRITICAL = iota // Critical log level (Always logged)
	ERROR           // Error log level
	WARNING         // Warning log level (Default level)
	INFO            // Info log level
	DEBUG           // Debug log level
	TRACE           // Trace log level

	UNKNOWN = -1 // used as error log type for unknown levels
)

Log Severity levels

View Source
const (
	Ldate         = iota // the date in the local time zone: 2009/01/23
	Ltime                // the time in the local time zone: 01:23:23
	Lmicroseconds        // microsecond resolution: 01:23:23.123123.  assumes Ltime.
	LUTC                 // if Ldate or Ltime is set, use UTC rather than the local time zone
)

constants for date format. Borrowing the same names from standard log package

View Source
const (
	Time = iota
	Name
	Source
	LongSource
	Separator
	LogLevel
)

Log message format constants to use in message header format pattern

View Source
const DEFAULT = "DEFAULT"

DEFAULT is the name of the default logger

Variables

This section is empty.

Functions

func Critical

func Critical(v ...interface{})

Critical logs a critical log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.CRITICAL))

log.Critical("CRT")
log.Error("ERR")
log.Warning("WRN")
log.Info("INF")
log.Debug("DBG")
log.Trace("TRC")
Output:

CRT

func Criticalf

func Criticalf(format string, v ...interface{})

Criticalf logs a formatted critical log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.CRITICAL))

log.Criticalf("%v", "CRT")
log.Errorf("%v", "ERR")
log.Warningf("%v", "WRN")
log.Infof("%v", "INF")
log.Debugf("%v", "DBG")
log.Tracef("%v", "TRC")
Output:

CRT

func Debug

func Debug(v ...interface{})

Debug logs a debug log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.DEBUG))

log.Critical("CRT")
log.Error("ERR")
log.Warning("WRN")
log.Info("INF")
log.Debug("DBG")
log.Trace("TRC")
Output:

CRT
ERR
WRN
INF
DBG

func Debugf

func Debugf(format string, v ...interface{})

Debugf logs a formatted debug log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.DEBUG))

log.Criticalf("%v", "CRT")
log.Errorf("%v", "ERR")
log.Warningf("%v", "WRN")
log.Infof("%v", "INF")
log.Debugf("%v", "DBG")
log.Tracef("%v", "TRC")
Output:

CRT
ERR
WRN
INF
DBG

func Error

func Error(v ...interface{})

Error logs a error log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.ERROR))

log.Critical("CRT")
log.Error("ERR")
log.Warning("WRN")
log.Info("INF")
log.Debug("DBG")
log.Trace("TRC")
Output:

CRT
ERR

func Errorf

func Errorf(format string, v ...interface{})

Errorf logs a formatted error log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.ERROR))

log.Criticalf("%v", "CRT")
log.Errorf("%v", "ERR")
log.Warningf("%v", "WRN")
log.Infof("%v", "INF")
log.Debugf("%v", "DBG")
log.Tracef("%v", "TRC")
Output:

CRT
ERR

func Info

func Info(v ...interface{})

Info logs a info log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.INFO))

log.Critical("CRT")
log.Error("ERR")
log.Warning("WRN")
log.Info("INF")
log.Debug("DBG")
log.Trace("TRC")
Output:

CRT
ERR
WRN
INF

func Infof

func Infof(format string, v ...interface{})

Infof logs a formatted info log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.INFO))

log.Criticalf("%v", "CRT")
log.Errorf("%v", "ERR")
log.Warningf("%v", "WRN")
log.Infof("%v", "INF")
log.Debugf("%v", "DBG")
log.Tracef("%v", "TRC")
Output:

CRT
ERR
WRN
INF

func Level

func Level() int

Level returns the current log level of the default logger

func LevelName

func LevelName(level int) string

LevelName is a convenience method to translate the log level into a name. It only works for loggers implementing the default severity scale.

func LevelSeverity added in v1.1.0

func LevelSeverity(name string) int

func LoggerLevel added in v1.0.1

func LoggerLevel(name string) (int, error)

LoggerLevel gets the current log level of the logger with the given name. ErrLoggerDoesNotExist is returned as an error if a logger with the given name doesn't is unknown.

func LoggerLevelName added in v1.0.1

func LoggerLevelName(name string) (string, error)

LoggerLevelName gets the current log level name of the logger with the given name. ErrLoggerDoesNotExist is returned as an error if a logger with the given name doesn't is unknown. Utility method for loggers using the standard severity scale.

func LoggerLevelNames added in v1.0.1

func LoggerLevelNames() map[string]string

LoggerLevelNames gets the current log level names of all known loggers. Only relevant if logger is using the standard severity scale.

func LoggerLevels added in v1.0.1

func LoggerLevels() map[string]int

LoggerLevels gets the current log levels of all known loggers

func SetDefaultLogger added in v1.1.0

func SetDefaultLogger(o Options) error

SetDefaultLogger allows overriding the default logger with different options

Example
_ = log.SetDefaultLogger(log.Standard().WithLogPrefix(log.Name, log.Source, log.Separator).WithStartingLevel(log.ERROR))

log.Criticalf("%v", "CRT")
log.Errorf("%v", "ERR")
log.Warningf("%v", "WRN")
log.Infof("%v", "INF")
log.Debugf("%v", "DBG")
log.Tracef("%v", "TRC")
Output:

DEFAULT example_test.go:213 - CRT
DEFAULT example_test.go:214 - ERR

func SetLevel

func SetLevel(level int)

SetLevel sets the log level of the default logger

func SetLoggerLevel added in v1.0.1

func SetLoggerLevel(name string, level int) error

SetLoggerLevel sets the log level of a logger by name. DEFAULT may be used to set the default logger level.

func SetLoggerLevels added in v1.0.1

func SetLoggerLevels(loggerLevels map[string]int) map[string]int

SetLoggerLevels sets the log levels of several loggers at once. If any logger is not found it will be omitted from the response

func Trace

func Trace(v ...interface{})

Trace logs a trace log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard())
log.SetLevel(log.TRACE)

log.Critical("CRT")
log.Error("ERR")
log.Warning("WRN")
log.Info("INF")
log.Debug("DBG")
log.Trace("TRC")
Output:

CRT
ERR
WRN
INF
DBG
TRC

func Tracef

func Tracef(format string, v ...interface{})

Tracef logs a formatted trace log entry through the default logger

Example
_ = log.SetDefaultLogger(log.Standard().WithStartingLevel(log.TRACE))

log.Criticalf("%v", "CRT")
log.Errorf("%v", "ERR")
log.Warningf("%v", "WRN")
log.Infof("%v", "INF")
log.Debugf("%v", "DBG")
log.Tracef("%v", "TRC")
Output:

CRT
ERR
WRN
INF
DBG
TRC

func Warning

func Warning(v ...interface{})

Warning logs a warning log entry through the default logger

Example
log.SetDefaultLogger(log.Standard())

log.Critical("CRT")
log.Error("ERR")
log.Warning("WRN")
log.Info("INF")
log.Debug("DBG")
log.Trace("TRC")
Output:

CRT
ERR
WRN

func Warningf

func Warningf(format string, v ...interface{})

Warningf logs a formatted warning log entry through the default logger

Example
log.SetDefaultLogger(log.Standard())

log.Criticalf("%v", "CRT")
log.Errorf("%v", "ERR")
log.Warningf("%v", "WRN")
log.Infof("%v", "INF")
log.Debugf("%v", "DBG")
log.Tracef("%v", "TRC")
Output:

CRT
ERR
WRN

Types

type Appender added in v1.1.0

type Appender interface {
	Print(logEntry *LogEntry)
}

Appender An Appender takes log entries and outputs it to whatever medium it implements

type AppendersLogger added in v1.1.0

type AppendersLogger interface {
	Options
}

func SyncedAppenders added in v1.1.0

func SyncedAppenders() AppendersLogger

type LogEntry added in v1.1.0

type LogEntry struct {
	Timestamp time.Time
	Level     int
	Message   string
	Source    *string
	Line      int
}

type Logger

type Logger interface {

	// SetLevel sets the current log level of the logger
	SetLevel(int)

	// Level returns the current log level of the logger
	Level() int

	// Critical logs the message(s) at the critical level
	Critical(v ...interface{})

	// Criticalf logs the formatted message at the critical level
	Criticalf(format string, v ...interface{})

	// Error logs the message(s) at the error level
	Error(v ...interface{})

	// Errorf logs the formatted message at the error level
	Errorf(format string, v ...interface{})

	// Warning logs the message(s) at the warning level
	Warning(v ...interface{})

	// Warningf logs the formatted message at the warning level
	Warningf(format string, v ...interface{})

	// Info logs the message(s) at the info level
	Info(v ...interface{})

	// Infof logs the formatted message at the info level
	Infof(format string, v ...interface{})

	// Debug logs the message(s) at the debug level
	Debug(v ...interface{})

	// Debugf logs the formatted message at the debug level
	Debugf(format string, v ...interface{})

	// Trace logs the message(s) at the trace level
	Trace(v ...interface{})

	// Tracef logs the formatted message at the trace level
	Tracef(format string, v ...interface{})
}

Logger defines the interface a Logger implementation must provide

func Get

func Get(name string) (Logger, error)

Get will create or get an existing logger with the given name. If the logger doesn't exist it will be created with the default options (warning level, logs to stdout and non-failing criticals). The name must be a non-empty string (may be spaces).

func GetWithOptions

func GetWithOptions(name string, options Options) (Logger, error)

GetWithOptions will create a log with the provided options if it doesn't exist yet or returns an existing log if the provided options are the same as the options the existing logger was created with. Trying to get an existing logger with different options. The name logger may not be an empty string (can be filled spaces).

type Options

type Options interface {
	// DateFlags sets the format flags for the logger
	DateFlags(flags int) Options

	// WithFailingCriticals sets the logger to fail (exit process) when logging a critical
	WithFailingCriticals() Options

	// WithoutFailingCriticals sets the logger to log criticals as plain log entries (process doesn't break)
	WithoutFailingCriticals() Options

	// WithStartingLevel sets the initial log level the logger has
	WithStartingLevel(startingLevel int) Options

	// WithLevelLogPrefix sets the log prefix format for a specific level
	WithLevelLogPrefix(logLevel int, flags ...uint) Options

	// WithLogPrefix sets the log prefix format for all levels
	WithLogPrefix(flags ...uint) Options
}

Options represents a logger options object and methods available to configure it

type StandardWriter added in v1.1.0

type StandardWriter interface {
	Options
	WithWriter(writer io.Writer) Options
}

func Standard added in v1.1.0

func Standard() StandardWriter

Standard creates an Options object for standard logging

Example
logger, _ := log.GetWithOptions("TRC", log.Standard().WithLogPrefix(log.Name, log.Separator).WithStartingLevel(log.TRACE))

logger.Critical("CRT")
logger.Error("ERR")
logger.Warning("WRN")
logger.Info("INF")
logger.Debug("DBG")
logger.Trace("TRC")

logger, _ = log.GetWithOptions("DBG", log.Standard().WithLogPrefix(log.Name, log.Separator))
logger.SetLevel(log.DEBUG)

logger.Critical("CRT")
logger.Error("ERR")
logger.Warning("WRN")
logger.Info("INF")
logger.Debug("DBG")
logger.Trace("TRC")

logger, _ = log.GetWithOptions("INF", log.Standard().WithLogPrefix(log.Name, log.Separator))
logger.SetLevel(log.INFO)

logger.Critical("CRT")
logger.Error("ERR")
logger.Warning("WRN")
logger.Info("INF")
logger.Debug("DBG")
logger.Trace("TRC")

logger, _ = log.GetWithOptions("WRN", log.Standard().WithLogPrefix(log.Name, log.Separator))
logger.SetLevel(log.WARNING)

logger.Critical("CRT")
logger.Error("ERR")
logger.Warning("WRN")
logger.Info("INF")
logger.Debug("DBG")
logger.Trace("TRC")
Output:

TRC - CRT
TRC - ERR
TRC - WRN
TRC - INF
TRC - DBG
TRC - TRC
DBG - CRT
DBG - ERR
DBG - WRN
DBG - INF
DBG - DBG
INF - CRT
INF - ERR
INF - WRN
INF - INF
WRN - CRT
WRN - ERR
WRN - WRN

Jump to

Keyboard shortcuts

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