scriba

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 4, 2025 License: MIT Imports: 4 Imported by: 0

README

Scriba

A flexible, structured logging library for Go with support for multiple formatters, drivers, and middleware integrations.

Features

  • Structured Logging: Add contextual fields to your log entries
  • Multiple Log Levels: Debug, Info, Warn, Error, and Fatal
  • Flexible Formatters: JSON, Pretty (with customizable themes), and MessagePack
  • Pluggable Drivers: Console, OpenTelemetry, and custom drivers
  • Chi Integration: Middleware for HTTP request logging and panic recovery
  • Context-Aware: Pass context through your application for distributed tracing
  • Thread-Safe: Safe for concurrent use
  • Zero Dependencies Core: Minimal dependencies in the core library

Installation

go get github.com/ams-tech-fin/scriba

Quick Start

package main

import (
    "context"
    "errors"
    "os"

    "github.com/ams-tech-fin/scriba"
    "github.com/ams-tech-fin/scriba/driver"
    "github.com/ams-tech-fin/scriba/formatter"
)

func main() {
    // Create a logger with pretty formatter
    logger := scriba.New(
        scriba.WithDriver(
            driver.NewConsoleDriver(os.Stdout),
            formatter.NewPrettyFormatter(),
            scriba.LevelDebug,
        ),
    )

    ctx := context.Background()

    // Log at different levels
    logger.Debug(ctx, "Debug message", scriba.F("key", "value"))
    logger.Info(ctx, "Application started", scriba.F("port", 8080))
    logger.Warn(ctx, "Warning message", scriba.F("threshold", 90))
    logger.Error(ctx, "An error occurred", errors.New("example error"))
}

Usage

Creating a Logger
logger := scriba.New(
    scriba.WithDriver(
        driver.NewConsoleDriver(os.Stdout),
        formatter.NewJSONFormatter(),
        scriba.LevelInfo,
    ),
    scriba.WithMinLevel(scriba.LevelDebug),
    scriba.WithBaseFields(
        scriba.F("app", "myapp"),
        scriba.F("version", "1.0.0"),
    ),
)
Log Levels
logger.Debug(ctx, "Debug message")
logger.Info(ctx, "Info message")
logger.Warn(ctx, "Warning message")
logger.Error(ctx, "Error message", err)
logger.Fatal(ctx, "Fatal message", err) // Calls os.Exit(1)
Adding Fields
// Add fields to a single log entry
logger.Info(ctx, "User logged in",
    scriba.F("user_id", 12345),
    scriba.F("ip", "192.168.1.1"),
)

// Create a child logger with persistent fields
userLogger := logger.WithFields(
    scriba.F("user_id", 12345),
    scriba.F("session_id", "abc123"),
)
userLogger.Info(ctx, "Action performed") // Will include user_id and session_id
Formatters
JSON Formatter
jsonFormatter := formatter.NewJSONFormatter()

Output:

{"time":"2025-12-04T16:00:00Z","level":"INFO","message":"User logged in","fields":{"user_id":12345}}
Pretty Formatter
prettyFormatter := formatter.NewPrettyFormatter()

Output:

[2025-12-04T16:00:00Z] INFO  User logged in user_id=12345
Pretty Formatter with Theme
theme := formatter.TICDefaultTheme() // Colorful theme using github.com/ams-tech-fin/tic
prettyFormatter := formatter.NewPrettyFormatterWithTheme(theme)

// Disable colors with environment variable
prettyFormatter.DisableColors = os.Getenv("NO_COLOR") == "1"
MessagePack Formatter
msgpackFormatter := formatter.NewMsgPackFormatter()
Drivers
Console Driver
consoleDriver := driver.NewConsoleDriver(os.Stdout)
// or
consoleDriver := driver.NewConsoleDriver(os.Stderr)
OpenTelemetry Driver
otelDriver := driver.NewOTELDriver()
Multiple Drivers

You can configure multiple drivers with different formatters and minimum log levels:

logger := scriba.New(
    // JSON to stdout for production
    scriba.WithDriver(
        driver.NewConsoleDriver(os.Stdout),
        formatter.NewJSONFormatter(),
        scriba.LevelInfo,
    ),
    // Pretty to stderr for debugging
    scriba.WithDriver(
        driver.NewConsoleDriver(os.Stderr),
        formatter.NewPrettyFormatter(),
        scriba.LevelDebug,
    ),
)

Chi Middleware

Request Logger

Log all HTTP requests with detailed information:

package main

import (
    "net/http"

    "github.com/go-chi/chi/v5"
    "github.com/go-chi/chi/v5/middleware"

    "github.com/ams-tech-fin/scriba"
    "github.com/ams-tech-fin/scriba/driver"
    "github.com/ams-tech-fin/scriba/formatter"
    "github.com/ams-tech-fin/scriba/scriba_chi"
)

func main() {
    logger := scriba.New(
        scriba.WithDriver(
            driver.NewConsoleDriver(os.Stdout),
            formatter.NewJSONFormatter(),
            scriba.LevelInfo,
        ),
    )

    r := chi.NewRouter()

    // Add request ID middleware (optional but recommended)
    r.Use(middleware.RequestID)

    // Add Scriba request logger
    r.Use(scriba_chi.RequestLogger(logger))

    // Add panic recovery
    r.Use(scriba_chi.Recoverer(logger))

    r.Get("/", func(w http.ResponseWriter, r *http.Request) {
        // Access logger from context
        log := scriba_chi.FromContext(r.Context())
        log.Info(r.Context(), "Handling request")

        w.Write([]byte("Hello, World!"))
    })

    http.ListenAndServe(":8080", r)
}

The request logger automatically logs:

  • HTTP method and path
  • Host and remote address
  • User agent
  • Response status code
  • Response size in bytes
  • Request duration in milliseconds
  • Request ID (if using chi's RequestID middleware)
Recoverer Middleware

Automatically recover from panics and log them:

r.Use(scriba_chi.Recoverer(logger))

When a panic occurs, it will:

  • Log the panic with stack trace
  • Return a 500 Internal Server Error response
  • Prevent the server from crashing
Context Logger

Access the request-scoped logger from your handlers:

r.Get("/user/:id", func(w http.ResponseWriter, r *http.Request) {
    log := scriba_chi.FromContext(r.Context())
    userID := chi.URLParam(r, "id")

    log.Info(r.Context(), "Fetching user", scriba.F("user_id", userID))

    // Your handler logic here
})

Advanced Usage

Custom Time Function
logger := scriba.New(
    scriba.WithNowFunc(func() time.Time {
        return time.Now().In(location)
    }),
)
Custom Formatter

Implement the Formatter interface:

type Formatter interface {
    Format(entry Entry) ([]byte, error)
}
Custom Driver

Implement the Driver interface:

type Driver interface {
    Write(ctx context.Context, entry Entry, formatted []byte) error
}

Examples

See the cmd/demo directory for a basic example and cmd/demo_chi for a Chi integration example.

Run the demos:

# Basic demo
go run cmd/demo/demo.go

# Chi middleware demo
go run cmd/demo_chi/demo_chi.go

License

MIT License - see LICENSE for details

Copyright (c) 2025 AMS Tecnologia e Serviços Financeiros LTDA (AMS Soft)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Driver

type Driver interface {
	Write(ctx context.Context, entry Entry, formatted []byte) error
}

type Entry

type Entry struct {
	Time    time.Time
	Level   Level
	Message string
	Fields  Fields
	Err     error

	TraceID string
	SpanID  string
}

type Field

type Field struct {
	Key   string
	Value any
}

func F

func F(key string, value any) Field

type Fields

type Fields []Field

type Formatter

type Formatter interface {
	Format(entry Entry) ([]byte, error)
}

type Level

type Level int8
const (
	LevelDebug Level = iota
	LevelInfo
	LevelWarn
	LevelError
	LevelFatal
)

func (Level) String

func (l Level) String() string

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

func New

func New(opts ...Option) *Logger

func (*Logger) Debug

func (l *Logger) Debug(ctx context.Context, msg string, fields ...Field)

func (*Logger) Error

func (l *Logger) Error(ctx context.Context, msg string, err error, fields ...Field)

func (*Logger) Fatal

func (l *Logger) Fatal(ctx context.Context, msg string, err error, fields ...Field)

func (*Logger) Info

func (l *Logger) Info(ctx context.Context, msg string, fields ...Field)

func (*Logger) Warn

func (l *Logger) Warn(ctx context.Context, msg string, fields ...Field)

func (*Logger) WithFields

func (l *Logger) WithFields(fields ...Field) *Logger

type Option

type Option func(*Logger)

func WithBaseFields

func WithBaseFields(fields ...Field) Option

func WithDriver

func WithDriver(d Driver, f Formatter, min Level) Option

func WithMinLevel

func WithMinLevel(min Level) Option

func WithNowFunc

func WithNowFunc(fn func() time.Time) Option

Directories

Path Synopsis
cmd
demo command
demo_chi command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL