log

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: May 30, 2019 License: Apache-2.0, HPND, MIT Imports: 18 Imported by: 39

README

gone/log

Golang logging library GoDoc GoReportCard Coverage

Package gone/log is a drop-in replacement for the standard Go logging library "log" which is fully source code compatible support all the standard library API while at the same time offering advanced logging features through an extended API.

The design goals of gone/log was:

  • Standard library source level compatibility with mostly preserved behavior.
  • Leveled logging with syslog levels.
  • Structured key/value logging
  • Hierarchical context-able logging to have k/v data in context logged automatically.
  • Low resource usage to allow more (debug) log-statements even if they don't result in output.
  • Light syntax to encourage logging on INFO/DEBUG level. (and low cost of doing so)
  • Flexibility in how log events are output.
  • A fast simple lightweight default in systemd new-daemon style only outputting message to standard output.

See the examples in api_test.go

Logging Overview

Logging is done through *log.Logger objects. They implement all the logging API.

A log event is created by calling one of the logging methods on a *log.Logger object - like ERROR(). Loggers are arranged in a hierarchy. Traversing it will find a Handler chain. The event is then sent through the Handler chain until it ends at a formatting Handler. Potentially the formatted event is then sent through a chain of Writers to finally reach it's *os.File destination.

diagram

Every Logger has its own config, which determines the max log level for which it will generate log events. Whether an event will be generated is determined by the exact Logger on which a log method was called.

A Logger can have associated a Handler - but need not to.

Logger objects can be named, in which case they are participate in a global hierarchy. This hierarchy is traversed for a log event until a Logger with a Handler is found. The event is then passed to that Handler.

The event is then passed along a chain of Handler objects which determines whether and how the event will be logged. Handlers can be any object implementing the Handler interface.

Normally the Handler chain ends i a "Formatting" Handler - a Handler which converts the log event to a log-line. The log line can then be passed to a chain of Writers, which again can do filtering and other decisions. In the end a Writer can Write() the log line to an *os.File.

Handler chains need not end in Formatters and Writers. A Handler could easily be written which just (say) was a statsd network client.

On every Logger (named or not) you can call With() to get a "child" Logger which stores key/value context data to be logged with every log event. Such Loggers always have the same name as their parent. They are just a shorthand to not write all key/value context with every log statement.

Example

The library is 100% source code compatible with the standard library logger

    import "github.com/One-com/gonelog/log"

    log.Println("Hello log")

    mylog := log.New(os.Stdout,"PFX:",log.LstdFlags)
    mylog.Fatal("Arggh")

... at the same time as providing several extra features:

h := log.NewStdFormatter(os.Stdout,"",log.LstdFlags|log.Llevel|log.Lpid|log.Lshortfile)
l := log.NewLogger(syslog.LOG_WARN,h)

err := DangerousOperation()
if err != nil {
	l.ERROR("An error happened", "err", err)
}

context_logger := l.With("session", session-id)

context_logger.WARN("Session will expire soon")

Plese see the GoDoc documentation

Documentation

Overview

Package log is a drop-in replacement for the standard Go logging library "log" which is fully source code compatible support all the standard library API while at the same time offering advanced logging features through an extended API.

The design goals of gonelog was:

  • Standard library source level compatibility with mostly preserved behaviour.
  • Leveled logging with syslog levels.
  • Structured key/value logging
  • Hierarchical contextable logging to have k/v data in context logged automatically.
  • Low resource usage to allow more (debug) log-statements even if they don't result in output.
  • Light syntax to encourage logging on INFO/DEBUG level. (and low cost of doing so)
  • Flexibility in how log events are output.
  • A fast simple lightweight default in systemd newdaemon style only outputting <level>message to standard output.
  • Facilitating configuring logging for libraries by the application.

Synopsis

Out of the box the default logger with package level methods works like the standard library *log.Logger with all the standard flags and methods:

import "github.com/One-com/gonelog/log"

log.Println("Hello log")

mylog := log.New(os.Stdout,"PFX:",LstdFlags)
mylog.Fatal("Arggh")

Under the hood the default *log.Logger is however a log context object which can have key/value data and which generate log events with a syslog level and hands them of to a log Handler for formatting and output.

The default Logger supports all this as well, using log level constants source code compatible with the "log/syslog" package through the github.com/One-com/gone/log/syslog package:

package syslog
const (
	// Severity.

	// From /usr/include/sys/syslog.h.
	// These are the same on Linux, BSD, and OS X.
	LOG_EMERG Priority = iota
	LOG_ALERT
	LOG_CRIT
	LOG_ERR
	LOG_WARNING
	LOG_NOTICE
	LOG_INFO
	LOG_DEBUG
)

Logging with key/value data is (in its most simple form) done by calling level specific functions. First argument is the message, subsequenct arguments key/value data:

    	log.DEBUG("hi", "key", "value")
	log.INFO("hi again")
	log.NOTICE("more insisting hi")
	log.WARN("Hi?")
	log.ERROR("Hi!", "key1","value1", "key2", "value2")
	log.CRIT("HI! ")
	log.ALERT("HEY THERE, WAKE UP!")

Earch *log.Logger object has a current "log level" which determines the maximum log level for which events are actually generated. Logging above that level will be ignored. This log level can be controlled:

log.SetLevel(syslog.LOG_WARN)
log.DecLevel()
log.IncLevel()

Calling Fatal*() and Panic*() will in addition to Fataling/panicing log at level ALERT.

The Print*() methods will log events with a configurable "default" log level - which default to INFO.

Per default the Logger *will* generate log event for Print*() calls even though the log level is lower. The Logger can be set to respect the actual log level also for Print*() statements by the second argument to SetPrintLevel()

log.SetPrintLevel(syslog.LOG_NOTICE,true)

A new custom Logger with its own behavior and formatting handler can be created:

  	h := log.NewStdFormatter(os.Stdout,"",log.LstdFlags|log.Llevel|log.Lpid|log.Lshortfile)
	l := log.NewLogger(syslog.LOG_ERROR, h)
	l.DoTime(true)
	l.DoCodeInfo(true)

A customer Logger will not per default spend time timestamping events or registring file/line information. You have to enable that explicitly (it's not enabled by setting the flags on a formatting handler).

When having key/value data which you need to have logged in all log events, but don't want to remember to put into every log statement, you can create a "child" Logger:

reqlog := l.With( "session", uuid.NewUUID() )
reqlog.ERROR("Invalid session")

To simply set the standard logger in a minimal mode where it only outputs <level>message to STDOUT and let an external daemon supervisor/log system do the rest (including timestamping) just do:

log.Minimal()

Having many log statements can be expensive. Especially if the arguments to be logged are resource intensive to compute and there's no log events generated anyway.

There are 2 ways to get around that. The first is do do Lazy evaluation of arguments:

log.WARN("heavy", "fib123", log.Lazy(func() interface{} {return fib(123)} ))

The other is to pick an comma-ok style log function:

if f,ok := l.DEBUGok(); ok  { f("heavy", "fib123", fib(123)) }

Sometimes it can be repetitive to make a lot of log statements logging many attributes of the same kinda of object by explicitly accessing every attribute. To make that simpler, every object can implement the Logable interface by creating a LogValues() function returning the attributes to be logged (with keys). The object can then be logged by directly providing it as an argument to a log function:

type Request struct {
   IP string
   Method string
}

func (r *Request) LogValues() log.KeyValues {
   return []interface{}{
      "ip", r.IP,
      "meth", r.Method,
   }
}

req := &Request{ IP : "127.0.0.1", Method : "GET"}

log.NOTICE("Got request", req)

Loggers can have names, placing them in a global "/" separated hierarchy.

It's recommended to create a Logger by mentioning it by name using GetLogger("logger/name") - instead of creating unnamed Loggers with NewLogger(). If such a logger exists you will get it returned, so you can configure it and set the formatter/output. Otherwise a new logger by that name is created. Libraries are encouraged to published the names of their Loggers and to name Loggers after their Go package. This works exactly like the Python "logging" library - with one exception: When Logging an event at a Logger the tree of Loggers by name are only traversed towards to root to find the first Logger having a Handler attached, not returning an error. The log-event is then sent to that handler. If that handler returns an error, the parent Logger and its Handler is tried. This allows to contruct a "Last Resort" parent for errors in the default log Handler. The Python behaviour is to send the event to all Handlers found in the Logger tree. This is not the way it's done here. Only one Handler will be given the event to log. If you wan't more Handlers getting the event, use a MultiHandler.

	package main

	import (
	       "mylib" // which logs to a gonelog *log.Logger
	       "github.com/One-com/gone/log"
       	       "github.com/One-com/gone/log/syslog"
	       "os"
	)

	func main() {
	     log.SetLevel(syslog.WARN) // application will log at warn level
	     log.GetLogger("mylib").SetLevel(syslog.LOG_ERROR) // mylib will log at error level
	     log.SetOutput(os.Stderr) // Log events from mylib will be propagated up
	     mylib.FuncWhichLogsOnError()
	}

Happy logging.

Index

Examples

Constants

View Source
const (
	// Bits or'ed together to control what's printed.
	// There is no control the format they present (as described in the comments).
	// The prefix is followed by a colon only when Llongfile or Lshortfile
	// is specified.
	// For example, flags Ldate | Ltime (or LstdFlags) produce,
	//	2009/01/23 01:23:23 message
	// while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
	//	2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
	Ldate         = 1 << iota // the date in the local time zone: 2009/01/23
	Ltime                     // the time in the local time zone: 01:23:23
	Lmicroseconds             // microsecond resolution: 01:23:23.123123.  assumes Ltime.
	Llongfile                 // full file name and line number: /a/b/c/d.go:23
	Lshortfile                // final file name element and line number: d.go:23. overrides Llongfile
	LUTC                      // if Ldate or Ltime is set, use UTC rather than the local time zone

	Llevel // prefix the log line with a syslog level <L>
	Lpid   // Include the process ID
	Lcolor // Do color logging to terminals
	Lname  // Log the name of the Logger generating the event

	LstdFlags = Ldate | Ltime // stdlib compatible

	LminFlags = Llevel // Simple systemd/syslog compatible level spec. Let external log system take care of timestamps etc.
)

These flags define which text to prefix to each log entry generated by the Logger. Extension of the std log library

LvlDEFAULT is the default log level at which Print*() functions will log. Leveled logging is provided with the 8 syslog levels Additional 2 pseudo-levels ("Fatal"/ "Panic") which log at Alert-level, but have side-effects like the stdlogger. (os.Exit(1)/panic()) Print*() functions will produce log-events with a "default" level.

Variables

View Source
var ErrNotLogged = errors.New("No handler found to log event")

ErrNotLogged is returned by some Log functions (Log()/Output()) if no Handler was found to log an event.

Functions

func ALERT

func ALERT(msg string, kv ...interface{})

ALERT - Requests the default logger to create a log event

func AutoColoring

func AutoColoring()

AutoColoring turns on coloring for the default logger if the output Writer is connected to a TTY

func CRIT

func CRIT(msg string, kv ...interface{})

CRIT - Requests the default logger to create a log event

func DEBUG

func DEBUG(msg string, kv ...interface{})

DEBUG - Requests the default logger to create a log event

func DecLevel

func DecLevel() bool

DecLevel - Decrease the log level of the default Logger

func ERROR

func ERROR(msg string, kv ...interface{})

ERROR - Requests the default logger to create a log event

func Fatal

func Fatal(v ...interface{})

Fatal - Compatible with the standard library

func Fatalf

func Fatalf(format string, v ...interface{})

Fatalf - Compatible with the standard library

func Fatalln

func Fatalln(v ...interface{})

Fatalln - Compatible with the standard library

func Flags

func Flags() int

Flags - Compatible with the standard library

func INFO

func INFO(msg string, kv ...interface{})

INFO - Requests the default logger to create a log event

func IncLevel

func IncLevel() bool

IncLevel - Increase the log level of the default Logger

func Level

func Level() syslog.Priority

Level returns the default Logger's log level.

func Log

func Log(level syslog.Priority, msg string, kv ...interface{})

Log is the simplest Logger method. Provide the log level (syslog.LOG_*) your self.

func Minimal

func Minimal()

Minimal sets the default logger to the minimal mode, where it doesn't log timestamps But only emits systemd/syslog-compatible "<level>message" lines.

Example
package main

import (
	"github.com/One-com/gone/log"
)

func main() {
	log.Minimal() // change default Logger to not be stdlib compatible but minimal
	log.ERROR("fejl")
}
Output:

<3>fejl

func NOTICE

func NOTICE(msg string, kv ...interface{})

NOTICE - Requests the default logger to create a log event

func NewJSONFormatter

func NewJSONFormatter(w io.Writer, options ...HandlerOption) *jsonformatter

NewJSONFormatter creates a new formatting Handler writing log events as JSON to the supplied Writer.

func NewMinFormatter

func NewMinFormatter(w io.Writer, options ...HandlerOption) *stdformatter

NewMinFormatter creates a standard formatter and applied the supplied options It will default log.LminFlags to provide simple <level>message logging

Example
package main

import (
	"github.com/One-com/gone/log"
	"github.com/One-com/gone/log/syslog"
	"os"
)

func main() {
	h := log.NewMinFormatter(log.SyncWriter(os.Stdout), log.PrefixOpt("PFX:"))
	l := log.NewLogger(syslog.LOG_WARNING, h)
	l.ERROR("fejl")
}
Output:

<3>PFX:fejl

func NewStdFormatter

func NewStdFormatter(w io.Writer, prefix string, flag int) *stdformatter

NewStdFormatter creates a standard formatter capable of simulating the standard library logger.

func NewStdlibAdapter

func NewStdlibAdapter(logger *Logger, level syslog.Priority, options ...StdlibAdapterOption) io.Writer

NewStdlibAdapter returns a new StdlibAdapter wrapper around the passed logger. It's designed to be passed to the standard library's log.SetOutput()

func Output

func Output(calldepth int, s string) error

Output compatible with the standard library

Example
package main

import (
	"github.com/One-com/gone/log"
	"os"
)

func output(l *log.Logger, msg string) {
	l.Output(2, msg)
}

func main() {
	l := log.New(os.Stdout, "", log.Lshortfile)
	l.DoCodeInfo(true)
	log.SetOutput(os.Stdout)
	log.SetFlags(log.Lshortfile)
	log.SetPrefix("")

	output(l, "output1")
	log.Output(1, "output2")
}
Output:

api_test.go:22: output1
api_test.go:23: output2

func Panic

func Panic(v ...interface{})

Panic - Compatible with the standard library

func Panicf

func Panicf(format string, v ...interface{})

Panicf - Compatible with the standard library

func Panicln

func Panicln(v ...interface{})

Panicln - Compatible with the standard library

func Prefix

func Prefix() string

Prefix - Compatible with the standard library

func Print

func Print(v ...interface{})

Print - Compatible with the standard library

func Printf

func Printf(format string, v ...interface{})

Printf - Compatible with the standard library

func Println

func Println(v ...interface{})

Println - Compatible with the standard library

func SetFlags

func SetFlags(flag int)

SetFlags - Compatible with the standard library

func SetLevel

func SetLevel(level syslog.Priority) bool

SetLevel set the Logger log level. returns success

func SetOutput

func SetOutput(w io.Writer)

SetOutput - Compatible with the standard library

func SetPrefix

func SetPrefix(prefix string)

SetPrefix - Compatible with the standard library

func SetPrintLevel

func SetPrintLevel(level syslog.Priority, respect bool) bool

SetPrintLevel sets the log level used by Print*() calls. If the second argument is true, Println(), Printf(), Print() will respect the Logger log level. If the second argument is false, log event will be generated regardless of Logger log level. Handlers and Writers may still filter the event out.

Example
package main

import (
	"github.com/One-com/gone/log"
	"github.com/One-com/gone/log/syslog"
	"os"
)

func main() {
	l := log.GetLogger("my/lib")
	h := log.NewStdFormatter(log.SyncWriter(os.Stdout), "", log.Llevel|log.Lname)
	l.SetHandler(h)
	l.AutoColoring()
	l.SetLevel(syslog.LOG_ERROR)
	l.SetPrintLevel(syslog.LOG_NOTICE, false)

	l.Print("ignoring level")
}
Output:

<5>(my/lib) ignoring level

func SyncWriter

func SyncWriter(w io.Writer) io.Writer

SyncWriter encapsulates an io.Writer in a Mutex, so only one Write operation is done at a time.

func WARN

func WARN(msg string, kv ...interface{})

WARN - Requests the default logger to create a log event

func WriterFunc

func WriterFunc(fn func(b []byte) (n int, err error)) io.Writer

WriterFunc makes an io.Writer out of a function by calling it on Write()

Types

type CloneableHandler

type CloneableHandler interface {
	Handler
	Clone(options ...HandlerOption) CloneableHandler
}

CloneableHandler allows you to call ApplyHandlerOptions() on a Logger to swap in a new Handler modified by the provided HandlerOptions

type EvWriter

type EvWriter interface {
	EvWrite(e Event, b []byte) (n int, err error)
	io.Writer
}

EvWriter is a Writer which wants to know the original event of the []byte buffer (for filtering) Is has to also be a io.Writer, else it can't be used in a formatter.

func EventWriter

func EventWriter(w io.Writer) EvWriter

EventWriter creates a dummy EvWriter from an io.Writer

func EventWriterFunc

func EventWriterFunc(fn func(e Event, b []byte) (n int, err error)) EvWriter

EventWriterFunc created a new EvWriter from a function taking the event and a formattet logline. Such functions need to be aware that e can be nil

func LevelFilterWriter

func LevelFilterWriter(max syslog.Priority, w io.Writer) EvWriter

LevelFilterWriter creates a filtering EventWriter which writes whats below (or equal) max level to The underlying io.Writer

func MultiEventWriter

func MultiEventWriter(writers ...EvWriter) EvWriter

MultiEventWriter creates a writer that duplicates its writes to all the provided writers, similar to the Unix tee(1) command, providing all with the original event to do filtering.

type Event

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

Event is the basic log event type. Exported to be able to implement Handler interface for external packages.

func (Event) FileInfo

func (e Event) FileInfo() (string, int)

FileInfo returns the file and line number of a log event.

func (Event) KvData

func (e Event) KvData() KeyValues

KvData returns the structured list of key/value data

func (Event) Level

func (e Event) Level() syslog.Priority

Level returns the log level of the event

func (Event) LoggerName

func (e Event) LoggerName() string

LoggerName returns the name of the logger logging the event.

func (Event) Message

func (e Event) Message() string

Message returns the log message of the event

func (Event) Time

func (e Event) Time() (t time.Time)

Time returns the timestamp of an event.

type EventKeyNames

type EventKeyNames struct {
	Lvl  string
	Name string
	Time string
	Msg  string
	File string
	Line string
}

EventKeyNames holds keynames for fixed event fields, when needed (such as in JSON)

type Handler

type Handler interface {
	Log(e Event) error
}

Handler is the interface needed to be a part of the Handler chain.

Events are sent from a logger down a chain of Handlers. The final Handler (which doesn't call other handlers) is called a Formatter. Formatters turn the event into something else (like a log-line) and are also Handlers. Formatters implement this interface to receive events.

Some Handlers pass the Event to further handlers while doing things like filtering, which is harder to do on formatted log-lines.

In other words: Once Events has been created, a Handler can ensure it's shipped to the log system. Formatters are a special kind og Handlers which ends the handler pipeline and convert the *Event to []byte (and does something with the bytes)

Example
package main

import (
	"github.com/One-com/gone/log"
	"os"
)

func main() {
	h := log.NewMinFormatter(log.SyncWriter(os.Stdout), log.PrefixOpt("PFX:"))
	l := log.GetLogger("mylog")
	l.SetHandler(h)
	l.ERROR("fejl")
	l.ApplyHandlerOptions(log.FlagsOpt(log.Llevel | log.Lname))
	l.WARN("advarsel")
}
Output:

<3>PFX:fejl
<4>PFX:(mylog) advarsel

func FilterHandler

func FilterHandler(fn func(e Event) bool, h Handler) Handler

FilterHandler lets a function evaluate whether to discard the Event or pass it on to a next Handler

func HandlerFunc

func HandlerFunc(fn func(e Event) error) Handler

HandlerFunc generates a Handler from a function, by calling it when Log is called.

func LvlFilterHandler

func LvlFilterHandler(maxLvl syslog.Priority, h Handler) Handler

LvlFilterHandler discards events with a level above maxLvl

func MultiHandler

func MultiHandler(hs ...Handler) Handler

MultiHandler distributes the event to several Handlers if an error happen the last error is returned.

type HandlerOption

type HandlerOption func(CloneableHandler)

HandlerOption is an option-function provided by the package of a Handler

func FlagsOpt

func FlagsOpt(flags int) HandlerOption

FlagsOpt - Standard Formatter Option to set flags

func KeyNamesOpt

func KeyNamesOpt(keys *EventKeyNames) HandlerOption

KeyNamesOpt is a JSON Formatter Option to set flags

func LevelPrefixOpt

func LevelPrefixOpt(arr *[8]string) HandlerOption

LevelPrefixOpt - Standard Formatter option to set LevelPrefixes

func OutputOpt

func OutputOpt(w io.Writer) HandlerOption

OutputOpt - Standard Formatter option so set Output

func PrefixOpt

func PrefixOpt(prefix string) HandlerOption

PrefixOpt - Standard Formatter option to set Prefix

func TimeFormatOpt

func TimeFormatOpt(layout string) HandlerOption

TimeFormatOpt is a JSON Formatter Option to set timestamp formatting

type KV

type KV map[string]interface{}

KV is a map of key/value pairs to pass to a Logger context or to a log function for structured logging. Value can be any stringable object, or a Valuer which resolves to a stringable object.

func (KV) LogValues

func (kv KV) LogValues() KeyValues

LogValues implment Logable for KV

type KeyValues

type KeyValues []interface{}

KeyValues is a slice of interfaces alternating between key and value for data to be logged. Keys are at even numbered indexes and must be string. Values can be any stringable object or a Valuer which resolves to a stringable object.

type Lazy

type Lazy func() interface{}

Lazy evaluation of values to log returns stringable objects

type LevelLogger

type LevelLogger interface {

	// Will generate a log event with this level if the Logger log level is
	// high enough.
	// The event will have the given log message and key/value structured data.
	Log(level syslog.Priority, message string, kv ...interface{}) error

	// further interfaces
	StdLogger
}

LevelLogger makes available methods compatible with the stdlib logger and an extended API for leveled logging. LevelLogger is implemented by *log.Logger

type LogFunc

type LogFunc func(msg string, kv ...interface{})

LogFunc is the type of the function returned by *ok() methods, which will log at the level queried about if called.

func ALERTok

func ALERTok() (LogFunc, bool)

ALERTok - If the default Logger is logging at the requested level a function creating such a log event will be returned.

func CRITok

func CRITok() (LogFunc, bool)

CRITok - If the default Logger is logging at the requested level a function creating such a log event will be returned.

func DEBUGok

func DEBUGok() (LogFunc, bool)

DEBUGok - If the default Logger is logging at the requested level a function creating such a log event will be returned.

func ERRORok

func ERRORok() (LogFunc, bool)

ERRORok - If the default Logger is logging at the requested level a function creating such a log event will be returned.

func INFOok

func INFOok() (LogFunc, bool)

INFOok - If the default Logger is logging at the requested level a function creating such a log event will be returned.

func NOTICEok

func NOTICEok() (LogFunc, bool)

NOTICEok - If the default Logger is logging at the requested level a function creating such a log event will be returned.

func WARNok

func WARNok() (LogFunc, bool)

WARNok - If the default Logger is logging at the requested level a function creating such a log event will be returned.

type Logable

type Logable interface {
	LogValues() KeyValues
}

Logable is the interface needed for an object to be provided as a value to a nil key and then being allowed to generate it's k/v log values it self by returning them from LogValues()

Example
package main

import (
	"bytes"
	"fmt"
	"github.com/One-com/gone/log"
)

type MyObj struct {
	Key1 string
	Key2 string
}

func (o *MyObj) LogValues() log.KeyValues {
	return []interface{}{"key1", o.Key1, "key2", o.Key2}
}

func main() {

	obj := &MyObj{"foo", "bar"}

	var b bytes.Buffer
	l := log.New(&b, "", 0)
	l.With(log.KV{"orange": "apple"}, "a", "b").ERROR("An", obj, "pif", "paf")

	fmt.Println(b.String())
}
Output:

An orange=apple a=b key1=foo key2=bar pif=paf

type Logger

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

Logger implements a stdlib *log.Logger source code compatible interface and extra methods for supporting leveled, structured and context logging.

Don't create these your self. Use a constructor function. Once created, its member attributes cannot be changed (to avoid races), Exceptions are: * Changing the config, which goes through atomic operations * Changing the handler, which can be atomically replaced.

There's a race between changing both, so beware! If you swap in a handler which does file/line-recording without changing config to DoCodeInfo() first, there will no code-info in the log-events during the race. Repeat: There's no way to change handler and config atomically together. So don't enable a handler using something the config doesn't support (timestamps/codeinfo) unless you can live with potentially a few log lines with wrong content. All attributes are reference-like attributes. Copying them will not gain you anything, but effectively just having two "pointers" to the same logger. Copying values of this type is discouraged, but in principle legal, since the direct members never change. The new copy will behave like the old, and modifications to one of them will affect the other.

Logger allows for contextual logging, by keeping K/V data to be logged with all events and to create sub child loggers with additional K/V data.

func Default

func Default() *Logger

Default returns the default Logger - which is also the root of the name hierarchy.

func GetLogger

func GetLogger(name string) (l *Logger)

GetLogger creates a new Logger or returns an already existing with the given name.

Example
package main

import (
	"github.com/One-com/gone/log"
	"os"
)

func main() {
	l := log.GetLogger("my/lib")
	h := log.NewStdFormatter(log.SyncWriter(os.Stdout), "", log.Llevel|log.Lname)
	l.SetHandler(h)
	l2 := log.GetLogger("my/lib/module")

	l3 := l2.With("k", "v")

	l3.NOTICE("notice")
}
Output:

<5>(my/lib/module) notice k=v

func New

func New(out io.Writer, prefix string, flags int) *Logger

New will instantiate a logger with the same functionality (and limitations) as the std lib logger.

Example

Compatible with std lib

package main

import (
	"github.com/One-com/gone/log"
	"os"
)

func main() {
	l := log.New(os.Stdout, "", log.Llevel)
	l.Println("notice")
}
Output:

<6>notice

func NewLogger

func NewLogger(level syslog.Priority, handler Handler) (l *Logger)

NewLogger creates a new unamed Logger out side of the named Logger hierarchy.

Example
package main

import (
	"github.com/One-com/gone/log"
	"github.com/One-com/gone/log/syslog"
	"os"
)

func main() {
	h := log.NewStdFormatter(log.SyncWriter(os.Stdout), "", log.Llevel)
	l := log.NewLogger(syslog.LOG_WARNING, h)
	l.SetPrintLevel(syslog.LOG_NOTICE, false)

	// Traditional.
	// Evaluates arguments unless Lazy is used, but doesn't generate
	// Events above log level
	l.DEBUG("hej")
	l.INFO("hej")
	l.NOTICE("hej")
	l.WARN("hej")
	l.ERROR("hej")
	l.CRIT("hej")
	l.ALERT("hej")

	// Optimal
	// Doesn't do anything but checking the log level unless
	// something should be logged
	// A filtering handler would still be able to discard log events
	// based on level. Use Lazy to only evaluate just before formatting
	// Even by doing so a filtering writer might still discard the log line
	if f, ok := l.DEBUGok(); ok {
		f("dav")
	}
	if f, ok := l.INFOok(); ok {
		f("dav")
	}
	if f, ok := l.NOTICEok(); ok {
		f("dav")
	}
	if f, ok := l.WARNok(); ok {
		f("dav")
	}
	if f, ok := l.ERRORok(); ok {
		f("dav")
	}
	if f, ok := l.CRITok(); ok {
		f("dav")
	}
	if f, ok := l.ALERTok(); ok {
		f("dav")
	}

	// Primitive ... Allows for dynamically choosing log level.
	// Otherwise behaves like Traditional
	l.Log(syslog.LOG_DEBUG, "hop")
	l.Log(syslog.LOG_INFO, "hop")
	l.Log(syslog.LOG_NOTICE, "hop")
	l.Log(syslog.LOG_WARN, "hop")
	l.Log(syslog.LOG_ERROR, "hop")
	l.Log(syslog.LOG_CRIT, "hop")
	l.Log(syslog.LOG_ALERT, "hop")

	// Std logger compatible.
	// Will log with the default-level (default "INFO") - if that log-level is enabled.
	l.Print("default")
	// Fatal and Panic logs with level "ALERT"
	l.Fatal("fatal")
}
Output:

func With

func With(kv ...interface{}) *Logger

With will create a sub-context K/V logger of the default logger with additional key/value context.

Example
package main

import (
	"github.com/One-com/gone/log"
	"github.com/One-com/gone/log/syslog"
	"os"
)

func main() {
	l := log.GetLogger("my/lib")
	h := log.NewStdFormatter(log.SyncWriter(os.Stdout), "", log.Llevel|log.Lname)
	l.SetHandler(h)
	l.SetLevel(syslog.LOG_ERROR)

	l2 := l.With("key", "value")

	l3 := l2.With("more", "data")

	l3.ERROR("message")
}
Output:

<3>(my/lib) message more=data key=value

func (*Logger) ALERT

func (l *Logger) ALERT(msg string, kv ...interface{})

ALERT - Log a message and optional KV values at syslog ALERT level.

func (*Logger) ALERTok

func (l *Logger) ALERTok() (LogFunc, bool)

ALERTok will return whether the logger generates events at this level, and a function which will do the logging when called.

func (*Logger) ApplyHandlerOptions

func (l *Logger) ApplyHandlerOptions(opt ...HandlerOption)

ApplyHandlerOptions clones the current Handles and tries to apply the supplied HandlerOptions to the clone - then swaps in the clone atomically to not loose Log events. Supplied HandlerOptions must be compatible with the current Handler, or the Handler will/(should) reject it and treat it as a No-Op. If the attached Handler does not support Cloning or HandlerOptions and/or you are using a more complex Handler hierarchy, you should probably create the new Handler Manually and use SetHandler()

func (*Logger) AutoColoring

func (l *Logger) AutoColoring()

AutoColoring asks the current Handler to test if there's a TTY attached to an output and if so, apply coloring to the formatter.

func (*Logger) CRIT

func (l *Logger) CRIT(msg string, kv ...interface{})

CRIT - Log a message and optional KV values at syslog CRIT level.

func (*Logger) CRITok

func (l *Logger) CRITok() (LogFunc, bool)

CRITok will return whether the logger generates events at this level, and a function which will do the logging when called.

func (*Logger) DEBUG

func (l *Logger) DEBUG(msg string, kv ...interface{})

DEBUG - Log a message and optional KV values at syslog DEBUG level.

func (*Logger) DEBUGok

func (l *Logger) DEBUGok() (LogFunc, bool)

DEBUGok will return whether the logger generates events at this level, and a function which will do the logging when called.

func (*Logger) DecLevel

func (l *Logger) DecLevel() bool

DecLevel tries to decrease the log level

func (*Logger) DefaultLevel

func (l *Logger) DefaultLevel() syslog.Priority

DefaultLevel returns the current log level of Print*() methods. Deprecated, use PrintLevel()

func (*Logger) Do

func (l *Logger) Do(level syslog.Priority) bool

Do is Setlevel() - For completeness returns success

func (*Logger) DoCodeInfo

func (l *Logger) DoCodeInfo(doCode bool) bool

DoCodeInfo tries to turn on or off registering the file and line of the log call. Formatters which try to log this info will not give meaningful info if this is turned off. It can fail if some other go-routine simultaneous is manipulating the config. Returning whether the change was successful

func (*Logger) DoTime

func (l *Logger) DoTime(doTime bool) bool

DoTime tries to turn on or off timestamping. It can fail if some other go-routine simultaneous is manipulating the config. If the generated log-events are not timestamped on creation some formatters will create their own timestamp anyway. Having this global option saves time.Now() calls if no one is using the time info (which is the case for minimal logging). It also enables using a single timestamp for all formatting of the log event. Returning whether the change was successful

func (*Logger) Does

func (l *Logger) Does(level syslog.Priority) bool

Does returns whether the Logger would generate an event at this level? This can be used for optimal performance logging

func (*Logger) DoingCodeInfo

func (l *Logger) DoingCodeInfo() bool

DoingCodeInfo returns whether the Logger is currently recording file/line info for all log events

func (*Logger) DoingDefaultLevel

func (l *Logger) DoingDefaultLevel() (syslog.Priority, bool)

DoingDefaultLevel returns whether a log.Println() would actually generate a log event with the current config. It's equivalent to l.Does(l.DefaultLevel()) - but atomically Deprecated, use DoingPrintLevel()

func (*Logger) DoingPrintLevel

func (l *Logger) DoingPrintLevel() (syslog.Priority, bool)

DoingPrintLevel returns whether a log.Println() would actually generate a log event with the current config. It's equivalent to l.Does(l.PrintLevel()) - but atomically

func (*Logger) DoingTime

func (l *Logger) DoingTime() bool

DoingTime returns whether the Logger is currently timestamping all events on creation

func (*Logger) ERROR

func (l *Logger) ERROR(msg string, kv ...interface{})

ERROR - Log a message and optional KV values at syslog ERROR level.

func (*Logger) ERRORok

func (l *Logger) ERRORok() (LogFunc, bool)

ERRORok will return whether the logger generates events at this level, and a function which will do the logging when called.

func (*Logger) Fatal

func (l *Logger) Fatal(v ...interface{})

Fatal compatible with the standard lib logger

func (*Logger) Fatalf

func (l *Logger) Fatalf(format string, v ...interface{})

Fatalf compatible with the standard lib logger

func (*Logger) Fatalln

func (l *Logger) Fatalln(v ...interface{})

Fatalln compatible with the standard lib logger

func (*Logger) Flags

func (l *Logger) Flags() int

Flags compatible with the standard lib logger

func (*Logger) INFO

func (l *Logger) INFO(msg string, kv ...interface{})

INFO - Log a message and optional KV values at syslog INFO level.

func (*Logger) INFOok

func (l *Logger) INFOok() (LogFunc, bool)

INFOok will return whether the logger generates events at this level, and a function which will do the logging when called.

func (*Logger) IncLevel

func (l *Logger) IncLevel() bool

IncLevel tries to increase the log level

func (*Logger) Level

func (l *Logger) Level() syslog.Priority

Level returns the current log level

func (*Logger) Log

func (l *Logger) Log(level syslog.Priority, msg string, kv ...interface{}) (err error)

Log is the simplest Logger method

func (*Logger) LogFromCaller

func (l *Logger) LogFromCaller(calldepth int, level syslog.Priority, msg string, kv ...interface{}) error

LogFromCaller is like Log() but lets you offset the calldepth used to compute CodeInfo (file/line) from stack info, the same way as the stdlib log.Output() function does.

func (*Logger) NOTICE

func (l *Logger) NOTICE(msg string, kv ...interface{})

NOTICE - Log a message and optional KV values at syslog NOTICE level.

func (*Logger) NOTICEok

func (l *Logger) NOTICEok() (LogFunc, bool)

NOTICEok will return whether the logger generates events at this level, and a function which will do the logging when called.

func (*Logger) Output

func (l *Logger) Output(calldepth int, s string) error

Output compatible with the standard lib logger

func (*Logger) Panic

func (l *Logger) Panic(v ...interface{})

Panic compatible with the standard lib logger

func (*Logger) Panicf

func (l *Logger) Panicf(format string, v ...interface{})

Panicf compatible with the standard lib logger

func (*Logger) Panicln

func (l *Logger) Panicln(v ...interface{})

Panicln compatible with the standard lib logger

func (*Logger) Prefix

func (l *Logger) Prefix() string

Prefix compatible with the standard lib logger

func (*Logger) Print

func (l *Logger) Print(v ...interface{})

Print compatible with the standard lib logger

func (*Logger) PrintLevel

func (l *Logger) PrintLevel() syslog.Priority

PrintLevel returns the current log level of Print*() methods

func (*Logger) Printf

func (l *Logger) Printf(format string, v ...interface{})

Printf compatible with the standard lib logger

func (*Logger) Println

func (l *Logger) Println(v ...interface{})

Println compatible with the standard lib logger

func (*Logger) SetFlags

func (l *Logger) SetFlags(flag int)

SetFlags compatible with the standard lib logger

func (*Logger) SetHandler

func (l *Logger) SetHandler(h Handler)

SetHandler atomically swaps in a different root of the Handler tree

func (*Logger) SetLevel

func (l *Logger) SetLevel(level syslog.Priority) bool

SetLevel set the Logger log level. returns success

func (*Logger) SetOutput

func (l *Logger) SetOutput(w io.Writer)

SetOutput compatible with the standard lib logger

func (*Logger) SetPrefix

func (l *Logger) SetPrefix(prefix string)

SetPrefix compatible with the standard lib logger

func (*Logger) SetPrintLevel

func (l *Logger) SetPrintLevel(level syslog.Priority, respect bool) bool

SetPrintLevel sets the level which Print*() methods are logging with. "respect" indicated whether Print*() statements will respect the Logger loglevel or generate events anyway. (with the default log level). Without "respect" the logger can generate events above its loglevel. Such events can however still be filtered out by filter-handler, or filter-writers, or by external systems like syslog. returns success

func (*Logger) WARN

func (l *Logger) WARN(msg string, kv ...interface{})

WARN - Log a message and optional KV values at syslog WARN level.

func (*Logger) WARNok

func (l *Logger) WARNok() (LogFunc, bool)

WARNok will return whether the logger generates events at this level, and a function which will do the logging when called.

func (*Logger) With

func (l *Logger) With(kv ...interface{}) *Logger

With ties a sub-context to the Logger and create a new logger which will log the supplied K/V values as context with every log event.

type MaybeTtyWriter

type MaybeTtyWriter interface {
	IsTty() bool
	io.Writer
}

MaybeTtyWriter is a writer which know whether the underlying writer is a TTY

type StdFormatter

type StdFormatter interface {
	Flags() int
	Prefix() string
}

StdFormatter allows quering a formatting handler for flags and prefix compatible with the stdlib log library

type StdLogger

type StdLogger interface {
	Fatal(v ...interface{})
	Fatalf(format string, v ...interface{})
	Fatalln(v ...interface{})

	Panic(v ...interface{})
	Panicf(format string, v ...interface{})
	Panicln(v ...interface{})

	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

StdLogger is the interface used by the standard lib *log.Logger This is the API for actually logging stuff.

type StdLoggerFull

type StdLoggerFull interface {
	StdLogger
	StdMutableFormatter
	Output(calldepth int, s string) error
}

StdLoggerFull is mostly for documentation purposes. This is the full set of methods supported by the standard logger. You would only use the extra methods when you know exactly which kind of logger you are dealing with anyway.

type StdMutableFormatter

type StdMutableFormatter interface {
	StdFormatter
	SetFlags(flag int)
	SetPrefix(prefix string)
	SetOutput(w io.Writer)
}

StdMutableFormatter is the interface for a Logger which directly can change the stdlib flags, prefix and output io.Writer attributes in a synchronized manner. Since gonelog Handlers are immutable, it's not used for Formatters.

type StdlibAdapter

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

StdlibAdapter wraps a Logger and allows it to be passed to the stdlib logger's SetOutput. It will extract date/timestamps, filenames, and messages, and place them under relevant keys. It uses regular expressions to parse the output of the standard logger to parse it in structured form to the gonelog logger. This is not an ideal solution. Prefer to use a Gonelogger directly

func (StdlibAdapter) Write

func (a StdlibAdapter) Write(p []byte) (int, error)

type StdlibAdapterOption

type StdlibAdapterOption func(*StdlibAdapter)

StdlibAdapterOption sets a parameter for the StdlibAdapter.

func FileKey

func FileKey(key string) StdlibAdapterOption

FileKey sets the key for the file and line field. By default, it's "file".

func MessageKey

func MessageKey(key string) StdlibAdapterOption

MessageKey sets the key for the actual log message. By default, it's "msg".

func Parse

func Parse() StdlibAdapterOption

Parse instruct the adapter to try parse the stdlib log message to pick out fields

func TimestampKey

func TimestampKey(key string) StdlibAdapterOption

TimestampKey sets the key for the timestamp field. By default, it's "ts".

type StdlibWriter

type StdlibWriter struct{}

StdlibWriter implements io.Writer by invoking the stdlib log.Print. It's designed to be passed to a Formatting Handler as the Writer, for cases where it's necessary to redirect all gonelog log output to the stdlib logger.

func (StdlibWriter) Write

func (w StdlibWriter) Write(p []byte) (int, error)

Write implements io.Writer.

Directories

Path Synopsis
Package syslog provides the syslog level contants source code compatible with the standard library.
Package syslog provides the syslog level contants source code compatible with the standard library.

Jump to

Keyboard shortcuts

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