golog

package module
v0.0.0-...-7c322ca Latest Latest
Warning

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

Go to latest
Published: Dec 7, 2011 License: BSD-2-Clause Imports: 13 Imported by: 0

README

About this package

This package is designed to support better logging for Go. Specifically, this project aims to support different levels of logging and the ability to customize log output via custom implementations of the interfaces provided in the package. In addition, all logged messages are wrapped in closures and are only evaluated and rendered if they will be outputed.

You can install this package via:

goinstall github.com/awreece/golog

Using this package

Introductory usage

The easiest way to start using this package is to use the Global PackageLogger and the exported global namespace wrapper functions. For example:

package mypackage

import "github.com/awreece/golog"

func Foo() {
	golog.Info("Hello, world")
	golog.Warningf("Error %d", 4)
	golog.Errorc(func() { return verySlowStringFunction() })
	golog.Fatal("Error opening file:", err)
}

The Global PackageLogger outputs to default files set by flags. For example, to log to stderr and to temp.log at log level WARNING, invoke the binary using this package as follows: ./mybinary --golog.logfile=/dev/stderr --golog.logfile=temp.log --golog.minloglevel=1

This package also makes it easy to log to a testing harness in addition to files. To do this, invoke StartTestLogging(t) at the start of every test and StopTestLogging() at the end. For example:

package mypackage

import (
	"github.com/awreece/golog"
	"testing"
)

func TestFoo(t *testing.T) {
	golog.StartTestLogging(t); defer golog.StopTestLogging()

	// Test the Foo() function.
	Foo()
}

While in test logging mode, calls to Fatal() (and DefaultLogger.FailNow()) will call testing.(*T).FailNow() rather than exiting the program abruptly.

Another common way to use this pacakge is to create a local PackageLogger. This can either be declared on the package level or passed in by value.

Advanced usage

This package is highly modular and configurable; different components can be plugged in to modify the behavior. For example, to speed up logging, an advanced user could try creating a LocationLogger using the NoLocation function, or even create a custom location function.

Advanced users can further take advantage of the modularity of the package to implement and control individual parts. For example, logging in XML format should be done by writing a proper LogOuter.

Understanding this package

This package was designed to be highly modular, with different interfaces for each logical component. The important types are:

  • A LogMessage is a logged message with associated metadata.

  • A LogOuter controls the formatted output of a LogMessage.

  • A MultiLogOuter multiplexes an outputted message to a set of keyed LogOuters. The associated MultiLogOuterFlag automatically add logfiles to the associated set of LogOuters.

  • A Logger decides whether or not to log a message, and if so renders the message and outputs it.

  • A LocationLogger is a wrapper for a Logger that generates a closure to return a LogMessage with the associate metadata and is the first easily usable entrypoint into this package.

  • A StringLogger is a wrapper for a LocationLogger that exports methods for logging at semantic levels.

  • A PackageLogger has a set of functions designed be quickly useful and is the expected entry point into this package.

For additional documenation, see the godoc output for this package.

Documentation

Overview

This package is designed to support better logging for Go. Specifically, this project aims to support different levels of logging and the ability to customize log output via custom implementations of the interfaces provided in the package. In addition, all logged messages are wrapped in closures and are only evaluated and rendered if they will be outputed.

The easiest way to start using this package is to use the Global PackageLogger and the exported global namespace wrapper functions. For example:

package mypackage

import "github.com/awreece/golog"

func Foo() {
	golog.Info("Hello, world")
	golog.Warningf("Error %d", 4)
	golog.Errorc(func() { return verySlowStringFunction() })
	golog.Fatal("Error opening file:", err)
}

The Global PackageLogger outputs to default files set by flags. For example, to log to stderr and to temp.log, invoke the binary with the additional flags --golog.logfile=/dev/stderr --golog.logfile=temp.log.

This package also makes it easy to log to a testing harness in addition to files. To do this, invoke StartTestLogging(t) at the start of every test and StopTestLogging() at the end. For example:

package mypackage

import (
	"github.com/awreece/golog"
	"testing"
)

func TestFoo(t *testing.T) {
	golog.StartTestLogging(t); defer golog.StopTestLogging()

	// Test the Foo() function.
	Foo()
}

While in test logging mode, calls to Fatal() (and DefaultLogger.FailNow()) will call testing.(*T).FailNow() rather than exiting the program abruptly.

Another common way to use this pacakge is to create a local PackageLogger. This can either be declared on the package level or passed in by value.

Advanced usage This package is highly modular and configurable; different components can be plugged in to modify the behavior. For example, to speed up logging, an advanced user could try creating a LocationLogger using the NoLocation function, or even create a custom location function.

Advanced users can further take advantage of the modularity of the package to implement and control individual parts. For example, logging in XML format should be done by writing a proper LogOuter.

This package was designed to be highly modular, with different interfaces for each logical component. The important types are:

- A LogMessage is a logged message with associated metadata.

- A LogOuter controls the formatted output of a LogMessage.

- A MultiLogOuter multiplexes an outputted message to a set of keyed LogOuters. The associated MultiLogOuterFlag automatically adds logfiles to the associated set of LogOuters.

- A Logger decides whether or not to log a message, and if so renders the message and outputs it.

- A LocationLogger is a wrapper for a Logger that generates a closure to return a LogMessage with the associate metadata and is the first easily usable entrypoint into this package.

- A StringLogger is a wrapper for a LocationLogger that exports methods for logging at semantic levels.

- A PackageLogger has a set of functions designed be quickly useful and is the expected entry point into this package.

Better logging for Go.

Index

Constants

View Source
const (
	INFO int = iota
	WARNING
	ERROR
	FATAL
)

Variables

This section is empty.

Functions

func AddLogOuter

func AddLogOuter(key string, outer LogOuter)

Wrapper for Global.AddLogOuter().

func Error

func Error(msg ...interface{})

Wrapper for Global.Error().

func Errorc

func Errorc(closure func() string)

Wrapper for Global.Errorc().

func Errorf

func Errorf(fmt string, vals ...interface{})

Wrapper for Global.Errorf().

func ExitError

func ExitError()

func Fatal

func Fatal(msg ...interface{})

Wrapper for Global.Fatal().

func Fatalc

func Fatalc(closure func() string)

Wrapper for Global.Fatalc().

func Fatalf

func Fatalf(fmt string, vals ...interface{})

Wrapper for Global.Fatalf().

func Info

func Info(msg ...interface{})

Wrapper for Global.Info().

func Infoc

func Infoc(closure func() string)

Wrapper for Global.Infoc().

func Infof

func Infof(fmt string, vals ...interface{})

Wrapper for Global.Infof().

func RemoveLogOuter

func RemoveLogOuter(key string)

Wrapper for Global.RemoveLogOuter().

func SetMinLogLevel

func SetMinLogLevel(level int)

Wrapper for Global.SetMinLogLevel().

func StartTestLogging

func StartTestLogging(t TestController)

Wrapper for Global.StartTestLogging().

func StopTestLogging

func StopTestLogging()

Wrapper for Global.StopTestLogging().

func Warning

func Warning(msg ...interface{})

Wrapper for Global.Warning().

func Warningc

func Warningc(closure func() string)

Wrapper for Global.Warningc().

func Warningf

func Warningf(fmt string, vals ...interface{})

Wrapper for Global.Warningf().

Types

type LocationFlag

type LocationFlag int
const (
	None LocationFlag = 1 << iota
	Package
	Function
	File
	Line
	Hostname
	DefaultMetadata = File | Line
	All             = Package | Function | File | Line | Hostname
)

type LocationLogger

type LocationLogger interface {
	Logger
	LogDepth(level int, closure func() string, depth int)
}

A LocationLogger wraps useful methods for outputting strings by creating a LogMessage with the relevant metadata.

func NewDefaultLocationLogger

func NewDefaultLocationLogger() LocationLogger

Returns a LocationLogger wrapping the DefaultLogger.

func NewLocationLogger

func NewLocationLogger(l Logger, metadataFunc MetadataFunc) LocationLogger

Returns a new LocationLogger wrapping the associated logger, and using the provided function to generate the metadata. For example:

log := NewLocationLogger(NewDefaultLogger(), NoLocation)

type LogMessage

type LogMessage struct {
	Level       int
	Nanoseconds time.Time
	Message     string
	// A map from the type of metadata to the metadata, if present.
	// By convention, fields in this map will be entirely lowercase and
	// single word.
	Metadata map[string]string
}

type LogOuter

type LogOuter interface {
	// Output a LogMessage (to a file, to stderr, to a tester, etc). Output
	// must be safe to call from multiple threads.
	Output(*LogMessage)
}

func NewFileLogOuter

func NewFileLogOuter(filename string) (LogOuter, error)

Returns a LogOuter wrapping the file, or an error if the file cannot be opened.

func NewTestLogOuter

func NewTestLogOuter(t TestController) LogOuter

Return a LogOuter wrapping the TestControlller.

func NewUDPLogOuter

func NewUDPLogOuter(raddr string) (LogOuter, error)

Returns a LogOuter that forwards LogMessages in json format to UDP network address. TODO(awreece): Use protobuf?

func NewWriterLogOuter

func NewWriterLogOuter(f io.Writer) LogOuter

Returns a LogOuter wrapping the io.Writer.

type Logger

type Logger interface {
	// If the message is to be logged, evaluates the closure and outputs
	// the result.
	Log(level int, closure func() *LogMessage)
	// Fail and halt standard control flow.
	FailNow()
	// All future calls to log with log only if the message is at
	// level or higher.
	// TODO(awreece) Put in different interface to keep Logger agnostic?
	SetMinLogLevel(level int)
}

Logger.Log uses the level to determine whether or not to output the arguments. Logger.Log will output the provided arguments exactly, without additional formatting such as adding a prefix etc. In addition, Logger.Log must be thread safe. The FailNow() function flushes the Logger and performs some action. The action performed by FailNow() is deliberately unspecified, but could include os.Exit(1) or testing.(*T).FailNow(), etc.

type LoggerFlag

type LoggerFlag interface {
	Logger
	flag.Value
}

A Logger that can be used as a flag to set minloglevel. For example,

var myLogger LoggerFlag = NewDefaultLogger()

func init() {
	flag.Var(myLogger, "minloglevel", "Log messages at or above "+
		"this level")
}

func NewDefaultLogger

func NewDefaultLogger() LoggerFlag

Return a default initialized log outer.

func NewLogger

func NewLogger(outer LogOuter, minloglevel int, failFunc func()) LoggerFlag

Construct a new Logger that writes any messages of level minloglevel or higher to the given LogOuter. Calls to Logger.FailNow() call the provided failFunc closure.

type MetadataFunc

type MetadataFunc func(skip int) map[string]string

TODO(awreece) comment this Skip 0 refers to the function calling this function. Walks up the stack skip frames and returns the metatdata for that frame.

var NoLocation MetadataFunc = func(skip int) map[string]string {

	return make(map[string]string)
}

func MakeMetadataFunc

func MakeMetadataFunc(flags LocationFlag) MetadataFunc

Returns a function the computes the specified fields of metadata for the log message.

flags is the set of locations to add to the metadata. For example,

MakeMetadataFunc(File | Line | Hostname)

type MultiLogOuter

type MultiLogOuter interface {
	LogOuter
	// Add the LogOuter, associating it with the key.
	AddLogOuter(key string, outer LogOuter)
	// Remove the LogOuter associated with the key.
	RemoveLogOuter(key string)
}

A MultiLogOuter is a LogOuter with multiple keyed LogOuters. All functions should be safe to call in a multi-threaded environment.

type MultiLogOuterFlag

type MultiLogOuterFlag interface {
	MultiLogOuter
	flag.Value
}

A MultiLogOuter than can also be used as a flag for setting logfiles. For example, it is possible to use a logger other than default via:

var myOuter MultiLogOuterFlag = NewMultiLogOuter()

func init() {
	flag.Var(myOuter,
		"mypack.logfile",
		"Log to file - can be provided multiple times")
}

func NewDefaultMultiLogOuter

func NewDefaultMultiLogOuter() MultiLogOuterFlag

Create a new MultiLogOuter initialized with a mapping of "default" to the default MultiLogOuter.

func NewMultiLogOuter

func NewMultiLogOuter() MultiLogOuterFlag

Create an empty new MutliLogOuter.

type PackageLogger

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

A PackageLogger is the expected entry point into this package. It is a StringLogger that also provides the StartTestLogging and StopTestLogging, as well as the ability to add and remove LogOuters and modify minloglevel.

var Global *PackageLogger

func NewDefaultPackageLogger

func NewDefaultPackageLogger() *PackageLogger

Construct a new PackageLogger with sensible defaults.

func NewPackageLogger

func NewPackageLogger(outer MultiLogOuter, minloglevel int,
	failFunc func(), metadataFunc MetadataFunc) *PackageLogger

func (*PackageLogger) AddLogOuter

func (l *PackageLogger) AddLogOuter(key string, outer LogOuter)

Export MutliLogOuter.AddLogOuter().

func (*PackageLogger) Error

func (l *PackageLogger) Error(msg ...interface{})

Implement StringLogger.Error().

func (*PackageLogger) Errorc

func (l *PackageLogger) Errorc(closure func() string)

Implement StringLogger.Errorc().

func (*PackageLogger) Errorf

func (l *PackageLogger) Errorf(fmt string, vals ...interface{})

Implement StringLogger.Errorf().

func (*PackageLogger) Fatal

func (l *PackageLogger) Fatal(msg ...interface{})

Implement StringLogger.Fatal().

func (*PackageLogger) Fatalc

func (l *PackageLogger) Fatalc(closure func() string)

Implement StringLogger.Fatalc()

func (*PackageLogger) Fatalf

func (l *PackageLogger) Fatalf(fmt string, vals ...interface{})

Implement StringLogger.Fatalf()

func (*PackageLogger) Info

func (l *PackageLogger) Info(msg ...interface{})

Implements StringLogger.Info().

func (*PackageLogger) Infoc

func (l *PackageLogger) Infoc(closure func() string)

Implement StringLogger.Infoc()

func (*PackageLogger) Infof

func (l *PackageLogger) Infof(fmt string, vals ...interface{})

Implement StringLogger.Infof().

func (*PackageLogger) Log

func (l *PackageLogger) Log(level int, msg ...interface{})

Implement StringLogger.Log()

func (*PackageLogger) Logc

func (l *PackageLogger) Logc(level int, closure func() string)

Implement StringLogger.Logc()

func (*PackageLogger) Logf

func (l *PackageLogger) Logf(level int, format string, msg ...interface{})

Implement StringLogger.Logf()

func (*PackageLogger) RemoveLogOuter

func (l *PackageLogger) RemoveLogOuter(key string)

Export MutliLogOuter.RemoveLogOuter().

func (*PackageLogger) SetMinLogLevel

func (l *PackageLogger) SetMinLogLevel(level int)

Export Logger.SetMinLogLevel(). Note - this will affect MinLogLevel of underlying Logger.

func (*PackageLogger) StartTestLogging

func (l *PackageLogger) StartTestLogging(t TestController)

Associates TestController with a the "testing LogOuter and updates l.FailNow() to call t.FailNow().

func (*PackageLogger) StopTestLogging

func (l *PackageLogger) StopTestLogging()

Removes the testing logger and restores l.FailNow() to its previous state.

func (*PackageLogger) Warning

func (l *PackageLogger) Warning(msg ...interface{})

Implement StringLogger.Warning().

func (*PackageLogger) Warningc

func (l *PackageLogger) Warningc(closure func() string)

Implement StringLogger.Warningc().

func (*PackageLogger) Warningf

func (l *PackageLogger) Warningf(fmt string, vals ...interface{})

Implement StringLogger.Warningf().

type StringLogger

type StringLogger interface {
	// Log the message at the level provided, formatting the message as if
	// via a call to fmt.Sprint (only rendering string if the message will
	// be logged).
	Log(level int, msg ...interface{})
	// Log the message at the level provided, formatting the message as if
	// via a call to fmt.Sprintf (only rendering the string if the message
	// will be logged).
	Logf(level int, fmt string, val ...interface{})
	// Log the message at the level provided. Only evaluates the closure if
	// the message will be logged.
	Logc(int, func() string)
	// Log the message at the INFO level, formatting the message as if via
	// a call to fmt.Sprint and only rendering the string if the message
	// will be logged.
	Info(msg ...interface{})
	// Log the message at the INFO level, formatting the message as if via
	// a call to fmt.Sprintf and only rendering the string if the message
	// will be logged.
	Infof(string, ...interface{})
	// Log the message at the INFO level, only evaluating the closure and
	// rendering the string if the message will be logged.
	Infoc(func() string)
	// Log the message at the WARNING level, formatting the message as if via
	// a call to fmt.Sprint and only rendering the string if the message
	// will be logged.
	Warning(...interface{})
	// Log the message at the WARNING level, formatting the message as if via
	// a call to fmt.Sprintf and only rendering the string if the message
	// will be logged.
	Warningf(string, ...interface{})
	// Log the message at the WARNING level, only evaluating the closure and
	// rendering the string if the message will be logged.
	Warningc(func() string)
	// Log the message at the ERROR level, formatting the message as if via
	// a call to fmt.Sprint and only rendering the string if the message
	// will be logged.
	Error(...interface{})
	// Log the message at the ERROR level, formatting the message as if via
	// a call to fmt.Sprintf and only rendering the string if the message
	// will be logged.
	Errorf(string, ...interface{})
	// Log the message at the ERROR level, only evaluating the closure and
	// rendering the string if the message will be logged.
	Errorc(func() string)
	// Log the message at the FATAL level, formatting the message as if via
	// a call to fmt.Sprint and only rendering the string if the message
	// will be logged. Afterwards, calls a LogOuter.FailNow().
	Fatal(...interface{})
	// Log the message at the FATAL level, formatting the message as if via
	// a call to fmt.Sprintf and only rendering the string if the message
	// will be logged. Afterwards, calls a LogOuter.FailNow()
	Fatalf(string, ...interface{})
	// Log the message at the FATAL level, only evaluating the closure and
	// rendering the string if the message will be logged. Afterwards,
	// calls a LogOuter.FailNow().
	Fatalc(func() string)
}

type TestController

type TestController interface {
	// We will assume that testers insert newlines in manner similar to
	// the FEATURE of testing.T where it inserts extra newlines. >.<
	Log(...interface{})
	FailNow()
}

We want to allow an abitrary testing framework.

Jump to

Keyboard shortcuts

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