Skip to main content

Basic logging

The simplest way to get started is to create a logger and log some messages.
import "github.com/blairtcg/velo"

logger := velo.New(nil)
defer logger.Close() // flushes the buffer

logger.Info("Application started")
logger.Debug("Debugging information")
logger.Warn("This is a warning")
logger.Error("An error occurred")
Always call logger.Close() before your application exits to ensure asynchronous logs are flushed. Use defer to guarantee cleanup.

Logging with fields

Standard interface (loosely typed)

Use the standard interface when you want clean, minimal code. It accepts loosely typed key-value pairs.
logger := velo.New(nil)
defer logger.Close()

logger.Info("failed to fetch URL",
  "url", url,
  "attempt", 3,
  "backoff", time.Second,
)

LogFields API (strongly typed)

Use the LogFields API when performance and type safety are critical. This approach uses strongly typed fields to eliminate memory allocations caused by interface boxing.
logger := velo.New(nil)
defer logger.Close()

logger.LogFields(velo.InfoLevel, "failed to fetch URL",
  velo.String("url", url),
  velo.Int("attempt", 3),
  velo.Duration("backoff", time.Second),
)
The LogFields API guarantees zero allocations on the hot path, making it ideal for extreme high throughput applications.

Log levels

Velo supports standard log levels. Use the convenience methods for cleaner code:
logger.Debug("Detailed information for debugging")
logger.DebugFields("Detailed info", velo.String("key", "value"))

Creating contextual loggers

Use With() or WithFields() to create a child logger with preset fields:
requestLogger := logger.With(
  "request_id", requestID,
  "user_id", userID,
)

requestLogger.Info("Processing request")
// Automatically includes request_id and user_id

Using with Go’s slog

If you use Go’s standard structured logging library, you can configure Velo as your slog.Handler:
import (
    "log/slog"
    "github.com/blairtcg/velo"
)

logger := slog.New(velo.NewSlogHandler())
slog.SetDefault(logger)

// Now use slog as usual
slog.Info("Application started")

Advanced configuration

For production use, configure Velo with async mode and JSON formatting:
import (
    "os"
    "github.com/blairtcg/velo"
)

logger := velo.NewWithOptions(os.Stdout, velo.Options{
    Level:            velo.InfoLevel,
    Async:            true,
    BufferSize:       8192,
    OverflowStrategy: velo.OverflowSync,
    Formatter:        velo.JSONFormatter,
    ReportTimestamp:  true,
    TimeFormat:       velo.DefaultTimeFormat,
    Prefix:           "[myapp]",
})
defer logger.Close()

logger.Info("Server started", "port", 8080)

Available field types

When using the strongly typed API, Velo provides these field constructors:
  • velo.String(key, value) - String values
  • velo.Int(key, value) - Integer values
  • velo.Duration(key, value) - Time durations
  • velo.Bool(key, value) - Boolean values
  • velo.Float64(key, value) - Floating point values
  • velo.Time(key, value) - Timestamps
  • velo.Error(err) - Error values
  • And many more…
See the field constructors in the source code for the complete list of available types.

Next steps

Configuration options

Explore all available configuration options in the Options struct

Performance tuning

Learn about buffer sizes, overflow strategies, and optimization techniques

Build docs developers (and LLMs) love