Documentation ¶
Overview ¶
Package slog provides structured, context-aware logging. It is intended for use by applications that make use of the golang.org/x/net/context package. (See https://blog.golang.org/context for more information).
The idea is that the application can build up information on the current request, transaction, or operation and store it in the current context. When an event occurs that needs to be logged, the built-up context is included in the log message.
file, err := os.Open(filename) if err != nil { // message logged will include any logging context stored in ctx slog.Error(ctx, "cannot open file", slog.WithValue("filename", filename), slog.WithError(err)) } // Output: (assuming userip has been set in the context) // 2009-11-10T12:34:56.789 error msg="cannot open file" filename=/etc/hosts error="file does not exist" userip=123.231.111.222
Out of the box, this package logs to stdout in logfmt format. (https://brandur.org/logfmt). Other formats are planned (including pretty TTY output), and a handler mechanism exists to integrate with external logging providers.
See the examples for more details. A more comprehensive guide is available at https://github.com/spkg/slog
Example ¶
package main import ( "errors" log "github.com/spkg/slog" "golang.org/x/net/context" ) func main() { // everything logged needs a context ctx := context.Background() log.Info(ctx, "program started") if err := doFirstThing(ctx, 5, 4); err != nil { // ... error processing here ... } // YYYY-MM-DDTHH:MM:SS.FFFFFF info msg="program started" // YYYY-MM-DDTHH:MM:SS.FFFFFF error msg="cannot do third thing" error="error message goes here" a=5 b=4 } // doFirstThing illustrates setting a new logging context. // Any message logged with the new context will have values for // a and b. func doFirstThing(ctx context.Context, a, b int) error { // add some logging to the context ctx = log.NewContext(ctx, log.Property{Key: "a", Value: a}, log.Property{Key: "b", Value: b}) // ... perform some more processing and then return doSecondThing(ctx) } func doSecondThing(ctx context.Context) error { if err := doThirdThing(); err != nil { // log the message at the first point where the context is available return log.Error(ctx, "cannot do third thing", log.WithError(err)) } return nil } func doThirdThing() error { // this function has no context so it does not log, // it just returns an error message return errors.New("error message goes here") }
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // Default is the default logger. Default = New() )
var (
MinLevel = LevelInfo
)
MinLevel is the minimum level that will be logged. The calling program can change this value at any time.
Functions ¶
func AddHandler ¶
func AddHandler(h Handler)
AddHandler appends the handler to the list of handlers for the default logger.
Example ¶
package main import ( "log" "net/http" "github.com/spkg/slog" "golang.org/x/net/context" ) type ExternalHandler struct { // ... details for accessing external handler ... } func (h *ExternalHandler) Handle(msgs []*slog.Message) { // ... send to msgs to external logging handler ... } func main() { slog.AddHandler(&ExternalHandler{}) } func main(ctx context.Context) { // Creates a HTTP server whose error log will write to the // default slog.Logger. Any panics that are recovered will // have the details logged via slog. httpServer := &http.Server{ Addr: ":8080", ErrorLog: log.New(slog.NewWriter(ctx), "http", 0), } slog.Info(ctx, "web server started", slog.WithValue("addr", httpServer.Addr)) if err := httpServer.ListenAndServe(); err != nil { slog.Error(ctx, "web server failed", slog.WithError(err)) } // 2009-11-10T12:34:56.789 info msg="web server started" addr=:8080 // 2009-11-10T12:35:57:987 error msg="http: panic serving 123.1:2.3:36145 runtime error: invalid memory address or nil pointer dereference" } func main(ctx context.Context, n1, n2 int) error { if err := doSomethingWith(n1, n2); err != nil { return slog.Error(ctx, "cannot doSomething", slog.WithValue("n1", n1), slog.WithValue("n2", n2), slog.WithError(err)) } // .. more processing and then ... return nil } func main(ctx context.Context, n1, n2 int) error { if err := doSomethingWith(n1, n2); err != nil { return slog.Error(ctx, "doSomethingWith failed", slog.WithValue("n1", n1), slog.WithValue("n2", n2)) } // ... more processing and then ... return nil } func main(ctx context.Context) error { if err := doSomething(); err != nil { return slog.Error(ctx, "doSomething failed", slog.WithError(err)) } // ... more processing and then ... return nil } func main(ctx context.Context, n1, n2 int) error { ctx = slog.NewContext(ctx, slog.Property{Key: "n1", Value: n1}, slog.Property{Key: "n2", Value: n2}) if err := doSomethingWith(n1, n2); err != nil { return slog.Error(ctx, "doSomethingWith failed", slog.WithError(err)) } slog.Debug(ctx, "did something with") // ... more processing and then ... return nil } func doSomethingWith(n1 int, n2 int) error { return nil } func doSomething() error { return nil } func doAnotherThing() error { return nil } func doOneMoreThing() error { return nil }
Output:
func NewContext ¶
NewContext returns a new context that has one or more properties associated with it for logging purposes. The properties will be included in any log message logged with this context.
func NewWriter ¶
NewWriter creates a new writer that can be used to integrate with the standard log package. The main use case for this is to log messages generated from the standard library, in particular the net/http package. See the example for more information.
func SetMinLevel ¶
func SetMinLevel(level Level)
SetMinLevel sets the minimum log level for the default logger. By default the minimum log level is LevelInfo.
Types ¶
type Handler ¶
type Handler interface {
Handle(msgs []*Message)
}
Handler is an interface for message handlers. A message handler is added to a Logger to perform arbitrary process of log messages.
type Level ¶
type Level int
Level indicates the level of a log message.
const ( LevelDebug Level = iota // Debugging only LevelInfo // Informational LevelWarning // Warning LevelError // Error condition )
Values for Level.
func (Level) MarshalText ¶
MarshalText implements the encoding.TextMarshaler interface.
func (*Level) UnmarshalText ¶
UnmarshalText implements the encoding.TextUnmarshaler interface.
type Logger ¶
type Logger interface { Debug(ctx context.Context, text string, opts ...Option) *Message Info(ctx context.Context, text string, opts ...Option) *Message Warn(ctx context.Context, text string, opts ...Option) *Message Error(ctx context.Context, text string, opts ...Option) *Message NewWriter(ctx context.Context) io.Writer SetOutput(w io.Writer) SetMinLevel(level Level) AddHandler(h Handler) }
Logger is an interface for logging.
type Message ¶
type Message struct { Timestamp time.Time Level Level Text string Err error Properties []Property Context []Property // contains filtered or unexported fields }
Message contains all of the log message information. Note that *Message implements the error interface.
func Debug ¶
Debug logs a debug level message to the default logger. Returns a non-nil *Message, which can be used as an error value.
func Error ¶
Error logs an error level message to the default logger. Returns a non-nil *Message, which can be used as an error value.
func Info ¶
Info logs an informational level message to the default logger. Returns a non-nil *Message, which can be used as an error value.
func Warn ¶
Warn logs a warning level message to the default logger. Returns a non-nil *Message, which can be used as an error value.
func (*Message) Code ¶
Code returns the code associated with the message. Implements the Coder interface.
func (*Message) Logfmt ¶
Logfmt writes the contents of the message to the buffer in logfmt format. See https://brandur.org/logfmt for a description of logfmt. Returns number of bytes written to w.
type Option ¶
type Option func(*Message)
An Option is a function option that can be applied when logging a message. See the example for how they are used. Options is based on Dave Cheney's article "Functional options for friendly APIs" (http://goo.gl/l2KaW3) that can be applied to a Message.
func WithCode ¶
WithCode associates an arbitrary code with the Message that is logged. This is useful for associating a pre-agreed error code with the message.
func WithStatusCode ¶
WithStatusCode sets a status code associated with the log message. This is useful for associating a HTTP status code, but the status can be any number that makes sense for the application.