2017-05-12 05:24:39 +00:00
|
|
|
// Package zerolog provides a lightweight logging library dedicated to JSON logging.
|
|
|
|
//
|
|
|
|
// A global Logger can be use for simple logging:
|
|
|
|
//
|
|
|
|
// import "github.com/rs/zerolog/log"
|
|
|
|
//
|
|
|
|
// log.Info().Msg("hello world")
|
|
|
|
// // Output: {"time":1494567715,"level":"info","message":"hello world"}
|
|
|
|
//
|
|
|
|
// NOTE: To import the global logger, import the "log" subpackage "github.com/rs/zerolog/log".
|
|
|
|
//
|
|
|
|
// Fields can be added to log messages:
|
|
|
|
//
|
|
|
|
// log.Info().Str("foo", "bar").Msg("hello world")
|
|
|
|
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
|
|
|
//
|
|
|
|
// Create logger instance to manage different outputs:
|
|
|
|
//
|
|
|
|
// logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
|
|
|
// logger.Info().
|
|
|
|
// Str("foo", "bar").
|
|
|
|
// Msg("hello world")
|
|
|
|
// // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
|
|
|
|
//
|
|
|
|
// Sub-loggers let you chain loggers with additional context:
|
|
|
|
//
|
|
|
|
// sublogger := log.With().Str("component": "foo").Logger()
|
|
|
|
// sublogger.Info().Msg("hello world")
|
|
|
|
// // Output: {"time":1494567715,"level":"info","message":"hello world","component":"foo"}
|
|
|
|
//
|
|
|
|
// Level logging
|
|
|
|
//
|
2017-05-15 18:16:13 +00:00
|
|
|
// zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
2017-05-12 05:24:39 +00:00
|
|
|
//
|
|
|
|
// log.Debug().Msg("filtered out message")
|
|
|
|
// log.Info().Msg("routed message")
|
|
|
|
//
|
|
|
|
// if e := log.Debug(); e.Enabled() {
|
|
|
|
// // Compute log output only if enabled.
|
|
|
|
// value := compute()
|
|
|
|
// e.Str("foo": value).Msg("some debug message")
|
|
|
|
// }
|
|
|
|
// // Output: {"level":"info","time":1494567715,"routed message"}
|
|
|
|
//
|
|
|
|
// Customize automatic field names:
|
|
|
|
//
|
|
|
|
// log.TimestampFieldName = "t"
|
|
|
|
// log.LevelFieldName = "p"
|
|
|
|
// log.MessageFieldName = "m"
|
|
|
|
//
|
|
|
|
// log.Info().Msg("hello world")
|
|
|
|
// // Output: {"t":1494567715,"p":"info","m":"hello world"}
|
|
|
|
//
|
|
|
|
// Log with no level and message:
|
|
|
|
//
|
|
|
|
// log.Log().Str("foo","bar").Msg("")
|
|
|
|
// // Output: {"time":1494567715,"foo":"bar"}
|
|
|
|
//
|
|
|
|
// Add contextual fields to global Logger:
|
|
|
|
//
|
|
|
|
// log.Logger = log.With().Str("foo", "bar").Logger()
|
|
|
|
//
|
|
|
|
// Sample logs:
|
|
|
|
//
|
2017-09-02 03:07:47 +00:00
|
|
|
// sampled := log.Sample(&zerolog.BasicSampler{N: 10})
|
2017-05-12 05:24:39 +00:00
|
|
|
// sampled.Info().Msg("will be logged every 10 messages")
|
|
|
|
//
|
2017-12-01 17:52:37 +00:00
|
|
|
// Log with contextual hooks:
|
|
|
|
//
|
|
|
|
// // Create the hook:
|
|
|
|
// type SeverityHook struct{}
|
|
|
|
//
|
|
|
|
// func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
|
|
|
|
// if level != zerolog.NoLevel {
|
|
|
|
// e.Str("severity", level.String())
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // And use it:
|
|
|
|
// var h SeverityHook
|
|
|
|
// log := zerolog.New(os.Stdout).Hook(h)
|
|
|
|
// log.Warn().Msg("")
|
|
|
|
// // Output: {"level":"warn","severity":"warn"}
|
|
|
|
//
|
2018-03-08 15:41:28 +00:00
|
|
|
//
|
|
|
|
// Caveats
|
|
|
|
//
|
|
|
|
// There is no fields deduplication out-of-the-box.
|
|
|
|
// Using the same key multiple times creates new key in final JSON each time.
|
|
|
|
//
|
|
|
|
// logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
|
|
|
|
// logger.Info().
|
|
|
|
// Timestamp().
|
|
|
|
// Msg("dup")
|
|
|
|
// // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
|
|
|
|
//
|
2019-05-26 01:51:33 +00:00
|
|
|
// In this case, many consumers will take the last value,
|
|
|
|
// but this is not guaranteed; check yours if in doubt.
|
2017-05-12 05:24:39 +00:00
|
|
|
package zerolog
|
|
|
|
|
|
|
|
import (
|
2022-07-16 19:51:01 +00:00
|
|
|
"errors"
|
2017-09-02 02:56:35 +00:00
|
|
|
"fmt"
|
2017-05-12 05:24:39 +00:00
|
|
|
"io"
|
2017-05-19 16:56:31 +00:00
|
|
|
"io/ioutil"
|
2017-05-12 05:24:39 +00:00
|
|
|
"os"
|
2017-07-10 09:56:44 +00:00
|
|
|
"strconv"
|
2022-11-11 13:15:40 +00:00
|
|
|
"strings"
|
2017-05-12 05:24:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Level defines log levels.
|
2019-11-04 19:39:22 +00:00
|
|
|
type Level int8
|
2017-05-12 05:24:39 +00:00
|
|
|
|
|
|
|
const (
|
|
|
|
// DebugLevel defines debug log level.
|
|
|
|
DebugLevel Level = iota
|
|
|
|
// InfoLevel defines info log level.
|
|
|
|
InfoLevel
|
|
|
|
// WarnLevel defines warn log level.
|
|
|
|
WarnLevel
|
|
|
|
// ErrorLevel defines error log level.
|
|
|
|
ErrorLevel
|
|
|
|
// FatalLevel defines fatal log level.
|
|
|
|
FatalLevel
|
|
|
|
// PanicLevel defines panic log level.
|
|
|
|
PanicLevel
|
2017-12-01 17:52:37 +00:00
|
|
|
// NoLevel defines an absent log level.
|
|
|
|
NoLevel
|
2017-05-12 05:24:39 +00:00
|
|
|
// Disabled disables the logger.
|
|
|
|
Disabled
|
2019-11-18 17:34:23 +00:00
|
|
|
|
|
|
|
// TraceLevel defines trace log level.
|
|
|
|
TraceLevel Level = -1
|
2021-08-27 20:34:08 +00:00
|
|
|
// Values less than TraceLevel are handled as numbers.
|
2017-05-12 05:24:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func (l Level) String() string {
|
|
|
|
switch l {
|
2019-11-04 19:39:22 +00:00
|
|
|
case TraceLevel:
|
2021-05-13 22:05:00 +00:00
|
|
|
return LevelTraceValue
|
2017-05-12 05:24:39 +00:00
|
|
|
case DebugLevel:
|
2021-05-13 22:05:00 +00:00
|
|
|
return LevelDebugValue
|
2017-05-12 05:24:39 +00:00
|
|
|
case InfoLevel:
|
2021-05-13 22:05:00 +00:00
|
|
|
return LevelInfoValue
|
2017-05-12 05:24:39 +00:00
|
|
|
case WarnLevel:
|
2021-05-13 22:05:00 +00:00
|
|
|
return LevelWarnValue
|
2017-05-12 05:24:39 +00:00
|
|
|
case ErrorLevel:
|
2021-05-13 22:05:00 +00:00
|
|
|
return LevelErrorValue
|
2017-05-12 05:24:39 +00:00
|
|
|
case FatalLevel:
|
2021-05-13 22:05:00 +00:00
|
|
|
return LevelFatalValue
|
2017-05-12 05:24:39 +00:00
|
|
|
case PanicLevel:
|
2021-05-13 22:05:00 +00:00
|
|
|
return LevelPanicValue
|
2021-04-13 05:32:06 +00:00
|
|
|
case Disabled:
|
|
|
|
return "disabled"
|
2017-12-01 17:52:37 +00:00
|
|
|
case NoLevel:
|
|
|
|
return ""
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
2021-08-27 20:34:08 +00:00
|
|
|
return strconv.Itoa(int(l))
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2018-04-27 06:15:29 +00:00
|
|
|
// ParseLevel converts a level string into a zerolog Level value.
|
|
|
|
// returns an error if the input string does not match known values.
|
|
|
|
func ParseLevel(levelStr string) (Level, error) {
|
2023-03-10 15:15:23 +00:00
|
|
|
switch {
|
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(TraceLevel)):
|
2019-11-04 19:39:22 +00:00
|
|
|
return TraceLevel, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(DebugLevel)):
|
2018-04-27 06:15:29 +00:00
|
|
|
return DebugLevel, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(InfoLevel)):
|
2018-04-27 06:15:29 +00:00
|
|
|
return InfoLevel, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(WarnLevel)):
|
2018-04-27 06:15:29 +00:00
|
|
|
return WarnLevel, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(ErrorLevel)):
|
2018-04-27 06:15:29 +00:00
|
|
|
return ErrorLevel, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(FatalLevel)):
|
2018-04-27 06:15:29 +00:00
|
|
|
return FatalLevel, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(PanicLevel)):
|
2018-04-27 06:15:29 +00:00
|
|
|
return PanicLevel, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(Disabled)):
|
2021-04-13 05:32:06 +00:00
|
|
|
return Disabled, nil
|
2023-03-10 15:15:23 +00:00
|
|
|
case strings.EqualFold(levelStr, LevelFieldMarshalFunc(NoLevel)):
|
2018-04-27 06:15:29 +00:00
|
|
|
return NoLevel, nil
|
|
|
|
}
|
2021-08-27 20:34:08 +00:00
|
|
|
i, err := strconv.Atoi(levelStr)
|
|
|
|
if err != nil {
|
|
|
|
return NoLevel, fmt.Errorf("Unknown Level String: '%s', defaulting to NoLevel", levelStr)
|
|
|
|
}
|
|
|
|
if i > 127 || i < -128 {
|
|
|
|
return NoLevel, fmt.Errorf("Out-Of-Bounds Level: '%d', defaulting to NoLevel", i)
|
|
|
|
}
|
|
|
|
return Level(i), nil
|
2018-04-27 06:15:29 +00:00
|
|
|
}
|
|
|
|
|
2022-07-16 19:51:01 +00:00
|
|
|
// UnmarshalText implements encoding.TextUnmarshaler to allow for easy reading from toml/yaml/json formats
|
|
|
|
func (l *Level) UnmarshalText(text []byte) error {
|
|
|
|
if l == nil {
|
|
|
|
return errors.New("can't unmarshal a nil *Level")
|
|
|
|
}
|
|
|
|
var err error
|
|
|
|
*l, err = ParseLevel(string(text))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalText implements encoding.TextMarshaler to allow for easy writing into toml/yaml/json formats
|
|
|
|
func (l Level) MarshalText() ([]byte, error) {
|
|
|
|
return []byte(LevelFieldMarshalFunc(l)), nil
|
|
|
|
}
|
|
|
|
|
2017-05-12 05:24:39 +00:00
|
|
|
// A Logger represents an active logging object that generates lines
|
|
|
|
// of JSON output to an io.Writer. Each logging operation makes a single
|
2019-12-27 17:23:15 +00:00
|
|
|
// call to the Writer's Write method. There is no guarantee on access
|
2017-05-12 05:24:39 +00:00
|
|
|
// serialization to the Writer. If your Writer is not thread safe,
|
|
|
|
// you may consider a sync wrapper.
|
|
|
|
type Logger struct {
|
|
|
|
w LevelWriter
|
|
|
|
level Level
|
2017-08-29 01:52:15 +00:00
|
|
|
sampler Sampler
|
2017-05-20 02:43:59 +00:00
|
|
|
context []byte
|
2017-12-01 17:52:37 +00:00
|
|
|
hooks []Hook
|
2021-03-23 22:01:01 +00:00
|
|
|
stack bool
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2017-05-19 16:07:33 +00:00
|
|
|
// New creates a root logger with given output writer. If the output writer implements
|
|
|
|
// the LevelWriter interface, the WriteLevel method will be called instead of the Write
|
|
|
|
// one.
|
|
|
|
//
|
|
|
|
// Each logging operation makes a single call to the Writer's Write method. There is no
|
2019-12-27 17:23:15 +00:00
|
|
|
// guarantee on access serialization to the Writer. If your Writer is not thread safe,
|
2017-05-19 16:07:33 +00:00
|
|
|
// you may consider using sync wrapper.
|
2017-05-12 05:24:39 +00:00
|
|
|
func New(w io.Writer) Logger {
|
|
|
|
if w == nil {
|
2017-05-20 08:48:00 +00:00
|
|
|
w = ioutil.Discard
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
lw, ok := w.(LevelWriter)
|
|
|
|
if !ok {
|
|
|
|
lw = levelWriterAdapter{w}
|
|
|
|
}
|
2019-11-04 19:39:22 +00:00
|
|
|
return Logger{w: lw, level: TraceLevel}
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2017-06-02 07:24:52 +00:00
|
|
|
// Nop returns a disabled logger for which all operation are no-op.
|
|
|
|
func Nop() Logger {
|
|
|
|
return New(nil).Level(Disabled)
|
|
|
|
}
|
|
|
|
|
2017-08-06 02:47:55 +00:00
|
|
|
// Output duplicates the current logger and sets w as its output.
|
|
|
|
func (l Logger) Output(w io.Writer) Logger {
|
|
|
|
l2 := New(w)
|
|
|
|
l2.level = l.level
|
2017-08-29 01:52:15 +00:00
|
|
|
l2.sampler = l.sampler
|
2021-06-07 10:16:53 +00:00
|
|
|
l2.stack = l.stack
|
2017-12-01 17:52:37 +00:00
|
|
|
if len(l.hooks) > 0 {
|
|
|
|
l2.hooks = append(l2.hooks, l.hooks...)
|
|
|
|
}
|
2017-11-08 18:47:56 +00:00
|
|
|
if l.context != nil {
|
|
|
|
l2.context = make([]byte, len(l.context), cap(l.context))
|
|
|
|
copy(l2.context, l.context)
|
|
|
|
}
|
2017-08-06 02:47:55 +00:00
|
|
|
return l2
|
|
|
|
}
|
|
|
|
|
2017-05-12 05:24:39 +00:00
|
|
|
// With creates a child logger with the field added to its context.
|
|
|
|
func (l Logger) With() Context {
|
2017-05-20 02:43:59 +00:00
|
|
|
context := l.context
|
|
|
|
l.context = make([]byte, 0, 500)
|
|
|
|
if context != nil {
|
|
|
|
l.context = append(l.context, context...)
|
2020-05-06 02:44:34 +00:00
|
|
|
} else {
|
|
|
|
// This is needed for AppendKey to not check len of input
|
|
|
|
// thus making it inlinable
|
|
|
|
l.context = enc.AppendBeginMarker(l.context)
|
2017-05-20 02:43:59 +00:00
|
|
|
}
|
2017-05-12 05:24:39 +00:00
|
|
|
return Context{l}
|
|
|
|
}
|
|
|
|
|
2017-08-30 05:53:32 +00:00
|
|
|
// UpdateContext updates the internal logger's context.
|
|
|
|
//
|
|
|
|
// Use this method with caution. If unsure, prefer the With method.
|
|
|
|
func (l *Logger) UpdateContext(update func(c Context) Context) {
|
|
|
|
if l == disabledLogger {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if cap(l.context) == 0 {
|
2018-02-07 21:24:48 +00:00
|
|
|
l.context = make([]byte, 0, 500)
|
2017-08-30 05:53:32 +00:00
|
|
|
}
|
2020-06-24 23:11:26 +00:00
|
|
|
if len(l.context) == 0 {
|
|
|
|
l.context = enc.AppendBeginMarker(l.context)
|
|
|
|
}
|
2017-08-30 05:53:32 +00:00
|
|
|
c := update(Context{*l})
|
|
|
|
l.context = c.l.context
|
|
|
|
}
|
|
|
|
|
2017-06-05 19:59:25 +00:00
|
|
|
// Level creates a child logger with the minimum accepted level set to level.
|
2017-05-12 05:24:39 +00:00
|
|
|
func (l Logger) Level(lvl Level) Logger {
|
2017-09-03 18:01:28 +00:00
|
|
|
l.level = lvl
|
|
|
|
return l
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2019-06-20 23:44:55 +00:00
|
|
|
// GetLevel returns the current Level of l.
|
|
|
|
func (l Logger) GetLevel() Level {
|
|
|
|
return l.level
|
|
|
|
}
|
|
|
|
|
2017-08-29 01:52:15 +00:00
|
|
|
// Sample returns a logger with the s sampler.
|
|
|
|
func (l Logger) Sample(s Sampler) Logger {
|
2017-09-03 18:01:28 +00:00
|
|
|
l.sampler = s
|
|
|
|
return l
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2017-12-01 17:52:37 +00:00
|
|
|
// Hook returns a logger with the h Hook.
|
|
|
|
func (l Logger) Hook(h Hook) Logger {
|
|
|
|
l.hooks = append(l.hooks, h)
|
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2019-11-04 19:39:22 +00:00
|
|
|
// Trace starts a new message with trace level.
|
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
|
|
|
func (l *Logger) Trace() *Event {
|
|
|
|
return l.newEvent(TraceLevel, nil)
|
|
|
|
}
|
|
|
|
|
2017-05-12 05:24:39 +00:00
|
|
|
// Debug starts a new message with debug level.
|
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Debug() *Event {
|
2017-12-01 17:52:37 +00:00
|
|
|
return l.newEvent(DebugLevel, nil)
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Info starts a new message with info level.
|
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Info() *Event {
|
2017-12-01 17:52:37 +00:00
|
|
|
return l.newEvent(InfoLevel, nil)
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Warn starts a new message with warn level.
|
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Warn() *Event {
|
2017-12-01 17:52:37 +00:00
|
|
|
return l.newEvent(WarnLevel, nil)
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Error starts a new message with error level.
|
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Error() *Event {
|
2017-12-01 17:52:37 +00:00
|
|
|
return l.newEvent(ErrorLevel, nil)
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
2019-04-19 22:24:32 +00:00
|
|
|
|
|
|
|
// Err starts a new message with error level with err as a field if not nil or
|
|
|
|
// with info level if err is nil.
|
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
|
|
|
func (l *Logger) Err(err error) *Event {
|
|
|
|
if err != nil {
|
|
|
|
return l.Error().Err(err)
|
|
|
|
}
|
2019-10-04 14:31:06 +00:00
|
|
|
|
|
|
|
return l.Info()
|
2019-04-19 22:24:32 +00:00
|
|
|
}
|
2017-05-12 05:24:39 +00:00
|
|
|
|
|
|
|
// Fatal starts a new message with fatal level. The os.Exit(1) function
|
2018-09-28 01:11:43 +00:00
|
|
|
// is called by the Msg method, which terminates the program immediately.
|
2017-05-12 05:24:39 +00:00
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Fatal() *Event {
|
2017-12-01 17:52:37 +00:00
|
|
|
return l.newEvent(FatalLevel, func(msg string) { os.Exit(1) })
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-28 01:11:43 +00:00
|
|
|
// Panic starts a new message with panic level. The panic() function
|
|
|
|
// is called by the Msg method, which stops the ordinary flow of a goroutine.
|
2017-05-12 05:24:39 +00:00
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Panic() *Event {
|
2017-12-01 17:52:37 +00:00
|
|
|
return l.newEvent(PanicLevel, func(msg string) { panic(msg) })
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-28 01:11:43 +00:00
|
|
|
// WithLevel starts a new message with level. Unlike Fatal and Panic
|
|
|
|
// methods, WithLevel does not terminate the program or stop the ordinary
|
2021-12-21 12:07:54 +00:00
|
|
|
// flow of a goroutine when used with their respective levels.
|
2017-07-10 09:56:44 +00:00
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) WithLevel(level Level) *Event {
|
2017-07-10 09:56:44 +00:00
|
|
|
switch level {
|
2019-11-04 19:39:22 +00:00
|
|
|
case TraceLevel:
|
|
|
|
return l.Trace()
|
2017-07-10 09:56:44 +00:00
|
|
|
case DebugLevel:
|
|
|
|
return l.Debug()
|
|
|
|
case InfoLevel:
|
|
|
|
return l.Info()
|
|
|
|
case WarnLevel:
|
|
|
|
return l.Warn()
|
|
|
|
case ErrorLevel:
|
|
|
|
return l.Error()
|
|
|
|
case FatalLevel:
|
2018-09-28 01:11:43 +00:00
|
|
|
return l.newEvent(FatalLevel, nil)
|
2017-07-10 09:56:44 +00:00
|
|
|
case PanicLevel:
|
2018-09-28 01:11:43 +00:00
|
|
|
return l.newEvent(PanicLevel, nil)
|
2017-12-01 17:52:37 +00:00
|
|
|
case NoLevel:
|
|
|
|
return l.Log()
|
2017-07-10 09:56:44 +00:00
|
|
|
case Disabled:
|
2017-11-05 13:22:20 +00:00
|
|
|
return nil
|
2017-07-10 09:56:44 +00:00
|
|
|
default:
|
2021-08-27 20:34:08 +00:00
|
|
|
return l.newEvent(level, nil)
|
2017-07-10 09:56:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-12 05:24:39 +00:00
|
|
|
// Log starts a new message with no level. Setting GlobalLevel to Disabled
|
|
|
|
// will still disable events produced by this method.
|
|
|
|
//
|
|
|
|
// You must call Msg on the returned event in order to send the event.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Log() *Event {
|
2017-12-01 17:52:37 +00:00
|
|
|
return l.newEvent(NoLevel, nil)
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
|
2017-09-02 02:56:35 +00:00
|
|
|
// Print sends a log event using debug level and no extra field.
|
|
|
|
// Arguments are handled in the manner of fmt.Print.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Print(v ...interface{}) {
|
2017-09-02 02:56:35 +00:00
|
|
|
if e := l.Debug(); e.Enabled() {
|
Fix handling of printing caller with Write, Print, and Printf. (#315)
* Add event.CallerSkipFrame(skip int)
This indicates that, for this event, we should skip an additional
specified number of frames.
This is cumulative, calling it twice for the same event will add both
numbers together, and this is in addition to any skip frame settings set
through the context, or globally.
The indended purpose is for wrappers to Msg or Msgf, so that the actual
caller is always printed correctly.
* Use CallerSkipFrame for Print, Printf, and Write.
This allows us to use the correct caller when using these 3 functions.
Co-authored-by: Zephaniah E. Loss-Cutler-Hull <warp@aehallh.com>
2021-05-13 15:22:27 +00:00
|
|
|
e.CallerSkipFrame(1).Msg(fmt.Sprint(v...))
|
2017-09-02 02:56:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Printf sends a log event using debug level and no extra field.
|
|
|
|
// Arguments are handled in the manner of fmt.Printf.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) Printf(format string, v ...interface{}) {
|
2017-09-02 02:56:35 +00:00
|
|
|
if e := l.Debug(); e.Enabled() {
|
Fix handling of printing caller with Write, Print, and Printf. (#315)
* Add event.CallerSkipFrame(skip int)
This indicates that, for this event, we should skip an additional
specified number of frames.
This is cumulative, calling it twice for the same event will add both
numbers together, and this is in addition to any skip frame settings set
through the context, or globally.
The indended purpose is for wrappers to Msg or Msgf, so that the actual
caller is always printed correctly.
* Use CallerSkipFrame for Print, Printf, and Write.
This allows us to use the correct caller when using these 3 functions.
Co-authored-by: Zephaniah E. Loss-Cutler-Hull <warp@aehallh.com>
2021-05-13 15:22:27 +00:00
|
|
|
e.CallerSkipFrame(1).Msg(fmt.Sprintf(format, v...))
|
2017-09-02 02:56:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-02 06:17:28 +00:00
|
|
|
// Write implements the io.Writer interface. This is useful to set as a writer
|
|
|
|
// for the standard library log.
|
|
|
|
func (l Logger) Write(p []byte) (n int, err error) {
|
|
|
|
n = len(p)
|
|
|
|
if n > 0 && p[n-1] == '\n' {
|
|
|
|
// Trim CR added by stdlog.
|
|
|
|
p = p[0 : n-1]
|
|
|
|
}
|
Fix handling of printing caller with Write, Print, and Printf. (#315)
* Add event.CallerSkipFrame(skip int)
This indicates that, for this event, we should skip an additional
specified number of frames.
This is cumulative, calling it twice for the same event will add both
numbers together, and this is in addition to any skip frame settings set
through the context, or globally.
The indended purpose is for wrappers to Msg or Msgf, so that the actual
caller is always printed correctly.
* Use CallerSkipFrame for Print, Printf, and Write.
This allows us to use the correct caller when using these 3 functions.
Co-authored-by: Zephaniah E. Loss-Cutler-Hull <warp@aehallh.com>
2021-05-13 15:22:27 +00:00
|
|
|
l.Log().CallerSkipFrame(1).Msg(string(p))
|
2017-06-02 06:17:28 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-12-01 17:52:37 +00:00
|
|
|
func (l *Logger) newEvent(level Level, done func(string)) *Event {
|
2017-05-19 16:56:31 +00:00
|
|
|
enabled := l.should(level)
|
|
|
|
if !enabled {
|
2022-01-04 16:12:02 +00:00
|
|
|
if done != nil {
|
|
|
|
done("")
|
|
|
|
}
|
2017-11-05 13:22:20 +00:00
|
|
|
return nil
|
2017-05-19 16:56:31 +00:00
|
|
|
}
|
2018-05-09 10:51:52 +00:00
|
|
|
e := newEvent(l.w, level)
|
2017-06-06 17:23:34 +00:00
|
|
|
e.done = done
|
2018-02-07 21:24:48 +00:00
|
|
|
e.ch = l.hooks
|
2021-05-05 12:40:45 +00:00
|
|
|
if level != NoLevel && LevelFieldName != "" {
|
2019-03-02 00:08:23 +00:00
|
|
|
e.Str(LevelFieldName, LevelFieldMarshalFunc(level))
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
2020-05-06 02:44:34 +00:00
|
|
|
if l.context != nil && len(l.context) > 1 {
|
2018-05-10 22:01:41 +00:00
|
|
|
e.buf = enc.AppendObjectData(e.buf, l.context)
|
2017-12-01 17:52:37 +00:00
|
|
|
}
|
2021-03-23 22:01:01 +00:00
|
|
|
if l.stack {
|
|
|
|
e.Stack()
|
|
|
|
}
|
2017-05-12 05:24:39 +00:00
|
|
|
return e
|
|
|
|
}
|
|
|
|
|
|
|
|
// should returns true if the log event should be logged.
|
2017-11-05 13:22:20 +00:00
|
|
|
func (l *Logger) should(lvl Level) bool {
|
2018-04-17 22:52:22 +00:00
|
|
|
if lvl < l.level || lvl < GlobalLevel() {
|
2017-05-12 05:24:39 +00:00
|
|
|
return false
|
|
|
|
}
|
2017-08-29 01:52:15 +00:00
|
|
|
if l.sampler != nil && !samplingDisabled() {
|
|
|
|
return l.sampler.Sample(lvl)
|
2017-05-12 05:24:39 +00:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|