lgr

package module
v0.11.1 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2023 License: MIT Imports: 13 Imported by: 283

README

lgr - simple logger with some extras

Build Status Coverage Status godoc

install

go get github.com/go-pkgz/lgr

usage

    l := lgr.New(lgr.Msec, lgr.Debug, lgr.CallerFile, lgr.CallerFunc) // allow debug and caller info, timestamp with milliseconds
    l.Logf("INFO some important message, %v", err)
    l.Logf("DEBUG some less important message, %v", err)

output looks like this:

2018/01/07 13:02:34.000 INFO  {svc/handler.go:101 h.MyFunc1} some important message, can't open file myfile.xyz
2018/01/07 13:02:34.015 DEBUG {svc/handler.go:155 h.MyFunc2} some less important message, file is too small`

Without lgr.Caller* it will drop {caller} part

details

interfaces and default loggers
  • lgr package provides a single interface lgr.L with a single method Logf(format string, args ...interface{}). Function wrapper lgr.Func allows making lgr.L from a function directly.
  • Default logger functionality can be used without lgr.New (see "global logger")
  • Two predefined loggers available: lgr.NoOp (do-nothing logger) and lgr.Std (passing directly to stdlib log)
options

lgr.New call accepts functional options:

  • lgr.Debug - turn debug mode on to allow messages with "DEBUG" level (filtered otherwise)
  • lgr.Trace - turn trace mode on to allow messages with "TRACE" abd "DEBUG" levels both (filtered otherwise)
  • lgr.Out(io.Writer) - sets the output writer, default os.Stdout
  • lgr.Err(io.Writer) - sets the error writer, default os.Stderr
  • lgr.CallerFile - adds the caller file info
  • lgr.CallerFunc - adds the caller function info
  • lgr.CallerPkg - adds the caller package
  • lgr.LevelBraces - wraps levels with "[" and "]"
  • lgr.Msec - adds milliseconds to timestamp
  • lgr.Format - sets a custom template, overwrite all other formatting modifiers.
  • lgr.Secret(secret ...) - sets list of the secrets to hide from the logging outputs.
  • lgr.Map(mapper) - sets mapper functions to change elements of the logging output based on levels.
  • lgr.StackTraceOnError - turns on stack trace for ERROR level.

example: l := lgr.New(lgr.Debug, lgr.Msec)

formatting templates:

Several predefined templates provided and can be passed directly to lgr.Format, i.e. lgr.Format(lgr.WithMsec)

	Short      = `{{.DT.Format "2006/01/02 15:04:05"}} {{.Level}} {{.Message}}`
	WithMsec   = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} {{.Message}}`
	WithPkg    = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerPkg}}) {{.Message}}`
	ShortDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}}) {{.Message}}`
	FuncDebug  = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFunc}}) {{.Message}}`
	FullDebug  = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}} {{.CallerFunc}}) {{.Message}}`

User can make a custom template and pass it directly to lgr.Format. For example:

    lgr.Format(`{{.Level}} - {{.DT.Format "2006-01-02T15:04:05Z07:00"}} - {{.CallerPkg}} - {{.Message}}`)

Note: formatter (predefined or custom) adds measurable overhead - the cost will depend on the version of Go, but is between 30 and 50% in recent tests with 1.12. You can validate this in your environment via benchmarks: go test -bench=. -run=Bench

levels

lgr.Logf recognize prefixes like INFO or [INFO] as levels. The full list of supported levels - TRACE, DEBUG, INFO, WARN, ERROR, PANIC and FATAL.

  • TRACE will be filtered unless lgr.Trace option defined
  • DEBUG will be filtered unless lgr.Debug or lgr.Trace options defined
  • INFO and WARN don't have any special behavior attached
  • ERROR sends messages to both out and err writers
  • FATAL and send messages to both out and err writers and exit(1)
  • PANIC does the same as FATAL but in addition sends dump of callers and runtime info to err.
mapper

Elements of the output can be altered with a set of user defined function passed as lgr.Map options. Such a mapper changes the value of an element (i.e. timestamp, level, message, caller) and has separate functions for each level. Note: both level and messages elements handled by the same function for a given level.

A typical use-case is to produce colorful output with a user-define colorization library.

example with fatih/color:

	colorizer := lgr.Mapper{
		ErrorFunc:  func(s string) string { return color.New(color.FgHiRed).Sprint(s) },
		WarnFunc:   func(s string) string { return color.New(color.FgHiYellow).Sprint(s) },
		InfoFunc:   func(s string) string { return color.New(color.FgHiWhite).Sprint(s) },
		DebugFunc:  func(s string) string { return color.New(color.FgWhite).Sprint(s) },
		CallerFunc: func(s string) string { return color.New(color.FgBlue).Sprint(s) },
		TimeFunc:   func(s string) string { return color.New(color.FgCyan).Sprint(s) },
	}

	logOpts := []lgr.Option{lgr.Msec, lgr.LevelBraces, lgr.Map(colorizer)}
adaptors

lgr logger can be converted to io.Writer or *log.Logger

  • lgr.ToWriter(l lgr.L, level string) io.Writer - makes io.Writer forwarding write ops to underlying lgr.L
  • lgr.ToStdLogger(l lgr.L, level string) *log.Logger - makes standard logger on top of lgr.L

level parameter is optional, if defined (non-empty) will enforce the level.

  • lgr.SetupStdLogger(opts ...Option) initializes std global logger (log.std) with lgr logger and given options. All standard methods like log.Print, log.Println, log.Fatal and so on will be forwarder to lgr.
global logger

Users should avoid global logger and pass the concrete logger as a dependency. However, in some cases a global logger may be needed, for example migration from stdlib log to lgr. For such cases log "github.com/go-pkgz/lgr" can be imported instead of log package.

Global logger provides lgr.Printf, lgr.Print and lgr.Fatalf functions. User can customize the logger by calling lgr.Setup(options ...). The instance of this logger can be retrieved with lgr.Default()

Documentation

Overview

Package lgr provides a simple logger with some extras. Primary way to log is Logf method. The logger's output can be customized in 2 ways:

  • by setting individual formatting flags, i.e. lgr.New(lgr.Msec, lgr.CallerFunc)
  • by passing formatting template, i.e. lgr.New(lgr.Format(lgr.Short))

Leveled output works for messages based on text prefix, i.e. Logf("INFO some message") means INFO level. Debug and trace levels can be filtered based on lgr.Trace and lgr.Debug options. ERROR, FATAL and PANIC levels send to err as well. FATAL terminate caller application with os.Exit(1) and PANIC also prints stack trace.

Index

Constants

View Source
const (
	// Short logging format
	Short = `{{.DT.Format "2006/01/02 15:04:05"}} {{.Level}} {{.Message}}`
	// WithMsec is a logging format with milliseconds
	WithMsec = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} {{.Message}}`
	// WithPkg is WithMsec logging format with caller package
	WithPkg = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerPkg}}) {{.Message}}`
	// ShortDebug is WithMsec logging format with caller file and line
	ShortDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}}) {{.Message}}`
	// FuncDebug is WithMsec logging format with caller function
	FuncDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFunc}}) {{.Message}}`
	// FullDebug is WithMsec logging format with caller file, line and function
	FullDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}} {{.CallerFunc}}) {{.Message}}`
)

Variables

View Source
var NoOp = Func(func(format string, args ...interface{}) {})

NoOp logger

View Source
var Std = Func(func(format string, args ...interface{}) { stdlog.Printf(format, args...) })

Std logger sends to std default logger directly

Functions

func CallerFile added in v0.1.4

func CallerFile(l *Logger)

CallerFile adds caller info with file, and line number. Ignored if Format option used.

func CallerFunc added in v0.1.4

func CallerFunc(l *Logger)

CallerFunc adds caller info with function name. Ignored if Format option used.

func CallerPkg added in v0.3.0

func CallerPkg(l *Logger)

CallerPkg adds caller's package name. Ignored if Format option used.

func Debug

func Debug(l *Logger)

Debug turn on dbg mode

func Fatalf added in v0.2.0

func Fatalf(format string, args ...interface{})

Fatalf simplifies replacement of std logger

func LevelBraces added in v0.1.4

func LevelBraces(l *Logger)

LevelBraces surrounds level with [], i.e. [INFO]. Ignored if Format option used.

func Msec added in v0.2.0

func Msec(l *Logger)

Msec adds .msec to timestamp. Ignored if Format option used.

func Print added in v0.1.2

func Print(line string)

Print simplifies replacement of std logger

func Printf

func Printf(format string, args ...interface{})

Printf simplifies replacement of std logger

func Setup added in v0.1.1

func Setup(opts ...Option)

Setup default logger with options

func SetupStdLogger added in v0.8.0

func SetupStdLogger(opts ...Option)

SetupStdLogger makes the default std logger with lgr.L

func StackTraceOnError added in v0.10.0

func StackTraceOnError(l *Logger)

StackTraceOnError turns on stack trace for ERROR level.

func ToStdLogger added in v0.5.0

func ToStdLogger(l L, level string) *log.Logger

ToStdLogger makes standard logger

func Trace added in v0.6.0

func Trace(l *Logger)

Trace turn on trace + dbg mode

Types

type Func

type Func func(format string, args ...interface{})

Func type is an adapter to allow the use of ordinary functions as Logger.

func (Func) Logf

func (f Func) Logf(format string, args ...interface{})

Logf calls f(format, args...)

type L

type L interface {
	Logf(format string, args ...interface{})
}

L defines minimal interface used to log things

func Default added in v0.1.1

func Default() L

Default returns pre-constructed def logger (debug off, callers disabled)

type Logger

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

Logger provided simple logger with basic support of levels. Thread safe

func New

func New(options ...Option) *Logger

New makes new leveled logger. By default writes to stdout/stderr. default format: 2018/01/07 13:02:34.123 DEBUG some message 123

func (*Logger) Logf

func (l *Logger) Logf(format string, args ...interface{})

Logf implements L interface to output with printf style. DEBUG and TRACE filtered out by dbg and trace flags. ERROR and FATAL also send the same line to err writer. FATAL and PANIC adds runtime stack and os.exit(1), like panic.

type Mapper added in v0.9.0

type Mapper struct {
	MessageFunc mapFunc // message mapper on all levels
	ErrorFunc   mapFunc // message mapper on ERROR level
	WarnFunc    mapFunc // message mapper on WARN level
	InfoFunc    mapFunc // message mapper on INFO level
	DebugFunc   mapFunc // message mapper on DEBUG level

	CallerFunc mapFunc // caller mapper, all levels
	TimeFunc   mapFunc // time mapper, all levels
}

Mapper defines optional functions to change elements of the logged message for each part, based on levels. Only some mapFunc can be defined, by default does nothing. Can be used to alter the output, for example making some part of the output colorful.

type Option

type Option func(l *Logger)

Option func type

func CallerDepth added in v0.5.0

func CallerDepth(n int) Option

CallerDepth sets number of stack frame skipped for caller reporting, 0 by default

func Err

func Err(w io.Writer) Option

Err sets error writer, stderr by default

func Format added in v0.6.0

func Format(f string) Option

Format sets output layout, overwrites all options for individual parts, i.e. Caller*, Msec and LevelBraces

func Map added in v0.9.0

func Map(m Mapper) Option

Map sets mapper functions to change elements of the logged message based on levels.

func Out

func Out(w io.Writer) Option

Out sets output writer, stdout by default

func Secret added in v0.7.0

func Secret(vals ...string) Option

Secret sets list of substring to be hidden, i.e. replaced by "******" Useful to prevent passwords or other sensitive tokens to be logged.

type Writer added in v0.5.0

type Writer struct {
	L
	// contains filtered or unexported fields
}

Writer holds lgr.L and wraps with io.Writer interface

func ToWriter added in v0.5.0

func ToWriter(l L, level string) *Writer

ToWriter makes io.Writer for given lgr.L with optional level

func (*Writer) Write added in v0.5.0

func (w *Writer) Write(p []byte) (n int, err error)

Write to lgr.L

Jump to

Keyboard shortcuts

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