xlog

package module
v0.9.39 Latest Latest
Warning

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

Go to latest
Published: Apr 29, 2024 License: Apache-2.0 Imports: 17 Imported by: 64

README

Coverage Status

xlog logging package

Cloned from https://github.com/coreos/pkg/tree/master/capnslog

This clone has slight modifications on the original code, adding ability to specify log lever per package, and exposing Logger interface, not an implementation structure.

In this implementation the DEBUG level is above TRACE as trace is used to trace important functions calls and maybe enable on the cloud more friequently than DEBUG

How to use

var logger = xlog.NewPackageLogger("github.com/yourorg/yourrepo", "yourpackage")

logger.KV(xlog.INFO, "version", v1, "any", override)

How to configure

	if withStackdriver {
		formatter := stackdriver.NewFormatter(os.Stderr, cfg.Logs.LogsName)
		xlog.SetFormatter(formatter)
	} else {
		formatter := xlog.NewColorFormatter(os.Stderr, true)
		xlog.SetFormatter(formatter)
	}

Set log level for different packages

Config example:

log_levels: 
  - repo: "*"
    level: INFO
  - repo: github.com/effective-security/server
    package: "*"
    level: TRACE

Configuration at start up:

	// Set log levels for each repo
	if cfg.LogLevels != nil {
		for _, ll := range cfg.LogLevels {
			l, _ := xlog.ParseLevel(ll.Level)
			if ll.Repo == "*" {
				xlog.SetGlobalLogLevel(l)
			} else {
				xlog.SetPackageLogLevel(ll.Repo, ll.Package, l)
			}
			logger.Infof("logger=%q, level=%v", ll.Repo, l)
		}
	}

Need to log to files?

This example shows how to use with logrotate package

	if cfg.Logs.Directory != "" && cfg.Logs.Directory != nullDevName {
		os.MkdirAll(cfg.Logs.Directory, 0644)

		var sink io.Writer
		if flags.isStderr {
			// This will allow to also print the logs on stderr
			sink = os.Stderr
			xlog.SetFormatter(xlog.NewColorFormatter(sink, true))
		} else {
			// do not redirect stderr to our log files
			log.SetOutput(os.Stderr)
		}

		logRotate, err := logrotate.Initialize(cfg.Logs.Directory, cfg.ServiceName, cfg.Logs.MaxAgeDays, cfg.Logs.MaxSizeMb, true, sink)
		if err != nil {
			logger.Errorf("reason=logrotate, folder=%q, err=[%+v]", cfg.Logs.Directory, err)
			return errors.WithMessage(err, "failed to initialize log rotate")
		}
		// Close logRotate when application terminates
		app.OnClose(logRotate)
	}

Design Principles

package main is the place where logging gets turned on and routed

A library should not touch log options, only generate log entries. Libraries are silent until main lets them speak.

All log options are runtime-configurable

Still the job of main to expose these configurations. main may delegate this to, say, a configuration webhook, but does so explicitly.

There is one log object per package. It is registered under its repository and package name

main activates logging for its repository and any dependency repositories it would also like to have output in its logstream. main also dictates at which level each subpackage logs.

There is one output stream, and it is an io.Writer composed with a formatter

Splitting streams is probably not the job of your program, but rather, your log aggregation framework. If you must split output streams, again, main configures this and you can write a very simple two-output struct that satisfies io.Writer.

Fancy colorful formatting and JSON output are beyond the scope of a basic logging framework -- they're application/log-collector dependant. These are, at best, provided as options, but more likely, provided by your application.

Log objects are an interface

An object knows best how to print itself. Log objects can collect more interesting metadata if they wish, however, because text isn't going away anytime soon, they must all be marshalable to text. The simplest log object is a string, which returns itself. If you wish to do more fancy tricks for printing your log objects, see also JSON output -- introspect and write a formatter which can handle your advanced log interface. Making strings is the only thing guaranteed.

Log levels have specific meanings:
  • CRITICAL: Unrecoverable. Must fail.
  • ERROR: Data has been lost, a request has failed for a bad reason, or a required resource has been lost
  • WARNING: (Hopefully) Temporary conditions that may cause errors, but may work fine. A replica disappearing (that may reconnect) is a warning.
  • NOTICE: Normal, but important (uncommon) log information.
  • INFO: Normal, working log information, everything is fine, but helpful notices for auditing or common operations.
  • TRACE: Anything goes, from logging every function call as part of a common operation, to tracing execution of a query.
  • DEBUG: Print debug data.

Documentation

Overview

Package xlog has slight modifications on the original code, adding ability to specify log lever per package, and exposing Logger interface, not an implementation structure.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ColorOff = []byte("\033[0m")
)

color pallete map

View Source
var ExitFunc = os.Exit

ExitFunc can be overriten

View Source
var LevelColors = map[LogLevel][]byte{
	CRITICAL: colorLightRed,
	ERROR:    colorLightRed,
	WARNING:  colorLightOrange,
	NOTICE:   colorLightGreen,
	INFO:     colorLightCyan,
	DEBUG:    colorDebug,
	TRACE:    colorGray,
}

LevelColors provides colors map

View Source
var Stderr *log.Logger

Stderr is an instance of standard logger to Stderr

View Source
var TimeNowFn = time.Now

TimeNowFn to override in unit tests

Functions

func Caller

func Caller(depth int) (name string, file string, line int)

Caller returns caller function name, and location

func ContextEntries

func ContextEntries(ctx context.Context) []any

ContextEntries returns log entries

func ContextWithKV

func ContextWithKV(ctx context.Context, entries ...any) context.Context

ContextWithKV returns context with values to be added to logs, entries in "key1=value1, ..., keyN=valueN" format.

Example
package main

import (
	"context"
	"os"

	"github.com/effective-security/xlog"
)

func main() {
	var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "string_formatter")
	f := xlog.NewStringFormatter(os.Stdout)
	xlog.SetFormatter(f)

	ctx := xlog.ContextWithKV(context.Background(), "key1", 1, "key2", "val2")

	logger.ContextKV(ctx, xlog.INFO, "k3", 3)

}
Output:

time=2021-04-01T00:00:00Z level=I pkg=string_formatter func=ExampleContextWithKV key1=1 key2="val2" k3=3

func EscapedString

func EscapedString(value any) string

EscapedString returns string value stuitable for logging

func OnError

func OnError(fn OnErrorFn)

OnError allows to specify a callback for ERROR levels. This is useful to reports metrics on ERROR in a package

func SetFormatter

func SetFormatter(f Formatter)

SetFormatter sets the formatting function for all logs.

func SetGlobalLogLevel

func SetGlobalLogLevel(l LogLevel)

SetGlobalLogLevel sets the log level for all packages in all repositories registered with PackageLogger.

func SetPackageLogLevel

func SetPackageLogLevel(repo, pkg string, l LogLevel)

SetPackageLogLevel sets the log level for a package in repo logger

func SetRepoLevel

func SetRepoLevel(cfg RepoLogLevel)

SetRepoLevel sets repo log level

func SetRepoLevels

func SetRepoLevels(cfg []RepoLogLevel)

SetRepoLevels sets repo log levels per package

func SetRepoLogLevel

func SetRepoLogLevel(repo string, l LogLevel)

SetRepoLogLevel sets the log level for all packages in repo logger

Types

type Formatter

type Formatter interface {
	// Format log entry string to the stream,
	// the entries are separated by space
	Format(pkg string, level LogLevel, depth int, entries ...any)
	// FormatKV log entry string to the stream,
	// the entries are key/value pairs
	FormatKV(pkg string, level LogLevel, depth int, entries ...any)
	// Flush the logs
	Flush()
	// Options allows to configure formatter behavior
	Options(ops ...FormatterOption) Formatter
}

Formatter defines an interface for formatting logs

func GetFormatter

func GetFormatter() Formatter

GetFormatter returns current formatter

func NewDefaultFormatter

func NewDefaultFormatter(out io.Writer) Formatter

NewDefaultFormatter returns an instance of default formatter

func NewJSONFormatter

func NewJSONFormatter(w io.Writer) Formatter

NewJSONFormatter returns an instance of JsonFormatter

func NewNilFormatter

func NewNilFormatter() Formatter

NewNilFormatter is a helper to produce a new LogFormatter struct. It logs no messages so that you can cause part of your logging to be silent.

func NewPrettyFormatter

func NewPrettyFormatter(w io.Writer) Formatter

NewPrettyFormatter returns an instance of PrettyFormatter

func NewStringFormatter

func NewStringFormatter(w io.Writer) Formatter

NewStringFormatter returns string-based formatter

type FormatterOption

type FormatterOption int

FormatterOption specifies additional formatter options

const (
	// FormatWithCaller allows to configure if the caller shall be logged
	FormatWithCaller FormatterOption = iota + 1
	// FormatNoCaller disables log the caller
	FormatNoCaller
	// FormatSkipTime allows to configure skipping the time log
	FormatSkipTime
	// FormatSkipLevel allows to configure skipping the level log
	FormatSkipLevel
	// FormatWithLocation allows to print the file:line for each log
	FormatWithLocation
	// FormatWithColor allows to print color logs
	FormatWithColor
	// FormatPrintEmpty allows to print empty values
	FormatPrintEmpty
)

type JSONFormatter

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

JSONFormatter provides default logs format

Example
package main

import (
	"os"
	"time"

	"github.com/effective-security/xlog"
	"github.com/pkg/errors"
)

func main() {
	xlog.TimeNowFn = func() time.Time {
		date, _ := time.Parse("2006-01-02", "2021-04-01")
		return date
	}

	var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "json_formatter")
	f := xlog.NewJSONFormatter(os.Stdout)
	xlog.SetFormatter(f)

	list := []string{"item 1", "item 2"}
	obj := struct {
		Foo     string
		Bar     int
		private string
	}{"foo", 5, "shoud not print"}

	f.Format("format", xlog.WARNING, 1, "string1", "string 2", list, obj)
	f.FormatKV("format_kv", xlog.WARNING, 1, "key1", "value 2", "key2", 2, "list", list, "obj", obj)

	logger.KV(xlog.ERROR, "reason", "with time, level, caller", "err", errors.New("just a string").Error(), "number", 123)

	f.Options(xlog.FormatWithLocation)
	logger.KV(xlog.ERROR, "reason", "location",
		"err", errors.New("just a string").Error(),
		"number", 123,
		"list", list,
		"obj", obj,
	)

	f.Options(xlog.FormatSkipTime, xlog.FormatSkipLevel, xlog.FormatNoCaller)
	logger.KV(xlog.ERROR, "reason", "skip time, level, caller",
		"err", errors.New("just a string").Error(),
		"number", 123,
		"list", list,
		"obj", obj,
	)

}
Output:

{"func":"ExampleJSONFormatter","level":"W","msg":"string1string 2[item 1 item 2] {foo 5 shoud not print}","pkg":"format","time":"2021-04-01T00:00:00Z"}
{"func":"ExampleJSONFormatter","key1":"value 2","key2":2,"level":"W","list":["item 1","item 2"],"obj":{"Foo":"foo","Bar":5},"pkg":"format_kv","time":"2021-04-01T00:00:00Z"}
{"err":"just a string","func":"ExampleJSONFormatter","level":"E","number":123,"pkg":"json_formatter","reason":"with time, level, caller","src":"example_test.go:140","time":"2021-04-01T00:00:00Z"}
{"err":"just a string","func":"ExampleJSONFormatter","level":"E","list":["item 1","item 2"],"number":123,"obj":{"Foo":"foo","Bar":5},"pkg":"json_formatter","reason":"location","src":"example_test.go:143","time":"2021-04-01T00:00:00Z"}
{"err":"just a string","func":"ExampleJSONFormatter","list":["item 1","item 2"],"number":123,"obj":{"Foo":"foo","Bar":5},"pkg":"json_formatter","reason":"skip time, level, caller","src":"example_test.go:151"}

func (*JSONFormatter) Flush

func (c *JSONFormatter) Flush()

Flush the logs

func (*JSONFormatter) Format

func (c *JSONFormatter) Format(pkg string, l LogLevel, depth int, entries ...any)

Format log entry string to the stream

func (*JSONFormatter) FormatKV

func (c *JSONFormatter) FormatKV(pkg string, l LogLevel, depth int, entries ...any)

FormatKV log entry string to the stream, the entries are key/value pairs

func (*JSONFormatter) Options

func (c *JSONFormatter) Options(ops ...FormatterOption) Formatter

Options allows to configure formatter behavior

type KeyValueLogger

type KeyValueLogger interface {
	// KV logs entries in "key1=value1, ..., keyN=valueN" format
	KV(level LogLevel, entries ...any)

	// ContextKV logs entries in "key1=value1, ..., keyN=valueN" format,
	// and add log entries from ctx as well.
	// ContextWithKV method can be used to add extra values to context
	ContextKV(ctx context.Context, level LogLevel, entries ...any)

	// WithValues adds some key-value pairs of context to a logger.
	// See Info for documentation on how key/value pairs work.
	WithValues(keysAndValues ...any) KeyValueLogger
}

KeyValueLogger interface for generic logger

type LogLevel

type LogLevel int8

LogLevel is the set of all log levels.

const (
	// CRITICAL is the lowest log level; only errors which will end the program will be propagated.
	CRITICAL LogLevel = iota - 1
	// ERROR is for errors that are not fatal but lead to troubling behavior.
	ERROR
	// WARNING is for errors which are not fatal and not errors, but are unusual. Often sourced from misconfigurations.
	WARNING
	// NOTICE is for normal but significant conditions.
	NOTICE
	// INFO is a log level for common, everyday log updates.
	INFO
	// TRACE is for (potentially) call by call tracing of programs.
	TRACE
	// DEBUG is the default hidden level for more verbose updates about internal processes.
	DEBUG
)

func ParseLevel

func ParseLevel(s string) (LogLevel, error)

ParseLevel translates some potential loglevel strings into their corresponding levels.

func (LogLevel) Char

func (l LogLevel) Char() string

Char returns a single-character representation of the log level.

func (*LogLevel) Set

func (l *LogLevel) Set(s string) error

Set the log level

func (LogLevel) String

func (l LogLevel) String() string

String returns a multi-character representation of the log level.

type Logger

type Logger interface {
	KeyValueLogger
	StdLogger
}

Logger interface for generic logger

func NewNilLogger

func NewNilLogger() Logger

NewNilLogger creates new nil logger

type NilFormatter

type NilFormatter struct {
}

NilFormatter is a no-op log formatter that does nothing.

func (*NilFormatter) Flush

func (*NilFormatter) Flush()

Flush is included so that the interface is complete, but is a no-op.

func (*NilFormatter) Format

func (*NilFormatter) Format(_ string, _ LogLevel, _ int, _ ...any)

Format does nothing.

func (*NilFormatter) FormatKV

func (*NilFormatter) FormatKV(pkg string, level LogLevel, depth int, entries ...any)

FormatKV log entry string to the stream, the entries are key/value pairs

func (*NilFormatter) Options

func (c *NilFormatter) Options(ops ...FormatterOption) Formatter

Options allows to configure formatter behavior

type NilLogger

type NilLogger struct {
}

NilLogger does not produce any output

func (*NilLogger) ContextKV

func (l *NilLogger) ContextKV(_ context.Context, _ LogLevel, _ ...any)

ContextKV logs entries in "key1=value1, ..., keyN=valueN" format, and add log entries from ctx as well. ContextWithKV method can be used to add extra values to context

func (*NilLogger) Debug

func (l *NilLogger) Debug(entries ...any)

Debug does nothing

func (*NilLogger) Debugf

func (l *NilLogger) Debugf(format string, args ...any)

Debugf does nothing

func (*NilLogger) Error

func (l *NilLogger) Error(entries ...any)

Error does nothing

func (*NilLogger) Errorf

func (l *NilLogger) Errorf(format string, args ...any)

Errorf does nothing

func (*NilLogger) Fatal

func (l *NilLogger) Fatal(args ...any)

Fatal does nothing

func (*NilLogger) Fatalf

func (l *NilLogger) Fatalf(format string, args ...any)

Fatalf does nothing

func (*NilLogger) Fatalln

func (l *NilLogger) Fatalln(args ...any)

Fatalln does nothing

func (*NilLogger) Info

func (l *NilLogger) Info(entries ...any)

Info does nothing

func (*NilLogger) Infof

func (l *NilLogger) Infof(format string, args ...any)

Infof does nothing

func (*NilLogger) KV

func (l *NilLogger) KV(_ LogLevel, entries ...any)

KV does nothing

func (*NilLogger) Notice

func (l *NilLogger) Notice(entries ...any)

Notice does nothing

func (*NilLogger) Noticef

func (l *NilLogger) Noticef(format string, args ...any)

Noticef does nothing

func (*NilLogger) Panic

func (l *NilLogger) Panic(args ...any)

Panic does nothing

func (*NilLogger) Panicf

func (l *NilLogger) Panicf(format string, args ...any)

Panicf does nothing

func (*NilLogger) Trace

func (l *NilLogger) Trace(entries ...any)

Trace does nothing

func (*NilLogger) Tracef

func (l *NilLogger) Tracef(format string, args ...any)

Tracef does nothing

func (*NilLogger) Warning

func (l *NilLogger) Warning(entries ...any)

Warning does nothing

func (*NilLogger) Warningf

func (l *NilLogger) Warningf(format string, args ...any)

Warningf does nothing

func (*NilLogger) WithValues

func (l *NilLogger) WithValues(keysAndValues ...any) KeyValueLogger

WithValues adds some key-value pairs of context to a logger. See Info for documentation on how key/value pairs work.

type OnErrorFn

type OnErrorFn func(pkg string)

OnErrorFn allows to be called when an error is logged in a package

type PackageLogger

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

PackageLogger is logger implementation for packages

func NewPackageLogger

func NewPackageLogger(repo string, pkg string) (p *PackageLogger)

NewPackageLogger creates a package logger object. This should be defined as a global var in your package, referencing your repo.

func (*PackageLogger) ContextKV

func (p *PackageLogger) ContextKV(ctx context.Context, l LogLevel, entries ...any)

ContextKV logs entries in "key1=value1, ..., keyN=valueN" format, and add log entries from ctx as well. ContextWithKV method can be used to add extra values to context

func (*PackageLogger) Debug

func (p *PackageLogger) Debug(entries ...any)

Debug is implementation for stdlib compatibility

func (*PackageLogger) Debugf

func (p *PackageLogger) Debugf(format string, args ...any)

Debugf is implementation for stdlib compatibility

func (*PackageLogger) Error

func (p *PackageLogger) Error(entries ...any)

Error is implementation for stdlib compatibility

func (*PackageLogger) Errorf

func (p *PackageLogger) Errorf(format string, args ...any)

Errorf is implementation for stdlib compatibility

func (*PackageLogger) Fatal

func (p *PackageLogger) Fatal(args ...any)

Fatal is implementation for stdlib compatibility

func (*PackageLogger) Fatalf

func (p *PackageLogger) Fatalf(format string, args ...any)

Fatalf is implementation for stdlib compatibility

func (*PackageLogger) Flush

func (p *PackageLogger) Flush()

Flush the logs

func (*PackageLogger) Info

func (p *PackageLogger) Info(entries ...any)

Info is implementation for stdlib compatibility

func (*PackageLogger) Infof

func (p *PackageLogger) Infof(format string, args ...any)

Infof is implementation for stdlib compatibility

func (*PackageLogger) KV

func (p *PackageLogger) KV(l LogLevel, entries ...any)

KV prints key=value pairs

func (*PackageLogger) LevelAt

func (p *PackageLogger) LevelAt(l LogLevel) bool

LevelAt returns the current log level

func (*PackageLogger) Log

func (p *PackageLogger) Log(l LogLevel, args ...any)

Log a message at any level between ERROR and TRACE

func (*PackageLogger) Logf

func (p *PackageLogger) Logf(l LogLevel, format string, args ...any)

Logf a formatted string at any level between ERROR and TRACE

func (*PackageLogger) Notice

func (p *PackageLogger) Notice(entries ...any)

Notice is implementation for stdlib compatibility

func (*PackageLogger) Noticef

func (p *PackageLogger) Noticef(format string, args ...any)

Noticef is implementation for stdlib compatibility

func (*PackageLogger) Panic

func (p *PackageLogger) Panic(args ...any)

Panic is implementation for stdlib compatibility

func (*PackageLogger) Panicf

func (p *PackageLogger) Panicf(format string, args ...any)

Panicf is implementation for stdlib compatibility

func (*PackageLogger) Trace

func (p *PackageLogger) Trace(entries ...any)

Trace is implementation for stdlib compatibility

func (*PackageLogger) Tracef

func (p *PackageLogger) Tracef(format string, args ...any)

Tracef is implementation for stdlib compatibility

func (*PackageLogger) Warning

func (p *PackageLogger) Warning(entries ...any)

Warning is implementation for stdlib compatibility

func (*PackageLogger) Warningf

func (p *PackageLogger) Warningf(format string, args ...any)

Warningf is implementation for stdlib compatibility

func (*PackageLogger) WithValues

func (p *PackageLogger) WithValues(keysAndValues ...any) KeyValueLogger

WithValues adds some key-value pairs of context to a logger. See Info for documentation on how key/value pairs work.

type PrettyFormatter

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

PrettyFormatter provides default logs format

Example
package main

import (
	"os"
	"time"

	"github.com/effective-security/xlog"
	"github.com/pkg/errors"
)

func main() {
	xlog.TimeNowFn = func() time.Time {
		date, _ := time.Parse("2006-01-02", "2021-04-01")
		return date
	}

	var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "pretty_formatter")
	f := xlog.NewPrettyFormatter(os.Stdout)
	xlog.SetFormatter(f)
	xlog.SetPackageLogLevel("github.com/effective-security/xlog", "pretty_formatter", xlog.DEBUG)

	list := []string{"item 1", "item 2"}
	obj := struct {
		Foo     string
		Bar     int
		private string
	}{"foo", 5, "shout not print"}

	f.Format("format", xlog.WARNING, 1, "string1", "string 2", list, obj)
	f.FormatKV("format_kv", xlog.DEBUG, 1, "key1", "value 2", "key2", 2, "list", list, "obj", obj)

	logger.KV(xlog.ERROR, "option", "with time, level, caller, collor", "err", errors.New("just a string").Error(), "number", 123)
	logger.KV(xlog.INFO, "option", "with time, level, caller, collor", "float", 1.1)
	logger.KV(xlog.NOTICE, "option", "with time, level, caller, collor", "key2", 2, "list", list, "obj", obj)
	logger.KV(xlog.TRACE, "option", "with time, level, caller, collor", "key2", 2, "list", list, "obj", obj)
	logger.KV(xlog.DEBUG, "option", "with time, level, caller, collor", "key2", 2, "list", list, "obj", obj)

	f.Options(xlog.FormatWithLocation)
	logger.KV(xlog.ERROR, "reason", "location",
		"err", errors.New("just a string").Error(),
		"number", 123,
		"list", list,
		"obj", obj,
	)

	f.Options(xlog.FormatSkipTime, xlog.FormatSkipLevel, xlog.FormatNoCaller)
	logger.KV(xlog.ERROR, "reason", "skip time, level, caller",
		"err", errors.New("just a string").Error(),
		"number", 123,
		"list", list,
		"obj", obj,
		"empty", "",
		"nil", nil,
	)

}
Output:

2021-04-01 00:00:00.000000 W | pkg=format, func=ExamplePrettyFormatter, "string1", "string 2", ["item 1","item 2"], {"Foo":"foo","Bar":5}
2021-04-01 00:00:00.000000 D | pkg=format_kv, func=ExamplePrettyFormatter, key1="value 2", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5}
2021-04-01 00:00:00.000000 E | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", err="just a string", number=123
2021-04-01 00:00:00.000000 I | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", float=1.1
2021-04-01 00:00:00.000000 N | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5}
2021-04-01 00:00:00.000000 T | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5}
2021-04-01 00:00:00.000000 D | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5}
2021-04-01 00:00:00.000000 E | pkg=pretty_formatter, src=example_test.go:91, func=ExamplePrettyFormatter, reason="location", err="just a string", number=123, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5}
pkg=pretty_formatter, src=example_test.go:99, reason="skip time, level, caller", err="just a string", number=123, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5}

func (*PrettyFormatter) Flush

func (c *PrettyFormatter) Flush()

Flush the logs

func (*PrettyFormatter) Format

func (c *PrettyFormatter) Format(pkg string, l LogLevel, depth int, entries ...any)

Format log entry string to the stream

func (*PrettyFormatter) FormatKV

func (c *PrettyFormatter) FormatKV(pkg string, l LogLevel, depth int, entries ...any)

FormatKV log entry string to the stream, the entries are key/value pairs

func (*PrettyFormatter) Options

func (c *PrettyFormatter) Options(ops ...FormatterOption) Formatter

Options allows to configure formatter behavior

type RepoLogLevel

type RepoLogLevel struct {
	// Repo specifies the repo name, or '*' for all repos [Global]
	Repo string `json:"repo,omitempty" yaml:"repo,omitempty"`
	// Package specifies the package name
	Package string `json:"package,omitempty" yaml:"package,omitempty"`
	// Level specifies the log level for the repo [ERROR,WARNING,NOTICE,INFO,DEBUG,TRACE].
	Level string `json:"level,omitempty" yaml:"level,omitempty"`
}

RepoLogLevel contains information about the log level per repo. Use * to set up global level.

func GetRepoLevels

func GetRepoLevels() []RepoLogLevel

GetRepoLevels returns currently configured levels

type RepoLogger

type RepoLogger map[string]*PackageLogger

RepoLogger specifies a map of repo => PackageLogger

func GetRepoLogger

func GetRepoLogger(repo string) (RepoLogger, error)

GetRepoLogger may return the handle to the repository's set of packages' loggers.

func MustRepoLogger

func MustRepoLogger(repo string) RepoLogger

MustRepoLogger returns the handle to the repository's packages' loggers.

func (RepoLogger) ParseLogLevelConfig

func (r RepoLogger) ParseLogLevelConfig(conf string) (map[string]LogLevel, error)

ParseLogLevelConfig parses a comma-separated string of "package=loglevel", in order, and returns a map of the results, for use in SetLogLevel.

func (RepoLogger) SetLogLevel

func (r RepoLogger) SetLogLevel(m map[string]LogLevel)

SetLogLevel takes a map of package names within a repository to their desired loglevel, and sets the levels appropriately. Unknown packages are ignored. "*" is a special package name that corresponds to all packages, and will be processed first.

func (RepoLogger) SetRepoLogLevel

func (r RepoLogger) SetRepoLogLevel(l LogLevel)

SetRepoLogLevel sets the log level for all packages in the repository.

type StdLogger

type StdLogger interface {
	Fatal(args ...any)
	Fatalf(format string, args ...any)

	Panic(args ...any)
	Panicf(format string, args ...any)

	Info(entries ...any)
	Infof(format string, args ...any)

	Error(entries ...any)
	Errorf(format string, args ...any)

	Warning(entries ...any)
	Warningf(format string, args ...any)

	Notice(entries ...any)
	Noticef(format string, args ...any)

	Debug(entries ...any)
	Debugf(format string, args ...any)

	Trace(entries ...any)
	Tracef(format string, args ...any)
}

StdLogger interface for generic logger

type StringFormatter

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

StringFormatter defines string-based formatter

Example
package main

import (
	"os"

	"github.com/effective-security/xlog"
	"github.com/pkg/errors"
)

func main() {
	var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "string_formatter").WithValues("prefix", "addon")
	f := xlog.NewStringFormatter(os.Stdout)
	xlog.SetFormatter(f)

	list := []string{"item 1", "item 2"}
	obj := struct {
		Foo     string
		Bar     int
		private string
	}{"foo", 5, "shout not print"}

	f.Format("format", xlog.WARNING, 1, "string1", "string 2", list, obj)
	f.FormatKV("format_kv", xlog.WARNING, 1, "key1", "value 2", "key2", 2, "list", list, "obj", obj)

	logger.KV(xlog.ERROR, "reason", "with time, level, caller", "err", errors.New("just a string").Error(), "number", 123)

	f.Options(xlog.FormatWithLocation)
	logger.KV(xlog.ERROR, "reason", "location",
		"err", errors.New("just a string").Error(),
		"number", 123,
		"list", list,
		"obj", obj,
	)

	f.Options(xlog.FormatSkipTime, xlog.FormatSkipLevel, xlog.FormatNoCaller)
	logger.KV(xlog.ERROR, "reason", "skip time, level, caller",
		"err", errors.New("just a string").Error(),
		"number", 123,
		"list", list,
		"obj", obj,
		"empty", "",
	)

}
Output:

time=2021-04-01T00:00:00Z level=W pkg=format func=ExampleStringFormatter "string1" "string 2" ["item 1","item 2"] {"Foo":"foo","Bar":5}
time=2021-04-01T00:00:00Z level=W pkg=format_kv func=ExampleStringFormatter key1="value 2" key2=2 list=["item 1","item 2"] obj={"Foo":"foo","Bar":5}
time=2021-04-01T00:00:00Z level=E pkg=string_formatter func=ExampleStringFormatter prefix="addon" reason="with time, level, caller" err="just a string" number=123
time=2021-04-01T00:00:00Z level=E pkg=string_formatter src=example_test.go:39 func=ExampleStringFormatter prefix="addon" reason="location" err="just a string" number=123 list=["item 1","item 2"] obj={"Foo":"foo","Bar":5}
pkg=string_formatter src=example_test.go:47 prefix="addon" reason="skip time, level, caller" err="just a string" number=123 list=["item 1","item 2"] obj={"Foo":"foo","Bar":5}

func (*StringFormatter) Flush

func (s *StringFormatter) Flush()

Flush the logs

func (*StringFormatter) Format

func (s *StringFormatter) Format(pkg string, l LogLevel, depth int, entries ...any)

Format log entry string to the stream

func (*StringFormatter) FormatKV

func (s *StringFormatter) FormatKV(pkg string, l LogLevel, depth int, entries ...any)

FormatKV log entry string to the stream, the entries are key/value pairs

func (*StringFormatter) Options

func (s *StringFormatter) Options(ops ...FormatterOption) Formatter

Options allows to configure formatter behavior

Directories

Path Synopsis
Package logrotate implements additional functionality for io writers & closers
Package logrotate implements additional functionality for io writers & closers

Jump to

Keyboard shortcuts

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