Moves I/O to a background worker for better performance:
logger := velo.NewWithOptions(os.Stderr, velo.Options{ Async: true, BufferSize: 8192, // Must be power of 2, defaults to 8192})defer logger.Close() // Critical: flush the bufferlogger.Info("non-blocking log")
Async mode parallelizes formatting and I/O, keeping your hot paths fast. Always call Close() to flush buffered logs before exit.
Control what happens when the async buffer fills up:
OverflowSync (default)
OverflowDrop
OverflowBlock
Temporarily switch to synchronous writes:
logger := velo.NewWithOptions(os.Stderr, velo.Options{ Async: true, OverflowStrategy: velo.OverflowSync, // Default})// When buffer is full, calling goroutine writes directly// Prevents log loss but temporarily blocks
Discard logs when buffer is full:
logger := velo.NewWithOptions(os.Stderr, velo.Options{ Async: true, OverflowStrategy: velo.OverflowDrop,})// Maintains low latency at the cost of log loss
Block until space becomes available:
logger := velo.NewWithOptions(os.Stderr, velo.Options{ Async: true, OverflowStrategy: velo.OverflowBlock,})// Guarantees no log loss but can severely impact latency
OverflowBlock should be used with caution as it can cause unpredictable application latency under high load.
logger := velo.NewWithOptions(os.Stderr, velo.Options{ ReportTimestamp: true, TimeFormat: time.RFC3339, // Use RFC3339 instead of default})logger.Info("custom time format")// Output: 2026-03-03T10:15:30Z INFO custom time format
logger := velo.NewWithOptions(os.Stderr, velo.Options{ ReportStacktrace: true,})logger.Error("error occurred", "error", err)// Includes full stack trace in output
Stack traces are captured for:
All logs at ErrorLevel or higher
Any log containing an error field (when ReportStacktrace: true)
Stack trace capture incurs significant performance overhead. Enable only when debugging or in low-error-rate environments.
Automatically extract fields from context.Context:
logger := velo.NewWithOptions(os.Stderr, velo.Options{ ContextExtractor: func(ctx context.Context) []velo.Field { var fields []velo.Field if requestID, ok := ctx.Value("request_id").(string); ok { fields = append(fields, velo.String("request_id", requestID)) } if userID, ok := ctx.Value("user_id").(string); ok { fields = append(fields, velo.String("user_id", userID)) } return fields },})// Use with LogContextlogger.LogContext(ctx, velo.InfoLevel, "operation completed")// Automatically includes request_id and user_id from context