log

package
v8.0.0 Latest Latest
Warning

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

Go to latest
Published: Jan 30, 2024 License: Apache-2.0, BSD-2-Clause, BSD-3-Clause, + 1 more Imports: 8 Imported by: 0

Documentation

Overview

Package log contains utilities for sensible logging.

ATC components written in Go should use this package rather than a third-party library. This package also provides log *levels*, which are not really supported by the standard log package, so it's generally better to use this than even that standard library.

Inspired by https://www.goinggo.net/2013/11/using-log-package-in-go.html

Usage

Normally, one will have some command-line program that takes in some kind of configuration either via command-line arguments or a configuration file, and want that configuration to define how logging happens. The easiest way to logging up and running is to put that configuration into a type that implements this package's Config interface, like:

type Configuration struct {
	ErrorLogs     string `json:"errorLogs"`
	WarningLogs   string `json:"warningLogs"`
	InfoLogs      string `json:"infoLogs"`
	DebugLogs     string `json:"debugLogs"`
	EventLogs     string `json:"eventLogs"`
	EnableFeature bool   `json:"enableFeature"`
}

func (c Configuration) ErrorLog() string { return c.ErrorLogs}
func (c Configuration) WarningLog() string { return c.WarningLogs }
func (c Configuration) InfoLog() string { return c.InfoLogs }
func (c Configuration) DebugLog() string { return c.DebugLogs }
func (c Configuration) EventLog() string { return c.EventLogs }

Then the configuration can be unmarshaled from JSON and the resulting Configuration can be passed directly to InitCfg, and then everything is set-up and ready to go.

Index

Constants

View Source
const (
	DebugPrefix = "DEBUG: "
	InfoPrefix  = "INFO: "
	WarnPrefix  = "WARNING: "
	ErrPrefix   = "ERROR: "
	EventPrefix = ""
)

These are prefixes prepended to messages for the various log levels.

View Source
const (
	DebugFlags = log.Lshortfile
	InfoFlags  = log.Lshortfile
	WarnFlags  = log.Lshortfile
	ErrFlags   = log.Lshortfile
	EventFlags = 0
)

These constants are flags used to create the underlying "log.Logger", defining what's in the prefix for different types of log messages.

Refer to the "log" package documentation for details.

View Source
const (
	// LogLocationStdout indicates the stdout IO stream.
	LogLocationStdout = "stdout"
	// LogLocationStderr indicates the stderr IO stream.
	LogLocationStderr = "stderr"
	// LogLocationNull indicates the null IO stream (/dev/null).
	LogLocationNull = "null"
)
View Source
const LogLocationFile = "/var/log/trafficcontrol/tc-health-client.log"

LogLocationFile specify where health client logs should go.

Deprecated: It is unclear why this constant is in this package at all, and it will almost certainly be removed in the future.

View Source
const StaticFileDir = "/opt/traffic_monitor/static/"

StaticFileDir is the directory that contains static HTML and Javascript files for Traffic Monitor.

Deprecated: It is unclear why this constant is in this package at all, and it will almost certainly be removed in the future.

Variables

View Source
var (
	Debug   *log.Logger
	Info    *log.Logger
	Warning *log.Logger
	Error   *log.Logger
	Event   *log.Logger
	// Access is NOT initialized by Init nor InitCfg in any way. To initialize
	// it, use InitAccess.
	Access *log.Logger
)

These are the loggers for the various log levels, which can be accessed directly, but in general the functions exported by this package should be used instead.

Functions

func Accessln

func Accessln(v ...interface{})

Accessln prints an "access"-level log to the Access logging stream.

This does NOT use the same message formatting as the other logging functions like Errorf. Instead, it prints only the information it's given, formatted according to the format string (if present) as defined by the fmt package. For example, if line 36 of foo.go invokes this like so:

log.Accessln("%s\n", "my message")

... the resulting log line will look like:

my message

func Close

func Close(c io.Closer, context string)

Close calls `Close()` on the given Closer, and logs any error that results from that call.

On error, the context is logged, followed by a colon and the error message. Specifically, it calls Errorf with the context and error using the format '%v: %v'.

This is primarily designed to be used in `defer`, for example:

defer log.Close(resp.Body, "readData fetching /foo/bar")

Note that some Go linting tools may not properly detect this as both Closing the Closer and checking the error value that Close returns, but it does both of those things, we swear.

func Closef

func Closef(c io.Closer, contextFormat string, v ...interface{})

Closef acts like Close, with a given format string and values, followed by a colon, the error message, and a newline.

The given values are not coerced, concatenated, or printed unless an error occurs, so this is more efficient than Close in situations where the message passed to Close would have been generated with fmt.Sprintf.

This actually results in two distinct lines being printed in the Error log stream. For example, if line 36 of foo.go invokes this like so:

log.Closef(resp.Body, "doing %s", "something")

... and resp.Body.Close() returns a non-nil error with the message "failed", the resulting log lines will look like:

ERROR: log.go:271: 2006-01-02T15:04:05Z: doing something
ERROR: log.go:272: 2006-01-02T15:04:05Z: : failed

(please please please don't count on those line numbers).

func Debugf

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

Debugf prints a formatted message to the Debug logging stream.

The message format is identical to Errorf, but using the log-level prefix "DEBUG: ".

func Debugln

func Debugln(v ...interface{})

Debugln prints a line to the Debug stream.

The message format is identical to Errorln, but using the log-level prefix "DEBUG: ".

func Errorf

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

Errorf prints a formatted message to the Error logging stream.

Formatting is handled identically to the fmt package, but the final message actually printed to the stream will be prefixed with the log level and timestamp just like Errorln. Also, if the final formatted message does not end in a newline character, one will be appended, so it's not necessary to do things like e.g.

Errorf("%v\n", 5)

Instead, just:

Errorf("%v", 5)

will suffice, and will print exactly the same message.

func Errorln

func Errorln(v ...interface{})

Errorln prints a line to the Error stream.

This will use default formatting for all of its passed parameters, as defined by the fmt package. The resulting line is first prefixed with the log level - in this case "ERROR: " - and the current timestamp, as well as the context in which it was logged. For example, if line 36 of foo.go invokes this like so:

log.Errorln("something wicked happened")

... the resulting log line will look like:

ERROR: foo.go:36: 2006-01-02T15:04:05Z: something wicked happened

(assuming the log call occurred at the time package's formatting reference date/time). This allows multiple log streams to be directed to the same file for output and still be distinguishable by their log-level prefix.

func EventRaw

func EventRaw(s string)

EventRaw writes the given string directly to the Event log stream with absolutely NO formatting - trailing newline, timestamp, log-level etc.

Go's fmt.Printf/Sprintf etc. are very slow, so using this with string concatenation is by far the fastest way to log, and should be used for frequent logs.

func Eventf

func Eventf(t time.Time, format string, v ...interface{})

Eventf prints an "event"-level log to the Event logging stream.

This does NOT use the same message formatting as the other logging functions like Errorf. Instead, it prints the time at which the event occurred as the number of seconds since the Unix epoch to three decimal places of sub-second precision, followed by the trailing parameters formatted according to the format string as defined by the fmt package. For example, if line 36 of foo.go invokes this like so:

log.Eventf(time.Now(), "%s\n", "my message")

... the resulting log line will look like:

1136214245.000 my message

Note that this WILL NOT add trailing newlines if the resulting formatted message string doesn't end with one.

func EventfRaw

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

EventfRaw writes a formatted message to the Event log stream.

The formatting is just like Eventf, but no timestamp prefix will be added.

func GetLogWriter

func GetLogWriter(location LogLocation) (io.WriteCloser, error)

GetLogWriter creates a writable stream from the given LogLocation.

If the requested log location is a file, it will be opened with the write-only, create, and append flags in permissions mode 0644. If that open operation causes an error, it is returned.

As a special case, if the location is an empty string, the returned stream will be nil - this is the same behavior as passing LogLocationNull.

func GetLogWriters

GetLogWriters uses the passed Config to set up and return log streams.

This bails at the first encountered error creating a log stream, and returns the error without trying to create any further streams.

The returned streams still need to be initialized, usually with Init. To create and initialize the logging streams at the same time, refer to InitCfg.

func Infof

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

Infof prints a formatted message to the Info logging stream.

The message format is identical to Errorf, but using the log-level prefix "INFO: ".

func Infoln

func Infoln(v ...interface{})

Infoln prints a line to the Info stream.

The message format is identical to Errorln, but using the log-level prefix "INFO: ".

func Init

func Init(eventW, errW, warnW, infoW, debugW io.WriteCloser)

Init initializes the logs - except the Access log stream - with the given io.WriteClosers.

If `Init` was previously called, existing loggers are Closed. If you have loggers which are not Closers or which must not be Closed, wrap them with `log.NopCloser`.

func InitAccess

func InitAccess(accessW io.WriteCloser)

InitAccess initializes the Access logging stream with the given io.WriteCloser.

func InitCfg

func InitCfg(cfg Config) error

InitCfg uses the passed configuration to both create and initialize all logging streams.

func InitTestingLogging

func InitTestingLogging(tb testing.TB, warningsAreErrors bool)

InitTestingLogging initializes all logging functions to write their outputs to the logging output of the given testing context. If warningsAreErrors is true, warnings are logged using t.Error - marking the test as failed. Otherwise, errors are logged using t.Log. In either case, any errors logged cause the test to be marked as failed and are logged using t.Error, and the Info, Event, and Debug streams are always logged using t.Log.

func LLog

func LLog() llog.Log

LLog returns an llog.Log, for passing to libraries using llog.

Note the returned Log will have writers tied to loggers at its time of creation. Thus, it's safe to reuse LLog if an application never re-initializes the loggers, such as when reloading config on a HUP signal. If the application re-initializes loggers, LLog should be called again to get a new llog.Log associated with the new log locations.

func Logf

func Logf(logger *log.Logger, format string, v ...interface{})

Logf should generally be avoided, use the Init or InitCfg and Errorf, Warnln, etc functions instead.

It logs to the given logger, in the same format as the standard log functions. This should only be used in rare and unusual circumstances when the standard loggers and functions can't.

func Logln

func Logln(logger *log.Logger, v ...interface{})

Logln should generally be avoided, use the built-in Init or InitCfg and Errorf, Warnln, etc functions instead. It logs to the given logger, in the same format as the standard log functions. This should only be used in rare and unusual circumstances when the standard loggers and functions can't.

func NopCloser

func NopCloser(w io.Writer) io.WriteCloser

NopCloser returns an io.WriteCloser which wraps the passed io.Writer with a Close method that just does nothing but return a nil error. This allows non-closable streams to be used for logging.

func StandardLogger

func StandardLogger(logger *log.Logger, prefix string) *log.Logger

StandardLogger returns a new Logger which will write the appropriate prefix for standard log Printf calls. This allows the given logger to prefix correctly when passed to third-party or standard library functions which only know about the standard Logger interface. It does this by wrapping logger's error print as a writer, and sets that as the new Logger's io.Writer.

prefix is a prefix to add, which will be added immediately before messages, but after any existing prefix on logger and the timestamp.

func Warnf

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

Warnf prints a formatted message to the Warning logging stream.

The message format is identical to Errorf, but using the log-level prefix "WARNING: ".

func Warnln

func Warnln(v ...interface{})

Warnln prints a line to the Warning stream.

The message format is identical to Errorln, but using the log-level prefix "WARNING: ".

func Write

func Write(w io.Writer, b []byte, context string)

Write calls the Write method of the given Writer with the passed byte slice as an argument, and logs any error that arises from that call.

On error, the context is logged, followed by a colon and the error message, and a trailing newline is guaranteed. For example, if line 36 of foo.go invokes this like so:

log.Write(someWriter, []byte("write me"), "trying to write")

... and someWriter.Write() returns a non-nil error with the message "failed", the resulting log line will look like:

ERROR: log.go:294: 2006-01-02T15:04:05Z: trying to write: failed

(please please please don't count on that line number).

func Writef

func Writef(w io.Writer, b []byte, contextFormat string, v ...interface{})

Writef acts like Write, with a given format string and values, followed by a colon, the error message, and a newline.

The given values are not coerced, concatenated, or printed unless an error occurs, so this is more efficient than Write in situations where the message passed to Write would have been generated with fmt.Sprintf.

This actually results in two distinct lines being printed in the Error log stream. For example, if line 36 of foo.go invokes this like so:

log.Writef(someWriter, "doing %s", "something")

... and someWriter.Write() returns a non-nil error with the message "failed", the resulting log lines will look like:

ERROR: log.go:320: 2006-01-02T15:04:05Z: doing something
ERROR: log.go:321: 2006-01-02T15:04:05Z: : failed

(please please please don't count on those line numbers).

Types

type Config

type Config interface {
	ErrorLog() LogLocation
	WarningLog() LogLocation
	InfoLog() LogLocation
	DebugLog() LogLocation
	EventLog() LogLocation
}

Config structures represent logging configurations, which can be accessed by this package for setting up the logging system via GetLogWriters.

type LogLocation

type LogLocation string

LogLocation is a location to log to. This may be stdout, stderr, null (/dev/null), or a valid file path.

Jump to

Keyboard shortcuts

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