Documentation
¶
Overview ¶
Package loq provides components for use with Go's log/slog library, intended to make logs easy to write and easier to read.
Handler offers:
- Uncluttered line-oriented output, without giving up machine-parsable structure.
- Color coding by severity level.
- Named severity levels beyond those defined by slog.
- Flexible order and selection of fields.
- Customizable time format.
- Generally better performance and fewer allocations than slog's handlers.
TreeHandler offers:
- A handler hierarchy with inheritable log levels, useful for filtering log output from components within a program. (Works with any slog-compatible handler.)
Logger offers:
- Printf-style message formatting. (Works with any slog-compatible handler.)
- An embedded *slog.Logger for API compatibility.
Index ¶
- Constants
- func Crit(msg string, args ...any)
- func CritAf(attrs []slog.Attr, format string, args ...any)
- func Critaf(attrs []any, format string, args ...any)
- func Critf(format string, args ...any)
- func Debug(msg string, args ...any)
- func DebugAf(attrs []slog.Attr, format string, args ...any)
- func Debugaf(attrs []any, format string, args ...any)
- func Debugf(format string, args ...any)
- func Error(msg string, args ...any)
- func ErrorAf(attrs []slog.Attr, format string, args ...any)
- func Erroraf(attrs []any, format string, args ...any)
- func Errorf(format string, args ...any)
- func Info(msg string, args ...any)
- func InfoAf(attrs []slog.Attr, format string, args ...any)
- func Infoaf(attrs []any, format string, args ...any)
- func Infof(format string, args ...any)
- func Log(ctx context.Context, level slog.Level, msg string, args ...any)
- func LogAf(level slog.Level, attrs []slog.Attr, format string, args ...any)
- func LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr)
- func Logaf(level slog.Level, attrs []any, format string, args ...any)
- func Logf(level slog.Level, format string, args ...any)
- func Notice(msg string, args ...any)
- func NoticeAf(attrs []slog.Attr, format string, args ...any)
- func Noticeaf(attrs []any, format string, args ...any)
- func Noticef(format string, args ...any)
- func Trace(msg string, args ...any)
- func TraceAf(attrs []slog.Attr, format string, args ...any)
- func Traceaf(attrs []any, format string, args ...any)
- func Tracef(format string, args ...any)
- func Warn(msg string, args ...any)
- func WarnAf(attrs []slog.Attr, format string, args ...any)
- func Warnaf(attrs []any, format string, args ...any)
- func Warnf(format string, args ...any)
- type Handler
- type Level
- type LevelVar
- type Logger
- func (l Logger) Child(name string, level slog.Leveler) Logger
- func (l Logger) Crit(msg string, args ...any)
- func (l Logger) CritAf(attrs []slog.Attr, format string, args ...any)
- func (l Logger) Critaf(attrs []any, format string, args ...any)
- func (l Logger) Critf(format string, args ...any)
- func (l Logger) Debug(msg string, args ...any)
- func (l Logger) DebugAf(attrs []slog.Attr, format string, args ...any)
- func (l Logger) Debugaf(attrs []any, format string, args ...any)
- func (l Logger) Debugf(format string, args ...any)
- func (l Logger) Error(msg string, args ...any)
- func (l Logger) ErrorAf(attrs []slog.Attr, format string, args ...any)
- func (l Logger) Erroraf(attrs []any, format string, args ...any)
- func (l Logger) Errorf(format string, args ...any)
- func (l Logger) Info(msg string, args ...any)
- func (l Logger) InfoAf(attrs []slog.Attr, format string, args ...any)
- func (l Logger) Infoaf(attrs []any, format string, args ...any)
- func (l Logger) Infof(format string, args ...any)
- func (l Logger) Log(ctx context.Context, level slog.Level, msg string, args ...any)
- func (l Logger) LogAf(level slog.Level, attrs []slog.Attr, format string, args ...any)
- func (l Logger) LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr)
- func (l Logger) LogWrapped(ctx context.Context, level slog.Level, attrs []slog.Attr, anyattrs []any, ...)
- func (l Logger) Logaf(level slog.Level, attrs []any, format string, args ...any)
- func (l Logger) Logf(level slog.Level, format string, args ...any)
- func (l Logger) Named(name string, level slog.Leveler) Logger
- func (l Logger) Notice(msg string, args ...any)
- func (l Logger) NoticeAf(attrs []slog.Attr, format string, args ...any)
- func (l Logger) Noticeaf(attrs []any, format string, args ...any)
- func (l Logger) Noticef(format string, args ...any)
- func (l Logger) RestoreTerminal()
- func (l Logger) Trace(msg string, args ...any)
- func (l Logger) TraceAf(attrs []slog.Attr, format string, args ...any)
- func (l Logger) Traceaf(attrs []any, format string, args ...any)
- func (l Logger) Tracef(format string, args ...any)
- func (l Logger) Warn(msg string, args ...any)
- func (l Logger) WarnAf(attrs []slog.Attr, format string, args ...any)
- func (l Logger) Warnaf(attrs []any, format string, args ...any)
- func (l Logger) Warnf(format string, args ...any)
- func (l Logger) With(args ...any) Logger
- func (l Logger) WithGroup(name string) Logger
- type Options
- type TreeHandler
- func (h *TreeHandler) Child(name string, level slog.Leveler) *TreeHandler
- func (h *TreeHandler) Enabled(ctx context.Context, level slog.Level) bool
- func (h *TreeHandler) Handle(ctx context.Context, rec slog.Record) error
- func (h *TreeHandler) Named(name string, level slog.Leveler) *TreeHandler
- func (h *TreeHandler) WithAttrs(attrs []slog.Attr) slog.Handler
- func (h *TreeHandler) WithGroup(name string) slog.Handler
Constants ¶
const LevelInherit slog.Level = math.MinInt
LevelInherit tells a TreeHandler to use its parent's severity level.
Variables ¶
This section is empty.
Functions ¶
func LogAf ¶
LogAf logs to slog.Default with attributes and Printf-style message formatting.
func LogAttrs ¶
LogAttrs mirrors slog.LogAttrs, with optimizations for our Handler type.
func Logaf ¶
Logaf logs to slog.Default with attributes processed as slog.Logger.Log does, and Printf-style message formatting.
func Logf ¶
Logf logs to slog.Default with Printf-style message formatting.
Types ¶
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler handles log records produced by a Logger, writing each record to an io.Writer as a line of text. Output formatting follows the Options passed to NewHandler. A *Handler implements the slog.Handler interface. All of its methods are safe for concurrent use.
func NewHandler ¶
NewHandler creates a Handler that writes to out, using the given Options. If opts is nil, uses default options. It may run the tput command (unix) or change console mode (Windows) if the Options.Format string contains a {color} placeholder. (Handler.RestoreTerminal will restore the original console mode.)
func (*Handler) RestoreTerminal ¶
func (h *Handler) RestoreTerminal()
RestoreTerminal restores the terminal to its original mode if NewHandler() changed it. This is not strictly necessary, since terminal mode is only changed to enable color support on Windows, where leaving it enabled after a program exits generally does no harm. Nevertheless, programs are encouraged to call this method when exiting, out of respect for the next program to run in the same Windows console. It does nothing on unix.
type Logger ¶
Logger wraps *slog.Logger to add Printf-style formatting, as well as optimizations when used with our Handler type. All of its methods are safe for concurrent use.
func AsTreeLogger ¶
AsTreeLogger creates a Logger with a new TreeHandler wrapping the given handler.
If the given attribute key is not empty, named descendants of the TreeHandler will add their name to each log record in an attribute with this key. (Note: This feature and WithGroup are not recommended for use together, since that would place the attribute in the group instead of at top level. Instead, consider exposing a name via With before calling WithGroup.)
func New ¶
New creates a Logger with a new Handler. Arguments are passed to NewHandler.
func NewTreeLogger ¶
NewTreeLogger creates a Logger with a new TreeHandler wrapping a new Handler.
If the given attribute key is not empty, named descendants of the TreeHandler will add their name to each log record in an attribute with this key. (Note: This feature and WithGroup are not recommended for use together, since that would place the attribute in the group instead of at top level. Instead, consider exposing a name via With before calling WithGroup.)
func (Logger) Child ¶
Child creates a TreeHandler-based logger descended from an existing one, with the handler returned by TreeHandler.Child.
func (Logger) Crit ¶
Crit is equivalent to Logger.Log at LevelCrit.
func (Logger) CritAf ¶
CritAf is equivalent to Logger.LogAf at LevelCrit.
func (Logger) Critaf ¶
Critaf is equivalent to Logger.Logaf at LevelCrit.
func (Logger) Critf ¶
Critf is equivalent to Logger.Logf at LevelCrit.
func (Logger) Debug ¶
Debug is equivalent to Logger.Log at LevelDebug.
func (Logger) DebugAf ¶
DebugAf is equivalent to Logger.LogAf at LevelDebug.
func (Logger) Debugaf ¶
Debugaf is equivalent to Logger.Logaf at LevelDebug.
func (Logger) Debugf ¶
Debugf is equivalent to Logger.Logf at LevelDebug.
func (Logger) Error ¶
Error is equivalent to Logger.Log at LevelError.
func (Logger) ErrorAf ¶
ErrorAf is equivalent to Logger.LogAf at LevelError.
func (Logger) Erroraf ¶
Erroraf is equivalent to Logger.Logaf at LevelError.
func (Logger) Errorf ¶
Errorf is equivalent to Logger.Logf at LevelError.
func (Logger) Info ¶
Info is equivalent to Logger.Log at LevelInfo.
func (Logger) InfoAf ¶
InfoAf is equivalent to Logger.LogAf at LevelInfo.
func (Logger) Infoaf ¶
Infoaf is equivalent to Logger.Logaf at LevelInfo.
func (Logger) Infof ¶
Infof is equivalent to Logger.Logf at LevelInfo.
func (Logger) Log ¶
Log overrides slog.Logger.Log, with optimizations for our Handler type.
func (Logger) LogAttrs ¶
LogAttrs overrides slog.Logger.LogAttrs, with optimizations for our Handler type.
func (Logger) LogWrapped ¶
func (l Logger) LogWrapped( ctx context.Context, level slog.Level, attrs []slog.Attr, anyattrs []any, msg string, fmtargs []any)
LogWrapped builds and handles a slog.Record on behalf of methods like Logf. It must be called through exactly one wrapper function in order for the Record.PC field (representing the log call site) to be correct.
This method is exported for the sake of applications wishing to log through their own helper/wrapper functions.
func (Logger) Logaf ¶
Logaf logs with attributes processed as slog.Logger.Log does, and Printf-style message formatting.
func (Logger) Named ¶
Named creates a TreeHandler-based logger related to an existing one, with the handler returned by TreeHandler.Named.
func (Logger) Notice ¶
Notice is equivalent to Logger.Log at LevelNotice.
func (Logger) NoticeAf ¶
NoticeAf is equivalent to Logger.LogAf at LevelNotice.
func (Logger) Noticeaf ¶
Noticeaf is equivalent to Logger.Logaf at LevelNotice.
func (Logger) Noticef ¶
Noticef is equivalent to Logger.Logf at LevelNotice.
func (Logger) RestoreTerminal ¶
func (l Logger) RestoreTerminal()
RestoreTerminal calls Handler.RestoreTerminal if this Logger uses a Handler (or a TreeHandler wrapping one). It does nothing if this Logger uses some other handler type. Programs are encouraged to call it when exiting.
func (Logger) Trace ¶
Trace is equivalent to Logger.Log at LevelTrace.
func (Logger) TraceAf ¶
TraceAf is equivalent to Logger.LogAf at LevelTrace.
func (Logger) Traceaf ¶
Traceaf is equivalent to Logger.Logaf at LevelTrace.
func (Logger) Tracef ¶
Tracef is equivalent to Logger.Logf at LevelTrace.
func (Logger) Warn ¶
Warn is equivalent to Logger.Log at LevelWarn.
func (Logger) WarnAf ¶
WarnAf is equivalent to Logger.LogAf at LevelWarn.
func (Logger) Warnaf ¶
Warnaf is equivalent to Logger.Logaf at LevelWarn.
func (Logger) Warnf ¶
Warnf is equivalent to Logger.Logf at LevelWarn.
func (Logger) With ¶
With overrides slog.Logger.With to return our Logger type
type Options ¶
type Options struct {
// Defines log record field placement in a line of output.
// Each field is represented by a {fieldname} placeholder,
// as described in the [Options] documentation.
// Text between placeholders is preserved.
// Any occurence of {{ double open braces outside of placeholders
// reduces to one { brace.
// Any occurence of }} double close braces within placeholders
// reduces to one } brace.
// If empty, Format defaults to "{time} {message:t\t}{attrs}".
Format string
// A [time.Layout] string for {time} placeholders
// and [slog.KindTime] attributes.
// If empty, defaults to [time.DateTime].
Time string
// Custom severity level color codes for use by {color} placeholders.
//
// Each mapped color applies to its assigned severity level
// and levels that are numerically higher,
// until the next level with a mapped color is reached.
// The lowest level's color also applies to levels below it.
//
// A color code is a string that can be either a single letter or
// a six-digit hexadecimal number preceded by a # character.
//
// Lowercase letters rgbcmykw represent the 8 basic palette colors:
// r=red g=green b=blue c=cyan m=magenta y=yellow k=black w=white
//
// Uppercase letters RGBCMYKW represent brighter versions of those colors,
// falling back to the basic colors if unsupported by the output terminal.
//
// Lowercase letter a represents gray or a dim version of the
// default text color, depending on the terminal's capabilities.
// This is generally a better choice than K (bright black) because
// it adapts to a wider variety of terminals.
//
// A # followed by a numeric color code directly specifies
// a color's red, green, and blue component intensities,
// using two hexadecimal digits for each of red, green, and blue: #RRGGBB
// If the output terminal (or terminfo entry) lacks direct color support,
// it falls back to no change in color (no-op).
//
// An underscore instead of a letter or numeric code represents
// no change in color relative to preceding text.
//
// If this map is empty, a default map will be used: {
// LevelTrace: "a", // dim
// LevelInfo: "_", // unchanged color
// LevelNotice: "g", // green
// LevelWarn: "y", // yellow
// LevelError: "r", // red
// }
Colors map[Level]string
// Custom severity level names for use by {level} placeholders.
// If this map is empty, default level names will be used.
Levels map[Level]string
// Determines the minimum [slog.Record.Level]
// required for a record to be written.
// Programs wishing to dynamically adjust this level
// can use a [slog.LevelVar].
// If nil, defaults to [slog.LevelInfo].
Level slog.Leveler
// contains filtered or unexported fields
}
Options contains options for a Handler...
Format String ¶
The Format string contains static text and field placeholders, defining what information should be included in each log message.
Field Placeholders ¶
A placeholder in the format string indicates where a log record field or other dynamic value should appear in log messages. It is written in the format string as {fieldname}.
Some placeholders accept optional subformats, written as {fieldname:subformat}.
{time}
Represents a slog.Record.Time field.
The subformat is a time.Layout string. If not given, it defaults to the value in Options.Time.
Example: "{time:15:04:05}"
{level}
Represents a slog.Record.Level field. Produces the name of a log record's severity level or a description of that level relative to a named level.
Default level names can be overridden by Options.Levels.
{message} or {msg}
Represents a slog.Record.Message field.
The subformat is a framing style, described in the next section.
{attr.K}
Represents a single attribute with the given key K. An attribute within a group can be chosen with a dotted key: {attr.G.K}
The subformat is a framing style, described in the next section.
{attributes} or {attrs}
Represents the attributes in a slog.Record field, except any that are referenced in an {attr.K} placeholder.
Attributes are formatted as a space-separated sequence of group.name=value entries. Non-numeric values use the quoted framing style, described in the next section. (A bool value is numeric.)
{source}
Represents a logger call's location within the source code.
The subformat has two parts: a layout template and a framing style. Both are optional.
The layout template uses letters n p l f to represent the file name, path, line, and function where the logger was called. All other runes in the layout template are written verbatim, so custom punctuation can be placed between those subfields.
Example: "{source:n:l f}"
Output: main.go:13 main.myfunc
If no layout template is given, it defaults to p:l
Example: "{source}"
Output: /build/hello/main.go:13
The framing style is described in the next section. If given, it must immediately follow the layout template. (In other words, it is the last part of the subformat.)
Example: "{source:n:l fq}"
Output: "main.go:13 main.myfunc"
{color}
Represents the start of severity level color-coding according to Options.Colors.
Emits nothing when the output device is not a terminal/console.
{nocolor}
Represents the end of severity level color-coding.
Emits nothing when the output device is not a terminal/console.
Framing Styles: ¶
A framing style is a way of encoding a dynamic value so that a parser can reliably distinguish it from surrounding text. It is chosen with 1-3 characters at the end of a field placeholder's subformat.
These framing styles are available:
The q (quoted) framing style
Writes a value surrounded by quotes, using single-character backslash escape codes \a\b\t\n\v\f\r\"\\ in place of their corresponding non-printable characters. Characters lacking single-character backslash escape codes (including ASCII 0-6, 14-31, 127) are written verbatim. Programs needing to write these as \xNN escape sequences should use methods like Logger.Infof("%q") rather than relying on this framing style.
Example: "{message:q} bye"
Message: hello-world
Output: "hello-world" bye
The tC (terminator character) framing style
Writes a value followed by the given character C. Any appearance of that character within the value is escaped in the output by doubling it. (C must be an ASCII character.)
Example: "{message:t-} bye"
Message: hello-world
Output: hello--world- bye
The tBC (terminator with custom escape char) variant framing style
Writes a value followed by the given character C. Any appearance of either B or C within the value is escaped in the output by prepending character B. (B and C must be ASCII characters.)
This variant might be helpful with log parsers that expect the field terminator to be escaped by something other than itself, such as a backslash.
Example: `{message:t\-} bye`
Message: hello-world
Output: hello\-world- bye
The t (terminator default) variant framing style, with no terminator character specified, defaults to the Tab character for B and C.
This use of whitespace as a terminator avoids visual clutter in the output.
Example: "{message:t}"
Message: hello-world
Output: hello-world
The bC (blank replacement character) framing style
Writes a value, or the given character C if the value is an empty string.
Example: "{message:b*} bye"
Message:
Output: * bye
The b (blank replacement default) variant framing style
Writes a value, or the - character if the value is an empty string.
Example: "{message:b} bye"
Message:
Output: - bye
The t framing style and all of its variants will omit the terminator character if it would appear at the end of a log line, to reduce visual clutter.
Framing styles are supported only in placeholders that can produce unpredictable values, such as {message}. Other placeholders can be made to match by surrounding/following them with static characters in the format string.
type TreeHandler ¶
type TreeHandler struct {
// contains filtered or unexported fields
}
TreeHandler is a slog.Handler that wraps any other handler, and allows creating named children to form a tree. Each child can have its own minimum severity level or inherit that of its parent. (The root TreeHandler defers to the wrapped handler's severity level.)
Related TreeHandlers can be used by a program's various components and subcomponents, for individual control of their log output.
All TreeHandler methods are safe for concurrent use.
func AsTreeHandler ¶
func AsTreeHandler(h slog.Handler, key string) *TreeHandler
AsTreeHandler wraps a slog.Handler in a TreeHandler, starting a new tree.
If the given handler is already a TreeHandler, it is simply returned.
If the given attribute key is not empty, named descendants of the TreeHandler will add their name to each log record as an attribute with that key. (Note: This feature and WithGroup are not recommended for use together, since that would place the attribute in a group instead of at top level. Instead, consider exposing a name via WithAttrs before calling WithGroup.)
func (*TreeHandler) Child ¶
func (h *TreeHandler) Child(name string, level slog.Leveler) *TreeHandler
Child calls Named to create or retrieve a TreeHandler descended from h. A dot and the given name are appended to that of h to form the new name. See TreeHandler.Named for details.
func (*TreeHandler) Enabled ¶
Enabled implements the slog.Handler method of the same name.
func (*TreeHandler) Handle ¶
Handle implements the slog.Handler method of the same name.
func (*TreeHandler) Named ¶
func (h *TreeHandler) Named(name string, level slog.Leveler) *TreeHandler
Named creates or retrieves a named TreeHandler related to h. If a handler by the given name already exists, returns it and discards level. If creating a new one, assigns it the given Leveler.
Dots in the name can be used to indicate hierarchy, much like slashes in a filesystem path. For example, a TreeHandler named "parent.child" descends from the one named "parent", which descends from the root TreeHandler.
Named automatically creates any ancestors that do not yet exist, assigning them LevelInherit. Since a TreeHandler and its Leveler cannot be replaced once created, any TreeHandler requiring a level other than LevelInherit must be explicitly created before its descendants. Using TreeHandler.Child instead of this method can prevent mistakes here.
The root TreeHandler can be retrieved by passing an empty name.
func (*TreeHandler) WithAttrs ¶
func (h *TreeHandler) WithAttrs(attrs []slog.Attr) slog.Handler
WithAttrs implements the slog.Handler method of the same name.
func (*TreeHandler) WithGroup ¶
func (h *TreeHandler) WithGroup(name string) slog.Handler
WithGroup implements the slog.Handler method of the same name.