Documentation
¶
Overview ¶
Package logger provides an flexible, extensible and powerful logging management tool based on the level, which has done the better balance between the flexibility and the performance.
Basic Principle
- The better performance
- Flexible, extensible, and powerful
- No any third-party dependencies
Features
- A simple, easy-to-understand API
- No any third-party dependencies for the core package.
- A flexible and powerful interface supporting many encoders
- Child loggers which inherit and add their own private context
- Lazy evaluation of expensive operations
- Support any `io.Writer` and provied some advanced `io.Writer` implementations
- Built-in support for logging to files, syslog, and the network
Encoder ¶
The core package provides three kinds of encoders:
- the text encoder based on Key-Value `KvTextEncoder`
- the text encoder based on Format `FmtTextEncoder`
- the json encoder based on Key-Value `KvStdJSONEncoder` and `KvSimpleJSONEncoder`
For the encoders based on Format, the arguments of the log output function, such as `Info()`, are the same as those of `fmt.Sprintf()`. For the encoders based on Key-Value, howerer, the first argument is the log description, and the rests are the key-value pairs, the number of which are even, for example,
logger.Info("log description", "key1", "value1", "key2", "value2")
You can use `LevelFilterEncoder` to filter some logs by the level, for example,
Writer ¶
All implementing the interface `io.Writer` are a Writer.
There are some the built-in writers in the core package, For example,
NetWriter SyslogWriter SizedRotatingFileWriter FileWriter ChannelWriter LevelFilterWriter SafeWriter DiscardWriter SyslogNetWriter MultiWriter BufferedWriter FailoverWriter
Performance ¶
The log framework itself has no any performance costs.
There may be some performance costs below:
- Use format arguments or Key-Value pairs when firing a log. For example, `logger.Info("hello %s", "world")` will allocate the 16-byte memory once for the encoder `FmtTextEncoder`, `logger.Info("hello world", "key", "value")` will allocate the 32-byte memory once for the encoder `KvTextEncoder`.
- Encode the arguments to `io.Writer`. For `string` or `[]byte`, there is no any performance cost, but for other types, such as `int`, it maybe have once memory allocation.
Index ¶
- Constants
- Variables
- func Debug(msg string, args ...interface{}) error
- func Error(msg string, args ...interface{}) error
- func Fatal(msg string, args ...interface{}) error
- func GetDepth() int
- func Info(msg string, args ...interface{}) error
- func MarshalJSON(w io.Writer, v interface{}) (n int, err error)
- func MayBeValuer(depth int, lvl Level, v interface{}) (interface{}, error)
- func MayWriteLevel(w Writer, level Level, bs []byte) (int, error)
- func Panic(msg string, args ...interface{}) error
- func Range(start, stop, step int) (r []int)
- func SetGlobalLogger(log Logger)
- func SizedRotatingFileWriter(filename string, size, count int, mode ...os.FileMode) (io.WriteCloser, error)
- func SyslogNetWriter(net, addr string, priority syslog.Priority, tag string) (io.Writer, io.Closer, error)
- func SyslogWriter(priority syslog.Priority, tag string) (io.Writer, io.Closer, error)
- func ToBytes(i interface{}, fmtSprintf ...bool) []byte
- func ToBytesErr(i interface{}, fmtSprintf ...bool) ([]byte, error)
- func ToString(i interface{}, fmtSprintf ...bool) string
- func ToStringErr(i interface{}, fmtSprintf ...bool) (string, error)
- func Trace(msg string, args ...interface{}) error
- func Warn(msg string, args ...interface{}) error
- func WriteIntoBuffer(w *bytes.Buffer, i interface{}, fmtSprintf ...bool) error
- func WriteString(w io.Writer, s string, quote ...bool) (n int, err error)
- type BufferPool
- type Byter
- type BytesPool
- type Encoder
- func EncoderFunc(w Writer, f FuncEncoder) Encoder
- func FilterEncoder(f func(lvl Level, msg string, args []interface{}, ctx []interface{}) bool, ...) Encoder
- func FmtTextEncoder(out Writer, conf ...EncoderConfig) Encoder
- func GetEncoder() Encoder
- func KvJSONEncoder(encodeJSON func(Writer, interface{}) error, w Writer, conf ...EncoderConfig) Encoder
- func KvSimpleJSONEncoder(w Writer, conf ...EncoderConfig) Encoder
- func KvStdJSONEncoder(w Writer, conf ...EncoderConfig) Encoder
- func KvTextEncoder(out Writer, conf ...EncoderConfig) Encoder
- func LevelFilterEncoder(level Level, encoder Encoder) Encoder
- func MultiEncoder(encoders ...Encoder) Encoder
- func NothingEncoder() Encoder
- type EncoderConfig
- type FuncEncoder
- type Level
- type LevelWriter
- type Logger
- func GetGlobalLogger() Logger
- func New(encoder Encoder) Logger
- func SimpleLogger(level, filepath string, args ...int) (Logger, io.Closer, error)
- func ToLogger(logger LoggerWithoutError) Logger
- func WithCtx(ctxs ...interface{}) Logger
- func WithDepth(depth int) Logger
- func WithEncoder(encoder Encoder) Logger
- func WithLevel(level Level) Logger
- type LoggerWithoutError
- type MarshalText
- type MultiError
- type StringWriter
- type Valuer
- type Writer
- func BufferedWriter(bufSize int, w Writer) Writer
- func ChannelWriter(ch chan<- []byte) Writer
- func DiscardWriter() Writer
- func FailoverWriter(outs ...Writer) Writer
- func FileWriter(path string, mode ...os.FileMode) (Writer, io.Closer, error)
- func GetWriter() Writer
- func MultiWriter(outs ...Writer) Writer
- func NetWriter(network, addr string) (Writer, io.Closer, error)
- func ReopenWriter(factory func() (w io.WriteCloser, reopen <-chan bool, err error)) (Writer, error)
- func SafeWriter(w Writer) Writer
- func WriterFunc(f func([]byte) (int, error)) Writer
Examples ¶
Constants ¶
const ( TextKVSep = "=" TextKVPairSep = " " )
The separators of the KV and the KV pair.
const ( LevelKey = "lvl" TimeKey = "t" MsgKey = "msg" )
Some key names. You can modify them to redefine them.
const DefaultLoggerDepth = 2
DefaultLoggerDepth is the depth for the default implementing logger.
Variables ¶
var ( NullBytes = []byte("null") TrueBytes = []byte("true") FalseBytes = []byte("false") CommaBytes = []byte{','} ColonBytes = []byte{':'} LeftBracketBytes = []byte{'['} RightBracketBytes = []byte{']'} LeftBraceBytes = []byte{'{'} RightBraceBytes = []byte{'}'} )
Predefine some json mark
var ( DefaultBytesPools = NewBytesPool() DefaultBufferPools = NewBufferPool() )
Some default global pools.
var ErrKeyValueNum = fmt.Errorf("the number of key-values must be even")
ErrKeyValueNum will be used when the number of key-values is not even.
var ErrPanic = fmt.Errorf("the panic level log")
ErrPanic will be used when firing a PANIC level log.
var (
ErrType = fmt.Errorf("not support the type")
)
Predefine some errors.
var Must muster
Must object provides the following writer creation functions which instead of returning an error parameter only return a writer and panic on failure: FileWriter, NetWriter, SyslogWriter, SyslogNetWriter.
Functions ¶
func Fatal ¶
Fatal fires a FATAL log then terminates the program.
The meaning of arguments is in accordance with the encoder.
func MarshalJSON ¶
MarshalJSON marshals a value v as JSON into w.
Support the types:
nil bool string float32 float64 int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 time.Time map[string]interface{} for json object json.Marshaler Array or Slice of the type above
Example ¶
buf := bytes.NewBuffer(nil) MarshalJSON(buf, 123) buf.WriteByte('\n') MarshalJSON(buf, 1.23) buf.WriteByte('\n') MarshalJSON(buf, "123") buf.WriteByte('\n') MarshalJSON(buf, time.Time{}) buf.WriteByte('\n') MarshalJSON(buf, []int{1, 2, 3}) buf.WriteByte('\n') MarshalJSON(buf, []string{"a", "b", "c"}) buf.WriteByte('\n') MarshalJSON(buf, []float64{1.2, 1.4, 1.6}) buf.WriteByte('\n') // MarshalJSON(buf, map[string]interface{}{"number": 123, "name": "abc"}) buf.WriteByte('\n') fmt.Printf("%s", buf.String())
Output:
func MayBeValuer ¶
MayBeValuer calls it and returns the result if v is Valuer. Or returns v without change.
func MayWriteLevel ¶
MayWriteLevel firstly tries to call the method WriteLevel to write the data. Or use Writer to write it.
func Panic ¶
Panic fires a PANIC log then panic.
The meaning of arguments is in accordance with the encoder.
func Range ¶
Range returns a integer range between start and stop, which progressively increase or descrease by step.
If step is positive, r[i] = start + step*i when i>0 and r[i]<stop.
If step is negative, r[i] = start + step*i but when i>0 and r[i]>stop.
If step is 0, it will panic.
func SetGlobalLogger ¶
func SetGlobalLogger(log Logger)
SetGlobalLogger sets the global logger to log.
If log is nil, it will do nothing.
Notice: for the global logger, it must be the builtin implementation.
func SizedRotatingFileWriter ¶
func SizedRotatingFileWriter(filename string, size, count int, mode ...os.FileMode) (io.WriteCloser, error)
SizedRotatingFileWriter returns a new file writer with rotating based on the size of the file.
It is thread-safe for concurrent writes.
The default permission of the log file is 0644.
func SyslogNetWriter ¶
func SyslogNetWriter(net, addr string, priority syslog.Priority, tag string) (io.Writer, io.Closer, error)
SyslogNetWriter opens a connection to a log daemon over the network and writes all logs to it.
func SyslogWriter ¶
SyslogWriter opens a connection to the system syslog daemon by calling syslog.New and writes all logs to it.
Example ¶
conf := EncoderConfig{IsLevel: true} out, c := Must.SyslogWriter(syslog.LOG_DEBUG, "testsyslog") defer c.Close() log := New(FmtTextEncoder(out, conf)) if err := log.Info("test %s %s", "syslog", "writer"); err != nil { fmt.Printf("Error: %s\n", err) }
Output:
func ToBytesErr ¶
ToBytesErr encodes a value to []byte.
For the time.Time, it uses time.RFC3339Nano to format it.
Support the types:
nil bool []byte string float32 float64 int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 time.Time interface error interface fmt.Stringer interface Byter interface MarshalText
For other types, use fmt.Sprintf("%v") to format it if fmtSprintf is true, or return the error ErrType.
func ToStringErr ¶
ToStringErr is the same as ToBytesErr, but returns string.
func WriteIntoBuffer ¶
WriteIntoBuffer is the same as ToBytesErr, but writes the result into w.
Types ¶
type BufferPool ¶
type BufferPool struct {
// contains filtered or unexported fields
}
BufferPool is the bytes.Buffer wrapper of sync.Pool
func NewBufferPool ¶
func NewBufferPool(bufSize ...int) BufferPool
NewBufferPool returns a new bytes.Buffer pool.
bufSize is the initializing size of the buffer. If the size is equal to or less than 0, it will be ignored, and use the default size, 1024.
func (BufferPool) Put ¶
func (p BufferPool) Put(b *bytes.Buffer)
Put places a bytes.Buffer to the pool.
type BytesPool ¶
type BytesPool struct {
// contains filtered or unexported fields
}
BytesPool is the []byte wrapper of sync.Pool
func NewBytesPool ¶
NewBytesPool returns a new []byte pool.
sliceCap is the capacity of []byte. If the size is equal to or less than 0, it will be ignored, and use the default size, 1024.
type Encoder ¶
type Encoder interface { // Reset the underlying writer. ResetWriter(Writer) // Return the underlying writer. // // Notice: only the most underlying encoder requires it. For the inner // encoder, such as FilterEncoder and MultiEncoder, it may be nil. // So, at the moment, the log information should be passed to the next encoder. Writer() Writer // Encode the log and write it into the underlying writer. Encode(depth int, level Level, msg string, args []interface{}, ctx []interface{}) error }
Encoder is a log encoder.
Notice: if the encoder implementation supports the level when writing data, it should firstly decide whether the writer is LevelWriter and use WriteLevel to write the log, not Write.
func EncoderFunc ¶
func EncoderFunc(w Writer, f FuncEncoder) Encoder
EncoderFunc converts a function to an hashable Encoder.
func FilterEncoder ¶
func FilterEncoder(f func(lvl Level, msg string, args []interface{}, ctx []interface{}) bool, encoder Encoder) Encoder
FilterEncoder returns an encoder that only forwards logs to the wrapped encoder if the given function evaluates true.
For example, filter those logs that the level is less than ERROR.
FilterEncoder(func(lvl Level, msg string, args []interface{}, ctxs []interface{}) bool { return level >= ERROR })
func FmtTextEncoder ¶
func FmtTextEncoder(out Writer, conf ...EncoderConfig) Encoder
FmtTextEncoder returns a text encoder based on the % formatter, which will output the result into out.
Notice: This encoder supports LevelWriter.
Example ¶
conf := EncoderConfig{IsLevel: true} encoder := FmtTextEncoder(os.Stdout, conf) log := New(encoder).Cxt("kv", "text", "example") log.Info("test %s %s", "value1", "value2")
Output: {kv}{text}{example} [INFO]: test value1 value2
func KvJSONEncoder ¶ added in v1.0.0
func KvJSONEncoder(encodeJSON func(Writer, interface{}) error, w Writer, conf ...EncoderConfig) Encoder
KvJSONEncoder encodes the log as the JSON and outputs it to w.
KvStdJSONEncoder and KvSimpleJSONEncoder will use this encoder.
func KvSimpleJSONEncoder ¶
func KvSimpleJSONEncoder(w Writer, conf ...EncoderConfig) Encoder
KvSimpleJSONEncoder returns a new JSON encoder using the funcion MarshalJSON to encode the log record.
Except for the type of Array and Slice, it does not use the reflection. So it's faster than the standard library json.
func KvStdJSONEncoder ¶
func KvStdJSONEncoder(w Writer, conf ...EncoderConfig) Encoder
KvStdJSONEncoder returns a new JSON encoder using the standard library, json, to encode the log record.
Example ¶
conf := EncoderConfig{IsLevel: true} encoder := KvStdJSONEncoder(os.Stdout, conf) log := New(encoder).Cxt("name", "example", "id", 123) log.Info("test", "key1", "value1", "key2", "value2")
Output: {"id":123,"key1":"value1","key2":"value2","lvl":"INFO","msg":"test","name":"example"}
func KvTextEncoder ¶
func KvTextEncoder(out Writer, conf ...EncoderConfig) Encoder
KvTextEncoder returns a text encoder based on the key-value pair, which will output the result into out.
Notice: This encoder supports LevelWriter.
Example ¶
conf := EncoderConfig{IsLevel: true} encoder := KvTextEncoder(os.Stdout, conf) log := New(encoder).Cxt("name", "example", "id", 123) log.Info("test", "key1", "value1", "key2", "value2")
Output: lvl=INFO name=example id=123 key1=value1 key2=value2 msg=test
func LevelFilterEncoder ¶
LevelFilterEncoder returns an encoder that only writes records which are greater than the given verbosity level to the wrapped Handler.
For example, to only output Error/PANIC/FATAL logs:
logger.LevelFilterEncoder(logger.ERROR, logger.KvTextEncoder(os.Stdout))
func MultiEncoder ¶
MultiEncoder uses many encoders to encode the log record.
It will return a MultiError if there is a error returned by an encoder in the corresponding order. For example,
encoders = ["kvtext", "kvjson"] enc1 := KvTextEncoder(os.Stdout) enc2 := KvJsonEncoder(os.Stderr) logger := New(MultiEncoder(enc1, enc2)) err := logger.Info("msg", "key", "value") if err != nil { errs := err.(MultiError) for i, e := range errs { if e != nil { fmt.Printf("%s: %s\n", encoders[i], e.Error()) } } }
func NothingEncoder ¶
func NothingEncoder() Encoder
NothingEncoder returns an encoder that does nothing.
type EncoderConfig ¶
type EncoderConfig struct { Slice []interface{} Map map[string]interface{} // If true, the encoder disable appending a newline. NotNewLine bool // TimeLayout is used to format time.Time. // // The default is time.RFC3339Nano. TimeLayout string // If true, the time uses UTC. IsTimeUTC bool // If ture, the encoder will encode the current time. IsTime bool // If ture, the encoder will encode the level. IsLevel bool // For the Key-Value encoder, it represents the key name of the time. // The global constant, TimeKey, will be used by default. TimeKey string // For the Key-Value encoder, it represents the key name of the level. // The global constant, LvlKey, will be used by default. LevelKey string // For the Key-Value encoder, it represents the key name of the message. // The global constant, MsgKey, will be used by default. MsgKey string // The separator between key and value, such as "=". // The global constant, TextKVSep, will be used by default. TextKVSep string // The separator between the key-value pairs, such as " ". // The global constant, TextKVPairSep, will be used by default. TextKVPairSep string }
EncoderConfig configures the encoder.
type FuncEncoder ¶ added in v0.3.0
type FuncEncoder func(w Writer, depth int, lvl Level, msg string, args []interface{}, ctx []interface{}) error
FuncEncoder stands for a function encoder, which is used to simplify the funcion signature.
type Level ¶
type Level int
Level represents a level.
const ( TRACE Level = iota // It will output the log unconditionally. DEBUG INFO WARN ERROR PANIC FATAL )
Predefine some levels
func NameToLevel ¶
NameToLevel returns the Level by the name, which is case Insensitive.
If the name is unknown, it will panic.
Notice: WARNING is the alias of WARN.
type LevelWriter ¶
LevelWriter supports not only Writer but also WriteLevel.
func LevelFilterWriter ¶
func LevelFilterWriter(lvl Level, w Writer) LevelWriter
LevelFilterWriter filters the logs whose level is less than lvl.
Example ¶
logger1 := New(FmtTextEncoder(os.Stdout)) logger1.Info("will output") writer := LevelFilterWriter(ERROR, os.Stdout) logger2 := New(FmtTextEncoder(writer)) logger2.Info("won't output")
Output: will output
func LevelWriterFunc ¶
func LevelWriterFunc(f func(Level, []byte) (int, error)) LevelWriter
LevelWriterFunc converts a function to LevelWriter.
type Logger ¶
type Logger interface { // Depth returns a new Logger with the stack depth. // // stackDepth is the calling depth of the logger, which will be passed to // the encoder. The default depth is the global variable DefaultLoggerDepth // for the new Logger. // // It should be used typically when you wrap the logger. For example, // // _logger := logger.New(logger.KvTextEncoder(os.Stdout)) // _logger = _logger.Depth(_logger.GetDepth() + 1) // // func Debug(m string, args ...interface{}) { _logger.Debug(m, args...) } // func Info(m string, args ...interface{}) { _logger.Debug(m, args...) } // func Warn(m string, args ...interface{}) { _logger.Debug(m, args...) } // ... // Depth(stackDepth int) Logger // Level returns a new Logger with the new level. Level(level Level) Logger // Encoder returns a new logger with the new encoder. Encoder(encoder Encoder) Logger // Ctx returns a new logger with the new contexts. Cxt(ctxs ...interface{}) Logger // Writer is the convenient function of GetEncoder().Writer(). Writer() io.Writer GetDepth() int GetLevel() Level GetEncoder() Encoder Trace(msg string, args ...interface{}) error Debug(msg string, args ...interface{}) error Info(msg string, args ...interface{}) error Warn(msg string, args ...interface{}) error Error(msg string, args ...interface{}) error Panic(msg string, args ...interface{}) error Fatal(msg string, args ...interface{}) error }
Logger is a logger interface.
func SimpleLogger ¶ added in v1.0.0
SimpleLogger returns a new Logger with the level and the writer will use os.Stdout if filepath is "", or use the file based on SizedRotatingFileWriter.
Notice: the file size is 1GB and the number is 30 by default. But you can change it by passing the last two parameters as follow.
FileLogger(level, filepath, 2*1024*1024*1024) // 2GB each file FileLogger(level, filepath, 2*1024*1024*1024, 10) // 2GB each file and 10 files
func ToLogger ¶ added in v0.3.0
func ToLogger(logger LoggerWithoutError) Logger
ToLogger converts the LoggerWithoutError to Logger.
Notice: LoggerWithoutError must be the built-in implementation returned by ToLoggerWithoutError.
func WithCtx ¶
func WithCtx(ctxs ...interface{}) Logger
WithCtx returns a new logger with the contexts.
In order to keep consistent with WithLevel and WithEncoder, we use WithCtx, not Ctx.
func WithEncoder ¶
WithEncoder returns a new logger with the encoder.
Since Encoder is the encoder type, we use WithEncoder as the function name.
type LoggerWithoutError ¶ added in v0.3.0
type LoggerWithoutError interface { Depth(stackDepth int) LoggerWithoutError Level(level Level) LoggerWithoutError Encoder(encoder Encoder) LoggerWithoutError Cxt(ctxs ...interface{}) LoggerWithoutError // Writer is the convenient function of GetEncoder().Writer(). Writer() io.Writer GetDepth() int GetLevel() Level GetEncoder() Encoder Trace(msg string, args ...interface{}) Debug(msg string, args ...interface{}) Info(msg string, args ...interface{}) Warn(msg string, args ...interface{}) Error(msg string, args ...interface{}) Panic(msg string, args ...interface{}) Fatal(msg string, args ...interface{}) }
LoggerWithoutError is equal to Logger, but not returning the error.
func ToLoggerWithoutError ¶ added in v0.3.0
func ToLoggerWithoutError(logger ...Logger) LoggerWithoutError
ToLoggerWithoutError converts the Logger to LoggerWithoutError.
If logger is missing, it will use the global logger by default.
type MarshalText ¶
MarshalText is an interface to marshal a value to text.
type MultiError ¶
type MultiError struct {
// contains filtered or unexported fields
}
MultiError represents more than one error.
func (MultiError) Error ¶
func (m MultiError) Error() string
type StringWriter ¶
StringWriter is a WriteString interface.
type Valuer ¶
A Valuer generates a log value, which represents a dynamic value that is re-evaluated with each log event before firing it.
func Caller ¶
Caller returns a Valuer that returns a file and line from a specified depth in the callstack.
If fullPath is true, it will return the full path of the file.
Example ¶
logger := New(KvTextEncoder(os.Stdout)).Cxt("caller1", Caller()) logger.Info("msg", "caller2", Caller())
Output: caller1=value_test.go:23 caller2=value_test.go:23 msg=msg
type Writer ¶ added in v1.0.0
Writer is equal to io.Writer.
We do it in order to collect the writers to show together in godoc.
func BufferedWriter ¶
BufferedWriter writes all records to a buffered channel of the given size which flushes into the wrapped handler whenever it is available for writing.
Since these writes happen asynchronously, all writes to a BufferedWriter never return an error and any errors from the wrapped writer are ignored.
func ChannelWriter ¶
ChannelWriter writes all logs to the given channel.
It blocks if the channel is full. Useful for async processing of log messages, it's used by BufferedWriter.
func DiscardWriter ¶
func DiscardWriter() Writer
DiscardWriter returns a writer which will discard all input.
func FailoverWriter ¶
FailoverWriter writes all log records to the first handler specified, but will failover and write to the second handler if the first handler has failed, and so on for all handlers specified.
For example, you might want to log to a network socket, but failover to writing to a file if the network fails, and then to standard out if the file write fails.
func FileWriter ¶
FileWriter returns a writer which writes log records to the give file.
If the path already exists, FileHook will append to the given file. If it does not, FileHook will create the file with mode 0644, but you can pass the second argument, mode, to modify it.
func GetWriter ¶ added in v1.0.0
func GetWriter() Writer
GetWriter returns the underlying writer of the global logger.
func MultiWriter ¶
MultiWriter writes one data to more than one destination.
func NetWriter ¶
NetWriter opens a socket to the given address and writes the log over the connection.
func ReopenWriter ¶
ReopenWriter returns a writer that can be closed then re-opened, which is used for logrotate typically.
Notice: it used SafeWriter to wrap the writer, so it's thread-safe.
func SafeWriter ¶
SafeWriter is guaranteed that only a single writing operation can proceed at a time.
It's necessary for thread-safe concurrent writes.