Documentation
¶
Overview ¶
Package log provides structured logging with fine grained control over libraries using a tree hierarchy of loggers.
Conventions ¶
1. no direct use of the log package, MUST create new logger.
2. library/application MUST have a library/application logger as their registry.
3. every package MUST have a package level logger as child of the registry, normally defined in pkg.go
4. logger is a registry and can contain children.
5. instance of struct should have their own logger as children of package logger
Index ¶
- Constants
- Variables
- func DisableSourceRecursive(root *Logger)
- func EnableSourceRecursive(root *Logger)
- func PreOrderDFS(root *Logger, visited map[*Logger]bool, cb func(l *Logger))
- func SetHandlerRecursive(root *Logger, handler Handler)
- func SetLevelRecursive(root *Logger, level Level)
- func ToStringTree(root *Logger) *structure.StringTreeNode
- type Field
- type FieldType
- type Fields
- type Handler
- type IOHandler
- func (h *IOHandler) Flush()
- func (h *IOHandler) HandleLog(level Level, time time.Time, msg string)
- func (h *IOHandler) HandleLogWithFields(level Level, time time.Time, msg string, fields Fields)
- func (h *IOHandler) HandleLogWithSource(level Level, time time.Time, msg string, source string)
- func (h *IOHandler) HandleLogWithSourceFields(level Level, time time.Time, msg string, source string, fields Fields)
- type Identity
- type Level
- type LoggableStruct
- type Logger
- func NewApplicationLogger() *Logger
- func NewFunctionLogger(packageLogger *Logger) *Logger
- func NewLibraryLogger() *Logger
- func NewMethodLogger(structLogger *Logger) *Logger
- func NewPackageLogger() *Logger
- func NewPackageLoggerWithSkip(skip int) *Logger
- func NewStructLogger(packageLogger *Logger, loggable LoggableStruct) *Logger
- func (l *Logger) AddChild(child *Logger)
- func (l *Logger) Debug(args ...interface{})
- func (l *Logger) DebugF(msg string, fields Fields)
- func (l *Logger) Debugf(format string, args ...interface{})
- func (l *Logger) DisableSource()
- func (l *Logger) EnableSource()
- func (l *Logger) Error(args ...interface{})
- func (l *Logger) ErrorF(msg string, fields Fields)
- func (l *Logger) Errorf(format string, args ...interface{})
- func (l *Logger) Fatal(args ...interface{})
- func (l *Logger) FatalF(msg string, fields Fields)
- func (l *Logger) Fatalf(format string, args ...interface{})
- func (l *Logger) Identity() *Identity
- func (l *Logger) Info(args ...interface{})
- func (l *Logger) InfoF(msg string, fields Fields)
- func (l *Logger) Infof(format string, args ...interface{})
- func (l *Logger) IsDebugEnabled() bool
- func (l *Logger) IsErrorEnabled() bool
- func (l *Logger) IsInfoEnabled() bool
- func (l *Logger) IsTraceEnabled() bool
- func (l *Logger) IsWarnEnabled() bool
- func (l *Logger) Level() Level
- func (l *Logger) Panic(args ...interface{})
- func (l *Logger) PanicF(msg string, fields Fields)
- func (l *Logger) Panicf(format string, args ...interface{})
- func (l *Logger) PrintTree()
- func (l *Logger) PrintTreeTo(w io.Writer)
- func (l *Logger) SetHandler(h Handler)
- func (l *Logger) SetLevel(level Level)
- func (l *Logger) Trace(args ...interface{})
- func (l *Logger) TraceF(msg string, fields Fields)
- func (l *Logger) Tracef(format string, args ...interface{})
- func (l *Logger) Warn(args ...interface{})
- func (l *Logger) WarnF(msg string, fields Fields)
- func (l *Logger) Warnf(format string, args ...interface{})
- type LoggerType
- type Syncer
- type TestHandler
- func (h *TestHandler) Flush()
- func (h *TestHandler) HandleLog(level Level, time time.Time, msg string)
- func (h *TestHandler) HandleLogWithFields(level Level, time time.Time, msg string, fields Fields)
- func (h *TestHandler) HandleLogWithSource(level Level, time time.Time, msg string, source string)
- func (h *TestHandler) HandleLogWithSourceFields(level Level, time time.Time, msg string, source string, fields Fields)
- func (h *TestHandler) HasLog(level Level, msg string) bool
Examples ¶
Constants ¶
const MagicPackageLoggerFunctionName = "init"
const MagicStructLoggerFunctionName = "LoggerIdentity"
Variables ¶
var UnknownIdentity = Identity{Package: "unk", Type: UnknownLogger}
Functions ¶
func DisableSourceRecursive ¶ added in v0.0.4
func DisableSourceRecursive(root *Logger)
func EnableSourceRecursive ¶ added in v0.0.5
func EnableSourceRecursive(root *Logger)
FIXME: this fixed typo requires update in go.ice
func PreOrderDFS ¶
TODO: test it .... map traverse order is random, we need radix tree, it is need for pretty print as well
func SetHandlerRecursive ¶
func SetLevelRecursive ¶
func ToStringTree ¶
func ToStringTree(root *Logger) *structure.StringTreeNode
Types ¶
type Field ¶
Field is based on uber-go/zap https://github.com/uber-go/zap/blob/master/zapcore/field.go It can be treated as a Union, the value is stored in either Int, Str or Interface
type Handler ¶
type Handler interface {
// HandleLog accepts level, log time, formatted log message
HandleLog(level Level, time time.Time, msg string)
// HandleLogWithSource accepts formatted source line of log i.e., http.go:13
// TODO: pass frame instead of string so handler can use trace for error handling?
HandleLogWithSource(level Level, time time.Time, msg string, source string)
// HandleLogWithFields accepts fields with type hint,
// implementation should inspect the type field instead of using reflection
// TODO: pass pointer for fields?
HandleLogWithFields(level Level, time time.Time, msg string, fields Fields)
// HandleLogWithSourceFields accepts both source and fields
HandleLogWithSourceFields(level Level, time time.Time, msg string, source string, fields Fields)
// Flush writes the buffer to underlying storage
Flush()
}
Handler formats log message and writes to underlying storage, stdout, file, remote server etc. It MUST be thread safe because logger calls handler concurrently without any locking. There is NO log entry struct in gommon/log, which is used in many logging packages, the reason is if extra field is added to the interface, compiler would throw error on stale handler implementations.
func DefaultHandler ¶
func DefaultHandler() Handler
DefaultHandler returns the singleton defaultHandler instance, which logs to stdout in text format
type IOHandler ¶ added in v0.0.5
type IOHandler struct {
// contains filtered or unexported fields
}
IOHandler writes log to io.Writer, default handler uses os.Stderr
func (*IOHandler) Flush ¶ added in v0.0.5
func (h *IOHandler) Flush()
Flush implements Handler interface
func (*IOHandler) HandleLogWithFields ¶ added in v0.0.5
HandleLogWithFields implements Handler interface
func (*IOHandler) HandleLogWithSource ¶ added in v0.0.5
HandleLogWithSource implements Handler interface
type Identity ¶
type Identity struct {
Package string
Function string
Struct string
File string
Line int
Type LoggerType
}
Identity is set based on logger's initialization location, it is close to, but NOT exactly same as location of actual log. It is used for applying filter rules and print logger hierarchy.
func NewIdentityFromCaller ¶
TODO: document all the black magic here ... https://github.com/dyweb/gommon/issues/32
func (*Identity) Diff ¶
TODO: this is used for print tree like structure ... it's hard to maintain exact parent and child logger due to cycle import
func (*Identity) SourceLocation ¶
type Level ¶
type Level uint8
Level is log level TODO: allow change default logging level at compile time
Example ¶
fmt.Println(FatalLevel.String()) fmt.Println(FatalLevel.AlignedUpperString())
Output: fatal FATA
const ( // FatalLevel log error and call `os.Exit(1)` // TODO: allow user to add hooks before calling os.Exit? FatalLevel Level = iota // PanicLevel log error and call `panic` PanicLevel // ErrorLevel log error and do nothing // TODO: add integration with errors package ErrorLevel // WarnLevel log warning that is often ignored WarnLevel // InfoLevel log info InfoLevel // DebugLevel log debug message, user should enable DebugLevel logging when report bug DebugLevel // TraceLevel is very verbose, user should enable it only on packages they are currently investing instead of globally // TODO: add compile flag to use empty trace logger implementation to eliminate the call at runtime TraceLevel )
func (Level) AlignedUpperString ¶ added in v0.0.5
AlignedUpperString returns fixed length level string in uppercase
func (Level) ColoredAlignedUpperString ¶ added in v0.0.4
ColoredAlignedUpperString returns fixed length level string in uppercase, wrapped by terminal color characters, only works on *nix
func (Level) ColoredString ¶ added in v0.0.3
ColoredString returns level string wrapped by terminal color characters, only works on *nix
type LoggableStruct ¶
type LoggableStruct interface {
GetLogger() *Logger
SetLogger(logger *Logger)
LoggerIdentity(justCallMe func() *Identity) *Identity
}
LoggableStruct is used to inject a logger into the struct, the methods for the interface can and should be generated using gommon.
In struct initializer call dlog.NewStruct(pkgLogger, structInstancePointer)
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger is a concrete type instead of interface because most logic is in handler. There is NO lock when calling logging methods, handlers may have locks. Lock is used when updating logger attributes like Level.
For Printf style logging (Levelf), Logger formats string using fmt.Sprintf before passing it to handlers.
logger.Debugf("id is %d", id)
For structual logging (LevelF), Logger passes fields to handlers without any processing.
logger.DebugF("hi", log.Fields{log.Str("foo", "bar")})
If you want to mix two styles, call fmt.Sprintf before calling DebugF,
logger.DebugF(fmt.Sprintf("id is %d", id), log.Fields{log.Str("foo", "bar")})
func NewApplicationLogger ¶
func NewApplicationLogger() *Logger
Example ¶
logger := NewApplicationLogger() fmt.Println(logger.Identity().Package) fmt.Println(logger.Identity().Type)
Output: github.com/dyweb/gommon/log app
func NewFunctionLogger ¶
func NewLibraryLogger ¶
func NewLibraryLogger() *Logger
func NewMethodLogger ¶
func NewPackageLogger ¶
func NewPackageLogger() *Logger
func NewStructLogger ¶
func NewStructLogger(packageLogger *Logger, loggable LoggableStruct) *Logger
func (*Logger) AddChild ¶
TODO: allow release a child logger, this will be a trouble if we created 1,000 Client struct with its own logger...
func (*Logger) DisableSource ¶ added in v0.0.3
func (l *Logger) DisableSource()
func (*Logger) EnableSource ¶ added in v0.0.3
func (l *Logger) EnableSource()
func (*Logger) Fatal ¶
func (l *Logger) Fatal(args ...interface{})
Fatal calls os.Exit(1) after it writes and flushes the log
func (*Logger) FatalF ¶ added in v0.0.3
FatalF duplicates instead of calling Fatal to keep source line correct
func (*Logger) Identity ¶
Identity returns the identity set when the logger is created. NOTE: caller can modify the identity because all fields are public, but they should NOT do this
func (*Logger) IsDebugEnabled ¶
func (*Logger) IsErrorEnabled ¶
func (*Logger) IsInfoEnabled ¶
func (*Logger) IsTraceEnabled ¶
func (*Logger) IsWarnEnabled ¶
func (*Logger) Panic ¶
func (l *Logger) Panic(args ...interface{})
Panic calls panic after it writes and flushes the log
func (*Logger) PanicF ¶ added in v0.0.3
PanicF duplicates instead of calling Panic to keep source line correct
func (*Logger) PrintTreeTo ¶
PrintTreeTo prints logger as a tree, using current logger as root
func (*Logger) SetHandler ¶
type LoggerType ¶
type LoggerType uint8
LoggerType can be used for filtering loggers, it is set when creating logger
const ( UnknownLogger LoggerType = iota ApplicationLogger LibraryLogger PackageLogger FunctionLogger StructLogger MethodLogger )
func (LoggerType) String ¶
func (tpe LoggerType) String() string
type Syncer ¶ added in v0.0.3
type Syncer interface {
Sync() error
}
Syncer is implemented by os.File, handler implementation should check this interface and call Sync if they support using file as sink
type TestHandler ¶ added in v0.0.5
type TestHandler struct {
// contains filtered or unexported fields
}
TestHandler stores log as entry, its slice is protected by a RWMutex and safe for concurrent use
func NewTestHandler ¶
func NewTestHandler() *TestHandler
NewTestHandler returns a test handler, it should only be used in test, a concrete type instead of Handler interface is returned to reduce unnecessary type cast in test
func (*TestHandler) Flush ¶ added in v0.0.5
func (h *TestHandler) Flush()
Flush implements Handler interface
func (*TestHandler) HandleLog ¶ added in v0.0.5
func (h *TestHandler) HandleLog(level Level, time time.Time, msg string)
HandleLog implements Handler interface
func (*TestHandler) HandleLogWithFields ¶ added in v0.0.5
HandleLogWithFields implements Handler interface
func (*TestHandler) HandleLogWithSource ¶ added in v0.0.5
HandleLogWithSource implements Handler interface
func (*TestHandler) HandleLogWithSourceFields ¶ added in v0.0.5
func (h *TestHandler) HandleLogWithSourceFields(level Level, time time.Time, msg string, source string, fields Fields)
HandleLogWithSourceFields implements Handler interface
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
_examples
|
|
|
simple
command
|
|
|
uselib
command
|
|
|
handlers
|
|
|
cli
Package cli writes is same as builtin IOHandler except color and delta time.
|
Package cli writes is same as builtin IOHandler except color and delta time. |
|
json
Package json writes log in JSON format, it concatenates string directly and does not use encoding/json.
|
Package json writes log in JSON format, it concatenates string directly and does not use encoding/json. |