xlog: github.com/rs/xlog Index | Examples | Files | Directories

package xlog

import "github.com/rs/xlog"

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.

Code:

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

Code:

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)
}

Code:

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",
})

Code:

// 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))

Index

Examples

Package Files

handler.go levels.go nop.go output.go output_syslog.go std.go util.go xlog.go

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

func Debug Uses

func Debug(v ...interface{})

Debug calls the Debug() method on the default logger

func Debugf Uses

func Debugf(format string, v ...interface{})

Debugf calls the Debugf() method on the default logger

func Error Uses

func Error(v ...interface{})

Error calls the Error() method on the default logger

func Errorf Uses

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 Fatal Uses

func Fatal(v ...interface{})

Fatal calls the Fatal() method on the default logger

func Fatalf Uses

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 Uses

func IDFromContext(ctx context.Context) (xid.ID, bool)

IDFromContext returns the unique id associated to the request if any.

func IDFromRequest Uses

func IDFromRequest(r *http.Request) (xid.ID, bool)

IDFromRequest returns the unique id accociated to the request if any.

func Info Uses

func Info(v ...interface{})

Info calls the Info() method on the default logger

func Infof Uses

func Infof(format string, v ...interface{})

Infof calls the Infof() method on the default logger

func MethodHandler Uses

func MethodHandler(name string) func(next http.Handler) http.Handler

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 Uses

func NewContext(ctx context.Context, l Logger) context.Context

NewContext returns a copy of the parent context and associates it with the provided logger.

func NewHandler Uses

func NewHandler(c Config) func(http.Handler) http.Handler

NewHandler instanciates a new xlog HTTP handler.

If not configured, the output is set to NewConsoleOutput() by default.

func NewSyslogWriter Uses

func NewSyslogWriter(network, address string, prio syslog.Priority, tag string) io.Writer

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.

Code:

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

func RefererHandler Uses

func RefererHandler(name string) func(next http.Handler) http.Handler

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 Uses

func RemoteAddrHandler(name string) func(next http.Handler) http.Handler

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 Uses

func RequestHandler(name string) func(next http.Handler) http.Handler

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 Uses

func RequestIDHandler(name, headerName string) func(next http.Handler) http.Handler

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 Uses

func SetLogger(logger Logger)

SetLogger changes the global logger instance

Code:

xlog.SetLogger(xlog.New(xlog.Config{
    Level:  xlog.LevelInfo,
    Output: xlog.NewConsoleOutput(),
    Fields: xlog.F{
        "role": "my-service",
    },
}))

func URLHandler Uses

func URLHandler(name string) func(next http.Handler) http.Handler

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 Uses

func UserAgentHandler(name string) func(next http.Handler) http.Handler

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.

func Warn Uses

func Warn(v ...interface{})

Warn calls the Warn() method on the default logger

func Warnf Uses

func Warnf(format string, v ...interface{})

Warnf calls the Warnf() method on the default logger

type Config Uses

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 F Uses

type F map[string]interface{}

F represents a set of log message fields

type FilterOutput Uses

type FilterOutput struct {
    Cond   func(fields map[string]interface{}) bool
    Output Output
}

FilterOutput test a condition on the message and forward it to the child output if it returns true.

Code:

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

func (FilterOutput) Write Uses

func (f FilterOutput) Write(fields map[string]interface{}) (err error)

type Level Uses

type Level int

Level defines log levels

const (
    LevelDebug Level = iota
    LevelInfo
    LevelWarn
    LevelError
    LevelFatal
)

Log levels

func LevelFromString Uses

func LevelFromString(t string) (Level, error)

LevelFromString returns the level based on its string representation

func (Level) MarshalText Uses

func (l Level) MarshalText() ([]byte, error)

MarshalText lets Level implements the TextMarshaler interface used by encoding packages

func (Level) String Uses

func (l Level) String() string

String returns the string representation of the level.

func (*Level) UnmarshalText Uses

func (l *Level) UnmarshalText(text []byte) (err error)

UnmarshalText lets Level implements the TextUnmarshaler interface used by encoding packages

type LevelOutput Uses

type LevelOutput struct {
    Debug Output
    Info  Output
    Warn  Output
    Error Output
    Fatal Output
}

LevelOutput routes messages to different output based on the message's level.

Code:

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

func (LevelOutput) Write Uses

func (l LevelOutput) Write(fields map[string]interface{}) error

type Logger Uses

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 Uses

func Copy(l Logger) Logger

Copy returns a copy of the passed logger if the logger implements LoggerCopier or the NopLogger otherwise.

func FromContext Uses

func FromContext(ctx context.Context) Logger

FromContext gets the logger out of the context. If not logger is stored in the context, a NopLogger is returned.

func FromRequest Uses

func FromRequest(r *http.Request) Logger

FromRequest gets the logger in the request's context. This is a shortcut for xlog.FromContext(r.Context())

func New Uses

func New(c Config) Logger

New manually creates a logger.

This function should only be used out of a request. Use FromContext in request.

type LoggerCopier Uses

type LoggerCopier interface {
    // Copy returns a copy of the logger
    Copy() Logger
}

LoggerCopier defines a logger with copy support

type MultiOutput Uses

type MultiOutput []Output

MultiOutput routes the same message to serveral outputs. If one or more outputs return an error, the last error is returned.

Code:

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

func (MultiOutput) Write Uses

func (m MultiOutput) Write(fields map[string]interface{}) (err error)

type Output Uses

type Output interface {
    Write(fields map[string]interface{}) error
}

Output sends a log message fields to a destination.

func NewConsoleOutput Uses

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 Uses

func NewConsoleOutputW(w io.Writer, noTerm Output) Output

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 Uses

func NewJSONOutput(w io.Writer) Output

NewJSONOutput returns a new JSON output with the given writer.

func NewLogfmtOutput Uses

func NewLogfmtOutput(w io.Writer) Output

NewLogfmtOutput returns a new output using logstash JSON schema v1

func NewLogstashOutput Uses

func NewLogstashOutput(w io.Writer) Output

NewLogstashOutput returns an output to generate logstash friendly JSON format.

func NewSyslogOutput Uses

func NewSyslogOutput(network, address, tag string) Output

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 Uses

func NewSyslogOutputFacility(network, address, tag string, facility syslog.Priority) Output

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 Uses

func NewTrimFieldsOutput(trimFields []string, maxLen int, o Output) Output

NewTrimFieldsOutput trims listed field fields of type string with a value length greater than maxLen to maxLen.

func NewTrimOutput Uses

func NewTrimOutput(maxLen int, o Output) Output

NewTrimOutput trims any field of type string with a value length greater than maxLen to maxLen.

func NewUIDOutput Uses

func NewUIDOutput(field string, o Output) Output

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 Uses

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

OutputChannel is a send buffered channel between xlog and an Output.

func NewOutputChannel Uses

func NewOutputChannel(o Output) *OutputChannel

NewOutputChannel creates a consumer buffered channel for the given output with a default buffer of 100 messages.

func NewOutputChannelBuffer Uses

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 Uses

func (oc *OutputChannel) Close()

Close closes the output channel and release the consumer's go routine.

func (*OutputChannel) Flush Uses

func (oc *OutputChannel) Flush()

Flush flushes all the buffered message to the output

func (*OutputChannel) Write Uses

func (oc *OutputChannel) Write(fields map[string]interface{}) (err error)

Write implements the Output interface

type OutputFunc Uses

type OutputFunc func(fields map[string]interface{}) error

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 Uses

func (of OutputFunc) Write(fields map[string]interface{}) error

type RecorderOutput Uses

type RecorderOutput struct {
    Messages []F
}

RecorderOutput stores the raw messages in it's Messages field. This output is useful for testing.

func (*RecorderOutput) Reset Uses

func (l *RecorderOutput) Reset()

Reset empty the output from stored messages

func (*RecorderOutput) Write Uses

func (l *RecorderOutput) Write(fields map[string]interface{}) error

Directories

PathSynopsis
internal/term

Package xlog imports 20 packages (graph) and is imported by 32 packages. Updated 2017-12-28. Refresh now. Tools for package owners.