diff --git a/formatter.go b/formatter.go index a96f58a..3a2eff5 100644 --- a/formatter.go +++ b/formatter.go @@ -1,5 +1,15 @@ package logrus +// The Formatter interface is used to implement a custom Formatter. It takes an +// `Entry`. It exposes all the fields, including the default ones: +// +// * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. +// * `entry.Data["time"]`. The timestamp. +// * `entry.Data["level"]. The level the entry was logged at. +// +// Any additional fields added with `WithField` or `WithFields` are also in +// `entry.Data`. Format is expected to return an array of bytes which are then +// logged to `logger.Out`. type Formatter interface { Format(*Entry) ([]byte, error) } diff --git a/hooks.go b/hooks.go index cbd376e..0da2b36 100644 --- a/hooks.go +++ b/hooks.go @@ -1,18 +1,28 @@ package logrus +// A hook to be fired when logging on the logging levels returned from +// `Levels()` on your implementation of the interface. Note that this is not +// fired in a goroutine or a channel with workers, you should handle such +// functionality yourself if your call is non-blocking and you don't wish for +// the logging calls for levels returned from `Levels()` to block. type Hook interface { Levels() []Level Fire(*Entry) error } +// Internal type for storing the hooks on a logger instance. type levelHooks map[Level][]Hook +// Add a hook to an instance of logger. This is called with +// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. func (hooks levelHooks) Add(hook Hook) { for _, level := range hook.Levels() { hooks[level] = append(hooks[level], hook) } } +// Fire all the hooks for the passed level. Used by `entry.log` to fire +// appropriate hooks for a log entry. func (hooks levelHooks) Fire(level Level, entry *Entry) error { for _, hook := range hooks[level] { if err := hook.Fire(entry); err != nil { diff --git a/logger.go b/logger.go index 22e6ebc..a545afd 100644 --- a/logger.go +++ b/logger.go @@ -7,32 +7,63 @@ import ( ) type Logger struct { - Out io.Writer - Hooks levelHooks + // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a + // file, or leave it default which is `os.Stdout`. You can also set this to + // something more adventorous, such as logging to Kafka. + Out io.Writer + // Hooks for the logger instance. These allow firing events based on logging + // levels and log entries. For example, to send errors to an error tracking + // service, log to StatsD or dump the core on fatal errors. + Hooks levelHooks + // All log entries pass through the formatter before logged to Out. The + // included formatters are `TextFormatter` and `JSONFormatter` for which + // TextFormatter is the default. In development (when a TTY is attached) it + // logs with colors, but to a file it wouldn't. You can easily implement your + // own that implements the `Formatter` interface, see the `README` or included + // formatters for examples. Formatter Formatter - Level Level - mu sync.Mutex + // The logging level the logger should log at. This is typically (and defaults + // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be + // logged. `logrus.Debug` is useful in + Level Level + // Used to sync writing to the log. + mu sync.Mutex } +// Creates a new logger. Configuration should be set by changing `Formatter`, +// `Out` and `Hooks` directly on the default logger instance. You can also just +// instantiate your own: +// +// var log = &Logger{ +// Out: os.Stderr, +// Formatter: new(JSONFormatter), +// Hooks: make(levelHooks), +// Level: logrus.Debug, +// } +// +// It's recommended to make this a global instance called `log`. func New() *Logger { return &Logger{ - Out: os.Stdout, // Default to stdout, change it if you want. + Out: os.Stdout, Formatter: new(TextFormatter), Hooks: make(levelHooks), Level: Info, } } +// Adds a field to the log entry, note that you it doesn't log until you call +// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry. +// Ff you want multiple fields, use `WithFields`. func (logger *Logger) WithField(key string, value interface{}) *Entry { return NewEntry(logger).WithField(key, value) } +// Adds a struct of fields to the log entry. All it does is call `WithField` for +// each `Field`. func (logger *Logger) WithFields(fields Fields) *Entry { return NewEntry(logger).WithFields(fields) } -// Logger Printf family functions - func (logger *Logger) Debugf(format string, args ...interface{}) { NewEntry(logger).Debugf(format, args...) } @@ -65,8 +96,6 @@ func (logger *Logger) Panicf(format string, args ...interface{}) { NewEntry(logger).Panicf(format, args...) } -// Logger Print family functions - func (logger *Logger) Debug(args ...interface{}) { NewEntry(logger).Debug(args...) } @@ -99,8 +128,6 @@ func (logger *Logger) Panic(args ...interface{}) { NewEntry(logger).Panic(args...) } -// Logger Println family functions - func (logger *Logger) Debugln(args ...interface{}) { NewEntry(logger).Debugln(args...) } diff --git a/logrus.go b/logrus.go index 0257410..9fa2c99 100644 --- a/logrus.go +++ b/logrus.go @@ -1,15 +1,29 @@ package logrus +// Fields type, used to pass to `WithFields`. type Fields map[string]interface{} +// Level type type Level uint8 +// These are the different logging levels. You can set the logging level to log +// on your instance of logger, obtained with `logrus.New()`. const ( + // Panic level, highest level of severity. Logs and then calls panic with the + // message passed to Debug, Info, ... Panic Level = iota + // Fatal level. Logs and then calls `os.Exit(1)`. It will exit even if the + // logging level is set to Panic. Fatal + // Error level. Logs. Used for errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. Error + // Warn level. Non-critical entries that deserve eyes. Warn + // Info level. General operational entries about what's going on inside the + // application. Info + // Debug level. Usually only enabled when debugging. Very verbose logging. Debug )