Documentation ¶
Overview ¶
Package xlog is a logger coupled with HTTP net/context aware middleware.
Unlike most loggers, xlog will never block your application because one its outputs is lagging. The log commands are connected to their outputs through a buffered channel and will prefer to discard messages if the buffer get full. All message formatting, serialization and transport happen in a dedicated go routine.
Features:
- Per request log context
- Per request and/or per message key/value fields
- Log levels (Debug, Info, Warn, Error)
- Color output when terminal is detected
- Custom output (JSON, logfmt, …)
- Automatic gathering of request context like User-Agent, IP etc.
- Drops message rather than blocking execution
- Easy access logging thru github.com/rs/xaccess
It works best in combination with github.com/rs/xhandler.
Example (CombinedOutputs) ¶
package main import ( "github.com/rs/xlog" ) func main() { conf := xlog.Config{ Output: xlog.NewOutputChannel(xlog.MultiOutput{ // Output interesting messages to console 0: xlog.FilterOutput{ Cond: func(fields map[string]interface{}) bool { val, found := fields["type"] return found && val == "interesting" }, Output: xlog.NewConsoleOutput(), }, // Also setup by-level loggers 1: xlog.LevelOutput{ // Send debug messages to console if they match type Debug: xlog.FilterOutput{ Cond: func(fields map[string]interface{}) bool { val, found := fields["type"] return found && val == "interesting" }, Output: xlog.NewConsoleOutput(), }, }, // Also send everything over syslog 2: xlog.NewSyslogOutput("", "", ""), }), } lh := xlog.NewHandler(conf) _ = lh }
Output:
Example (Handler) ¶
package main import ( "errors" "log" "net/http" "os" "github.com/justinas/alice" "github.com/rs/xlog" ) func main() { c := alice.New() host, _ := os.Hostname() conf := xlog.Config{ // Set some global env fields Fields: xlog.F{ "role": "my-service", "host": host, }, } // Install the logger handler with default output on the console c = c.Append(xlog.NewHandler(conf)) // Plug the xlog handler's input to Go's default logger log.SetFlags(0) log.SetOutput(xlog.New(conf)) // Install some provided extra handler to set some request's context fields. // Thanks to those handler, all our logs will come with some pre-populated fields. c = c.Append(xlog.RemoteAddrHandler("ip")) c = c.Append(xlog.UserAgentHandler("user_agent")) c = c.Append(xlog.RefererHandler("referer")) c = c.Append(xlog.RequestIDHandler("req_id", "Request-Id")) // Here is your final handler h := c.Then(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Get the logger from the request's context. You can safely assume it // will be always there: if the handler is removed, xlog.FromContext // will return a NopLogger l := xlog.FromRequest(r) // Then log some errors if err := errors.New("some error from elsewhere"); err != nil { l.Errorf("Here is an error: %v", err) } // Or some info with fields l.Info("Something happend", xlog.F{ "user": "current user id", "status": "ok", }) })) http.Handle("/", h) if err := http.ListenAndServe(":8080", nil); err != nil { log.SetOutput(os.Stderr) // make sure we print to console log.Fatal(err) } }
Output:
Example (Log) ¶
package main import ( "context" "errors" "github.com/rs/xlog" ) func main() { ctx := context.TODO() l := xlog.FromContext(ctx) // Log a simple message l.Debug("message") if err := errors.New("some error"); err != nil { l.Errorf("Some error happened: %v", err) } // With optional fields l.Debugf("foo %s", "bar", xlog.F{ "field": "value", }) }
Output:
Example (Stdlog) ¶
package main import ( "log" "github.com/rs/xlog" ) func main() { // Define logger conf conf := xlog.Config{ Output: xlog.NewConsoleOutput(), } // Remove timestamp and other decorations of the std logger log.SetFlags(0) // Plug a xlog instance to Go's std logger log.SetOutput(xlog.New(conf)) }
Output:
Index ¶
- Variables
- func Debug(v ...interface{})
- func Debugf(format string, v ...interface{})
- func Error(v ...interface{})
- func Errorf(format string, v ...interface{})
- func Fatal(v ...interface{})
- func Fatalf(format string, v ...interface{})
- func IDFromContext(ctx context.Context) (xid.ID, bool)
- func IDFromRequest(r *http.Request) (xid.ID, bool)
- func Info(v ...interface{})
- func Infof(format string, v ...interface{})
- func MethodHandler(name string) func(next http.Handler) http.Handler
- func NewContext(ctx context.Context, l Logger) context.Context
- func NewHandler(c Config) func(http.Handler) http.Handler
- func NewSyslogWriter(network, address string, prio syslog.Priority, tag string) io.Writer
- func RefererHandler(name string) func(next http.Handler) http.Handler
- func RemoteAddrHandler(name string) func(next http.Handler) http.Handler
- func RequestHandler(name string) func(next http.Handler) http.Handler
- func RequestIDHandler(name, headerName string) func(next http.Handler) http.Handler
- func SetLogger(logger Logger)
- func URLHandler(name string) func(next http.Handler) http.Handler
- func UserAgentHandler(name string) func(next http.Handler) http.Handler
- func Warn(v ...interface{})
- func Warnf(format string, v ...interface{})
- type Config
- type F
- type FilterOutput
- type Level
- type LevelOutput
- type Logger
- type LoggerCopier
- type MultiOutput
- type Output
- func NewConsoleOutput() Output
- func NewConsoleOutputW(w io.Writer, noTerm Output) Output
- func NewJSONOutput(w io.Writer) Output
- func NewLogfmtOutput(w io.Writer) Output
- func NewLogstashOutput(w io.Writer) Output
- func NewSyslogOutput(network, address, tag string) Output
- func NewSyslogOutputFacility(network, address, tag string, facility syslog.Priority) Output
- func NewTrimFieldsOutput(trimFields []string, maxLen int, o Output) Output
- func NewTrimOutput(maxLen int, o Output) Output
- func NewUIDOutput(field string, o Output) Output
- type OutputChannel
- type OutputFunc
- type RecorderOutput
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( KeyTime = "time" KeyMessage = "message" KeyLevel = "level" KeyFile = "file" )
Common field names for log messages.
var Discard = OutputFunc(func(fields map[string]interface{}) error { return nil })
Discard is an Output that discards all log message going thru it.
var ErrBufferFull = errors.New("buffer full")
ErrBufferFull is returned when the output channel buffer is full and messages are discarded.
var NopLogger = &nop{}
NopLogger is an no-op implementation of xlog.Logger
Functions ¶
func Debugf ¶
func Debugf(format string, v ...interface{})
Debugf calls the Debugf() method on the default logger
func Errorf ¶
func Errorf(format string, v ...interface{})
Errorf calls the Errorf() method on the default logger
Go vet users: you may append %v at the end of you format when using xlog.F{} as a last argument to workaround go vet false alarm.
func Fatalf ¶
func Fatalf(format string, v ...interface{})
Fatalf calls the Fatalf() method on the default logger
Go vet users: you may append %v at the end of you format when using xlog.F{} as a last argument to workaround go vet false alarm.
func IDFromContext ¶
IDFromContext returns the unique id associated to the request if any.
func IDFromRequest ¶
IDFromRequest returns the unique id accociated to the request if any.
func Infof ¶
func Infof(format string, v ...interface{})
Infof calls the Infof() method on the default logger
func MethodHandler ¶
MethodHandler returns a handler setting the request's method as a field to the current context's logger using the passed name as field name.
func NewContext ¶
NewContext returns a copy of the parent context and associates it with the provided logger.
func NewHandler ¶
NewHandler instanciates a new xlog HTTP handler.
If not configured, the output is set to NewConsoleOutput() by default.
func NewSyslogWriter ¶
NewSyslogWriter returns a writer ready to be used with output modules. If network and address are empty, Dial will connect to the local syslog server.
Example ¶
package main import ( "log/syslog" "github.com/rs/xlog" ) func main() { conf := xlog.Config{ Output: xlog.NewOutputChannel(xlog.LevelOutput{ Debug: xlog.NewLogstashOutput(xlog.NewSyslogWriter("", "", syslog.LOG_LOCAL0|syslog.LOG_DEBUG, "")), Info: xlog.NewLogstashOutput(xlog.NewSyslogWriter("", "", syslog.LOG_LOCAL0|syslog.LOG_INFO, "")), Warn: xlog.NewLogstashOutput(xlog.NewSyslogWriter("", "", syslog.LOG_LOCAL0|syslog.LOG_WARNING, "")), Error: xlog.NewLogstashOutput(xlog.NewSyslogWriter("", "", syslog.LOG_LOCAL0|syslog.LOG_ERR, "")), }), } lh := xlog.NewHandler(conf) _ = lh }
Output:
func RefererHandler ¶
RefererHandler returns a handler setting the request's referer header as a field to the current context's logger using the passed name as field name.
func RemoteAddrHandler ¶
RemoteAddrHandler returns a handler setting the request's remote address as a field to the current context's logger using the passed name as field name.
func RequestHandler ¶
RequestHandler returns a handler setting the request's method and URL as a field to the current context's logger using the passed name as field name.
func RequestIDHandler ¶
RequestIDHandler returns a handler setting a unique id to the request which can be gathered using IDFromContext(ctx). This generated id is added as a field to the logger using the passed name as field name. The id is also added as a response header if the headerName is not empty.
The generated id is a URL safe base64 encoded mongo object-id-like unique id. Mongo unique id generation algorithm has been selected as a trade-off between size and ease of use: UUID is less space efficient and snowflake requires machine configuration.
func SetLogger ¶
func SetLogger(logger Logger)
SetLogger changes the global logger instance
Example ¶
package main import ( "github.com/rs/xlog" ) func main() { xlog.SetLogger(xlog.New(xlog.Config{ Level: xlog.LevelInfo, Output: xlog.NewConsoleOutput(), Fields: xlog.F{ "role": "my-service", }, })) }
Output:
func URLHandler ¶
URLHandler returns a handler setting the request's URL as a field to the current context's logger using the passed name as field name.
func UserAgentHandler ¶
UserAgentHandler returns a handler setting the request's client's user-agent as a field to the current context's logger using the passed name as field name.
Types ¶
type Config ¶
type Config struct { // Level is the maximum level to output, logs with lower level are discarded. Level Level // Fields defines default fields to use with all messages. Fields map[string]interface{} // Output to use to write log messages to. // // You should always wrap your output with an OutputChannel otherwise your // logger will be connected to its output synchronously. Output Output // DisablePooling removes the use of a sync.Pool for cases where logger // instances are needed beyond the scope of a request handler. This option // puts a greater pressure on GC and increases the amount of memory allocated // and freed. Use only if persistent loggers are a requirement. DisablePooling bool }
Config defines logger's configuration
type FilterOutput ¶
FilterOutput test a condition on the message and forward it to the child output if it returns true.
Example ¶
package main import ( "github.com/rs/xlog" ) func main() { conf := xlog.Config{ Output: xlog.NewOutputChannel(xlog.FilterOutput{ // Match messages containing a field type = interesting Cond: func(fields map[string]interface{}) bool { val, found := fields["type"] return found && val == "interesting" }, // Output matching messages to the console Output: xlog.NewConsoleOutput(), }), } lh := xlog.NewHandler(conf) _ = lh }
Output:
func (FilterOutput) Write ¶
func (f FilterOutput) Write(fields map[string]interface{}) (err error)
type Level ¶
type Level int
Level defines log levels
func LevelFromString ¶
LevelFromString returns the level based on its string representation
func (Level) MarshalText ¶
MarshalText lets Level implements the TextMarshaler interface used by encoding packages
func (*Level) UnmarshalText ¶
UnmarshalText lets Level implements the TextUnmarshaler interface used by encoding packages
type LevelOutput ¶
LevelOutput routes messages to different output based on the message's level.
Example ¶
package main import ( "github.com/rs/xlog" ) func main() { conf := xlog.Config{ Output: xlog.NewOutputChannel(xlog.LevelOutput{ // Send debug message to console Debug: xlog.NewConsoleOutput(), // and error messages to syslog Error: xlog.NewSyslogOutput("", "", ""), // other levels are discarded }), } lh := xlog.NewHandler(conf) _ = lh }
Output:
func (LevelOutput) Write ¶
func (l LevelOutput) Write(fields map[string]interface{}) error
type Logger ¶
type Logger interface { // Implements io.Writer so it can be set a output of log.Logger io.Writer // SetField sets a field on the logger's context. All future messages on this logger // will have this field set. SetField(name string, value interface{}) // GetFields returns all the fields set on the logger GetFields() F // Debug logs a debug message. If last parameter is a map[string]string, it's content // is added as fields to the message. Debug(v ...interface{}) // Debug logs a debug message with format. If last parameter is a map[string]string, // it's content is added as fields to the message. Debugf(format string, v ...interface{}) // Info logs a info message. If last parameter is a map[string]string, it's content // is added as fields to the message. Info(v ...interface{}) // Info logs a info message with format. If last parameter is a map[string]string, // it's content is added as fields to the message. Infof(format string, v ...interface{}) // Warn logs a warning message. If last parameter is a map[string]string, it's content // is added as fields to the message. Warn(v ...interface{}) // Warn logs a warning message with format. If last parameter is a map[string]string, // it's content is added as fields to the message. Warnf(format string, v ...interface{}) // Error logs an error message. If last parameter is a map[string]string, it's content // is added as fields to the message. Error(v ...interface{}) // Error logs an error message with format. If last parameter is a map[string]string, // it's content is added as fields to the message. Errorf(format string, v ...interface{}) // Fatal logs an error message followed by a call to os.Exit(1). If last parameter is a // map[string]string, it's content is added as fields to the message. Fatal(v ...interface{}) // Fatalf logs an error message with format followed by a call to ox.Exit(1). If last // parameter is a map[string]string, it's content is added as fields to the message. Fatalf(format string, v ...interface{}) // Output mimics std logger interface Output(calldepth int, s string) error // OutputF outputs message with fields. OutputF(level Level, calldepth int, msg string, fields map[string]interface{}) }
Logger defines the interface for a xlog compatible logger
func Copy ¶
Copy returns a copy of the passed logger if the logger implements LoggerCopier or the NopLogger otherwise.
func FromContext ¶
FromContext gets the logger out of the context. If not logger is stored in the context, a NopLogger is returned.
func FromRequest ¶
FromRequest gets the logger in the request's context. This is a shortcut for xlog.FromContext(r.Context())
type LoggerCopier ¶
type LoggerCopier interface { // Copy returns a copy of the logger Copy() Logger }
LoggerCopier defines a logger with copy support
type MultiOutput ¶
type MultiOutput []Output
MultiOutput routes the same message to serveral outputs. If one or more outputs return an error, the last error is returned.
Example ¶
package main import ( "github.com/rs/xlog" ) func main() { conf := xlog.Config{ Output: xlog.NewOutputChannel(xlog.MultiOutput{ // Output everything to console 0: xlog.NewConsoleOutput(), // and also to local syslog 1: xlog.NewSyslogOutput("", "", ""), }), } lh := xlog.NewHandler(conf) _ = lh }
Output:
func (MultiOutput) Write ¶
func (m MultiOutput) Write(fields map[string]interface{}) (err error)
type Output ¶
Output sends a log message fields to a destination.
func NewConsoleOutput ¶
func NewConsoleOutput() Output
NewConsoleOutput returns a Output printing message in a colored human readable form on the stderr. If the stderr is not on a terminal, a LogfmtOutput is returned instead.
func NewConsoleOutputW ¶
NewConsoleOutputW returns a Output printing message in a colored human readable form with the provided writer. If the writer is not on a terminal, the noTerm output is returned.
func NewJSONOutput ¶
NewJSONOutput returns a new JSON output with the given writer.
func NewLogfmtOutput ¶
NewLogfmtOutput returns a new output using logstash JSON schema v1
func NewLogstashOutput ¶
NewLogstashOutput returns an output to generate logstash friendly JSON format.
func NewSyslogOutput ¶
NewSyslogOutput returns JSONOutputs in a LevelOutput with writers set to syslog with the proper priority added to a LOG_USER facility. If network and address are empty, Dial will connect to the local syslog server.
func NewSyslogOutputFacility ¶
NewSyslogOutputFacility returns JSONOutputs in a LevelOutput with writers set to syslog with the proper priority added to the passed facility. If network and address are empty, Dial will connect to the local syslog server.
func NewTrimFieldsOutput ¶
NewTrimFieldsOutput trims listed field fields of type string with a value length greater than maxLen to maxLen.
func NewTrimOutput ¶
NewTrimOutput trims any field of type string with a value length greater than maxLen to maxLen.
func NewUIDOutput ¶
NewUIDOutput returns an output filter adding a globally unique id (using github.com/rs/xid) to all message going thru this output. The o parameter defines the next output to pass data to.
type OutputChannel ¶
type OutputChannel struct {
// contains filtered or unexported fields
}
OutputChannel is a send buffered channel between xlog and an Output.
func NewOutputChannel ¶
func NewOutputChannel(o Output) *OutputChannel
NewOutputChannel creates a consumer buffered channel for the given output with a default buffer of 100 messages.
func NewOutputChannelBuffer ¶
func NewOutputChannelBuffer(o Output, bufSize int) *OutputChannel
NewOutputChannelBuffer creates a consumer buffered channel for the given output with a customizable buffer size.
func (*OutputChannel) Close ¶
func (oc *OutputChannel) Close()
Close closes the output channel and release the consumer's go routine.
func (*OutputChannel) Flush ¶
func (oc *OutputChannel) Flush()
Flush flushes all the buffered message to the output
func (*OutputChannel) Write ¶
func (oc *OutputChannel) Write(fields map[string]interface{}) (err error)
Write implements the Output interface
type OutputFunc ¶
OutputFunc is an adapter to allow the use of ordinary functions as Output handlers. If it is a function with the appropriate signature, OutputFunc(f) is a Output object that calls f on Write().
func (OutputFunc) Write ¶
func (of OutputFunc) Write(fields map[string]interface{}) error
type RecorderOutput ¶
type RecorderOutput struct {
Messages []F
}
RecorderOutput stores the raw messages in it's Messages field. This output is useful for testing.
func (*RecorderOutput) Reset ¶
func (l *RecorderOutput) Reset()
Reset empty the output from stored messages
func (*RecorderOutput) Write ¶
func (l *RecorderOutput) Write(fields map[string]interface{}) error