log

package module
v0.0.0-...-6ce1c43 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2017 License: BSD-3-Clause Imports: 9 Imported by: 0

README

Build Status Build Status GoDoc Go Report Card

log

A small structured logging library for Golang. Documentation is available at GoDoc.

Releases

Master branch is the stable production-ready branch.

Features

  • Only standard library dependencies
  • Output configurations can be modified at runtime
  • Default formatter formats log messages as JSON encoded string. Custom formatters can be used.

Example

package main

import (
	"fmt"
	"github.com/szxp/log"
	"os"
)

func main() {
	// register an io.Writer in the DefaultRouter
	// everything that is not a debug message will be written to stdout
	log.Output{
		Id:        "stdout1",
		Writer:    os.Stdout,
		Formatter: nil,
		Filter:    log.Not(log.Eq("level", "debug")),
	}.Register()

	// optional error callback in the DefaultRouter for debugging purposes
	log.OnError(func(err error, fields log.Fields, o log.Output) {
		fmt.Printf("%v: %+v: %+v", err, fields, o)
	})

	// create a logger
	logger := log.LoggerConfig{
		// TimeFormat: time.RFC3339,      // optional, see standard time package for custom formats

		Name:       "loggername",      // optional, name of the logger
		UTC:        true,              // optional, use UTC rather than local time zone
		FileLine:   log.ShortFileLine, // optional, include file and line number
		SortFields: true,              // optional, sort field keys in increasing order
		Router:     nil,               // optional, defaults to log.DefaultRouter
	}.NewLogger()

	// produce some log messages
	logger.Log(log.Fields{
		"level": "info",
		"user": log.Fields{
			"id":       1,
			"username": "admin",
		},
		"activated": true,
		"projects":  []string{"p1", "p2", "p3"},
	})

	logger.Log(log.Fields{
		"level":   "debug",
		"details": "...",
	})

	// output reconfiguration in the DefaultRouter
	// for example disable filtering on Stdout
	log.Output{
		Id:        "stdout1",
		Writer:    os.Stdout,
		Formatter: nil,
		Filter:    nil,
	}.Register()

	// Output:
	// {"activated":true,"file":"example_test.go:44","level":"info","logger":"loggername","projects":["p1","p2","p3"],"user":{"id":1,"username":"admin"}}

}

Documentation

Overview

Package log is a structured logging library.

Example
package main

import (
	"fmt"
	"github.com/szxp/log"
	"os"
)

func main() {
	// register an io.Writer in the DefaultRouter
	// everything that is not a debug message will be written to stdout
	log.Output{
		Id:        "stdout1",
		Writer:    os.Stdout,
		Formatter: nil,
		Filter:    log.Not(log.Eq("level", "debug")),
	}.Register()

	// optional error callback in the DefaultRouter for debugging purposes
	log.OnError(func(err error, fields log.Fields, o log.Output) {
		fmt.Printf("%v: %+v: %+v", err, fields, o)
	})

	// create a logger
	logger := log.LoggerConfig{
		// TimeFormat: time.RFC3339,      // optional, see standard time package for custom formats

		Name:       "loggername",      // optional, name of the logger
		UTC:        true,              // optional, use UTC rather than local time zone
		FileLine:   log.ShortFileLine, // optional, include file and line number
		SortFields: true,              // optional, sort field keys in increasing order
		Router:     nil,               // optional, defaults to log.DefaultRouter
	}.NewLogger()

	// produce some log messages
	logger.Log(log.Fields{
		"level": "info",
		"user": log.Fields{
			"id":       1,
			"username": "admin",
		},
		"activated": true,
		"projects":  []string{"p1", "p2", "p3"},
	})

	logger.Log(log.Fields{
		"level":   "debug",
		"details": "...",
	})

	// output reconfiguration in the DefaultRouter
	// for example disable filtering on Stdout
	log.Output{
		Id:        "stdout1",
		Writer:    os.Stdout,
		Formatter: nil,
		Filter:    nil,
	}.Register()

	// Output is something like this:
	// {"activated":true,"file":"example_test.go:44","level":"info","logger":"loggername","projects":["p1","p2","p3"],"user":{"id":1,"username":"admin"}}

}

Index

Examples

Constants

View Source
const (
	// FieldTime is the name of the time field.
	FieldTime = "time"

	// FieldLogger is the name of the logger field.
	FieldLogger = "logger"

	// FieldFile is the name of the file field.
	FieldFile = "file"

	// FieldSort is the name of the field that indicates
	// if the keys should be sorted in the JSON encoded
	// log message.
	FieldSort = "_sort"
)
View Source
const (
	// ShortFileLine is a config option,
	// for the final file name element and line number.
	ShortFileLine = iota + 1

	// LongFileLine is a config option,
	// for the full file path and line number.
	LongFileLine
)

Variables

View Source
var DefaultRouter = &defaultRouter{}

DefaultRouter is used by those Loggers which are created without a Router. It can be used simultaneously from multiple goroutines.

Functions

func OnError

func OnError(f func(err error, fields Fields, o Output))

OnError registers an error handler callback in the DefaultRouter.

The callback will be called if an error occurs while writing a log message to an io.Writer.

Example
package main

import (
	"fmt"
	"github.com/szxp/log"
)

func main() {
	log.OnError(func(err error, fields log.Fields, o log.Output) {
		fmt.Printf("%v: %+v: %+v", err, fields, o)
	})
}

Types

type Fields

type Fields map[string]interface{}

Fields represents a log message, a key-value map where keys are strings and a value can be a number, a string, a bool, an array, a slice, nil or another Fields object.

Example
package main

import (
	"github.com/szxp/log"
	"time"
)

func main() {
	logger := log.LoggerConfig{
		TimeFormat: time.RFC3339,      // optional, see standard time package for custom formats
		Name:       "loggername",      // optional, name of the logger
		UTC:        true,              // optional, use UTC rather than local time zone
		FileLine:   log.ShortFileLine, // optional, include file and line number
		SortFields: true,              // optional, sort field keys in increasing order
		Router:     nil,               // optional, defaults to log.DefaultRouter
	}.NewLogger()

	logger.Log(log.Fields{
		"level": "info",
		"user": log.Fields{
			"id":       1,
			"username": "admin",
		},
		"activated": true,
		"projects":  []string{"p1", "p2", "p3"},
	})
}

func (Fields) MarshalJSON

func (f Fields) MarshalJSON() ([]byte, error)

MarshalJSON marshals the fields into a JSON object.

When iterating over the field keys, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next. So field keys may appear in any order in the log message.

Keys that begin with underscore will be skipped.

If the Fields object contains a "_sort" key with a true bool value the keys will appear in increasing order in the JSON encoded string.

Create a logger with the SortFields config option set to true if you want the keys in all log messages to be sorted.

func (Fields) Value

func (f Fields) Value(path []string) (interface{}, bool)

Value returns the value at the given path. The second return value indicates if the path exists.

type Filter

type Filter interface {
	// Match evaluates the filter.
	Match(fields Fields) (bool, error)
}

Filter represents a filter condition.

func And

func And(filters ...Filter) Filter

And returns a composite filter consisting of multiple filters and-ed together.

Filters are evaluated left to right, they are tested for possible "short-circuit" evaluation using the following rules: false && (anything) is short-circuit evaluated to false.

Example
package main

import (
	"github.com/szxp/log"
	"os"
)

func main() {
	log.Output{
		Id:     "stdout1",
		Writer: os.Stdout,
		Filter: log.And(
			log.Eq("user.id", 1),
			log.Eq("level", "trace"),
		),
	}.Register()
}

func Eq

func Eq(path string, value interface{}) Filter

Eq returns a filter that checks if the value at the given path is equal to the given value. Path is a dot-separated field names.

Example
package main

import (
	"github.com/szxp/log"
	"os"
)

func main() {
	log.Output{
		Id:     "stdout1",
		Writer: os.Stdout,
		Filter: log.Eq("use.id", 1),
	}.Register()
}

func FieldExist

func FieldExist(path string) Filter

FieldExist returns a filter that checks if the given path exists in the log message. Path is a dot-separated field names.

Example
package main

import (
	"github.com/szxp/log"
	"os"
)

func main() {
	log.Output{
		Id:     "stdout1",
		Writer: os.Stdout,
		Filter: log.FieldExist("user.id"),
	}.Register()
}

func Not

func Not(filter Filter) Filter

Not returns a composite filter inverting the given filter.

Example
package main

import (
	"github.com/szxp/log"
	"os"
)

func main() {
	log.Output{
		Id:     "stdout1",
		Writer: os.Stdout,
		Filter: log.Not(log.Eq("user.id", 1)),
	}.Register()
}

func Or

func Or(filters ...Filter) Filter

Or returns a composite filter consisting of multiple filters or-ed together.

Filters are evaluated left to right, they are tested for possible "short-circuit" evaluation using the following rules: true || (anything) is short-circuit evaluated to true.

Example
package main

import (
	"github.com/szxp/log"
	"os"
)

func main() {
	log.Output{
		Id:     "stdout1",
		Writer: os.Stdout,
		Filter: log.Or(
			log.Eq("username", "admin"),
			log.Eq("username", "bot"),
		),
	}.Register()
}

type Formatter

type Formatter interface {
	// Format returns a textual representation of the fields as a []byte.
	Format(fields Fields) ([]byte, error)
}

Formatter converts a log message into a []byte.

var DefaultFormatter Formatter = &JSONFormatter{}

DefaultFormatter converts a log message into JSON. It is used when there is no formatter associated with the io.Writer. It can be used simultaneously from multiple goroutines.

type JSONFormatter

type JSONFormatter struct{}

JSONFormatter converts a log message into JSON encoded string.

JSONFormatter is safe for concurrent use by multiple goroutines.

func (*JSONFormatter) Format

func (f *JSONFormatter) Format(fields Fields) ([]byte, error)

Format returns the fields as a valid JSON.

type Logger

type Logger interface {
	// Log writes a message.
	Log(fields Fields)
}

Logger writes a message.

type LoggerConfig

type LoggerConfig struct {
	// Name of the logger. A non empty name will be
	// added to the log message at the key FieldLogger.
	//
	// The value at the key FieldLogger can be overridden
	// by specifying a custom value at that key.
	Name string

	// TimeFormat specifies the format of the timestamp.
	// If non empty, a timestamp in local time zone
	// according to the specified format will be
	// added to the log message at the key FieldTime.
	// Set UTC to true to use UTC rather than the
	// local time zone.
	//
	// The value at the key FieldTime can be overridden
	// by specifying a custom value at that key.
	//
	// See the standard time package for details on how
	// to define time formats:
	// https://golang.org/pkg/time/#pkg-constants
	TimeFormat string

	// UTC configures a logger to use UTC rather than the
	// local time zone. Assumes a non empty TimeFormat.
	UTC bool

	// FileLine, if not zero, adds the file name and line
	// number to the log message at the key FieldFile.
	//
	// Use LongFileLine for the full file path and line number.
	// Use ShortFileLine for the final file name element and
	// line number.
	//
	// The value at the key FieldFile can be overridden
	// by specifying a custom value at that key.
	FileLine int

	// SortFields indicates if the keys in the Fields
	// object should be sorted in increasing order
	// when marshaling the Fields object into JSON.
	//
	// The option can be overridden by providing a "_sort"
	// key with a bool value in the Fields object.
	SortFields bool

	// Router will forward the log messages to the registered
	// Writers. If not specified the default router will
	// be used.
	Router Router
}

LoggerConfig can be used to create a new Logger.

Example
package main

import (
	"github.com/szxp/log"
	"time"
)

func main() {
	logger := log.LoggerConfig{
		TimeFormat: time.RFC3339,      // optional, see standard time package for custom formats
		Name:       "loggername",      // optional, name of the logger
		UTC:        true,              // optional, use UTC rather than local time zone
		FileLine:   log.ShortFileLine, // optional, include file and line number
		SortFields: true,              // optional, sort field keys in increasing order
		Router:     nil,               // optional, defaults to log.DefaultRouter
	}.NewLogger()

	logger.Log(log.Fields{
		"level": "info",
		"user": log.Fields{
			"id":       1,
			"username": "admin",
		},
		"activated": true,
		"projects":  []string{"p1", "p2", "p3"},
	})
}

func (LoggerConfig) NewLogger

func (c LoggerConfig) NewLogger() Logger

NewLogger creates and returns a new logger that forwards the fields to the router associated with the logger. If the Router is not specified in the Logger the DefaultRouter will be used.

The returned Logger can be used simultaneously from multiple goroutines if and only if the Router associated with the Logger can be used simultaneously from multiple goroutines.

type Output

type Output struct {
	// Id identifies the output configuration. It can
	// be used to update the configuration later.
	Id string

	// Writer represents the storage backend that formatted
	// log messages will be written to.
	Writer io.Writer

	// Formatter converts a log message into a []byte.
	// It is optional.
	//
	// The formatter must be safe for concurrent use by multiple
	// goroutines. If the formatter is nil the DefaultFormatter
	// will be used that converts log messages into a
	// JSON encoded string.
	Formatter Formatter

	// Filter specifies which messages should be
	// written to the io.Writer. It is optional.
	Filter Filter
}

Output describes an output configuration in the DefaultRouter that formatted log messages will be written to.

Example
package main

import (
	"github.com/szxp/log"
	"os"
)

func main() {
	// register an io.Writer in the DefaultRouter
	// everything that is not a debug message will be written to stdout
	log.Output{
		Id:        "stdout1",
		Writer:    os.Stdout,
		Formatter: nil,
		Filter:    log.Not(log.Eq("level", "debug")),
	}.Register()
}

func (Output) Register

func (o Output) Register()

Register registers the output configuration in the DefaultRouter.

type Router

type Router interface {
	// Log writes the message to the registered Writers.
	Log(fields Fields)
}

Router generates lines of output to registered Writers.

Jump to

Keyboard shortcuts

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