multilogger

package module
v0.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2020 License: MIT Imports: 22 Imported by: 10

README

multilogger

Multilogger is a small logging wrapper based on logrus that writes logs simultaneously to the console, files or any other hook. Each of those logging methods can be given a different logging level. It exposes the same API as a regular logrus logger.

See multilogger godoc for full documentation.

multicolor

There is also a sub package used to handle colors and attributes. It is based on color which is an archived project but still useful.

See multicolor godoc for full documentation.

Documentation

Overview

Package multilogger is a thin wrapper around logrus https://github.com/sirupsen/logrus that writes logs simultaneously to many outputs at the same time. Each output (implemented as Hook) have their own logging level. It exposes the same API as a regular logrus logger.

How to use it

So, you can use multilogger to write logs to standard error with a minimal logging level (i.e. WarningLevel) and have the full debug log (i.e. DebugLevel or TraceLevel) written to a file.

import "github.com/coveooss/multilogger"
import "github.com/sirupsen/logrus"

func main() {
    log := New("test")                                         // By default, logs are sent to stderr and the logging level is set to WarningLevel
    log.AddHooks(NewFileHook("debug.log", logrus.DebugLevel))  // It is possible to add a file as a target for the logs
    log.AddHooks(NewFileHook("verbose.log", "trace"))          // The logging level could be expressed as string, logrus.Level or int
    log.Warning("This is a warning")
    log.Infof("This is an information %s", message)
}

Differences with logrus

  • The multilogger object is based on a logrus.Entry instead of a logrus.Logger.
  • The methods Print, Println and Printf are used to print information directly to stdout without log decoration. Within logrus, these methods are aliases to Info, Infoln and Infof.
  • It is not possible to set the global logging level with multilogger, the logging level is determined by hooks that are added to the logging object and the resulting logging level is the highest logging level defined for individual hooks.
  • Hooks are fired according to their own logging level while they were fired according to the global logging level with logrus.
  • The default formatter used by console and file hook is highly customizable.

Where is it used

This project is used in other Coveo projects to reduce visual clutter in CI systems while keeping debug logs available when errors arise:

gotemplate https://github.com/coveooss/gotemplate
terragrunt https://github.com/coveooss/terragrunt
tgf        https://github.com/coveooss/tgf

Index

Examples

Constants

View Source
const (
	// CallerEnvVar is an environment variable that enable the caller stack by default.
	CallerEnvVar = "MULTILOGGER_CALLER"
	// FormatEnvVar is an environment variable that allows users to set the default format used for log entry.
	FormatEnvVar = "MULTILOGGER_FORMAT"
	// FormatFileEnvVar is an environment variable that allows users to set the default format used for log entry using a file logger.
	FormatFileEnvVar = "MULTILOGGER_FILE_FORMAT"
	// DefaultFileFormat is the format used by NewFileHook if neither MULTILOGGER_FORMAT or MULTILOGGER_FILE_FORMAT are set.
	DefaultFileFormat = "%module:SquareBrackets,IgnoreEmpty,Space%%time% %-8level:upper% %message%"
	// DurationPrecisionEnvVar defines the duration precision that should be used to render duration
	DurationPrecisionEnvVar = "MULTILOGGER_DURATION_PRECISION"
)
View Source
const (
	// DefaultConsoleFormat is the format used by NewConsoleHook if MULTILOGGER_FORMAT is not set.
	DefaultConsoleFormat = "%module:Italic,Green,SquareBrackets,IgnoreEmpty,Space%%time% %-8level:upper,color% %message:color%"
)
View Source
const (
	// DisabledLevel can be set when one of the logging hooks should be disabled.
	DisabledLevel logrus.Level = math.MaxUint32
)

Variables

This section is empty.

Functions

func AcceptedLevels

func AcceptedLevels() []string

AcceptedLevels returns all accepted logrus levels.

func AcceptedLevelsString

func AcceptedLevelsString() string

AcceptedLevelsString returns all accepted logrus levels as a comma-separated string.

func FormatDurationClassic added in v0.5.1

func FormatDurationClassic(duration time.Duration) string

FormatDurationClassic returns a string to represent the duration using floating representation for values bellow 1 minutes.

func FormatDurationClassicLong added in v0.5.1

func FormatDurationClassicLong(duration time.Duration) string

FormatDurationClassicLong returns a string to represent the duration using floating representation for values bellow 1 minutes and display long units.

func FormatDurationNative added in v0.5.1

func FormatDurationNative(duration time.Duration) string

FormatDurationNative returns a string to represent the duration using the native golang duration format.

func FormatDurationNativeLong added in v0.5.1

func FormatDurationNativeLong(duration time.Duration) string

FormatDurationNativeLong returns a string to represent the duration using the native golang duration format using long units.

func FormatDurationPrecise added in v0.5.1

func FormatDurationPrecise(duration time.Duration) string

FormatDurationPrecise returns a string to represent the duration with precise unit for each segment 1d2h3m4s5ms6µs.

Example
durations := []time.Duration{
	0,
	time.Nanosecond,
	time.Microsecond,
	time.Millisecond,
	time.Second,
	time.Minute,
	time.Hour,
	day,
	week,
	month,
	year,
	9*year + 8*month + 7*day + 6*time.Hour + 5*time.Minute + 4*time.Second + 3*time.Millisecond + 2*time.Microsecond + 1*time.Nanosecond,
}

w := tabwriter.NewWriter(os.Stdout, 20, 0, 1, ' ', tabwriter.TabIndent)

fmt.Fprintln(w, "Native\tClassic\tPrecise\tRounded\tNative long\tRounded long\t")
fmt.Fprintln(w, "------\t-------\t-------\t-------\t-----------\t------------\t")

print := func(duration time.Duration) {
	fmt.Fprintf(w, "%v\t", duration)
	fmt.Fprintf(w, "%s\t", FormatDurationClassic(duration))
	fmt.Fprintf(w, "%s\t", FormatDurationPrecise(duration))
	fmt.Fprintf(w, "%s\t", FormatDurationRounded(duration))
	fmt.Fprintf(w, "%s\t", FormatDurationNativeLong(duration))
	fmt.Fprintf(w, "%s\t", FormatDurationRoundedLong(duration))
	fmt.Fprintln(w, "|")
}

var total time.Duration
for _, duration := range durations {
	total += duration
	print(duration)
	if duration != 0 {
		print(10 * duration)
		if total != duration {
			print(total)
		}
	}
}
w.Flush()

// // Output:
// Native                 Classic                       Precise                          Rounded             Native long                                 Rounded long
// ------                 -------                       -------                          -------             -----------                                 ------------
// 0s                     0s                            0s                               0s                  0 second                                    0 second                         |
// 1ns                    1ns                           1ns                              1ns                 1 nanosecond                                1 nanosecond                     |
// 10ns                   10ns                          10ns                             10ns                10 nanoseconds                              10 nanoseconds                   |
// 1µs                    1µs                           1µs                              1µs                 1 microsecond                               1 microsecond                    |
// 10µs                   10µs                          10µs                             10µs                10 microseconds                             10 microseconds                  |
// 1.001µs                1.001µs                       1µs1ns                           1µs                 1.001 microsecond                           1 microsecond                    |
// 1ms                    1ms                           1ms                              1ms                 1 millisecond                               1 millisecond                    |
// 10ms                   10ms                          10ms                             10ms                10 milliseconds                             10 milliseconds                  |
// 1.001001ms             1.001001ms                    1ms1µs1ns                        1ms                 1.001001 millisecond                        1 millisecond                    |
// 1s                     1s                            1s                               1s                  1 second                                    1 second                         |
// 10s                    10s                           10s                              10s                 10 seconds                                  10 seconds                       |
// 1.001001001s           1.001001001s                  1s1ms1µs1ns                      1s                  1.001001001 second                          1 second                         |
// 1m0s                   1m                            1m                               1m                  1 minute                                    1 minute                         |
// 10m0s                  10m                           10m                              10m                 10 minutes                                  10 minutes                       |
// 1m1.001001001s         1m1.001001001s                1m1s1ms1µs1ns                    1m1s                1 minute 1.001001001 second                 1 minute 1 second                |
// 1h0m0s                 1h                            1h                               1h                  1 hour                                      1 hour                           |
// 10h0m0s                10h                           10h                              10h                 10 hours                                    10 hours                         |
// 1h1m1.001001001s       1h1m1.001001001s              1h1m1s1ms1µs1ns                  1h1m                1 hour 1 minute 1.001001001 second          1 hour 1 minute                  |
// 24h0m0s                1d                            1d                               1d                  24 hours                                    1 day                            |
// 240h0m0s               1w3d                          1w3d                             1w3d                240 hours                                   1 week 3 days                    |
// 25h1m1.001001001s      1d1h1m1.001001001s            1d1h1m1s1ms1µs1ns                1d1h1m              25 hours 1 minute 1.001001001 second        1 day 1 hour 1 minute            |
// 168h0m0s               7d                            7d                               7d                  168 hours                                   7 days                           |
// 1680h0m0s              2mo1w3d                       2mo1w3d                          2mo1w3d             1680 hours                                  2 months 1 week 3 days           |
// 193h1m1.001001001s     8d1h1m1.001001001s            8d1h1m1s1ms1µs1ns                8d1h1m              193 hours 1 minute 1.001001001 second       8 days 1 hour 1 minute           |
// 720h0m0s               4w2d                          4w2d                             4w2d                720 hours                                   4 weeks 2 days                   |
// 7200h0m0s              10mo                          10mo                             10mo                7200 hours                                  10 months                        |
// 913h1m1.001001001s     5w3d1h1m1.001001001s          5w3d1h1m1s1ms1µs1ns              5w3d                913 hours 1 minute 1.001001001 second       5 weeks 3 days                   |
// 8640h0m0s              1y                            1y                               1y                  8640 hours                                  1 year                           |
// 86400h0m0s             10y                           10y                              10y                 86400 hours                                 10 years                         |
// 9553h1m1.001001001s    1y5w3d1h1m1.001001001s        1y5w3d1h1m1s1ms1µs1ns            1y5w3d              9553 hours 1 minute 1.001001001 second      1 year 5 weeks 3 days            |
// 83694h5m4.003002001s   9y8mo7d6h5m4.003002001s       9y8mo7d6h5m4s3ms2µs1ns           9y8mo7d             83694 hours 5 minutes 4.003002001 seconds   9 years 8 months 7 days          |
// 836940h50m40.03002001s 96y10mo1w5d12h50m40.03002001s 96y10mo1w5d12h50m40s30ms20µs10ns 96y10mo1w6d         836940 hours 50 minutes 40.03002001 seconds 96 years 10 months 1 week 6 days |
// 93247h6m5.004003002s   10y9mo2w1d7h6m5.004003002s    10y9mo2w1d7h6m5s4ms3µs2ns        10y9mo2w1d          93247 hours 6 minutes 5.004003002 seconds   10 years 9 months 2 weeks 1 day  |

func FormatDurationPreciseLong added in v0.5.1

func FormatDurationPreciseLong(duration time.Duration) string

FormatDurationPreciseLong returns a string to represent the duration with precise unit for each segment using long units.

func FormatDurationRounded added in v0.5.1

func FormatDurationRounded(duration time.Duration) string

FormatDurationRounded returns a string to represent the duration with all units and reduction of the precision for large value.

func FormatDurationRoundedLong added in v0.5.1

func FormatDurationRoundedLong(duration time.Duration) string

FormatDurationRoundedLong returns a string to represent the duration with all units and reduction of the precision for large value and display long units.

func FormatDurationRoundedNative added in v0.5.1

func FormatDurationRoundedNative(duration time.Duration) string

FormatDurationRoundedNative returns a string to represent the duration with reduction of the precision for large value.

func FormatDurationRoundedNativeLong added in v0.5.1

func FormatDurationRoundedNativeLong(duration time.Duration) string

FormatDurationRoundedNativeLong returns a string to represent the duration with reduction of the precision for large value and display long units.

func GetGlobalFileFormat added in v0.5.0

func GetGlobalFileFormat() string

GetGlobalFileFormat returns the currently globally set file log format

func GetGlobalFormat added in v0.5.0

func GetGlobalFormat() string

GetGlobalFormat returns the currently globally set console log format

func ParseBool added in v0.2.0

func ParseBool(value string) bool

ParseBool returns true for any value that is set and is not clearly a false. It never returns an error.

True values are: 1, t, true, yes, y, on (of any non false value) False values are: 0, f, false, no, n, off

func ParseLogLevel

func ParseLogLevel(level interface{}) logrus.Level

ParseLogLevel converts a string or number into a logging level. It panics if the supplied valid cannot be converted into a valid logrus Level.

func SetDurationPrecision added in v0.5.0

func SetDurationPrecision(precision time.Duration, override bool) (time.Duration, bool)

SetDurationPrecision allows duration to be rounded up to the desired precision

Example
const format = "%module:square% %time% %globaldelay:round% %message%"
log := getTestLogger("", logrus.InfoLevel).SetModule("Rounded").SetFormat(format)
defaultLog := getTestLogger("", logrus.TraceLevel).SetModule("Default").SetFormat(format)
defaultLog.Formatter().FormatDuration = FormatDurationNative

// We set the format of the log to include fields
SetDurationPrecision(time.Nanosecond, true)

for i := time.Duration(1); i < 365*24*time.Hour; {
	i *= 25 + time.Nanosecond
	t := baseTime.Add(i)
	log.WithTime(t).Infof("%v later", i)
	defaultLog.WithTime(t).Tracef("%v later", i)
}
Output:
[Rounded] 2018/06/24 12:34:56.789 (26ns) 26ns later
[Default] 2018/06/24 12:34:56.789 (26ns) 26ns later
[Rounded] 2018/06/24 12:34:56.789 (676ns) 676ns later
[Default] 2018/06/24 12:34:56.789 (676ns) 676ns later
[Rounded] 2018/06/24 12:34:56.789 (18µs) 17.576µs later
[Default] 2018/06/24 12:34:56.789 (17.576µs) 17.576µs later
[Rounded] 2018/06/24 12:34:56.789 (457µs) 456.976µs later
[Default] 2018/06/24 12:34:56.789 (456.976µs) 456.976µs later
[Rounded] 2018/06/24 12:34:56.800 (12ms) 11.881376ms later
[Default] 2018/06/24 12:34:56.800 (11.881376ms) 11.881376ms later
[Rounded] 2018/06/24 12:34:57.097 (309ms) 308.915776ms later
[Default] 2018/06/24 12:34:57.097 (308.915776ms) 308.915776ms later
[Rounded] 2018/06/24 12:35:04.820 (8s30ms) 8.031810176s later
[Default] 2018/06/24 12:35:04.820 (8.031810176s) 8.031810176s later
[Rounded] 2018/06/24 12:38:25.616 (3m29s) 3m28.827064576s later
[Default] 2018/06/24 12:38:25.616 (3m28.827064576s) 3m28.827064576s later
[Rounded] 2018/06/24 14:05:26.292 (1h30m) 1h30m29.503678976s later
[Default] 2018/06/24 14:05:26.292 (1h30m29.503678976s) 1h30m29.503678976s later
[Rounded] 2018/06/26 03:47:43.884 (1d15h13m) 39h12m47.095653376s later
[Default] 2018/06/26 03:47:43.884 (39h12m47.095653376s) 39h12m47.095653376s later
[Rounded] 2018/08/06 00:07:21.275 (6w) 1019h32m24.486987776s later
[Default] 2018/08/06 00:07:21.275 (1019h32m24.486987776s) 1019h32m24.486987776s later
[Rounded] 2021/07/03 00:37:33.450 (3y3w4d) 26508h2m36.661682176s later
[Default] 2021/07/03 00:37:33.450 (26508h2m36.661682176s) 26508h2m36.661682176s later

func SetGlobalFileFormat added in v0.5.0

func SetGlobalFileFormat(format string, override bool) (string, bool)

SetGlobalFileFormat configure the default format used for file logging and ensure that it is available for all applications by setting an environment variable

func SetGlobalFormat added in v0.5.0

func SetGlobalFormat(format string, override bool) (string, bool)

SetGlobalFormat configure the default format used for console logging and ensure that it is available for all applications by setting an environment variable

func TryParseLogLevel added in v0.2.0

func TryParseLogLevel(level interface{}) (logrus.Level, error)

TryParseLogLevel converts a string or number into a logging level.

Types

type Formatter added in v0.1.1

type Formatter struct {
	// Available standard keys: time, delay, globaldelay, delta, message, level, module, file, line, func.
	// Also can include custom fields but limited to strings.
	// All of fields need to be wrapped inside %% i.e %time% %message%
	TimestampFormat string
	FormatDuration  func(time.Duration) string
	FormatCaller    func(*runtime.Frame) string

	// RoundDuration allows user to define the granularity of durations
	RoundDuration time.Duration

	// ColorMap allows user to define the color attributes associated with the error level.
	// Attribute names are defined by http://github.com/fatih/color
	ColorMap map[logrus.Level][]multicolor.Attribute

	// LevelName allows user to rename default level name.
	LevelName map[logrus.Level]string
	// contains filtered or unexported fields
}

Formatter implements logrus.Formatter interface.

func NewFormatter added in v0.2.0

func NewFormatter(color bool, formats ...interface{}) *Formatter

NewFormatter creates a new formatter with color setting and takes the first defined format string as the log format.

func (*Formatter) Format added in v0.1.1

func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error)

Format building log message.

func (*Formatter) SetColor added in v0.2.0

func (f *Formatter) SetColor(color bool)

SetColor set color mode on the formatter.

func (*Formatter) SetLogFormat added in v0.2.0

func (f *Formatter) SetLogFormat(formats ...interface{}) *Formatter

SetLogFormat initialize the log format with the first defined format in the list.

type Hook added in v0.2.0

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

Hook represents a hook that logs at a given level. This struct must be extended to implement the Fire func.

func NewConsoleHook

func NewConsoleHook(name string, level interface{}, format ...interface{}) *Hook

NewConsoleHook creates a new hook to log information to console (default to stderr).

level: Accept any kind of object, but must be resolvable into a valid logrus level name.

func NewFileHook

func NewFileHook(filename string, isDir bool, level interface{}, format ...interface{}) *Hook

NewFileHook creates a new hook to log information into a file.

level: Accept any kind of object, but must be resolvable into a valid logrus level name.

func NewHook added in v0.2.0

func NewHook(name string, level interface{}, hook logrus.Hook) *Hook

NewHook generates a named hook wrapper that is able the handle its own logging level.

level: Accept any kind of object, but must be resolvable into a valid logrus level name.

func (*Hook) Fire added in v0.2.0

func (hook *Hook) Fire(entry *logrus.Entry) error

Fire writes logs to the console.

func (*Hook) Formatter added in v0.2.0

func (hook *Hook) Formatter() *Formatter

Formatter returns the Formatter associated to the hook. The function will panic if called upon a hook that do not support formatter.

func (*Hook) GetFormatter added in v0.2.0

func (hook *Hook) GetFormatter() logrus.Formatter

GetFormatter returns the formater associated to the hook. The function will panic if called upon a hook that do not support formatter.

func (*Hook) GetInnerHook added in v0.3.0

func (hook *Hook) GetInnerHook() logrus.Hook

GetInnerHook returns the inner hook actually used by the leveled hook.

func (*Hook) Levels added in v0.2.0

func (hook *Hook) Levels() []logrus.Level

Levels returns the levels that should be handled by the hook.

func (*Hook) SetColor added in v0.2.0

func (hook *Hook) SetColor(color bool) *Hook

SetColor allows setting color mode on hook that support it. The function will panic if called upon a hook that do not support formatter.

func (*Hook) SetFormat added in v0.2.0

func (hook *Hook) SetFormat(formats ...interface{}) *Hook

SetFormat allows setting a format string on hook that support it. The function will panic if called upon a hook that do not support formatter.

func (*Hook) SetFormatter added in v0.2.0

func (hook *Hook) SetFormatter(formatter logrus.Formatter) *Hook

SetFormatter allows setting a formatter on hook that support it. The function will panic if called upon a hook that do not support formatter.

func (*Hook) SetOut added in v0.2.0

func (hook *Hook) SetOut(out io.Writer) *Hook

SetOut allows configuring the logging stream for a hook that support it. The function will panic if called upon a hook that is not a valid ConsoleHook.

func (*Hook) SetStdout added in v0.2.0

func (hook *Hook) SetStdout(out io.Writer) *Hook

SetStdout allows configuring the output stream for a hook that support it. The function will panic if called upon a hook that is not a valid ConsoleHook.

type Logger added in v0.2.0

type Logger struct {
	*logrus.Entry
	PrintLevel logrus.Level
	Catcher    bool
	// contains filtered or unexported fields
}

Logger represents a logger that logs to both a file and the console at different (configurable) levels.

func New

func New(module string, hooks ...*Hook) *Logger

New creates a new Multilogger instance. If no hook is provided, it defaults to standard console logger at warning log level.

Example (Default)
log := getTestLogger("default")
log.Warning("This is a warning")
log.Println("The logging level is set to", log.GetLevel())
log.Printf("Module = %s\n", log.GetModule())
Output:
[default] 2018/06/24 12:34:56.789 WARNING  This is a warning
The logging level is set to warning
Module = default
Example (Log_catcher)
log := getTestLogger("catcher", logrus.TraceLevel)
cmd := exec.Command("cat")
stdin, _ := cmd.StdinPipe()
cmd.Stdout, cmd.Stderr = log, log
cmd.Start()

lines := []string{
	"Hello,",
	"",
	"This is a text that contains:",
	"[Error] Oops! there is an error",
	"This should be considered as a [warning] message",
	"This should go directly to output",
	"Format tags like %hello in output aren't considered",
}
for _, line := range lines {
	io.WriteString(stdin, line+"\n")
}
stdin.Close()
cmd.Wait()
Output:
Hello,

This is a text that contains:
[catcher] 2018/06/24 12:34:56.789 ERROR    Oops! there is an error
[catcher] 2018/06/24 12:34:56.789 WARNING  This should be considered as a warning message
This should go directly to output
Format tags like %hello in output aren't considered
Example (Log_catcher_disabled)
log := getTestLogger("catcher", logrus.TraceLevel)

// We disable the log catcher.
log.Catcher = false
fmt.Fprintln(log, "Hello,")
fmt.Fprintln(log)
fmt.Fprintln(log, "This is a text that contains:")
fmt.Fprintln(log, "[Error] Oops! there is an error")
fmt.Fprintln(log, "This should be considered as a [warning] message")
fmt.Fprintln(log, "This should go directly to output")
Output:
Hello,

This is a text that contains:
[Error] Oops! there is an error
This should be considered as a [warning] message
This should go directly to output
Example (Output_sent_to_info)
log := getTestLogger("catcher", logrus.TraceLevel)

// We send all regular text to the InfoLevel.
log.PrintLevel = logrus.InfoLevel
fmt.Fprintln(log, "This is a text that contains:")
fmt.Fprintln(log, "[Error] Oops! there is an error")
fmt.Fprintln(log, "This should be considered as a [warning] message")
fmt.Fprintln(log, "This should go directly to output")
Output:
[catcher] 2018/06/24 12:34:56.789 INFO     This is a text that contains:
[catcher] 2018/06/24 12:34:56.789 ERROR    Oops! there is an error
[catcher] 2018/06/24 12:34:56.789 WARNING  This should be considered as a warning message
[catcher] 2018/06/24 12:34:56.789 INFO     This should go directly to output
Example (SettingLoggingLevel)
// Logging level could be set by explicitely declaring the hook
log := New("console", NewConsoleHook("", logrus.InfoLevel))
log.Println("The logging level is set to", log.GetLevel())

// Or it can also be set after initializing the logger
// It is possible to use either a logrus.Level or a string to specify the level
log = New("console")
log.SetHookLevel("", "trace")
log.Println("The logging level is set to", log.GetLevel())
Output:
The logging level is set to info
The logging level is set to trace

func (*Logger) AddConsole added in v0.2.0

func (logger *Logger) AddConsole(name string, level interface{}, format ...interface{}) *Logger

AddConsole adds a console hook to the current logger.

Example
log := getTestLogger("json")

// We add an additional console hook.
log.AddConsole("json", logrus.WarnLevel, new(logrus.JSONFormatter))
log.Warning("New JSON log")
Output:
[json] 2018/06/24 12:34:56.789 WARNING  New JSON log
{"level":"warning","module-field":"json","msg":"New JSON log","time":"2018-06-24T12:34:56Z"}
Example (Overwrite)
log := getTestLogger("json")

// We overwrite the default console hook by not specifying a name to our new console.
// We also set the JSON formatter to pretty format the JSON code.
log.AddConsole("", logrus.WarnLevel, &logrus.JSONFormatter{PrettyPrint: true})
log.Warning("New JSON log")
Output:
{
  "level": "warning",
  "module-field": "json",
  "msg": "New JSON log",
  "time": "2018-06-24T12:34:56Z"
}

func (*Logger) AddError added in v0.2.0

func (logger *Logger) AddError(err error)

AddError let functions to add error to the current logger indicating that something went wrong in the logging process.

func (*Logger) AddFile added in v0.2.0

func (logger *Logger) AddFile(filename string, isDir bool, level interface{}, format ...interface{}) *Logger

AddFile adds a file hook to the current logger.

Example
log := getTestLogger("file")

var logfile string
if temp, err := ioutil.TempFile("", "example"); err != nil {
	log.Fatal(err)
} else {
	logfile = temp.Name()
	defer os.Remove(logfile)
}

log.AddFile(logfile, false, logrus.TraceLevel)
log.Info("This is information")
log.Warning("This is a warning")

content, _ := ioutil.ReadFile(logfile)
fmt.Println("Content of the log file is:")
fmt.Println(string(content))
Output:
[file] 2018/06/24 12:34:56.789 WARNING  This is a warning
Content of the log file is:

# 2018/06/24 12:34:56.789
[file] 2018/06/24 12:34:56.789 INFO     This is information
[file] 2018/06/24 12:34:56.789 WARNING  This is a warning
Example (Folder)
log := getTestLogger("file")

logDir, err := ioutil.TempDir("", "example")
if err != nil {
	log.Fatal(err)
}
defer os.RemoveAll(logDir)

// Adding a log folder and creating a child logger
log.AddFile(logDir, true, logrus.TraceLevel)
childLogger := log.Child("folder/module")

// Logging into the main logger and the child logger
log.Info("This is information")
childLogger.Warning("This is a warning")
childLogger.Info("This is information")

// Reading the main logger logs
firstFile := filepath.Join(logDir, "file.log")
firstContent, _ := ioutil.ReadFile(firstFile)
fmt.Println("Content of the first log file is:")
fmt.Println(string(firstContent))

// Reading the child logger logs
secondFile := filepath.Join(logDir, "file.folder", "module.log")
secondContent, _ := ioutil.ReadFile(secondFile)
fmt.Println("Content of the second log file is:")
fmt.Println(string(secondContent))
Output:
[file:folder/module] 2018/06/24 12:34:56.789 WARNING  This is a warning
Content of the first log file is:
# 2018/06/24 12:34:56.789
[file] 2018/06/24 12:34:56.789 INFO     This is information

Content of the second log file is:
# 2018/06/24 12:34:56.789
[file:folder/module] 2018/06/24 12:34:56.789 WARNING  This is a warning
[file:folder/module] 2018/06/24 12:34:56.789 INFO     This is information
Example (FolderWithInvalidModuleName)
// Create a test logger with lots of special chars in its name
loggerName := "/abc:def!/g$%?&*().,;`^<>/"
log := getTestLogger(loggerName)

logDir, err := ioutil.TempDir("", "example")
if err != nil {
	log.Fatal(err)
}
defer os.RemoveAll(logDir)

// Adding a log folder
log.AddFile(logDir, true, logrus.TraceLevel)

// Logging into the main logger and the child logger
log.Info("This is information")

// Reading the logs (all the special chars except OS separators and module separators (:) will be removed from the file name)
firstFile := filepath.Join(logDir, "abc.def", "g.log")
firstContent, _ := ioutil.ReadFile(firstFile)
fmt.Println(string(firstContent))
Output:
# 2018/06/24 12:34:56.789
[/abc:def!/g$%?&*().,;`^<>/] 2018/06/24 12:34:56.789 INFO     This is information

func (*Logger) AddHook added in v0.2.0

func (logger *Logger) AddHook(name string, level interface{}, hook logrus.Hook) *Logger

AddHook adds a hook to the hook collection and associated it with a name and a level. Can also be used to replace an existing hook.

func (*Logger) AddHooks added in v0.2.0

func (logger *Logger) AddHooks(hooks ...*Hook) *Logger

AddHooks adds a collection of hook wrapper as hook to the current logger.

func (*Logger) AddTime added in v0.2.0

func (logger *Logger) AddTime(duration time.Duration) *Logger

AddTime add the specified duration to the current logger if its time has been freezed. Useful for testing.

Example
log := getTestLogger("time", "Trace")

// We can create a logger with a fix moment in time.
t, _ := time.Parse(time.RFC3339, "2020-12-25T00:00:00Z")
log = log.WithTime(t)
log.Info("Log from fixed time")
log.AddTime(5 * time.Second).Trace("Log 5 seconds later")
log.AddTime(8 * time.Millisecond).Warning("Log 8 more milliseconds later")
Output:
[time] 2020/12/25 00:00:00.000 INFO     Log from fixed time
[time] 2020/12/25 00:00:05.000 TRACE    Log 5 seconds later
[time] 2020/12/25 00:00:05.008 WARNING  Log 8 more milliseconds later

func (*Logger) Child added in v0.2.0

func (logger *Logger) Child(child string) *Logger

Child clones the logger, appending the child's name to the parent's module name.

Example
log := getTestLogger("original", logrus.TraceLevel)
log.Info("Log from original")
log.Child("1").Trace("Log from first child")
log.Child("2").Trace("Log from second child")
Output:
[original] 2018/06/24 12:34:56.789 INFO     Log from original
[original:1] 2018/06/24 12:34:56.789 TRACE    Log from first child
[original:2] 2018/06/24 12:34:56.789 TRACE    Log from second child

func (*Logger) ClearError added in v0.2.0

func (logger *Logger) ClearError() error

ClearError cleans up the current error state of the logging process. It also returns the current error state.

func (*Logger) Close added in v0.2.0

func (logger *Logger) Close() error

Close implements io.Closer

func (*Logger) Copy added in v0.2.0

func (logger *Logger) Copy(module ...string) *Logger

Copy returns a new logger with the same hooks but a different module name. module is optional, if not supplied, the original module name will copied. If many name are supplied, they are joined with a - separator.

Example
log := getTestLogger("original", logrus.TraceLevel)
log.Info("Log from original")
log.Copy("copy").Trace("Log from copy")
log.Copy("").Debug("I have no module")
log.Copy().Debug("I have the same module as the original")
Output:
[original] 2018/06/24 12:34:56.789 INFO     Log from original
[copy] 2018/06/24 12:34:56.789 TRACE    Log from copy
2018/06/24 12:34:56.789 DEBUG    I have no module
[original] 2018/06/24 12:34:56.789 DEBUG    I have the same module as the original

func (*Logger) Formatter added in v0.3.0

func (logger *Logger) Formatter() (result *Formatter)

Formatter returns the Formatter associated to the default console hook.

Example (RoundDuration)
log := getTestLogger("RoundDuration", logrus.InfoLevel)

// We set the format of the log to include fields
log.SetFormat("%time% %globaldelay:round% %level:upper% %message%")
log.Formatter().RoundDuration = 5 * time.Millisecond

log.Info("Starting")
for i := time.Duration(1); i < 24*time.Hour; {
	i *= 10
	log.WithTime(baseTime.Add(i)).Infof("%v later", i)
}
Output:
2018/06/24 12:34:56.789 (<5ms) INFO Starting
2018/06/24 12:34:56.789 (<5ms) INFO 10ns later
2018/06/24 12:34:56.789 (<5ms) INFO 100ns later
2018/06/24 12:34:56.789 (<5ms) INFO 1µs later
2018/06/24 12:34:56.789 (<5ms) INFO 10µs later
2018/06/24 12:34:56.789 (<5ms) INFO 100µs later
2018/06/24 12:34:56.790 (<5ms) INFO 1ms later
2018/06/24 12:34:56.799 (10ms) INFO 10ms later
2018/06/24 12:34:56.889 (100ms) INFO 100ms later
2018/06/24 12:34:57.789 (1s) INFO 1s later
2018/06/24 12:35:06.789 (10s) INFO 10s later
2018/06/24 12:36:36.789 (1m40s) INFO 1m40s later
2018/06/24 12:51:36.789 (16m40s) INFO 16m40s later
2018/06/24 15:21:36.789 (2h47m) INFO 2h46m40s later
2018/06/25 16:21:36.789 (1d3h47m) INFO 27h46m40s later

func (*Logger) GetDefaultConsoleHook added in v0.3.0

func (logger *Logger) GetDefaultConsoleHook() *Hook

GetDefaultConsoleHook returns the default console hook.

func (*Logger) GetDefaultConsoleHookLevel added in v0.3.0

func (logger *Logger) GetDefaultConsoleHookLevel() logrus.Level

GetDefaultConsoleHookLevel returns the logging level associated to the default console hook.

func (*Logger) GetDefaultInnerHook added in v0.3.0

func (logger *Logger) GetDefaultInnerHook() (result logrus.Hook)

GetDefaultInnerHook returns the inner hook actually used by the default console hook.

func (*Logger) GetError added in v0.2.0

func (logger *Logger) GetError() error

GetError returns the current error state of the logging process.

func (*Logger) GetFormatter added in v0.3.0

func (logger *Logger) GetFormatter() (result logrus.Formatter)

GetFormatter returns the formater associated to the default console hook.

func (*Logger) GetHookLevel added in v0.2.0

func (logger *Logger) GetHookLevel(name string) logrus.Level

GetHookLevel returns the logging level associated with a specific logger.

func (*Logger) GetLevel added in v0.2.0

func (logger *Logger) GetLevel() logrus.Level

GetLevel returns the highest logger level registered by the hooks.

func (*Logger) GetModule added in v0.2.0

func (logger *Logger) GetModule() string

GetModule returns the module name associated to the current logger.

func (*Logger) Hook added in v0.2.0

func (logger *Logger) Hook(name string) *Hook

Hook returns the hook identified by name.

func (*Logger) IsLevelEnabled added in v0.2.0

func (logger *Logger) IsLevelEnabled(level logrus.Level) bool

IsLevelEnabled checks if the log level of the logger is greater than the level param

func (*Logger) ListHooks added in v0.2.0

func (logger *Logger) ListHooks() []string

ListHooks returns the list of registered hook names.

func (*Logger) Print added in v0.2.0

func (logger *Logger) Print(args ...interface{})

Print acts as fmt.Print but sends the output to a special logging level that allows multiple output support through Hooks.

ATTENTION, default behaviour for logrus.Print is to log at Info level.

func (*Logger) Printf added in v0.2.0

func (logger *Logger) Printf(format string, args ...interface{})

Printf acts as fmt.Printf but sends the output to a special logging level that allows multiple output support through Hooks.

ATTENTION, default behaviour for logrus.Printf is to log at Info level.

func (*Logger) Println added in v0.2.0

func (logger *Logger) Println(args ...interface{})

Println acts as fmt.Println but sends the output to a special logging level that allows multiple output support through Hooks.

ATTENTION, default behaviour for logrus.Println is to log at Info level.

func (*Logger) RemoveHook added in v0.2.0

func (logger *Logger) RemoveHook(name string) *Logger

RemoveHook deletes a hook from the hook collection.

func (*Logger) SetAllOutputs added in v0.3.0

func (logger *Logger) SetAllOutputs(out io.Writer) *Logger

SetAllOutputs allows configuring the output and the logging stream on the default console hook if there is.

func (*Logger) SetColor added in v0.3.0

func (logger *Logger) SetColor(color bool) *Logger

SetColor allows setting color mode on the default console hook if there is.

func (*Logger) SetDefaultConsoleHookLevel added in v0.3.0

func (logger *Logger) SetDefaultConsoleHookLevel(level interface{}) error

SetDefaultConsoleHookLevel set a new log level for the default console hook.

func (*Logger) SetExitFunc added in v0.2.0

func (logger *Logger) SetExitFunc(exitFunc func(int))

SetExitFunc let user define what should be executed when a logging call exit (default is call to os.Exit(int)).

func (*Logger) SetFormat added in v0.3.0

func (logger *Logger) SetFormat(formats ...interface{}) *Logger

SetFormat allows setting a format string on the default console hook if there is.

func (*Logger) SetFormatter added in v0.3.0

func (logger *Logger) SetFormatter(formatter logrus.Formatter) *Logger

SetFormatter allows setting a formatter to the default console hook if there is.

func (*Logger) SetHookLevel added in v0.2.0

func (logger *Logger) SetHookLevel(name string, level interface{}) error

SetHookLevel set a new log level for a registered hook.

func (*Logger) SetModule added in v0.3.0

func (logger *Logger) SetModule(module string) *Logger

SetModule sets the module name associated to the current logger.

func (*Logger) SetOut added in v0.3.0

func (logger *Logger) SetOut(out io.Writer) *Logger

SetOut allows configuring the logging stream on the default console hook if there is.

func (*Logger) SetReportCaller added in v0.2.0

func (logger *Logger) SetReportCaller(reportCaller bool) *Logger

SetReportCaller enables caller reporting to be added to each log entry.

func (*Logger) SetStdout added in v0.3.0

func (logger *Logger) SetStdout(out io.Writer) *Logger

SetStdout allows configuring the output stream on the default console hook if there is.

func (*Logger) TryAddHook added in v0.2.0

func (logger *Logger) TryAddHook(name string, level interface{}, hook logrus.Hook) (*Logger, error)

TryAddHook adds a hook to the hook collection and associated it with a name and a level. Can also be used to replace an existing hook.

func (*Logger) WithContext added in v0.2.0

func (logger *Logger) WithContext(ctx context.Context) *Logger

WithContext return a new logger with a new context.

func (*Logger) WithField added in v0.2.0

func (logger *Logger) WithField(key string, value interface{}) *Logger

WithField return a new logger with a single additional entry.

Example
log := getTestLogger("field", "Trace")

// We set the format of the log to include fields
log.SetFormat("%module:square% %time% %level:upper% %message% %fields%.")

// We create a new logger with additional context
log2 := log.WithField("hello", "world!").WithField("pi", math.Pi)
log.Info("No additional field")
log2.Info("With additional fields")
Output:
[field] 2018/06/24 12:34:56.789 INFO No additional field .
[field] 2018/06/24 12:34:56.789 INFO With additional fields hello=world! pi=3.141592653589793.

func (*Logger) WithFields added in v0.2.0

func (logger *Logger) WithFields(fields logrus.Fields) *Logger

WithFields return a new logger with a new fields value.

Example
log := getTestLogger("field", "Trace")

// We set the format of the log to include fields
log.SetFormat("%module:square% %time% %level:upper% %message% %fields%.")

// We create a new logger with additional context
log2 := log.WithFields(logrus.Fields{
	"hello": "world!",
	"pi":    math.Pi,
})
log.Info("No additional field")
log2.Info("With additional fields")
Output:
[field] 2018/06/24 12:34:56.789 INFO No additional field .
[field] 2018/06/24 12:34:56.789 INFO With additional fields hello=world! pi=3.141592653589793.

func (*Logger) WithTime added in v0.2.0

func (logger *Logger) WithTime(time time.Time) *Logger

WithTime return a new logger with a fixed time for log entry (useful for testing).

Example
log := getTestLogger("time", logrus.InfoLevel)

// We can create a logger with a fix moment in time.
t, _ := time.Parse(time.RFC3339, "2020-12-25T00:00:00Z")
log = log.WithTime(t)
log.Info("Log from fixed time")
Output:
[time] 2020/12/25 00:00:00.000 INFO     Log from fixed time

func (*Logger) Write added in v0.2.0

func (logger *Logger) Write(writeBuffer []byte) (int, error)

This methods intercepts every message written to stream if Catcher is set and determines if a logging function should be used.

Directories

Path Synopsis
Package multicolor is a complement to github.com/fatih/color.
Package multicolor is a complement to github.com/fatih/color.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL