log

package module
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2021 License: MIT Imports: 9 Imported by: 0

README

Go Log

Go Reference license

GoLog adds level based logging to logger(s) from standard library.

GoLog's API is designed to be expressive with sensible configuration defaults and to be easy to use.

Installation

go get -u github.com/codemedic/go-log

Getting Started

To get started, import the library and use one of the constructor functions, wrapped with log.Must. Make sure the logger is closed, once you are done with it, using defer l.Close(). Now you are all set to start logging.

Example
package main

import golog "github.com/codemedic/go-log"

func main() {
  // create syslog logger
  l := golog.Must(golog.NewSyslog())
  
  // make sure resources are freed up when we are done
  defer l.Close()

  // hello to the world
  l.Print("hello world!")
}

NOTE
Functions log.Print and log.Printf logs to Debug level by default. It is preferable to use a method that log to a specific level. The level logged to by log.Print and log.Printf can be changed using WithPrintLevel.

You can find more examples here.

Leveled Logging

The methods below provides leveled logging. They follow the same pattern as fmt.Print and fmt.Printf and uses the same format specification.

// Log string message at specific levels
Debug(value ...interface{})
Info(value ...interface{})
Warning(value ...interface{})
Error(value ...interface{})

// Log formatted string message at specific levels, similar to log.Printf from standard library
Debugf(format string, value ...interface{})
Infof(format string, value ...interface{})
Warningf(format string, value ...interface{})
Errorf(format string, value ...interface{})
Example
package main

import (
  "errors"
  golog "github.com/codemedic/go-log"
)

func main() {
  l := golog.Must(golog.NewSyslog())
  defer l.Close()

  l.Debug("debug message")
  l.Debugf("formatted %s message", "debug")

  l.Info("informational message")
  l.Infof("formatted %s message", "informational")

  l.Warning("warning message")
  l.Warningf("formatted %s message", "warning")

  l.Error("error message")
  l.Errorf("formatted %v message", errors.New("error"))
}

Options / Settings

See documentation for all available Options.

Example
package main

import golog "github.com/codemedic/go-log"

func main() {
  l := golog.Must(golog.NewSyslog(
    golog.OptionsMust(golog.Options(
      golog.WithLevelFromEnv("LOG_THRESHOLD", golog.Info),
      golog.WithSourceLocationFromEnv("LOG_CALLER_LOCATION", "short"),
      golog.WithSyslogTag("my-test-app"),
    ))))
  defer l.Close()

  l.Info("hello world!")
}

Standard log handler

Logging via standard logger is handled by default. This is meant for cases where the logging via the standard library is outside your control; a library used in your project for example. Those will be logged at Info level, but this behaviour can be customised using WithStdlogSorter.

Example
package main

import (
  "bytes"
  golog "github.com/codemedic/go-log"
)

func sortStdlog(b []byte) golog.Level {
  switch {
  case bytes.HasPrefix(b, []byte("WARNING")):
    fallthrough
  case bytes.HasPrefix(b, []byte("ERROR")):
    return golog.Warning
  case bytes.HasPrefix(b, []byte("DEBUG")):
    return golog.Disabled
  default:
    return golog.Info
  }
}

func main() {
  l, _ := golog.NewSyslog(golog.WithStdlogSorter(sortStdlog))
  defer l.Close()

  l.Info("hello world!")
}

Documentation

Overview

Package log adds easy, expressive configuration and leveled-logging to the logger(s) provided by the standard library.

Example
package main

import (
	"errors"
	"math/rand"

	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout())
	defer l.Close()

	l.Debug("debug message")
	l.Debugf("formatted %s message", "debug")

	l.Info("informational message")
	l.Infof("formatted %s message", "informational")

	l.Warning("warning message")
	l.Warningf("formatted %s message", "warning")

	l.Error("error message")
	l.Errorf("formatted %v message", errors.New("error"))

	// In cases where deriving debug data has a significant cost to memory, cpu or both, do it
	// only if the data is not going to be thrown away by the logger.
	if l.DebugEnabled() {
		data := rand.Int()
		l.Debugf("data: %d", data)
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrBadLevel = errors.New("bad level")

ErrBadLevel signifies that a string couldn't be translated to a valid logging level.

View Source
var ErrBadSyslogDaemonURL = errors.New("bad syslog daemon url")

ErrBadSyslogDaemonURL occurs when a given URL is not valid for syslog initialisation.

View Source
var ErrIncompatibleOption = errors.New("incompatible option")

ErrIncompatibleOption occurs when any of the given options are not compatible with the object being configured.

View Source
var ErrUnknownOption = errors.New("unknown option")

ErrUnknownOption signifies an option that couldn't be recognised.

Functions

This section is empty.

Types

type ConfigError

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

func (*ConfigError) As

func (w *ConfigError) As(target interface{}) bool

func (*ConfigError) Error

func (c *ConfigError) Error() string

func (*ConfigError) Is

func (w *ConfigError) Is(target error) bool

func (*ConfigError) Unwrap

func (w *ConfigError) Unwrap() error

type ConnectionError

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

func (*ConnectionError) As

func (w *ConnectionError) As(target interface{}) bool

func (*ConnectionError) Error

func (c *ConnectionError) Error() string

func (*ConnectionError) Is

func (w *ConnectionError) Is(target error) bool

func (*ConnectionError) Unwrap

func (w *ConnectionError) Unwrap() error

type Level

type Level int
const (
	Disabled Level = iota
	Debug
	Info
	Warning
	Error
)

func (Level) IsEnabled

func (l Level) IsEnabled(threshold Level) bool

IsEnabled return true if l is above or at the same level as threshold. If threshold is Disabled or is below l then returns false.

func (Level) String

func (l Level) String() string

type Log

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

func Must

func Must(l Log, err error) Log

Must ensures that a Log instance was initialised without error; panics if there was an error.

func New

func New(opt ...Option) (log Log, err error)

New creates a new logger with the specified options.

func NewLogfile

func NewLogfile(file string, perm os.FileMode, opt ...Option) (log Log, err error)

NewLogfile creates a new logger that logs to the specified file. A file is created with permissions specified in perm, if the file does not exist. If the file already exists, new records are appended to it. Additional options can be specified using opt.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewLogfile("/tmp/test-logfile.log", 0644,
		golog.OptionsMust(golog.Options(
			golog.WithLevelFromEnv("LOG_LEVEL", golog.Info),
			golog.WithUTCTimestampFromEnv("LOG_UTC", true),
			golog.WithSourceLocationFromEnv("LOG_SOURCE_LOCATION", "short"),
			golog.WithMicrosecondsTimestamp,
		))))

	defer l.Close()
}
Output:

func NewStderr

func NewStderr(opt ...Option) (Log, error)

NewStderr creates a new logger that logs to stderr. Additional options can be specified using opt.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStderr(
		golog.OptionsMust(golog.Options(
			golog.WithLevelFromEnv("LOG_LEVEL", golog.Info),
			golog.WithUTCTimestampFromEnv("LOG_UTC", true),
			golog.WithSourceLocationDisabled,
			golog.WithMicrosecondsTimestamp,
		))))

	defer l.Close()
}
Output:

func NewStdout

func NewStdout(opt ...Option) (Log, error)

NewStdout creates a new logger that logs to stdout. Additional options can be specified using opt.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.OptionsMust(golog.Options(
			golog.WithLevelFromEnv("LOG_LEVEL", golog.Info),
			golog.WithUTCTimestampFromEnv("LOG_UTC", true),
			golog.WithSourceLocationLong,
			golog.WithMicrosecondsTimestamp,
		))))

	defer l.Close()
}
Output:

func NewSyslog

func NewSyslog(opt ...Option) (log Log, err error)

NewSyslog creates a new syslog logger with the specified options.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewSyslog(
		golog.OptionsMust(golog.Options(
			// set the log-level dynamically from the environment
			golog.WithLevelFromEnv("LOG_LEVEL", golog.Info),
			// set the syslog tag
			golog.WithSyslogTag("test-syslog"),
			// write to syslog server over UDP
			golog.WithSyslogDaemonURL("udp://syslog.acme.com:514"),
		))))

	defer l.Close()
}
Output:

func (Log) Close

func (l Log) Close()

Close disables and closes the logger, freeing up any resources allocated to the logger. Once closed the logger will be disabled but it will remain safe to use (free from panics).

func (Log) Debug

func (l Log) Debug(value ...interface{})

func (Log) DebugEnabled

func (l Log) DebugEnabled() bool

DebugEnabled checks if DEBUG level is enabled for the logger. It can be used to check before performing any extra processing to generate data that is purely for logging, thereby avoiding the extra processing when DEBUG level is disabled.

Example:

if logger.DebugEnabled() {
  debugData := makeDebugData()
  logger.Debugf("debug data: %v", debugData)
}

func (Log) Debugf

func (l Log) Debugf(format string, value ...interface{})

func (Log) Error

func (l Log) Error(value ...interface{})

func (Log) Errorf

func (l Log) Errorf(format string, value ...interface{})

func (Log) Fatal

func (l Log) Fatal(value ...interface{})

func (Log) Fatalf

func (l Log) Fatalf(format string, value ...interface{})

func (Log) Fatalln added in v0.6.0

func (l Log) Fatalln(value ...interface{})

func (Log) Info

func (l Log) Info(value ...interface{})

func (Log) Infof

func (l Log) Infof(format string, value ...interface{})

func (Log) Panic added in v0.6.0

func (l Log) Panic(value ...interface{})

func (Log) Panicf added in v0.6.0

func (l Log) Panicf(format string, value ...interface{})

func (Log) Panicln added in v0.6.0

func (l Log) Panicln(value ...interface{})

func (Log) Print

func (l Log) Print(value ...interface{})

func (Log) Printf

func (l Log) Printf(format string, value ...interface{})

func (Log) Println added in v0.6.0

func (l Log) Println(value ...interface{})

func (Log) Warning

func (l Log) Warning(value ...interface{})

func (Log) Warningf

func (l Log) Warningf(format string, value ...interface{})

type Logger added in v0.3.1

type Logger interface {
	// Level gives the current threshold of the logger
	Level() Level
	// PrintLevel gives the level at which log.Print logs
	PrintLevel() Level
	// Logf is the workhorse function that logs each line; works in a similar way to fmt.Printf
	Logf(level Level, format string, value ...interface{})
	// Close closes the logger
	Close()
}

Logger interface provides means to extend this library

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option provides the interface through which all loggers can be configured.

func Options

func Options(opt ...interface{}) (Option, error)

Options combine multiple options into one composite option. It takes a list of Option or OptionLoader; the latter makes it possible to load options dynamically from environment, config files, etc

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.OptionsMust(
			golog.Options(
				golog.WithLevelFromEnv("LOG_LEVEL", golog.Info),
				golog.WithMicrosecondsTimestamp))))

	defer l.Close()
}
Output:

func OptionsMust added in v0.2.0

func OptionsMust(o Option, err error) Option

OptionsMust checks for errors from dynamic OptionLoader combined through Options. It panics if err is not nil otherwise returns o.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.OptionsMust(
			golog.Options(
				golog.WithLevelFromEnv("LOG_LEVEL", golog.Info),
				golog.WithMicrosecondsTimestamp))))

	defer l.Close()
}
Output:

func WithLevel

func WithLevel(level Level) Option

WithLevel specifies the level for loggers.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithLevel(golog.Info),
	))

	defer l.Close()

	l.Debug("hide me")
	l.Info("hello world!")
}
Output:

func WithMicrosecondsTimestamp

func WithMicrosecondsTimestamp(enable bool) Option

WithMicrosecondsTimestamp specifies whether loggers are to log timestamp with microseconds precision.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithMicrosecondsTimestamp(true),
	))

	defer l.Close()
}
Output:

func WithPrintLevel

func WithPrintLevel(level Level) Option

WithPrintLevel specifies the level for log.Print and log.Printf.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithPrintLevel(golog.Info),
	))

	defer l.Close()

	l.Print("hello world!")
}
Output:

func WithSourceLocationDisabled

func WithSourceLocationDisabled() Option

WithSourceLocationDisabled disables caller-location in log-lines.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithSourceLocationDisabled(),
	))

	defer l.Close()
}
Output:

func WithSourceLocationLong

func WithSourceLocationLong() Option

WithSourceLocationLong specifies the caller-location in log-lines to have long filename.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithSourceLocationLong(),
	))

	defer l.Close()
}
Output:

func WithSourceLocationShort

func WithSourceLocationShort() Option

WithSourceLocationShort specifies the caller-location in log-lines to have short filename.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithSourceLocationShort(),
	))

	defer l.Close()
}
Output:

func WithStdlogHandler added in v0.3.1

func WithStdlogHandler(enable bool) Option

WithStdlogHandler specifies whether the logger is to be setup as handler for logging through the standard logger. All messages that arrive via the global standard logger will be logged at INFO level.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithStdlogHandler(false),
	))

	defer l.Close()
}
Output:

func WithStdlogSorter added in v0.3.1

func WithStdlogSorter(sorter logSorter) Option

WithStdlogSorter sets up the callback that decides the level to which a log-line from global standard logger will be logged.

Example
package main

import (
	"bytes"

	golog "github.com/codemedic/go-log"
)

func main() {
	l, _ := golog.NewStdout(golog.WithStdlogSorter(func(b []byte) golog.Level {
		switch {
		case bytes.HasPrefix(b, []byte("WARNING")):
			fallthrough
		case bytes.HasPrefix(b, []byte("ERROR")):
			return golog.Warning // ERROR and WARNING lines as Warning
		case bytes.HasPrefix(b, []byte("INFO")):
			fallthrough
		case bytes.HasPrefix(b, []byte("DEBUG")):
			return golog.Disabled // disable DEBUG & INFO lines
		default:
			return golog.Info // everything else as Info
		}
	}))

	defer l.Close()
}
Output:

func WithSyslogDaemonURL

func WithSyslogDaemonURL(url string) Option

WithSyslogDaemonURL specifies the syslog daemon URL for syslog logger.

Example (Local)
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewSyslog(
		golog.WithSyslogDaemonURL("unixgram:///dev/log"),
	))

	defer l.Close()
}
Output:

Example (UDP)
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewSyslog(
		golog.WithSyslogDaemonURL("udp://syslog.acme.com:514"),
	))

	defer l.Close()
}
Output:

func WithSyslogTag

func WithSyslogTag(tag string) Option

WithSyslogTag specifies the tag for syslog logger.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewSyslog(
		golog.WithSyslogTag("my-app-name"),
	))

	defer l.Close()
}
Output:

func WithUTCTimestamp

func WithUTCTimestamp(enable bool) Option

WithUTCTimestamp specifies whether loggers are to log timestamp in UTC.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(
		golog.WithUTCTimestamp(true),
	))

	defer l.Close()
}
Output:

func WithWriter

func WithWriter(w io.WriteCloser) Option

WithWriter specifies the writer for a logger.

Example
package main

import (
	"os"

	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.New(
		golog.WithWriter(os.Stdout),
	))

	defer l.Close()
}
Output:

type OptionLoader

type OptionLoader func() (Option, error)

func WithLevelFromEnv

func WithLevelFromEnv(env string, defaultLevel Level) OptionLoader

WithLevelFromEnv makes a WithLevel option based on the specified environment variable env or defaultLevel if no environment variable was found.

func WithLevelString added in v0.6.0

func WithLevelString(str string) OptionLoader

WithLevelString specifies the level for loggers as a string.

Example
package main

import (
	"flag"

	golog "github.com/codemedic/go-log"
)

func main() {
	lvl := flag.String("level", "debug", "Log level")

	l := golog.Must(golog.NewSyslog(
		golog.OptionsMust(golog.Options(
			golog.WithSyslogTag("test-syslog"),
			// set the log-level to what is specified on commandline
			golog.WithLevelString(*lvl),
		))))

	defer l.Close()
}
Output:

func WithMicrosecondsTimestampFromEnv

func WithMicrosecondsTimestampFromEnv(env string, defaultEnable bool) OptionLoader

WithMicrosecondsTimestampFromEnv makes a WithMicrosecondsTimestamp option based on the specified environment variable env or defaultEnable if no environment variable was found.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(golog.OptionsMust(golog.Options(
		golog.WithMicrosecondsTimestampFromEnv("LOG_MICROSECOND_TIMESTAMP", true),
	))))

	defer l.Close()
}
Output:

func WithSourceLocation added in v0.6.0

func WithSourceLocation(value string) OptionLoader

WithSourceLocation specifies the caller-location format as a string; allowed values are "short", "long", "disabled".

Example
package main

import (
	"flag"

	golog "github.com/codemedic/go-log"
)

func main() {
	srcloc := flag.String("srcloc", "disabled", "Source location in log lines")

	l := golog.Must(golog.NewSyslog(
		golog.OptionsMust(golog.Options(
			golog.WithSyslogTag("test-syslog"),
			// set the source-location option as specified on commandline
			golog.WithSourceLocation(*srcloc),
		))))

	defer l.Close()
}
Output:

func WithSourceLocationFromEnv

func WithSourceLocationFromEnv(env string, defaultFormat string) OptionLoader

WithSourceLocationFromEnv sets the caller-location option based on either the specified environment variable env or the defaultFormat if no environment variable is found.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(golog.OptionsMust(golog.Options(
		golog.WithSourceLocationFromEnv("LOG_CALLER_LOCATION", "short"),
	))))

	defer l.Close()
}
Output:

func WithSyslogDaemonURLFromEnv

func WithSyslogDaemonURLFromEnv(env, defaultUrl string) OptionLoader

WithSyslogDaemonURLFromEnv makes a WithSyslogDaemonURL option based on the specified environment variable env or defaultUrl if no environment variable was found.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewSyslog(golog.OptionsMust(golog.Options(
		golog.WithSyslogDaemonURLFromEnv("LOG_SERVER", "udp://syslog.acme.com:514"),
	))))

	defer l.Close()
}
Output:

func WithUTCTimestampFromEnv

func WithUTCTimestampFromEnv(env string, defaultEnable bool) OptionLoader

WithUTCTimestampFromEnv makes a WithUTCTimestamp option based on the specified environment variable env or defaultEnable if no environment variable was found.

Example
package main

import (
	golog "github.com/codemedic/go-log"
)

func main() {
	l := golog.Must(golog.NewStdout(golog.OptionsMust(golog.Options(
		golog.WithUTCTimestampFromEnv("LOG_UTC", true),
	))))

	defer l.Close()
}
Output:

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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