multilogger

package module
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Jul 22, 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%"
)
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 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 SetDurationFormat added in v0.5.2

func SetDurationFormat(style DurationFormat, rounded, longUnit, override bool) bool

SetDurationFormat globally set the duration format preferences (across executables).

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 (globally set across executables).

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 = GetDurationFunc(NativeFormat, false, false)

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

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 DurationFormat added in v0.5.2

type DurationFormat int

DurationFormat represents the representation of a duration rendering format

const (
	// NativeFormat formats durations using the native golang duration format.
	NativeFormat DurationFormat = iota
	// PreciseFormat formats durations with precise unit for each segment 1d2h3m4s5ms6µs.
	PreciseFormat
	// ClassicFormat formats durations with higher units such as days, months, years,
	// but use floating value bellow minutes as native golang format does.
	ClassicFormat
)

type DurationFunc added in v0.5.2

type DurationFunc func(time.Duration) string

DurationFunc is the prototype used to represent a duration format function.

func GetDurationFunc added in v0.5.2

func GetDurationFunc(format DurationFormat, rounded, longUnit bool) DurationFunc

GetDurationFunc returns a function that can be used to format a duration.

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\tClassic Rounded\tPrecise\tPrecise Rounded\tNative long\tRounded long\t.")
fmt.Fprintln(w, "------\t-------\t---------------\t-------\t---------------\t-----------\t------------\t.")

print := func(duration time.Duration) {
	fmt.Fprintf(w, "%v\t", duration)
	fmt.Fprintf(w, "%s\t", GetDurationFunc(ClassicFormat, false, false)(duration))
	fmt.Fprintf(w, "%s\t", GetDurationFunc(ClassicFormat, true, false)(duration))
	fmt.Fprintf(w, "%s\t", GetDurationFunc(PreciseFormat, false, false)(duration))
	fmt.Fprintf(w, "%s\t", GetDurationFunc(PreciseFormat, true, false)(duration))
	fmt.Fprintf(w, "%s\t", GetDurationFunc(NativeFormat, false, true)(duration))
	fmt.Fprintf(w, "%s\t", GetDurationFunc(PreciseFormat, true, true)(duration))
	fmt.Fprintln(w, ".")
}

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

Native                 Classic                       Classic Rounded     Precise                          Precise Rounded     Native long                                 Rounded long                      .
------                 -------                       ---------------     -------                          ---------------     -----------                                 ------------                      .
0s                     0s                            0s                  0s                               0s                  0 second                                    0 second                          .
1ns                    1ns                           1ns                 1ns                              1ns                 1 nanosecond                                1 nanosecond                      .
10ns                   10ns                          10ns                10ns                             10ns                10 nanoseconds                              10 nanoseconds                    .
5ns                    5ns                           5ns                 5ns                              5ns                 5 nanoseconds                               5 nanoseconds                     .
1µs                    1µs                           1µs                 1µs                              1µs                 1 microsecond                               1 microsecond                     .
10µs                   10µs                          10µs                10µs                             10µs                10 microseconds                             10 microseconds                   .
5.005µs                5.005µs                       5.01µs              5µs5ns                           5µs10ns             5.005 microseconds                          5 microseconds 10 nanoseconds     .
1ms                    1ms                           1ms                 1ms                              1ms                 1 millisecond                               1 millisecond                     .
10ms                   10ms                          10ms                10ms                             10ms                10 milliseconds                             10 milliseconds                   .
5.005005ms             5.005005ms                    5.01ms              5ms5µs5ns                        5ms10µs             5.005005 milliseconds                       5 milliseconds 10 microseconds    .
1s                     1s                            1s                  1s                               1s                  1 second                                    1 second                          .
10s                    10s                           10s                 10s                              10s                 10 seconds                                  10 seconds                        .
5.005005005s           5.005005005s                  5.01s               5s5ms5µs5ns                      5s10ms              5.005005005 seconds                         5 seconds 10 milliseconds         .
1m0s                   1m                            1m                  1m                               1m                  1 minute                                    1 minute                          .
10m0s                  10m                           10m                 10m                              10m                 10 minutes                                  10 minutes                        .
5m5.005005005s         5m5.005005005s                5m5s                5m5s5ms5µs5ns                    5m5s                5 minutes 5.005005005 seconds               5 minutes 5 seconds               .
1h0m0s                 1h                            1h                  1h                               1h                  1 hour                                      1 hour                            .
10h0m0s                10h                           10h                 10h                              10h                 10 hours                                    10 hours                          .
5h5m5.005005005s       5h5m5.005005005s              5h5m                5h5m5s5ms5µs5ns                  5h5m                5 hours 5 minutes 5.005005005 seconds       5 hours 5 minutes                 .
24h0m0s                1d                            1d                  1d                               1d                  24 hours                                    1 day                             .
240h0m0s               1w3d                          1w3d                1w3d                             1w3d                240 hours                                   1 week 3 days                     .
125h5m5.005005005s     5d5h5m5.005005005s            5d5h5m              5d5h5m5s5ms5µs5ns                5d5h5m              125 hours 5 minutes 5.005005005 seconds     5 days 5 hours 5 minutes          .
168h0m0s               7d                            7d                  7d                               7d                  168 hours                                   7 days                            .
1680h0m0s              2mo1w3d                       2mo1w3d             2mo1w3d                          2mo1w3d             1680 hours                                  2 months 1 week 3 days            .
965h5m5.005005005s     5w5d5h5m5.005005005s          5w5d                5w5d5h5m5s5ms5µs5ns              5w5d                965 hours 5 minutes 5.005005005 seconds     5 weeks 5 days                    .
720h0m0s               4w2d                          4w2d                4w2d                             4w2d                720 hours                                   4 weeks 2 days                    .
7200h0m0s              10mo                          10mo                10mo                             10mo                7200 hours                                  10 months                         .
4565h5m5.005005005s    6mo1w3d5h5m5.005005005s       6mo1w3d             6mo1w3d5h5m5s5ms5µs5ns           6mo1w3d             4565 hours 5 minutes 5.005005005 seconds    6 months 1 week 3 days            .
8640h0m0s              1y                            1y                  1y                               1y                  8640 hours                                  1 year                            .
86400h0m0s             10y                           10y                 10y                              10y                 86400 hours                                 10 years                          .
47765h5m5.005005005s   5y6mo1w3d5h5m5.005005005s     5y6mo1w3d           5y6mo1w3d5h5m5s5ms5µs5ns         5y6mo1w3d           47765 hours 5 minutes 5.005005005 seconds   5 years 6 months 1 week 3 days    .
83694h5m4.003002001s   9y8mo7d6h5m4.003002001s       9y8mo7d             9y8mo7d6h5m4s3ms2µs1ns           9y8mo7d             83694 hours 5 minutes 4.003002001 seconds   9 years 8 months 7 days           .
836940h50m40.03002001s 96y10mo1w5d12h50m40.03002001s 96y10mo1w6d         96y10mo1w5d12h50m40s30ms20µs10ns 96y10mo1w6d         836940 hours 50 minutes 40.03002001 seconds 96 years 10 months 1 week 6 days  .
466235h30m25.02001501s 53y11mo2w2d11h30m25.02001501s 53y11mo2w2d         53y11mo2w2d11h30m25s20ms15µs10ns 53y11mo2w2d         466235 hours 30 minutes 25.02001501 seconds 53 years 11 months 2 weeks 2 days .

func TryGetDurationFunc added in v0.5.2

func TryGetDurationFunc(format DurationFormat, rounded, longUnit bool) (DurationFunc, error)

TryGetDurationFunc returns a function that can be used to format a duration.

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