oak

module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2025 License: MIT

README ΒΆ

Oak - Go Structured Logging Code Generator

Oak is a command-line tool that automatically generates LogValue() methods for Go structs to integrate with Go's log/slog package. It provides structured logging with built-in support for sensitive data redaction and field exclusion.

Features

  • πŸš€ Seamless Integration: Works with go generate workflow
  • πŸ”’ Security First: Automatic redaction of sensitive fields
  • βš™οΈ Configurable: YAML-based configuration for flexible field handling
  • 🎯 Type-Aware: Intelligent mapping to appropriate slog functions
  • πŸ“¦ Package-Friendly: Processes entire packages or individual files
  • πŸ”§ Pointer Safe: Handles nil pointers gracefully
  • 🏷️ Tag Support: Respects struct tags for field control

Installation

go install github.com/stuckinforloop/oak/cmd/oak@latest

Quick Start

  1. Create an oak.yaml configuration file in your project root:
packages:
  - ./internal/booking
redactKeys:
  - password
  - secret
  - creditcard
redactMessage: "[REDACTED]"
  1. Add the generate directive to your Go structs:
package booking

import "time"

//go:generate oak
type Reservation struct {
    ID          int
    GuestName   string
    Email       string
    Password    string           // Will be redacted (matches redactKeys)
    CreditCard  string `log:"redact"` // Will be redacted (explicit tag)
    CheckIn     time.Time
    Notes       string `log:"-"`      // Will be excluded from logs
    IsConfirmed bool
    Amount      float64
    ContactInfo *ContactInfo     // Pointer handled safely
}

//go:generate oak
type ContactInfo struct {
    Phone   string
    Address string
}
  1. Run code generation:
go generate ./...
# or
oak ./...
  1. Use the generated LogValue methods:
reservation := Reservation{
    ID: 123,
    GuestName: "John Doe",
    Email: "[email protected]",
    Password: "secret123",
    CreditCard: "4111-1111-1111-1111",
    CheckIn: time.Now(),
    Notes: "Private notes",
    IsConfirmed: true,
    Amount: 299.99,
    ContactInfo: &ContactInfo{
        Phone: "+1-555-0123",
        Address: "123 Main St",
    },
}

slog.Info("Processing reservation", "reservation", reservation)

Output:

Processing reservation reservation.ID=123 reservation.GuestName="John Doe" reservation.Email="[email protected]" reservation.Password="[REDACTED]" reservation.CreditCard="[REDACTED]" reservation.CheckIn="2024-01-15T10:30:00Z" reservation.IsConfirmed=true reservation.Amount=299.99 reservation.ContactInfo.Phone="+1-555-0123" reservation.ContactInfo.Address="123 Main St"

Note: The Notes field is completely excluded, and sensitive fields are redacted.

Usage

Command Line Options
# Process current directory based on oak.yaml
oak

# Process all packages recursively
oak ./...

# Process specific package
oak ./internal/booking
oak --package ./internal/booking

# Process specific file
oak --source ./internal/booking/booking.go

# Show help
oak --help

# Show version
oak --version
Configuration

Oak uses an oak.yaml file in your project root for configuration:

# List of packages to scan for //go:generate oak directives
packages:
  - ./internal/booking
  - ./pkg/user
  - ./cmd/server

# List of field names to automatically redact (case-insensitive)
redactKeys:
  - password
  - secret
  - token
  - apikey
  - api_key
  - privatekey
  - private_key
  - creditcard
  - ssn

# Message to use for redacted fields
redactMessage: "[REDACTED]"
Struct Tags

Oak supports struct tags for fine-grained control:

type User struct {
    ID       int
    Username string
    Password string `log:"redact"`  // Explicitly redact this field
    Notes    string `log:"-"`       // Exclude this field from logs
    Email    string                 // Normal logging
}
Supported Types

Oak intelligently maps Go types to appropriate slog functions:

  • Integers (int, int8, int16, int32, int64, uint, etc.) β†’ slog.Int64
  • Strings (string) β†’ slog.String
  • Booleans (bool) β†’ slog.Bool
  • Floats (float32, float64) β†’ slog.Float64
  • Complex types (structs, slices, maps, interfaces) β†’ slog.Any
  • Pointers β†’ Handled with nil checks, logging "null" for nil values
Generated Code Example

For the struct above, Oak generates:

// Code generated by oak. DO NOT EDIT.
package booking

import "log/slog"

// LogValue implements slog.LogValuer for Reservation
func (r Reservation) LogValue() slog.Value {
    return slog.GroupValue(
        slog.Int64("ID", int64(r.ID)),
        slog.String("GuestName", r.GuestName),
        slog.String("Email", r.Email),
        slog.String("Password", "[REDACTED]"),
        slog.String("CreditCard", "[REDACTED]"),
        slog.Any("CheckIn", r.CheckIn),
        slog.Bool("IsConfirmed", r.IsConfirmed),
        slog.Float64("Amount", r.Amount),
        func() slog.Attr {
            if r.ContactInfo == nil {
                return slog.String("ContactInfo", "null")
            }
            return slog.Any("ContactInfo", *r.ContactInfo)
        }(),
    )
}

Integration with go generate

Oak works seamlessly with Go's go generate tool:

  1. Add //go:generate oak comments to your structs
  2. Run go generate ./... as part of your build process
  3. Generated files are automatically created/updated

Requirements

  • Go 1.21+ (for log/slog support)
  • oak.yaml configuration file in project root

License

MIT License - see LICENSE file for details.

Directories ΒΆ

Path Synopsis
cmd
oak command
Code generated by oak.
Code generated by oak.
internal
cli

Jump to

Keyboard shortcuts

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