Documentation
¶
Overview ¶
Package output implements Sypl outputs: an output processes, and writes a message to its writer - anything implementing io.Writer.
Built-ins: Console (stdout), StdErr (error levels to stderr), File, and FileBased (files), SafeBuffer (an in-memory concurrent-safe buffer), ElasticSearch (one request per document), and the reliability set:
- Async: wraps ANY output into a bounded, buffered, asynchronous one - a single worker drains the buffer preserving FIFO order, with Block, DropNewest, or DropOldest full-buffer policies.
- ElasticSearchBulk (and ...WithDynamicIndex): batches documents into _bulk requests via esutil's BulkIndexer - the high-throughput sibling of ElasticSearch.
- RotatingFile: a file output with native size-based rotation, backup timestamping, and count/age pruning.
- Recorder: captures structured snapshots of everything written - a test-assertion helper for Sypl consumers.
Outputs that buffer implement `Flush() error`; outputs owning resources implement `Close() error` (io.Closer). Close is idempotent, and writes after Close return a typed, per-output sentinel error - never a panic. Flush after Close is a no-op.
Index ¶
- Variables
- func Recorder(maxLevel level.Level, processors ...processor.IProcessor) (*RecorderOutput, IOutput)
- type AsyncOption
- type AsyncPolicy
- type IOutput
- func Async(o IOutput, opts ...AsyncOption) IOutput
- func Console(maxLevel level.Level, processors ...processor.IProcessor) IOutput
- func File(name string, path string, maxLevel level.Level, ...) IOutput
- func FileBased(name string, maxLevel level.Level, writer io.Writer, ...) IOutput
- func New(name string, maxLevel level.Level, w io.Writer, ...) IOutput
- func RotatingFile(name, path string, maxLevel level.Level, cfg RotationConfig, ...) (IOutput, error)
- func SafeBuffer(maxLevel level.Level, processors ...processor.IProcessor) (*safebuffer.Buffer, IOutput)
- func StdErr(processors ...processor.IProcessor) IOutput
- type Proxy
- func (p *Proxy) AddProcessors(processors ...processor.IProcessor) IOutput
- func (p *Proxy) GetBuiltinLogger() *builtin.Builtin
- func (p *Proxy) GetFormatter() formatter.IFormatter
- func (p *Proxy) GetMaxLevel() level.Level
- func (p *Proxy) GetName() string
- func (p *Proxy) GetProcessors() []processor.IProcessor
- func (p *Proxy) GetProcessorsNames() []string
- func (p *Proxy) GetStatus() status.Status
- func (p *Proxy) GetWriter() io.Writer
- func (p *Proxy) SetFormatter(fmtr formatter.IFormatter) IOutput
- func (p *Proxy) SetMaxLevel(l level.Level) IOutput
- func (p *Proxy) SetProcessors(processors ...processor.IProcessor) IOutput
- func (p *Proxy) SetStatus(s status.Status)
- func (p *Proxy) SetWriter(w io.Writer) IOutput
- func (p *Proxy) String() string
- func (p *Proxy) Write(m message.IMessage) error
- type Record
- type RecorderOutput
- type RotationConfig
Constants ¶
This section is empty.
Variables ¶
var ( // ErrAsyncClosed is returned when writing to a closed async output. ErrAsyncClosed = errors.New("async output is closed") // ErrAsyncDropped is the sentinel wrapped into drop notifications // delivered to the error handler. Check it with `errors.Is`. ErrAsyncDropped = errors.New("async output dropped a message") )
var ErrRotatingFileClosed = errors.New("rotating file output is closed")
ErrRotatingFileClosed is returned when writing to a closed rotating file output.
ErrRotatingFileUnavailable is returned - wrapped with the underlying cause - while the rotating writer has no open live file: a mid-rotation failure closed it, and reopening the original path failed too. Every write (and Flush) retries the reopen first, so the output self-heals once the filesystem recovers. Check it with `errors.Is`.
NOTE: Deliberately NOT `os.ErrClosed`-classed: the output layer treats `os.ErrClosed` as a benign closed-writer condition, and swallows it - this error must surface (e.g. through `Sypl.SetErrorHandler`).
Functions ¶
func Recorder ¶
func Recorder(maxLevel level.Level, processors ...processor.IProcessor) (*RecorderOutput, IOutput)
Recorder is a built-in `output` - named `Recorder` - capturing a structured snapshot (level, original, and processed content, fields, tags, output, and processors names, timestamp) of every message it actually writes: level gating, flags, and processors are applied through the standard pipeline first. Designed for test assertions by Sypl consumers.
It returns both the concrete recorder - for `Messages`, `Len`, and `Reset` - and the `IOutput` to register on the logger; they're the same instance. Thread-safe.
Types ¶
type AsyncOption ¶
type AsyncOption func(*asyncOutput)
AsyncOption configures the async output wrapper.
func AsyncWithBufferSize ¶
func AsyncWithBufferSize(size int) AsyncOption
AsyncWithBufferSize sets the buffer capacity. Non-positive values fall back to the default (1024).
func AsyncWithErrorHandler ¶
func AsyncWithErrorHandler(handler func(error)) AsyncOption
AsyncWithErrorHandler sets the handler receiving the wrapped output's write errors, drop notifications (wrapping `ErrAsyncDropped`), interval-flush errors, and panics from the wrapped output - converted to errors, so a misbehaving sink never kills the worker, nor the host process. The handler may be called concurrently.
func AsyncWithFlushInterval ¶
func AsyncWithFlushInterval(interval time.Duration) AsyncOption
AsyncWithFlushInterval periodically flushes the WRAPPED output - useful for time-buffered inner outputs (e.g. the ElasticSearch bulk output). Zero (the default) disables it. Flush errors are delivered to the error handler.
func AsyncWithPolicy ¶
func AsyncWithPolicy(policy AsyncPolicy) AsyncOption
AsyncWithPolicy sets the full-buffer policy. Default: AsyncPolicyBlock.
type AsyncPolicy ¶
type AsyncPolicy int
AsyncPolicy determines what happens when a message is written to an async output whose buffer is full.
const ( // AsyncPolicyBlock blocks the writer until buffer space is available. // It's the default policy - no message is ever dropped. AsyncPolicyBlock AsyncPolicy = iota // AsyncPolicyDropNewest drops the incoming message. AsyncPolicyDropNewest // AsyncPolicyDropOldest drops the oldest buffered message, making room // for the incoming one. AsyncPolicyDropOldest )
Available policies.
type IOutput ¶
type IOutput interface {
meta.IMeta
// String interface.
String() string
// GetBuiltinLogger returns the Golang's builtin logger.
GetBuiltinLogger() *builtin.Builtin
// GetFormatter returns the formatter.
GetFormatter() formatter.IFormatter
// SetFormatter sets the formatter.
SetFormatter(fmtr formatter.IFormatter) IOutput
// GetMaxLevel returns the max level.
GetMaxLevel() level.Level
// SetMaxLevel sets the max level.
SetMaxLevel(l level.Level) IOutput
// AddProcessors adds one or more processors.
AddProcessors(processors ...processor.IProcessor) IOutput
// SetProcessors sets one or more processors.
SetProcessors(processors ...processor.IProcessor) IOutput
// GetProcessors returns registered processors.
GetProcessors() []processor.IProcessor
// GetProcessorsNames returns the names of the registered processors.
GetProcessorsNames() []string
// GetWriter returns the writer.
GetWriter() io.Writer
// SetWriter sets the writer.
SetWriter(w io.Writer) IOutput
// Write write the message to the defined output.
Write(m message.IMessage) error
}
IOutput specifies what an output does.
func Async ¶
func Async(o IOutput, opts ...AsyncOption) IOutput
Async wraps `o` into a bounded, buffered, asynchronous output: writes enqueue into a buffer (default capacity: 1024), and a single worker goroutine drains it to `o` - preserving FIFO order. All other `IOutput` methods are proxied to `o`, so Sypl-level dispatch (name matching, level checks, status checks) behaves identically.
Capabilities: - `Flush() error`: guarantees everything enqueued BEFORE the call was written to `o` (or dropped by policy), then flushes `o` - if `o` implements `Flush() error`. SNAPSHOT semantics: messages enqueued after the call may remain buffered, so Flush returns even under sustained concurrent writes. - `Close() error`: flushes, stops the worker, and closes `o` - if `o` implements `io.Closer`. Idempotent. Writes after Close return `ErrAsyncClosed`.
Hung sinks: direct Flush, and Close calls wait - UNBOUNDED - on the wrapped output's in-flight write, so a sink that never returns blocks them forever. The Fatal path's pre-exit flush is time-bounded (the process exits regardless), but direct Flush/Close are NOT: prefer bounded sinks (e.g. writers carrying I/O deadlines/timeouts), and `AsyncWithFlushInterval` for time-buffered inner outputs, so draining never depends on a single unbounded call.
See the `Async*` options for buffer size, full-buffer policy, error handling, and periodic flushing.
func Console ¶
func Console(maxLevel level.Level, processors ...processor.IProcessor) IOutput
Console is a built-in `output` - named `Console`, that writes to `stdout`.
func File ¶
func File(name string, path string, maxLevel level.Level, processors ...processor.IProcessor) IOutput
File is a built-in `output` - named `File`, that writes to the specified file.
NOTE: If the common used "-" is used, it will behave as a Console writing to stdout. NOTE: If no path is provided, it'll create one in the OS's temp directory. NOTE: If the dir and/or file does not exist, it will be created.
func FileBased ¶
func FileBased( name string, maxLevel level.Level, writer io.Writer, processors ...processor.IProcessor, ) IOutput
FileBased is a built-in `output`, that writes to the specified file.
func New ¶
func New(name string, maxLevel level.Level, w io.Writer, processors ...processor.IProcessor, ) IOutput
New is the Output factory.
func RotatingFile ¶
func RotatingFile( name, path string, maxLevel level.Level, cfg RotationConfig, processors ...processor.IProcessor, ) (IOutput, error)
RotatingFile is a built-in `output` that writes to the specified file, rotating it by size: when a write would push the live file beyond `cfg.MaxSizeBytes`, the file is closed, renamed to `<path>.<UTC timestamp>`, and reopened fresh - then backups beyond `cfg.MaxBackups`, or older than `cfg.MaxAgeDays`, are pruned (inline, no goroutines).
Capabilities: `Flush() error` (file sync), and idempotent `Close() error`. Writes after Close return `ErrRotatingFileClosed`.
Notes: - Unlike `File`, it returns an error - it never calls log.Fatalf. - Missing parent directories are created. - Any file named `<path>.*` is treated as a backup by pruning. - SELF-HEALING: a mid-rotation failure (e.g. the rename was denied) reopens the original path, so writes keep landing there - the failure is surfaced through the write's error, and rotation retries on the next size-threshold write. When even the reopen fails, writes return `ErrRotatingFileUnavailable` - retrying the reopen each time - until the filesystem recovers.
func SafeBuffer ¶
func SafeBuffer(maxLevel level.Level, processors ...processor.IProcessor) (*safebuffer.Buffer, IOutput)
SafeBuffer is a built-in `output` - named `Buffer`, that writes to the buffer.
func StdErr ¶
func StdErr(processors ...processor.IProcessor) IOutput
StdErr is a built-in `output` - named `StdErr`, that only writes to `stderr` message @ Error level.
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy forwards every `IOutput` method to the wrapped (inner) output, so wrappers - such as the async output - behave, from Sypl's dispatch perspective (name matching, level checks, status checks), exactly like the output they wrap.
Chainable setters return `self` - the outer wrapper - instead of the inner output, so the wrapping survives chained configuration calls, e.g. `Async(o).SetFormatter(f)`.
Exported so capability-carrying wrappers living outside this package - such as the `es` submodule's bulk output - can embed it.
func (*Proxy) AddProcessors ¶
func (p *Proxy) AddProcessors(processors ...processor.IProcessor) IOutput
AddProcessors adds one or more processors to the inner output.
func (*Proxy) GetBuiltinLogger ¶
GetBuiltinLogger returns the inner output's Golang's builtin logger.
func (*Proxy) GetFormatter ¶
func (p *Proxy) GetFormatter() formatter.IFormatter
GetFormatter returns the inner output's formatter.
func (*Proxy) GetMaxLevel ¶
GetMaxLevel returns the inner output's max level.
func (*Proxy) GetProcessors ¶
func (p *Proxy) GetProcessors() []processor.IProcessor
GetProcessors returns the inner output's registered processors.
func (*Proxy) GetProcessorsNames ¶
GetProcessorsNames returns the names of the inner output's registered processors.
func (*Proxy) SetFormatter ¶
func (p *Proxy) SetFormatter(fmtr formatter.IFormatter) IOutput
SetFormatter sets the inner output's formatter.
func (*Proxy) SetMaxLevel ¶
SetMaxLevel sets the inner output's max level.
func (*Proxy) SetProcessors ¶
func (p *Proxy) SetProcessors(processors ...processor.IProcessor) IOutput
SetProcessors sets one or more processors on the inner output.
type Record ¶
type Record struct {
// Fields is a copy of the message's structured fields.
Fields fields.Fields
// Level is the message's level.
Level level.Level
// OriginalContent is the message's content before processing.
OriginalContent string
// OutputName is the output the message was routed to.
OutputName string
// ProcessedContent is the exact text written - processors, and
// formatter applied.
ProcessedContent string
// ProcessorsNames is a copy of the processors names applied.
ProcessorsNames []string
// Tags is a copy of the message's tags - lexicographically sorted.
Tags []string
// Timestamp is the message's creation time.
Timestamp time.Time
}
Record is a structured snapshot of a message the recorder output actually wrote - level gating, flags, and processors all applied.
type RecorderOutput ¶
type RecorderOutput struct {
*Proxy
// contains filtered or unexported fields
}
RecorderOutput is an `IOutput` capturing a structured snapshot of every message it writes - a test-assertion helper for Sypl consumers.
func (*RecorderOutput) Len ¶
func (r *RecorderOutput) Len() int
Len returns how many records were captured.
func (*RecorderOutput) Messages ¶
func (r *RecorderOutput) Messages() []Record
Messages returns a defensive copy of the captured records.
func (*RecorderOutput) Reset ¶
func (r *RecorderOutput) Reset()
Reset discards the captured records.
type RotationConfig ¶
type RotationConfig struct {
// MaxSizeBytes is the size threshold: a write that would push the live
// file BEYOND it triggers a rotation first. A write landing exactly at
// the limit does not rotate. Must be positive.
MaxSizeBytes int64
// MaxBackups caps how many rotated backups are kept - the oldest
// beyond the cap are pruned on rotation. Zero keeps all.
MaxBackups int
// MaxAgeDays prunes - on rotation - backups whose modification time is
// older than this many days. Zero keeps all.
MaxAgeDays int
}
RotationConfig configures the rotating file output.