logging

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2021 License: NCSA Imports: 9 Imported by: 2

README

logging: A slightly more advanced logging apparatus for Go

logging provides basic compatibility with the standard library log package insofar as its basic API, with missing methods provided via a wrapper. However, logging also provides most "standard" (depending on whose standard you consult) logging levels available in logging utilities oft-used in other environments.

logging goes a step further than the stdlib log package--and a handful of other Golang logging libraries--in that it allows greater control over the log format by exposing an API to override output as it is logged. logging also provides a few other conveniences such as: Individual backends per logging level, hierarchical logging, and chained loggers.

Quick Start

This README is only intended as a quick start guide. For more detailed usage documentation, please refer to the docs/ directory in this repository (or in your local copy!).

To create and use a logger:

import "logging"

func main() {
    logger := logging.MustGetLogger("main")

    // Do something.

    logger.Error("an error occurred!")
}

To change the default logging level (logging.Warning):


logger := logging.MustGetLogger("main")

// Set the log level to info.
logger.SetLevel(logging.Info)

Defined Levels

logging defines the following levels: Fatal, Error, Warning, Notice, Info, and Debug. For each of these levels there is an exported log function with the suffix f (e.g. Error and Errorf) for logging C-style formatted strings and their arguments.

Additionally, logging also aliases common abbreviations; e.g., Warning() and Warn() are identical as are Information() and Info(). For compatibility with the standard library log, logging also defines Panic and Fatal functions.

Backends and Output Control

logging supports any backend that exposes an io.Writer interface. By default, logging will output entries to io.Stdout. To change this, call SetBackend() on any already-created Log instance.

Note: SetBackend() always wraps io.Writer instances with a synchronous wrapper to reduce the likelihood that output from multiple sources will be interleaved. If this is not desirable for whatever reason, SetRawBackend() will apply the specified backend without wrapping it in synchronization primitives.

It is also possible to configure Log instances with different backends depending on level. Here, we discuss examples of common use cases.

Change Backend

To change the backend to a file:


fp, _ := os.OpenFile("filename", os.O_WRONLY|os.O_TRUNC, os.FileMode(0644))
logger.SetBackend(fp)

To change the backend for certain levels:


fp, _ := os.OpenFile("filename", os.O_WRONLY|os.O_TRUNC, os.FileMode(0644))
logger.SetBackendForLevel(logging.Error)
logger.SetBackendForLevel(logging.Warning)

Note: This will only change the backend for the specified level.

Clear Backend

Sometimes it may be necessary to clear the backend associated with a specific level. This will force the logger for that level to revert to the default backend:

logger.ClearBackend(logging.Error)
Wrapper Support

As with SetBackend(), SetBackendForLevel() also includes an option to bypass the io.Writer synchronization by calling SetRawBackendForLevel().

All wrapped writers are of type *logging.SyncWriter and implement the Wrapper interface.

Chaining

logging provides an API for chaining multiple loggers together. This is mostly useful if you intend to direct output to different io.Writers depending on the configured logging level. For example, it's possible to output Info logs to STDOUT, Error logs to a specific error file, and everything to its own file for later analysis.

Chained loggers must start with the most specific log and complete the chain with the least restrictive. In our example, above, we might construct the logger chain as:

applog := logging.MustGetLogger("main")
applog.SetBackendForLevel(logging.Info, os.Stdout)
applog.SetBackendForLevel(logging.Error, errorLog) // errorLog is a file pointer

everything := logging.MustGetLogger("everything")
everything.SetBackend(everythingLog) // everythignLog is a file pointer

appLog.Chain(everything)

Inheritance

logging supports creating a logger hierarchy where a child logger inherits attributes from its parent. Creating an inheritance chain can be done in one of two ways. The first, by a method on the logger instead itself:

logger := logging.MustGetLogger("main")
httplogger := logger.Inherit("http")

And the second via a top-level function call:

logger := logging.MustGetLogger("main")
httplogger := logging.MustInheritLogger("main", "http")

Inherited loggers are stored in the top-level map using a dot-separated notation and can be retrieved similarly to other loggers:

httplogger := logging.MustGetLogger("main.http")

Note: MustGetLogger() does not currently support creating intermediate loggers using dot notation. This will instead create a logger with the name "main.http."

Iteration

It's possible to iterate through a list of loggers using inheritance and iteration. Each logger has an Iterate() method that accepts a function consuming a single *Log parameter that will apply this function to every child logger under its inheritance tree. This can be useful for disabling or redirecting the logging output of all child logs:

logger := logging.MustGetLogger("main")
logger.Iterate(func(lg *logging.Log) {
    // Discard all output for child loggers.
    lg.SetBackend(logging.Discard)
})

Formatters

logging exposes some primitives for crafting custom formatters. These formatters control how individual log entries are written to disk and could--in theory--be used to shuttle log entries to other sources (syslog, systemd-journald, etc). Currently, only two loggers are provided: The default logger, which provides simple text template replacement; and the template formatter which uses Golang's text/template to format output.

To create a formatter, it is necessary to register a function that matches the logging.FormatterFunc signature with a logger's SetFormatter() function. Formatters then receive the arguments: an io.Writer instance, a reference to the current logger instance of type *logging.Log, and a *logging.Message pointer.

logging.Message contains all of the metadata associated with a log entry: The timestamp, the error level, and its message.

When constructing a new formatter, it may be important to keep in mind a few things:

  • The io.Writer instance is the output channel that interfaces directly with the backend; this may be a file, STDOUT, or anything else implementing the io.Writer interface. This writer may not be buffered, so you will need to buffer your output internally if you plan on making several small writes per log entry. Doing so will improve throughput in most circumstances.
  • If you need to do initialization of an object, do so within a factory function that creates an instance of your formatter and return the logging.FormatterFunc from that.
  • You can use the formatter if you need to translate for a specific backend, such as when targeting syslog or systemd-journald.
  • logging.Log contains an internal options map (*Log.Options) that isn't used for anything logging-specific. Instead, it is intended as a metadata store for custom formatters. If you need to persist something per-logger, you should add it to the Options map and then access this from within your formatter. Be aware that this map is not protected by any synchronization primitives.

LICENSE

logging is licensed under the fairly liberal and highly permissive NCSA license. We prefer this license as it combines the best of BSD and MIT licenses while also providing coverage for associated documentation and other works that are not strictly considered original source code. Consequently, all signals documentation is likewise covered under the same license as the codebase itself.

As with BSD-like licenses, attribution is, of course, required.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	// Black escape sequence (normal font type).
	Black = []byte{0x33, '[', '3', '0', 'm'}

	// Red escape sequence (normal font type).
	Red = []byte{0x33, '[', '3', '1', 'm'}

	// Green escape sequence (normal font type).
	Green = []byte{0x33, '[', '3', '2', 'm'}

	// Yellow escape sequence (normal font type).
	Yellow = []byte{0x33, '[', '3', '3', 'm'}

	// Blue escape sequence (normal font type).
	Blue = []byte{0x33, '[', '3', '4', 'm'}

	// Magenta escape sequence (normal font type).
	Magenta = []byte{0x33, '[', '3', '5', 'm'}

	// Cyan escape sequence (normal font type).
	Cyan = []byte{0x33, '[', '3', '6', 'm'}

	// White escape sequence (normal font type).
	White = []byte{0x33, '[', '3', '7', 'm'}

	// Reset escape sequence.
	Reset = []byte{0x33, '[', '0', 'm'}
)
View Source
var Discard = ioutil.Discard
View Source
var Exit exitFunc

Exit provides a method for overriding Fatal* functions' default behavior. By default, this is defined in init.go and initialized here for replacement by user code, if necessary.

View Source
var Levels = []string{
	"INHERIT",
	"FATAL",
	"ERROR",
	"WARNING",
	"NOTICE",
	"INFO",
	"DEBUG",
}

Levels defines the supported RFC 5424 logging levels in this package.

View Source
var Panic panicFunc

Panic provides a method for overriding Panic* functions' default behavior. By default, this is defined in init.go and initialized here for replacement by user code, if necessary.

Stdout is the standard output writer, used globally by all writers by default to reduce risk of interleaving.

Functions

func WrapWriter

func WrapWriter(w io.Writer) io.Writer

WrapWriter accepts an io.Writer and returns it, guarded by a SyncWriter. This is the recommended entry point for implementations to utilize SyncWriters. If the provided writer is already wrapped, it will be returned instead.

Types

type BasicLogger

type BasicLogger interface {
	Fatal(...interface{})
	Fatalf(string, ...interface{})
	Fatalln(...interface{})
	Panic(...interface{})
	Panicf(string, ...interface{})
	Panicln(...interface{})
	Print(...interface{})
	Printf(string, ...interface{})
	Println(...interface{})
	Writer() io.Writer
}

type ExtendedLogger

type ExtendedLogger interface {
	Error(...interface{})
	Errorf(string, ...interface{})
	Warn(...interface{})
	Warning(...interface{})
	Warnf(string, ...interface{})
	Warningf(string, ...interface{})
	Notice(...interface{})
	Noticef(string, ...interface{})
	Info(...interface{})
	Information(...interface{})
	Infof(string, ...interface{})
	Informationf(string, ...interface{})
	Debug(...interface{})
	Debugf(string, ...interface{})

	BasicLogger
}

type FormatterFunc

type FormatterFunc func(io.Writer, *Log, *Message) error

FormatterFunc defines the type of a formatter function that can be used to override the use of Go templates. This function must accept the logger instance as its first argument followed by a single formatter (containing the message data) and return a string.

func NewDefaultFormatter

func NewDefaultFormatter(format string) FormatterFunc

NewDefaultFormatter returns the defaultFormatter used by logging for inline variable string replacement.

This implementation is exceedingly basic, simple, and fairly performant. It is approximately 3 times faster than the Golang text template formatter and should be used except in rare circumstances where conditional manipulation of logging entries is required.

func NewFastFormatter added in v1.1.0

func NewFastFormatter(format string) FormatterFunc

func NewTemplateFormatter

func NewTemplateFormatter(tpl string, funcs map[string]interface{}) FormatterFunc

NewTemplateFormatter returns a formatter backed by Golang's text templates for line-by-line templating support.

templateFormatters support context-sensitive template functions via the `funcs` argument here and can be used to conditionally manipulate logging output.

Be aware that the templateFormatter is approximately 3 times slower than the default formatter.

type Level

type Level int

Level defines a type for use internally for identifying logging levels.

const (
	Inherit Level = iota
	Fatal
	Error
	Warning
	Notice
	Info
	Debug
)

RFC 5424 levels (borrowed from syslog message facilities).

func LevelFromString

func LevelFromString(l string) Level

LevelFromString returns a Level value (internally an integer) given a matching string. This serves as a simple map between string -> integer values of error levels.

Some levels have aliases. INFO and WARN can be given as "information" or "warning," respectively.

The case of input values is ignored.

func (Level) Short

func (l Level) Short() string

Short string implementation.

func (Level) String

func (l Level) String() string

String implementation.

type Log

type Log struct {

	// This mutex covers the backends, log chain, options metadata, and child
	// loggers.
	sync.Mutex

	// Metadata options. Typically this map will be empty and isn't used
	// internally by the logger. However, it is provided for formatterOverrides
	// that may need additional metadata for configuration (such as enabling or
	// disabling colorized output, among other things).
	Options map[string]interface{}
	// contains filtered or unexported fields
}

Log container.

func MustGetDefaultLogger

func MustGetDefaultLogger() *Log

MustGetDefaultLogger returns the default logger and is a convenience function for `MustGetLogger("__main__")`. This name is chosen to avoid conflicts with other loggers used by client applications.

func MustGetDefaultLoggerWithLevel

func MustGetDefaultLoggerWithLevel(level Level) *Log

MustGetDefaultLoggerWithLevel returns the default logger with the specified logging level. This is a convenience function for calling `MustGetLoggerWithLevel("__main__", level)` and is primarily intended to provide an easy to remember call for configuring a primary (or default) logger for client application. "__main__" is chosen to avoid conflicts with other loggers.

func MustGetLogger

func MustGetLogger(name string) *Log

MustGetLogger always returns a logger instance associated with the name `name`, creating it if it doesn't exist.

func MustGetLoggerWithLevel

func MustGetLoggerWithLevel(name string, level Level) *Log

MustGetLoggerWithLevel always returnr a logger instance associated with the name `name` at the specified logging level, creating it if it doesn't exist. If the logger has already been created, no attempt will be made to reset the level. Useful if you wish to otherwise avoid clobbering a previously-configured logger instance.

func MustInheritLogger

func MustInheritLogger(parent, name string) *Log

MustInheritLogger always returns a logger instance that is either derived from the named parent logger or is itself a new logger instance. All parent properties are replicated onto the child.

`parent`, in this case, may reference a dot-separated fully qualified path name to the parent logger. If the child logger specified by `name` does not exist it will be created. If the parent inheritance chain doesn't exist, it will also be created.

func NewLogger

func NewLogger(name string) *Log

NewLogger creates and returns a new logger instance with the name `name`, associating it with the logger container in this module. This will always create a new logger.

If you simply wish to retrieve a logger instance if it exists (creating it if it does not), use MustGetLogger() instead.

func (*Log) AddFormatOverride

func (l *Log) AddFormatOverride(level Level, f FormatterFunc)

AddFormatOverride injects an override function for the level specified.

func (*Log) Chain

func (l *Log) Chain(logger *Log)

Chain another Log instance with the current logger. When a logger is configured to chain to another logger, any logging messages will be repeatedly dispatched down the chain until no more logger instances are found. In this way, it's possible to isolate multiple logger behaviors by error level.

For example, if you wish to create two loggers, one that logs only error messages (and nothing else) and another that logs everything (including error messages), such as might be necessary for applications that must write error messages to a file as well as to STDOUT, you can do the following:

errorsOnly := &bytes.Buffer{}

// Error logger.
errorLog := MustGetLogger("errors")
errorLog.SetBackend(nil)

// Clear the main backend.
errorLog.SetBackendForLevel(Error, errorLog)

// Everything else (remember, the default is to log to os.Stdout)...
everythingLog := MustGetLogger("everything")

// Chain the loggers starting with the most restrictive.
errorLog.Chain(everything)

// Now, when we call errorLog.*, it will always log to everythingLog.
errorLog.Error("This is an error. It is written to both.")
errorLog.Debug("This is a debug notice. It is written only to
    everythingLog.")

func (*Log) ClearBackend

func (l *Log) ClearBackend(level Level) *Log

ClearBackend removes the backend for the specified level.

func (*Log) Debug

func (l *Log) Debug(v ...interface{})

Debug logs debugging messages.

func (*Log) Debugf

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

Debugf logs debugging messages with formatted input.

func (*Log) DestroyLogger

func (l *Log) DestroyLogger(name string)

DestroyLogger destroys the child logger identified by `name` alongside any of its children.

func (*Log) Error

func (l *Log) Error(v ...interface{})

Error logs an error condition.

func (*Log) Errorf

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

Errorf logs an error condition with formatting.

func (*Log) Fatal

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

Fatal works similarly to the Go standard library log.Fatal. Like Fatalf, it's treated as as an error condition and exits the application. It additionally logs the message as Fatal.

func (*Log) Fatalf

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

Fatalf works identically to the Go standard library log.Fatalf, returning an error status and exiting the application. It additionally logs the message as Fatal.

func (*Log) Fatalln

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

Fatalln works similarly to the Go standard library log.Fatalln. Like Fatalf and Fatal, it's treated as an error condition and exits the application. It additionally logs the message as Fatal.

func (*Log) FullPath

func (l *Log) FullPath() string

FullPath returns the fully qualified name for the current logger.

func (*Log) GetLogger

func (l *Log) GetLogger(name string) (*Log, bool)

GetLogger returns the child logger associated with this parent by its name `name`. If no such logger is configured it will be created.

func (*Log) Info

func (l *Log) Info(v ...interface{})

Info logs an informational message.

func (*Log) Infof

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

Infof logs an informational message with formatting.

func (*Log) Information

func (l *Log) Information(v ...interface{})

Information is an alias for Info.

func (*Log) Informationf

func (l *Log) Informationf(format string, v ...interface{})

Informationf is an alias for Infof.

func (*Log) Inherit

func (l *Log) Inherit(name string) *Log

Inherit constructs a new logger from the parent instance and returns it. Inherited loggers retain all of their parent properties until they are manually changed and are configured with the special level value Inherit. Inherited loggers are registered globally with the parent's name as a dot-separated prefix (e.g. parent.child) and may be accessed via MustGetLogger or by the parent logger via parent.GetLogger.

Inherit will *always* overwrite an existing logger by the same name.

If a logger inheritance hierarchy declaration (e.g. a dot-separated name) is passed to this method, the last component will be used as the inherited logger name.

func (*Log) Iterate

func (l *Log) Iterate(fn func(*Log))

Iterate over the current logger's children, applying the function fn(). Callback functions receive the current logger as their sole argument.

Useful for modifying an entire logging tree.

func (*Log) Level

func (l *Log) Level() Level

GetLevel returns the level for the current logger or, if the level is set to the value Inherit, will return the level associated with the parent logger (if available).

If no suitable level is found, this will return Warning.

func (*Log) Name

func (l *Log) Name() string

Name returns the current logger's configured name.

func (*Log) Notice

func (l *Log) Notice(v ...interface{})

Notice logs a notice containing pertinent information. This does not indicate an error condition.

func (*Log) Noticef

func (l *Log) Noticef(format string, v ...interface{})

Noticef logs a notice containing pertinent information with formatting. This does not indicate an error condition.

func (*Log) Panic

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

Panic works similarly to the Go standard library log.Panic. Like Panicf, it's treated as as an error condition and panics. It additionally logs the message as fatal.

func (*Log) Panicf

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

Panicf works identically to the Go standard library log.Panicf, printing the error and returning a panic. As with Fatalf, this logs the message as fatal.

func (*Log) Panicln

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

Panicln works similarly to the Go standard library log.Panicln. Like Panicf and Panic, it's treated as a fatal error and returns a panic.

func (*Log) Print

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

Print works similarly to the Go standard library log.Print. Like Printf, it's treated as an informational message.

func (*Log) Printf

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

Printf works similarly to the Go standard library log.Printf with the exception that it's treated as an informational message.

func (*Log) Println

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

Println works similarly to the Go standard library log.Println. Like Printf and Print, it's treated as an informational message.

func (*Log) SetBackend

func (l *Log) SetBackend(backend io.Writer) *Log

SetBackend changes the default backend. This backend will be written to whenever any of the logging facility methods (Error, Critical, etc.) are called.

If you wish to override this backend for a specific logging level, use SetBackendForLevel.

Setting a backend with this function will wrap the given writer in a SyncWriter if it isn't already.

func (*Log) SetBackendForLevel

func (l *Log) SetBackendForLevel(level Level, backend io.Writer) *Log

SetBackendForLevel changes the backend to use for a specific level. Configuring this value will override the default backend for the specified level only.

For instance, creating the following:

buf := &bytes.Buffer{}
logger := MustGetLogger("example")
logger.SetBackendForLevel(Error, buf)

Will cause:

logger.Error("some error")

to save logging data to `buf`, while

logger.Critical("critical error!")
logger.Debug("some debugging information")

will both write to the default backend (os.Stdout).

To clear the backend for the specified level, reverting it back to using the default backend, call ClearBackend(level).

Setting a backend with this function will wrap the given writer in a SyncWriter if it isn't already.

func (*Log) SetFormatter

func (l *Log) SetFormatter(formatter FormatterFunc) *Log

func (*Log) SetLevel

func (l *Log) SetLevel(level Level) *Log

SetLevel changes the logger's level. Error messages that are at this level--or lower--will be logged; everything else will be ignored. Note that in this context "lower" means the literal integer value of the logger and not the relative importance of its data. For example, setting a logging level of Error will log anything at an Error or below (which includes Alert, Emergency, and Critical). Likewise, setting a logging level of Debug will log literally everything.

If you wish to control what the logger instance logs such as logging only Error-level messages, you'll need to manipulate the backends. This can be done by setting a backend for the Error level and clearing the default backend by setting it to nil.

func (*Log) SetOption

func (l *Log) SetOption(option string, value interface{})

SetOption is the recommended method for setting metadata values in the logger. It's possible to set options by manipulating the Log.Options map directly but there is no stability guarantee provided for its continued export status.

func (*Log) SetRawBackend

func (l *Log) SetRawBackend(backend io.Writer) *Log

SetRawBackend behaves identically to SetBackend with the exception that it does not wrap the backend argument in a SyncWriter.

func (*Log) SetRawBackendForLevel

func (l *Log) SetRawBackendForLevel(level Level, backend io.Writer) *Log

SetRawBackendForLevel behaves identically to SetBackendForLevel with the exception that it does not wrap the backend argument in a SyncWriter.

func (*Log) SetTimezone

func (l *Log) SetTimezone(tz *time.Location) *Log

SetTimezone sets the logger's timezone to the specified location. The logger uses time.UTC by default. Change this to time.Local to display the server's local time.

func (*Log) Warn

func (l *Log) Warn(v ...interface{})

Warn logs a warning.

func (*Log) Warnf

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

Warnf logs a warning with formatting.

func (*Log) Warning

func (l *Log) Warning(v ...interface{})

Warning is an alias for Warn.

func (*Log) Warningf

func (l *Log) Warningf(format string, v ...interface{})

Warningf is an alias for Warnf.

func (*Log) Writer

func (l *Log) Writer() io.Writer

Writer is provided to satisfy the BasicLogger interface as provided by the go `log` package. This will return either the configured backend, all backends, or both, depending on what is available. Backend levels are ignored.

type Logger

type Logger interface {
	Chain(*Log)
	DestroyLogger(string)
	GetLogger(string) *Log
	Inherit(string) *Log
	Iterate(func(*Log))
	SetBackend(io.Writer) *Log
	SetRawBackend(io.Writer) *Log
	SetBackendForLevel(Level, io.Writer) *Log
	SetRawBackendForLevel(Level, io.Writer) *Log
	ClearBackend(Level) *Log
	Name() string
	FullPath() string
	SetFormat(string) *Log
	SetLevel(Level) *Log
	Level() Level
	SetOption(string, interface{})
	SetTimezone(*time.Location) *Log
	Error(...interface{})
	Errorf(string, ...interface{})
	Warn(...interface{})
	Warnf(string, ...interface{})
	Warning(...interface{})
	Warningf(string, ...interface{})
	Notice(...interface{})
	Noticef(string, ...interface{})
	Info(...interface{})
	Infof(string, ...interface{})
	Information(...interface{})
	Informationf(string, ...interface{})
	Debug(...interface{})
	Debugf(string, ...interface{})
	Print(...interface{})
	Printf(string, ...interface{})
	Println(...interface{})
	Fatal(...interface{})
	Fatalf(string, ...interface{})
	Fatalln(...interface{})
	Panic(...interface{})
	Panicf(string, ...interface{})
	Panicln(...interface{})
	Writer() io.Writer
}

Logger defines the complete API for the logger implementation contained herein.

type Message

type Message struct {
	Timestamp time.Time
	Level     Level
	Message   string
}

Message instance. This is used internally for the formatter template.

func (*Message) FormatTime

func (f *Message) FormatTime(format string) string

FormatTime is the time formatting function. This is useful if client code wishes to use a Go template pipeline to change the format of the timestamp.

This is a convenience method and isn't required.

type StdLogger

type StdLogger interface {
	Fatal(...interface{})
	Fatalf(string, ...interface{})
	Fatalln(...interface{})
	Flags() int
	Output(int, string) error
	Panic(...interface{})
	Panicf(string, ...interface{})
	Panicln(...interface{})
	Prefix() string
	Print(...interface{})
	Printf(string, ...interface{})
	Println(...interface{})
	SetFlags(int)
	SetOutput(io.Writer)
	SetPrefix(string)
	Writer() io.Writer
}

StdLogger defines an interface matching the logger from the Golang standard library logger.

func CoreLogger

func CoreLogger(logger *Log) StdLogger

type SyncWriter

type SyncWriter struct {
	io.Writer
	sync.Mutex
}

SyncWriter provides an implementation of io.Writer that synchronizes logging messages such that interleaving output over a shared writer won't happen.

When using Logging's default settings, the internal reference to os.Stdout will be wrapped.

func (*SyncWriter) Wrapped

func (w *SyncWriter) Wrapped() io.Writer

Wrapped returns the wrapped writer.

func (*SyncWriter) Write

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

Write implementation satisfying io.Writer guarded by an internal mutex.

type Wrapper

type Wrapper interface {
	Wrapped() io.Writer
	Write([]byte) (int, error)
}

Wrapper defines an io.Writer wrapper type that exposes the wrapped io.Writer directly via the Wrapped() function member.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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