Documentation
¶
Overview ¶
Package xlog provides per-package structured and printf-style logging. Register loggers in libraries and configure the global formatter in main:
logger := xlog.NewPackageLogger("example.com/app", "main")
xlog.SetFormatter(xlog.NewJSONFormatter(os.Stderr))
logger.KV(xlog.INFO, "event", "started", "version", "v1")
Logging is synchronous by default and serialized across packages, including formatting and destination writes. NewSink plus the WithSink formatter option opt into a bounded record queue and one delivery worker: the producer renders the complete record, the worker batches and writes it, and no value is encoded twice. Sink-backed formatters are safe for concurrent use, so they are not serialized on the output lock. Applications own the sink's Close. Producer metadata and mutable values are captured before logging returns in both modes. Configuration uses a separate lock. Built-in output formatters expose ErrorFormatter; PackageLogger.FlushError reports delivery failures and flushes supported downstream queues/buffers. The default threshold is INFO; DEBUG is more verbose than TRACE. No output formatter is installed unless explicitly configured or selected by XLOG_FORMATTER on non-Windows platforms.
On non-Windows platforms, importing xlog redirects the standard log package through xlog at INFO and reads XLOG_LEVEL and XLOG_FORMATTER once. Stderr uses that same routing. ContextWithKV mutates existing shared log context state.
The logrotate subpackage adds file rotation and optional queued byte writes; its "extra sink" parameter is a second io.Writer, not a Sink. The stackdriver subpackage formats Cloud Logging records. See FINDINGS.md for remaining configuration, reentrancy, and size-limit issues, and Documentation/codemap.md for formatter contracts, ownership, and navigation.
Copyright 2018, Denis Issoupov ¶
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Index ¶
- Constants
- Variables
- func Caller(depth int) (name string, file string, line int)
- func ContextEntries(ctx context.Context) []any
- func ContextWithKV(ctx context.Context, entries ...any) context.Context
- func EscapedInt64(value int64) string
- func EscapedString(value any) string
- func EscapedUInt64(value uint64) string
- func FlushFormatter(f Formatter) error
- func FlushFormatterWithin(f Formatter, limit time.Duration) error
- func InstallFormatter(f Formatter) func()
- func OnError(fn OnErrorFn)
- func SetFormatter(f Formatter)
- func SetGlobalLogLevel(l LogLevel)
- func SetPackageLogLevel(repo, pkg string, l LogLevel)
- func SetRepoLevel(cfg RepoLogLevel)
- func SetRepoLevels(cfg []RepoLogLevel)
- func SetRepoLogLevel(repo string, l LogLevel)
- type ConcurrentFormatter
- type Config
- type ErrorFormatter
- type Formatter
- func GetFormatter() Formatter
- func NewDefaultFormatter(out io.Writer, ops ...FormatterOption) Formatter
- func NewJSONFormatter(w io.Writer, ops ...FormatterOption) Formatter
- func NewNilFormatter() Formatter
- func NewPrettyFormatter(w io.Writer, ops ...FormatterOption) Formatter
- func NewStringFormatter(w io.Writer, ops ...FormatterOption) Formatter
- type FormatterOption
- func FormatMaxLogLength(val int) FormatterOption
- func FormatPrintEmpty(val bool) FormatterOption
- func FormatSkipLevel(val bool) FormatterOption
- func FormatSkipTime(val bool) FormatterOption
- func FormatWithCaller(val bool) FormatterOption
- func FormatWithColor(val bool) FormatterOption
- func FormatWithLocation(val bool) FormatterOption
- func WithSink(s *Sink) FormatterOption
- type JSONFormatter
- type KeyValueLogger
- type LogLevel
- type Logger
- type NilFormatter
- type NilLogger
- func (l *NilLogger) ContextKV(_ context.Context, _ LogLevel, _ ...any)
- func (l *NilLogger) Debug(entries ...any)
- func (l *NilLogger) Debugf(format string, args ...any)
- func (l *NilLogger) Error(entries ...any)
- func (l *NilLogger) Errorf(format string, args ...any)
- func (l *NilLogger) Fatal(args ...any)
- func (l *NilLogger) Fatalf(format string, args ...any)
- func (l *NilLogger) Fatalln(args ...any)
- func (l *NilLogger) Info(entries ...any)
- func (l *NilLogger) Infof(format string, args ...any)
- func (l *NilLogger) KV(_ LogLevel, entries ...any)
- func (l *NilLogger) Notice(entries ...any)
- func (l *NilLogger) Noticef(format string, args ...any)
- func (l *NilLogger) Panic(args ...any)
- func (l *NilLogger) Panicf(format string, args ...any)
- func (l *NilLogger) Trace(entries ...any)
- func (l *NilLogger) Tracef(format string, args ...any)
- func (l *NilLogger) Warning(entries ...any)
- func (l *NilLogger) Warningf(format string, args ...any)
- func (l *NilLogger) WithValues(keysAndValues ...any) KeyValueLogger
- type OnErrorFn
- type Output
- func (o *Output) Bind(dest io.Writer, sink *Sink)
- func (o *Output) Buffer() *RecordBuffer
- func (o *Output) Concurrent() bool
- func (o *Output) Dest() io.Writer
- func (*Output) Discard(record *RecordBuffer)
- func (o *Output) Emit(record *RecordBuffer, level LogLevel)
- func (o *Output) Err() error
- func (o *Output) Flush()
- func (o *Output) FlushError() error
- func (o *Output) FlushWithin(limit time.Duration) error
- func (o *Output) Rebind(sink *Sink)
- func (o *Output) RecordError(err error)
- type OverflowPolicy
- type PackageLogger
- func (p *PackageLogger) ContextKV(ctx context.Context, l LogLevel, entries ...any)
- func (p *PackageLogger) Debug(entries ...any)
- func (p *PackageLogger) Debugf(format string, args ...any)
- func (p *PackageLogger) Error(entries ...any)
- func (p *PackageLogger) Errorf(format string, args ...any)
- func (p *PackageLogger) Fatal(args ...any)
- func (p *PackageLogger) Fatalf(format string, args ...any)
- func (p *PackageLogger) Flush()
- func (p *PackageLogger) FlushError() error
- func (p *PackageLogger) Info(entries ...any)
- func (p *PackageLogger) Infof(format string, args ...any)
- func (p *PackageLogger) KV(l LogLevel, entries ...any)
- func (p *PackageLogger) LevelAt(l LogLevel) bool
- func (p *PackageLogger) Log(l LogLevel, args ...any)
- func (p *PackageLogger) Logf(l LogLevel, format string, args ...any)
- func (p *PackageLogger) Notice(entries ...any)
- func (p *PackageLogger) Noticef(format string, args ...any)
- func (p *PackageLogger) Panic(args ...any)
- func (p *PackageLogger) Panicf(format string, args ...any)
- func (p *PackageLogger) Trace(entries ...any)
- func (p *PackageLogger) Tracef(format string, args ...any)
- func (p *PackageLogger) Warning(entries ...any)
- func (p *PackageLogger) Warningf(format string, args ...any)
- func (p *PackageLogger) WithValues(keysAndValues ...any) KeyValueLogger
- type PrettyFormatter
- type RecordBuffer
- type RepoLogLevel
- type RepoLogger
- type Sink
- type SinkOption
- type SinkStats
- type StdLogger
- type StringFormatter
- type WithValueString
Examples ¶
Constants ¶
const ( // DefaultSinkQueueBytes bounds the record bytes a sink keeps queued when // WithQueueBytes is not supplied. DefaultSinkQueueBytes = 8 << 20 // DefaultSinkBatchBytes is how many record bytes a sink worker coalesces // into a single destination write. DefaultSinkBatchBytes = 64 << 10 )
const ( // DefaultMaxLogMessageLength is the byte limit installed by Config.Apply // when MaxLogLength is zero. Constructors do not call Apply automatically. DefaultMaxLogMessageLength = 2 * 1024 )
Variables ¶
var ColorOff = []byte("\033[0m")
ColorOff resets ANSI color to terminal default.
var CriticalFlushTimeout = 2 * time.Second
CriticalFlushTimeout bounds both halves of a CRITICAL record's wait: queue admission when a sink is full, and the delivery barrier before Fatal calls ExitFunc or Panic panics. A stalled destination therefore delays process exit by at most twice this value instead of blocking it. Zero or negative waits forever. A record dropped at admission is counted in SinkStats.Dropped and reported through the formatter's Err. A Write already blocked in the destination cannot be interrupted, and records still queued on timeout stay queued.
var ExitFunc = os.Exit
ExitFunc terminates the process after Fatal or Fatalf; it defaults to os.Exit. Override and restore it only while logging is stopped, for example in tests.
var LevelColors = map[LogLevel][]byte{
CRITICAL: colorLightRed,
ERROR: colorLightRed,
WARNING: colorLightOrange,
NOTICE: colorLightGreen,
INFO: colorLightCyan,
DEBUG: colorDebug,
TRACE: colorGray,
}
LevelColors provides colors map
var Stderr *log.Logger
Stderr routes standard-library log messages through xlog at INFO; despite its name, its destination is the configured formatter, not necessarily os.Stderr. It is initialized only on non-Windows platforms.
var TimeNowFn = time.Now
TimeNowFn returns the current time. Override and restore it only while logging is stopped, for example in tests that do not run in parallel.
Functions ¶
func Caller ¶
Caller returns the function name, file, and line number of the caller at the given depth.
func ContextEntries ¶
ContextEntries returns alternating keys and values sorted by key, or nil when the context has no log state. The returned slice is an independent snapshot; referenced mutable values are not deeply copied and must remain read-only during logging.
func ContextWithKV ¶
ContextWithKV returns context with values to be added to logs, entries in "key1=value1, ..., keyN=valueN" format. The entries must come in pairs of key (string) and value; an odd number of entries or a non-string key will cause a panic. Nil or empty string values delete the corresponding key. Once a context contains log values, this mutates the shared log state and returns the same context; parents and siblings sharing that state see updates. Duplicate keys use the latest value. Entries are sorted by key.
Example ¶
package main
import (
"context"
"os"
"github.com/effective-security/xlog"
)
func main() {
var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "string_formatter")
f := xlog.NewStringFormatter(os.Stdout)
xlog.SetFormatter(f)
ctx := xlog.ContextWithKV(context.Background(), "key1", 1, "key2", "val2", "key3", nil)
logger.ContextKV(ctx, xlog.INFO, "k3", 3, "k4", "")
}
Output: time=2021-04-01T00:00:00Z level=I pkg=string_formatter func=ExampleContextWithKV key1=1 key2=val2 k3=3
func EscapedInt64 ¶ added in v0.11.54
EscapedInt64 formats an integer for text logs, prefixing an underscore when its magnitude is at least 9007199254740991. The result is not always JSON.
func EscapedString ¶
EscapedString renders a value for text logs, quoting selected strings and encoding composite values as JSON. It is not a JSON serializer: simple strings, times, durations, and underscore-prefixed large integers may be bare. Unsupported JSON values produce an empty string; encoding errors are ignored.
func EscapedUInt64 ¶ added in v0.11.54
EscapedUInt64 formats an integer for text logs, prefixing an underscore when it is at least 9007199254740991. The result is not always JSON.
func FlushFormatter ¶ added in v0.12.67
FlushFormatter flushes f and supported downstream buffers. Nil is a no-op. Legacy formatters without FlushError are flushed but cannot report errors. Direct callers must synchronize with formatting and destination shutdown.
func FlushFormatterWithin ¶ added in v0.12.67
FlushFormatterWithin flushes f like FlushFormatter, bounding the wait when f supports it. Formatters delivering through a Sink report a timeout instead of waiting for a stalled destination; inline formatters have no queue to drain, so they ignore the limit. A non-positive limit waits indefinitely.
func InstallFormatter ¶ added in v0.12.67
func InstallFormatter(f Formatter) func()
InstallFormatter temporarily installs f and returns an idempotent removal function. Overrides may be removed in any order; removed formatters are never restored by later removals. SetFormatter supersedes all installed overrides. Removal waits for admitted PackageLogger calls to finish, allowing the caller to flush and close f's destination safely. It does not flush or close f itself. Do not remove an override from inside its formatter or destination, or reuse its formatter elsewhere while closing it. Direct formatter calls are untracked.
func OnError ¶
func OnError(fn OnErrorFn)
OnError installs an ERROR observer, or removes it when fn is nil. The callback runs synchronously without holding configuration or output locks.
func SetFormatter ¶
func SetFormatter(f Formatter)
SetFormatter replaces the global formatter. Nil disables output. The old formatter is neither flushed nor closed; callers own its destination lifecycle.
func SetGlobalLogLevel ¶
func SetGlobalLogLevel(l LogLevel)
SetGlobalLogLevel sets the log level for all packages in all repositories already registered with NewPackageLogger. It does not set the default for future registrations. Derived loggers share their registered parent's level.
func SetPackageLogLevel ¶
SetPackageLogLevel updates a registered package. An empty pkg or "*" selects all registered packages in repo. Unknown repositories and packages are ignored.
func SetRepoLevel ¶
func SetRepoLevel(cfg RepoLogLevel)
SetRepoLevel applies a configuration entry. Invalid levels currently become CRITICAL because parsing errors are ignored; validate with ParseLevel first.
func SetRepoLevels ¶
func SetRepoLevels(cfg []RepoLogLevel)
SetRepoLevels sets repo log levels per package
func SetRepoLogLevel ¶
SetRepoLogLevel updates registered packages in repo; unknown repositories are ignored.
Types ¶
type ConcurrentFormatter ¶ added in v0.12.67
type ConcurrentFormatter interface {
Formatter
// Concurrent reports whether concurrent Format/FormatKV calls are safe.
Concurrent() bool
}
ConcurrentFormatter reports whether a formatter renders and delivers records without external serialization. PackageLogger stops serializing output for formatters that answer true, so their records are ordered by admission rather than by call order, preserving per-goroutine order. Formatters that embed Output answer true exactly when a Sink owns their destination.
Concurrent formatters exclude formatters that need exclusive output, not each other, so during an InstallFormatter handoff two concurrent formatters can be active at once. Their sinks must therefore not share one destination that is unsafe for concurrent writes.
type Config ¶ added in v0.11.54
type Config struct {
// PrintEmpty includes empty values in text output; JSON always includes them.
PrintEmpty bool
// SkipLevel omits the level in text and JSON output.
SkipLevel bool
// SkipTime omits the timestamp.
SkipTime bool
// WithCaller requests the caller's function name.
WithCaller bool
// WithColor enables ANSI colors in PrettyFormatter.
WithColor bool
// WithLocation requests the caller's file and line.
WithLocation bool
// MaxLogLength limits selected values/messages, not total record size.
MaxLogLength int
// contains filtered or unexported fields
}
Config holds formatter options. Support differs by formatter; see Documentation/codemap.md for the behavior matrix.
func (*Config) Apply ¶ added in v0.11.54
func (c *Config) Apply(opts ...FormatterOption)
Apply applies the options to the Config.
type ErrorFormatter ¶ added in v0.12.67
type ErrorFormatter interface {
Formatter
// Err returns the first encoding or destination error, or nil. It is safe
// to call concurrently with formatting. Errors remain available for the
// lifetime of the formatter; successful later records do not clear them.
Err() error
// FlushError flushes formatter and supported downstream buffers, returning
// the first recorded error. Like Format, it requires caller synchronization.
// This is a delivery barrier for ChannelWriter destinations, not an fsync.
FlushError() error
}
ErrorFormatter augments Formatter with delivery error reporting. Built-in output formatters implement it without changing the legacy Formatter interface.
type Formatter ¶
type Formatter interface {
// Format emits plain entries using the formatter's message representation.
Format(pkg string, level LogLevel, depth int, entries ...any)
// FormatKV emits alternating string keys and values as structured fields.
FormatKV(pkg string, level LogLevel, depth int, entries ...any)
// Flush flushes the formatter's buffer, not necessarily downstream buffers
// or durable storage. Implementations cannot return errors through this API.
Flush()
// Options mutates formatter configuration. Apply options before publishing
// the formatter with SetFormatter, or while logging is stopped.
Options(ops ...FormatterOption) Formatter
}
Formatter formats records and writes them to a destination. PackageLogger serializes output separately from configuration; direct calls require synchronization. See ErrorFormatter for optional error reporting and downstream flushing. Formatters, writers, and value serializers must not recursively emit logs through the same output path; configuration access is safe.
func NewDefaultFormatter ¶
func NewDefaultFormatter(out io.Writer, ops ...FormatterOption) Formatter
NewDefaultFormatter returns the default text formatter, a PrettyFormatter.
func NewJSONFormatter ¶
func NewJSONFormatter(w io.Writer, ops ...FormatterOption) Formatter
NewJSONFormatter returns a JSONFormatter writing one JSON object per record to w. Options apply before the destination is bound, so WithSink takes effect immediately.
func NewNilFormatter ¶
func NewNilFormatter() Formatter
NewNilFormatter is a helper to produce a new LogFormatter struct. It logs no messages so that you can cause part of your logging to be silent.
func NewPrettyFormatter ¶
func NewPrettyFormatter(w io.Writer, ops ...FormatterOption) Formatter
NewPrettyFormatter returns a readable text formatter writing to w. Options apply before the destination is bound, so WithSink takes effect immediately.
func NewStringFormatter ¶
func NewStringFormatter(w io.Writer, ops ...FormatterOption) Formatter
NewStringFormatter returns a text formatter writing to w. Options apply before the destination is bound, so WithSink takes effect immediately.
type FormatterOption ¶
type FormatterOption func(*Config)
FormatterOption is an option for formatter behavior.
func FormatMaxLogLength ¶ added in v0.11.54
func FormatMaxLogLength(val int) FormatterOption
FormatMaxLogLength limits rendered text KV values or a JSON plain message in bytes. Zero selects the default on Apply; negative values disable these limits. It does not limit whole records, JSON KV values, or Stackdriver output.
func FormatPrintEmpty ¶
func FormatPrintEmpty(val bool) FormatterOption
FormatPrintEmpty allows to configure printing empty values
func FormatSkipLevel ¶
func FormatSkipLevel(val bool) FormatterOption
FormatSkipLevel allows to configure skipping the level log
func FormatSkipTime ¶
func FormatSkipTime(val bool) FormatterOption
FormatSkipTime allows to configure skipping the time log
func FormatWithCaller ¶
func FormatWithCaller(val bool) FormatterOption
FormatWithCaller allows to configure if the caller shall be logged
func FormatWithColor ¶
func FormatWithColor(val bool) FormatterOption
FormatWithColor allows to configure printing color logs
func FormatWithLocation ¶
func FormatWithLocation(val bool) FormatterOption
FormatWithLocation allows to configure printing the file:line for each log
func WithSink ¶ added in v0.12.67
func WithSink(s *Sink) FormatterOption
type JSONFormatter ¶
JSONFormatter formats log entries as JSON objects. Do not copy it after first use.
Example ¶
package main
import (
"os"
"time"
"github.com/cockroachdb/errors"
"github.com/effective-security/xlog"
)
func main() {
xlog.TimeNowFn = func() time.Time {
date, _ := time.Parse("2006-01-02", "2021-04-01")
return date
}
var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "json_formatter")
f := xlog.NewJSONFormatter(os.Stdout)
xlog.SetFormatter(f)
list := []string{"item 1", "item 2"}
obj := struct {
Foo string
Bar int
private string
}{"foo", 5, "shoud not print"}
f.Format("format", xlog.WARNING, 1, "string1", "string 2", list, obj)
f.FormatKV("format_kv", xlog.WARNING, 1, "key1", "value 2", "key2", 2, "list", list, "obj", obj)
logger.KV(xlog.ERROR, "reason", "with time, level, caller", "err", errors.New("just a string").Error(), "number", 123)
f.Options(xlog.FormatWithLocation(true))
logger.KV(xlog.ERROR, "reason", "location",
"err", errors.New("just a string").Error(),
"number", 123,
"list", list,
"obj", obj,
)
f.Options(xlog.FormatSkipTime(true), xlog.FormatSkipLevel(true), xlog.FormatWithCaller(false))
logger.KV(xlog.ERROR, "reason", "skip time, level, caller",
"err", errors.New("just a string").Error(),
"number", 123,
"list", list,
"obj", obj,
)
}
Output: {"func":"ExampleJSONFormatter","level":"W","msg":"string1string 2[item 1 item 2] {foo 5 shoud not print}","pkg":"format","time":"2021-04-01T00:00:00Z"} {"func":"ExampleJSONFormatter","key1":"value 2","key2":2,"level":"W","list":["item 1","item 2"],"obj":{"Foo":"foo","Bar":5},"pkg":"format_kv","time":"2021-04-01T00:00:00Z"} {"err":"just a string","func":"ExampleJSONFormatter","level":"E","number":123,"pkg":"json_formatter","reason":"with time, level, caller","src":"example_test.go:140","time":"2021-04-01T00:00:00Z"} {"err":"just a string","func":"ExampleJSONFormatter","level":"E","list":["item 1","item 2"],"number":123,"obj":{"Foo":"foo","Bar":5},"pkg":"json_formatter","reason":"location","src":"example_test.go:143","time":"2021-04-01T00:00:00Z"} {"err":"just a string","func":"ExampleJSONFormatter","list":["item 1","item 2"],"number":123,"obj":{"Foo":"foo","Bar":5},"pkg":"json_formatter","reason":"skip time, level, caller","src":"example_test.go:151"}
func (*JSONFormatter) Format ¶
func (c *JSONFormatter) Format(pkg string, l LogLevel, depth int, entries ...any)
Format log entry string to the stream
func (*JSONFormatter) FormatKV ¶
func (c *JSONFormatter) FormatKV(pkg string, l LogLevel, depth int, entries ...any)
FormatKV log entry string to the stream, the entries are key/value pairs
func (*JSONFormatter) Options ¶
func (c *JSONFormatter) Options(ops ...FormatterOption) Formatter
Options allows to configure formatter behavior
type KeyValueLogger ¶
type KeyValueLogger interface {
// KV logs structured entries at level using the configured formatter.
KV(level LogLevel, entries ...any)
// ContextKV logs entries in "key1=value1, ..., keyN=valueN" format,
// and add log entries from ctx as well.
// ContextWithKV method can be used to add extra values to context
ContextKV(ctx context.Context, level LogLevel, entries ...any)
// WithValues derives a logger with additional alternating string keys and values.
WithValues(keysAndValues ...any) KeyValueLogger
}
KeyValueLogger logs structured records with alternating string keys and values.
type LogLevel ¶
type LogLevel int8
LogLevel is the set of all log levels.
const ( // CRITICAL is the lowest log level; only errors which will end the program will be propagated. CRITICAL LogLevel = iota - 1 // ERROR is for errors that are not fatal but lead to troubling behavior. ERROR // WARNING is for errors which are not fatal and not errors, but are unusual. Often sourced from misconfigurations. WARNING // NOTICE is for normal but significant conditions. NOTICE // INFO is a log level for common, everyday log updates. INFO // TRACE is for (potentially) call by call tracing of programs. TRACE // DEBUG is the default hidden level for more verbose updates about internal processes. DEBUG )
func ParseLevel ¶
ParseLevel translates some potential loglevel strings into their corresponding levels.
type Logger ¶
type Logger interface {
KeyValueLogger
StdLogger
}
Logger combines structured and printf-style logging.
type NilFormatter ¶
type NilFormatter struct {
}
NilFormatter is a no-op log formatter that does nothing.
func (*NilFormatter) Concurrent ¶ added in v0.12.67
func (*NilFormatter) Concurrent() bool
Concurrent reports that discarding records needs no output serialization.
func (*NilFormatter) Flush ¶
func (*NilFormatter) Flush()
Flush is included so that the interface is complete, but is a no-op.
func (*NilFormatter) Format ¶
func (*NilFormatter) Format(_ string, _ LogLevel, _ int, _ ...any)
Format does nothing.
func (*NilFormatter) FormatKV ¶
func (*NilFormatter) FormatKV(pkg string, level LogLevel, depth int, entries ...any)
FormatKV log entry string to the stream, the entries are key/value pairs
func (*NilFormatter) Options ¶
func (c *NilFormatter) Options(ops ...FormatterOption) Formatter
Options allows to configure formatter behavior
type NilLogger ¶
type NilLogger struct {
}
NilLogger discards ordinary and fatal logs. Panic methods call the standard logger and panic, so they can still produce output through its destination.
func (*NilLogger) Panic ¶
Panic logs through the standard logger and panics with fmt.Sprint(args...).
func (*NilLogger) Panicf ¶
Panicf logs through the standard logger and panics with the formatted message.
func (*NilLogger) WithValues ¶
func (l *NilLogger) WithValues(keysAndValues ...any) KeyValueLogger
WithValues ignores the fields and returns the same no-op logger.
type OnErrorFn ¶
type OnErrorFn func(pkg string)
OnErrorFn observes ERROR calls, including filtered ones. It runs synchronously without logger locks. Callbacks may use xlog configuration or log at other levels; logging ERROR recursively requires a caller-provided recursion guard. Concurrent ERROR calls may invoke the observer concurrently.
type Output ¶ added in v0.12.67
type Output struct {
// contains filtered or unexported fields
}
Output owns the destination side of a formatter: it hands out record buffers, delivers rendered records, retains the first delivery error, and implements the Err/Flush/FlushError half of ErrorFormatter. Formatters embed it, so third-party formatters gain Sink support by rendering into a RecordBuffer instead of writing to a destination themselves.
Without a Sink, records are written inline and the caller must serialize Emit, Flush, and FlushError, exactly as before. With a Sink, the sink worker owns the destination and its buffer, and Emit is safe for concurrent use. Do not copy an Output after first use.
func (*Output) Bind ¶ added in v0.12.67
Bind selects the destination and delivery mode. A nil sink writes records inline through an owned buffer; otherwise the sink worker owns the destination. Constructors and Options call Bind; it must not run concurrently with formatting, and it neither flushes nor closes a previous destination.
func (*Output) Buffer ¶ added in v0.12.67
func (o *Output) Buffer() *RecordBuffer
Buffer returns a pooled buffer to render one record into.
func (*Output) Concurrent ¶ added in v0.12.67
Concurrent reports whether rendering and emitting records is safe without external serialization. It is true exactly when a sink owns the destination.
func (*Output) Dest ¶ added in v0.12.67
Dest returns the bound destination, which remains owned by the caller.
func (*Output) Discard ¶ added in v0.12.67
func (*Output) Discard(record *RecordBuffer)
Discard releases a record buffer without delivering it. A formatter that cannot render a complete record discards it instead of emitting a partial one.
func (*Output) Emit ¶ added in v0.12.67
func (o *Output) Emit(record *RecordBuffer, level LogLevel)
Emit takes ownership of a rendered record and delivers it at the record's level. Inline delivery writes and flushes the record buffer; sink delivery hands the buffer to the worker, which releases it after the write. Delivery failures are retained and reported by Err, not returned: enqueueing is not delivery.
CRITICAL records bound their wait for queue space by CriticalFlushTimeout, so a stalled destination delays Fatal and Panic by at most that long instead of blocking process exit forever. Such a record is dropped and counted.
func (*Output) Err ¶ added in v0.12.67
Err returns the first formatter error, or the bound sink's first delivery error. It is safe to call concurrently with formatting.
func (*Output) Flush ¶ added in v0.12.67
func (o *Output) Flush()
Flush waits for delivery of previously emitted records. Use FlushError to observe failures.
func (*Output) FlushError ¶ added in v0.12.67
FlushError is an ordered delivery barrier: it flushes this formatter's buffer and supported downstream buffers, or waits for the sink worker to drain and flush every record admitted before the call. It is not an fsync, and a stalled destination can block it indefinitely. See FlushWithin for a bound.
func (*Output) FlushWithin ¶ added in v0.12.67
FlushWithin bounds a sink barrier, reporting a timeout instead of waiting for a stalled destination. A non-positive limit waits indefinitely. Inline delivery has no queue to drain, so it behaves like FlushError.
func (*Output) Rebind ¶ added in v0.12.67
Rebind reapplies the bound destination when options change the sink.
Formatters and sinks are expected to be configured once at startup: Options calls that do not change the sink are free, but switching an already-used formatter to a different sink is supported only for tests that control their own producers. Records already admitted to the previous sink are still delivered by that sink and can reach the destination after the new binding starts, and the previous binding keeps its batch buffer registered there, so flush the formatter before switching and do not switch repeatedly.
func (*Output) RecordError ¶ added in v0.12.67
RecordError retains the first error observed by this formatter. Later successful records never clear it. Nil is ignored.
type OverflowPolicy ¶ added in v0.12.67
type OverflowPolicy int
OverflowPolicy selects what a sink does with a record that does not fit in its queue.
const ( // OverflowBlock makes the producer wait for queue space. It is the default // and never loses a record. OverflowBlock OverflowPolicy = iota // OverflowDropNewest discards the submitted record instead of blocking the // producer, and counts it in SinkStats.Dropped. OverflowDropNewest )
type PackageLogger ¶
type PackageLogger struct {
// contains filtered or unexported fields
}
PackageLogger is logger implementation for packages
func NewPackageLogger ¶
func NewPackageLogger(repo string, pkg string) (p *PackageLogger)
NewPackageLogger creates a package logger object. This should be defined as a global var in your package, referencing your repo. Repeated calls for the same repo and pkg return the same pointer. New loggers start at INFO, regardless of earlier global or repository level settings.
func (*PackageLogger) ContextKV ¶
func (p *PackageLogger) ContextKV(ctx context.Context, l LogLevel, entries ...any)
ContextKV logs the provided key/value pairs at the given level, prefixed by any entries stored in the context via ContextWithKV. The entries must come in pairs of key (string) and value; built-in output formatters panic on non-string keys. A trailing key is treated as having a nil value. Filtered entries are not validated.
func (*PackageLogger) Debug ¶
func (p *PackageLogger) Debug(entries ...any)
Debug logs plain entries at DEBUG.
func (*PackageLogger) Debugf ¶
func (p *PackageLogger) Debugf(format string, args ...any)
Debugf logs a printf-style message at DEBUG.
func (*PackageLogger) Error ¶
func (p *PackageLogger) Error(entries ...any)
Error logs plain entries at ERROR.
func (*PackageLogger) Errorf ¶
func (p *PackageLogger) Errorf(format string, args ...any)
Errorf logs a printf-style message at ERROR.
func (*PackageLogger) Fatal ¶
func (p *PackageLogger) Fatal(args ...any)
Fatal logs fmt.Sprint(args...) at CRITICAL, then calls ExitFunc(1).
func (*PackageLogger) Fatalf ¶
func (p *PackageLogger) Fatalf(format string, args ...any)
Fatalf logs a printf-style message at CRITICAL, then calls ExitFunc(1).
func (*PackageLogger) Flush ¶
func (p *PackageLogger) Flush()
Flush flushes the current global formatter, or does nothing when it is nil. It does not guarantee durable storage. See FlushError for error reporting.
func (*PackageLogger) FlushError ¶ added in v0.12.67
func (p *PackageLogger) FlushError() error
FlushError flushes the current formatter and supported downstream buffers, including queued writes, and reports errors when supported by the formatter. It returns nil when output is disabled. It does not guarantee durable storage.
func (*PackageLogger) Info ¶
func (p *PackageLogger) Info(entries ...any)
Info logs plain entries at INFO.
func (*PackageLogger) Infof ¶
func (p *PackageLogger) Infof(format string, args ...any)
Infof logs a printf-style message at INFO.
func (*PackageLogger) KV ¶
func (p *PackageLogger) KV(l LogLevel, entries ...any)
KV logs the provided key/value pairs at the given level. The entries must come in pairs of key (string) and value; built-in output formatters panic on non-string keys. A trailing key is treated as having a nil value. Filtered entries are not validated.
func (*PackageLogger) LevelAt ¶
func (p *PackageLogger) LevelAt(l LogLevel) bool
LevelAt reports whether the logger's threshold includes l.
func (*PackageLogger) Log ¶
func (p *PackageLogger) Log(l LogLevel, args ...any)
Log logs plain entries at l, including CRITICAL and DEBUG. CRITICAL bypasses filtering but does not itself exit or panic.
func (*PackageLogger) Logf ¶
func (p *PackageLogger) Logf(l LogLevel, format string, args ...any)
Logf logs a printf-style message at l, including CRITICAL and DEBUG. CRITICAL bypasses filtering but does not itself exit or panic.
func (*PackageLogger) Notice ¶
func (p *PackageLogger) Notice(entries ...any)
Notice logs plain entries at NOTICE.
func (*PackageLogger) Noticef ¶
func (p *PackageLogger) Noticef(format string, args ...any)
Noticef logs a printf-style message at NOTICE.
func (*PackageLogger) Panic ¶
func (p *PackageLogger) Panic(args ...any)
Panic logs fmt.Sprint(args...) at CRITICAL, then panics with that message.
func (*PackageLogger) Panicf ¶
func (p *PackageLogger) Panicf(format string, args ...any)
Panicf logs a printf-style message at CRITICAL, then panics with that message.
func (*PackageLogger) Trace ¶
func (p *PackageLogger) Trace(entries ...any)
Trace logs plain entries at TRACE.
func (*PackageLogger) Tracef ¶
func (p *PackageLogger) Tracef(format string, args ...any)
Tracef logs a printf-style message at TRACE.
func (*PackageLogger) Warning ¶
func (p *PackageLogger) Warning(entries ...any)
Warning logs plain entries at WARNING.
func (*PackageLogger) Warningf ¶
func (p *PackageLogger) Warningf(format string, args ...any)
Warningf logs a printf-style message at WARNING.
func (*PackageLogger) WithValues ¶
func (p *PackageLogger) WithValues(keysAndValues ...any) KeyValueLogger
WithValues derives a logger with additional alternating string keys and values. The field slice is copied; referenced maps, pointers, and slices are not deeply copied and must not be mutated concurrently with logging. Derived loggers share the registered parent's level, including later configuration changes.
type PrettyFormatter ¶
PrettyFormatter renders readable text with optional colors. Do not copy it after first use.
Example ¶
package main
import (
"os"
"time"
"github.com/cockroachdb/errors"
"github.com/effective-security/xlog"
)
func main() {
xlog.TimeNowFn = func() time.Time {
date, _ := time.Parse("2006-01-02", "2021-04-01")
return date
}
var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "pretty_formatter")
f := xlog.NewPrettyFormatter(os.Stdout)
xlog.SetFormatter(f)
xlog.SetPackageLogLevel("github.com/effective-security/xlog", "pretty_formatter", xlog.DEBUG)
list := []string{"item 1", "item 2"}
obj := struct {
Foo string
Bar int
private string
}{"foo", 5, "shout not print"}
f.Format("format", xlog.WARNING, 1, "string1", "string 2", list, obj)
f.FormatKV("format_kv", xlog.DEBUG, 1, "key1", "value 2", "key2", 2, "list", list, "obj", obj)
logger.KV(xlog.ERROR, "option", "with time, level, caller, collor", "err", errors.New("just a string").Error(), "number", 123)
logger.KV(xlog.INFO, "option", "with time, level, caller, collor", "float", 1.1)
logger.KV(xlog.NOTICE, "option", "with time, level, caller, collor", "key2", 2, "list", list, "obj", obj)
logger.KV(xlog.TRACE, "option", "with time, level, caller, collor", "key2", 2, "list", list, "obj", obj)
logger.KV(xlog.DEBUG, "option", "with time, level, caller, collor", "key2", 2, "list", list, "obj", obj)
f.Options(xlog.FormatWithLocation(true))
logger.KV(xlog.ERROR, "reason", "location",
"err", errors.New("just a string").Error(),
"number", 123,
"list", list,
"obj", obj,
)
f.Options(xlog.FormatSkipTime(true), xlog.FormatSkipLevel(true), xlog.FormatWithCaller(false))
logger.KV(xlog.ERROR, "reason", "skip time, level, caller",
"err", errors.New("just a string").Error(),
"number", 123,
"list", list,
"obj", obj,
"empty", "",
"nil", nil,
)
}
Output: 2021-04-01 00:00:00.000000 W | pkg=format, func=ExamplePrettyFormatter, string1, "string 2", ["item 1","item 2"], {"Foo":"foo","Bar":5} 2021-04-01 00:00:00.000000 D | pkg=format_kv, func=ExamplePrettyFormatter, key1="value 2", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5} 2021-04-01 00:00:00.000000 E | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", err="just a string", number=123 2021-04-01 00:00:00.000000 I | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", float=1.1 2021-04-01 00:00:00.000000 N | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5} 2021-04-01 00:00:00.000000 T | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5} 2021-04-01 00:00:00.000000 D | pkg=pretty_formatter, func=ExamplePrettyFormatter, option="with time, level, caller, collor", key2=2, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5} 2021-04-01 00:00:00.000000 E | pkg=pretty_formatter, src=example_test.go:91, func=ExamplePrettyFormatter, reason=location, err="just a string", number=123, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5} pkg=pretty_formatter, src=example_test.go:99, reason="skip time, level, caller", err="just a string", number=123, list=["item 1","item 2"], obj={"Foo":"foo","Bar":5}
func (*PrettyFormatter) Format ¶
func (c *PrettyFormatter) Format(pkg string, l LogLevel, depth int, entries ...any)
Format log entry string to the stream
func (*PrettyFormatter) FormatKV ¶
func (c *PrettyFormatter) FormatKV(pkg string, l LogLevel, depth int, entries ...any)
FormatKV log entry string to the stream, the entries are key/value pairs
func (*PrettyFormatter) Options ¶
func (c *PrettyFormatter) Options(ops ...FormatterOption) Formatter
Options allows to configure formatter behavior
type RecordBuffer ¶ added in v0.12.67
type RecordBuffer struct {
// contains filtered or unexported fields
}
RecordBuffer holds one fully rendered log record, including its trailing newline. Formatters acquire a buffer with Output.Buffer, render the complete record into it, and pass ownership to Output.Emit, which writes it inline or hands it to a Sink worker. Buffers are pooled and reused: do not retain a buffer, its Bytes, or its Encoder after Emit returns.
func (*RecordBuffer) Buffer ¶ added in v0.12.67
func (r *RecordBuffer) Buffer() *bytes.Buffer
Buffer returns the record's byte buffer for direct rendering. Writes to it never fail, so text formatters can ignore their write results.
func (*RecordBuffer) Bytes ¶ added in v0.12.67
func (r *RecordBuffer) Bytes() []byte
Bytes returns the rendered record. It is valid until the record is emitted.
func (*RecordBuffer) Encoder ¶ added in v0.12.67
func (r *RecordBuffer) Encoder() *json.Encoder
Encoder returns a pooled JSON encoder appending to this record. HTML escaping is disabled and Encode appends the record's newline terminator.
func (*RecordBuffer) Len ¶ added in v0.12.67
func (r *RecordBuffer) Len() int
Len returns the rendered size of the record in bytes.
type RepoLogLevel ¶
type RepoLogLevel struct {
// Repo specifies the repo name, or '*' for all repos [Global]
Repo string `json:"repo,omitempty" yaml:"repo,omitempty"`
// Package specifies the package name
Package string `json:"package,omitempty" yaml:"package,omitempty"`
// Level specifies the log level for the repo [ERROR,WARNING,NOTICE,INFO,DEBUG,TRACE].
Level string `json:"level,omitempty" yaml:"level,omitempty"`
}
RepoLogLevel contains information about the log level per repo. Use * to set up global level.
func GetRepoLevels ¶
func GetRepoLevels() []RepoLogLevel
GetRepoLevels returns currently configured levels
type RepoLogger ¶
type RepoLogger map[string]*PackageLogger
RepoLogger maps package names within one repository to their registered loggers. Handles returned by GetRepoLogger alias the registry; do not mutate or iterate them concurrently with logger registration or configuration.
func GetRepoLogger ¶
func GetRepoLogger(repo string) (RepoLogger, error)
GetRepoLogger may return the handle to the repository's set of packages' loggers.
func MustRepoLogger ¶
func MustRepoLogger(repo string) RepoLogger
MustRepoLogger returns the handle to the repository's packages' loggers.
func (RepoLogger) ParseLogLevelConfig ¶
func (r RepoLogger) ParseLogLevelConfig(conf string) (map[string]LogLevel, error)
ParseLogLevelConfig parses a comma-separated string of "package=loglevel", in order, and returns a map of the results, for use in SetLogLevel.
func (RepoLogger) SetLogLevel ¶
func (r RepoLogger) SetLogLevel(m map[string]LogLevel)
SetLogLevel takes a map of package names within a repository to their desired loglevel, and sets the levels appropriately. Unknown packages are ignored. "*" is a special package name that corresponds to all packages, and will be processed first.
func (RepoLogger) SetRepoLogLevel ¶
func (r RepoLogger) SetRepoLogLevel(l LogLevel)
SetRepoLogLevel sets the log level for all packages in the repository.
type Sink ¶ added in v0.12.67
type Sink struct {
// contains filtered or unexported fields
}
Sink delivers rendered log records to formatter destinations on one FIFO worker, so producers pay encoding but not destination latency. Attach it with WithSink; one sink can serve several formatters and destinations, and the worker coalesces consecutive records for the same destination into one write.
The queue is bounded by record count and by retained bytes. A full queue blocks producers unless OverflowDropNewest is selected. Close stops the worker; without it the worker leaks. Destinations are flushed when supported and never closed. Do not copy a Sink.
func NewSink ¶ added in v0.12.67
func NewSink(capacity int, opts ...SinkOption) (*Sink, error)
NewSink starts a delivery worker holding up to capacity pending records. capacity must be positive. Stop application producers, then Close the sink, to drain and flush; a sink that is never closed leaks its worker.
Example ¶
package main
import (
"os"
"github.com/effective-security/xlog"
)
func main() {
sink, err := xlog.NewSink(256)
if err != nil {
panic(err)
}
formatter := xlog.NewStringFormatter(os.Stdout,
xlog.FormatSkipTime(true), xlog.FormatWithCaller(false), xlog.WithSink(sink))
remove := xlog.InstallFormatter(formatter)
l := xlog.NewPackageLogger("example.com/app", "main")
l.KV(xlog.INFO, "event", "started")
remove() // Wait for admitted producers before stopping the worker.
if err := sink.Close(); err != nil {
panic(err)
}
}
Output: level=I pkg=main event=started
func (*Sink) Close ¶ added in v0.12.67
Close rejects new records, wakes blocked producers, drains what was admitted, flushes destinations, and stops the worker. Concurrent and repeated calls wait for the same completion and return the same result. Remove installed formatters and stop producers first. Destinations are never closed here.
func (*Sink) CloseWithin ¶ added in v0.12.67
CloseWithin is Close bounded by limit. On timeout it returns an error and leaves the worker draining, so queued records may still be delivered. A non-positive limit waits indefinitely.
func (*Sink) Err ¶ added in v0.12.67
Err returns the first write or flush failure observed by the worker. Records admitted successfully can still fail later, so a nil Err before Flush or Close does not mean everything was delivered.
func (*Sink) Flush ¶ added in v0.12.67
Flush waits for every record whose logging call returned before this call to reach its destination, then flushes destinations that support Flush() error. A record still being submitted concurrently may or may not be covered, like any other unordered pair of operations. It is a delivery barrier, not an fsync, and a stalled destination blocks it.
func (*Sink) FlushWithin ¶ added in v0.12.67
FlushWithin is Flush bounded by limit, reporting a timeout instead of waiting for a stalled destination. A non-positive limit waits indefinitely. A barrier that times out is still completed by the worker.
type SinkOption ¶ added in v0.12.67
type SinkOption func(*sinkConfig)
SinkOption configures a Sink at construction.
func WithBatchBytes ¶ added in v0.12.67
func WithBatchBytes(size int) SinkOption
WithBatchBytes sets how many record bytes the worker coalesces into one destination write. The worker also writes whenever its queue drains, so this bounds batching rather than delaying records. The default is DefaultSinkBatchBytes.
func WithFlushInterval ¶ added in v0.12.67
func WithFlushInterval(interval time.Duration) SinkOption
WithFlushInterval flushes bound destinations that support Flush() error at the given interval. Zero, the default, flushes only on barriers and shutdown.
func WithMaxRecordBytes ¶ added in v0.12.67
func WithMaxRecordBytes(max int) SinkOption
WithMaxRecordBytes rejects rendered records larger than max, counting them in SinkStats.Oversize and reporting the rejection through the formatter's Err. Zero or negative, the default, admits records of any size; a record larger than the byte budget is then queued alone.
func WithOverflow ¶ added in v0.12.67
func WithOverflow(policy OverflowPolicy) SinkOption
WithOverflow selects the full-queue policy. The default is OverflowBlock, which still lets a CRITICAL record give up after CriticalFlushTimeout rather than block process exit.
func WithQueueBytes ¶ added in v0.12.67
func WithQueueBytes(max int) SinkOption
WithQueueBytes bounds the record bytes a sink keeps queued, in addition to its record capacity. Zero or negative disables the byte bound and leaves only the record count, which does not bound memory. The default is DefaultSinkQueueBytes.
type SinkStats ¶ added in v0.12.67
type SinkStats struct {
// Submitted counts records admitted to the queue.
Submitted uint64
// Written counts records handed to a destination buffer.
Written uint64
// Dropped counts records the sink refused to queue: discarded by
// OverflowDropNewest, or abandoned by a bounded caller that ran out of
// time waiting for space, such as a CRITICAL record before process exit.
Dropped uint64
// Oversize counts records rejected for exceeding WithMaxRecordBytes.
Oversize uint64
// QueuedRecords is the number of records waiting for delivery.
QueuedRecords int
// QueuedBytes is the number of record bytes waiting for delivery.
QueuedBytes int
// PeakRecords is the high-water mark of QueuedRecords.
PeakRecords int
// PeakBytes is the high-water mark of QueuedBytes.
PeakBytes int
}
SinkStats reports queue occupancy and delivery counters for one sink. Counters are cumulative; the queue gauges are instantaneous.
type StdLogger ¶
type StdLogger interface {
// Fatal logs a critical message and terminates the process for PackageLogger.
Fatal(args ...any)
// Fatalf formats a critical message and terminates the process for PackageLogger.
Fatalf(format string, args ...any)
// Panic logs a critical message and panics.
Panic(args ...any)
// Panicf formats a critical message and panics.
Panicf(format string, args ...any)
// Info logs plain entries at INFO.
Info(entries ...any)
// Infof logs a printf-style message at INFO.
Infof(format string, args ...any)
// Error logs plain entries at ERROR.
Error(entries ...any)
// Errorf logs a printf-style message at ERROR.
Errorf(format string, args ...any)
// Warning logs plain entries at WARNING.
Warning(entries ...any)
// Warningf logs a printf-style message at WARNING.
Warningf(format string, args ...any)
// Notice logs plain entries at NOTICE.
Notice(entries ...any)
// Noticef logs a printf-style message at NOTICE.
Noticef(format string, args ...any)
// Debug logs plain entries at DEBUG, the most verbose threshold.
Debug(entries ...any)
// Debugf logs a printf-style message at DEBUG.
Debugf(format string, args ...any)
// Trace logs plain entries at TRACE, below DEBUG in verbosity.
Trace(entries ...any)
// Tracef logs a printf-style message at TRACE.
Tracef(format string, args ...any)
}
StdLogger provides plain and printf-style logging. PackageLogger fatal methods exit and panic methods panic; NilLogger deliberately discards fatal calls.
type StringFormatter ¶
StringFormatter renders text records. Do not copy it after first use.
Example ¶
package main
import (
"os"
"github.com/cockroachdb/errors"
"github.com/effective-security/xlog"
)
func main() {
var logger = xlog.NewPackageLogger("github.com/effective-security/xlog", "string_formatter").WithValues("prefix", "addon")
f := xlog.NewStringFormatter(os.Stdout)
xlog.SetFormatter(f)
list := []string{"item 1", "item 2"} //nolint:goconst
obj := struct {
Foo string
Bar int
private string
}{"foo", 5, "shout not print"} //nolint:goconst
f.Format("format", xlog.WARNING, 1, "string1", "string 2", list, obj)
f.FormatKV("format_kv", xlog.WARNING, 1, "key1", "value 2", "key2", 2, "list", list, "obj", obj)
logger.KV(xlog.ERROR, "reason", "with time, level, caller", "err", errors.New("just a string").Error(), "number", 123)
f.Options(xlog.FormatWithLocation(true))
logger.KV(xlog.ERROR, "reason", "location",
"err", errors.New("just a string").Error(),
"number", 123,
"list", list,
"obj", obj,
)
f.Options(xlog.FormatSkipTime(true), xlog.FormatSkipLevel(true), xlog.FormatWithCaller(false))
logger.KV(xlog.ERROR, "reason", "skip time, level, caller",
"err", errors.New("just a string").Error(),
"number", 123,
"list", list,
"obj", obj,
"empty", "",
)
}
Output: time=2021-04-01T00:00:00Z level=W pkg=format func=ExampleStringFormatter string1 "string 2" ["item 1","item 2"] {"Foo":"foo","Bar":5} time=2021-04-01T00:00:00Z level=W pkg=format_kv func=ExampleStringFormatter key1="value 2" key2=2 list=["item 1","item 2"] obj={"Foo":"foo","Bar":5} time=2021-04-01T00:00:00Z level=E pkg=string_formatter func=ExampleStringFormatter prefix=addon reason="with time, level, caller" err="just a string" number=123 time=2021-04-01T00:00:00Z level=E pkg=string_formatter src=example_test.go:39 func=ExampleStringFormatter prefix=addon reason=location err="just a string" number=123 list=["item 1","item 2"] obj={"Foo":"foo","Bar":5} pkg=string_formatter src=example_test.go:47 prefix=addon reason="skip time, level, caller" err="just a string" number=123 list=["item 1","item 2"] obj={"Foo":"foo","Bar":5}
func (*StringFormatter) Format ¶
func (s *StringFormatter) Format(pkg string, l LogLevel, depth int, entries ...any)
Format log entry string to the stream
func (*StringFormatter) FormatKV ¶
func (s *StringFormatter) FormatKV(pkg string, l LogLevel, depth int, entries ...any)
FormatKV log entry string to the stream, the entries are key/value pairs
func (*StringFormatter) Options ¶
func (s *StringFormatter) Options(ops ...FormatterOption) Formatter
Options allows to configure formatter behavior
type WithValueString ¶ added in v0.10.44
type WithValueString interface {
// ValueString returns the value's human-readable name.
ValueString() string
}
WithValueString supplies a display name for values such as generated enums.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package logrotate integrates lumberjack file rotation with xlog and provides a ChannelWriter for optional background byte writes.
|
Package logrotate integrates lumberjack file rotation with xlog and provides a ChannelWriter for optional background byte writes. |
|
Package stackdriver provides xlog's Google Cloud Logging (formerly Stackdriver) formatter.
|
Package stackdriver provides xlog's Google Cloud Logging (formerly Stackdriver) formatter. |