Documentation Index
Fetch the complete documentation index at: https://mintlify.com/aarock1234/go-template/llms.txt
Use this file to discover all available pages before exploring further.
The log package initializes the default slog logger with tint for colorized, structured output and provides utilities to inject request-scoped values from context.
Installation
import "github.com/aarock1234/go-template/pkg/log"
Simply importing the package is enough to configure the logger:
import (
"log/slog"
_ "github.com/aarock1234/go-template/pkg/log" // Initialize logger
)
Features
- Colorized output: Automatically detects TTY and enables colors
- Structured logging: Built on Go’s standard
log/slog
- Context injection: Add request-scoped values to all log records
- Configurable log level: Set via
LOG_LEVEL environment variable
- Human-readable timestamps: Formatted as “Mon, Jan 2 2006, 3:04:05 pm MST”
Quick Start
package main
import (
"context"
"log/slog"
"github.com/aarock1234/go-template/pkg/log"
)
func main() {
// Basic logging
slog.Info("server started", slog.Int("port", 8080))
slog.Debug("debug information", slog.String("module", "main"))
slog.Warn("warning message")
slog.Error("error occurred", slog.String("error", "connection failed"))
// Context-aware logging
ctx := log.WithIdempotencyKey(context.Background(), "req-123")
slog.InfoContext(ctx, "processing request") // Includes idempotency_key
}
Functions
WithIdempotencyKey
Returns a copy of the context carrying the given idempotency key.
func WithIdempotencyKey(ctx context.Context, key string) context.Context
The idempotency key to inject into log records
Example:
func handleRequest(w http.ResponseWriter, r *http.Request) {
// Extract idempotency key from header
key := r.Header.Get("Idempotency-Key")
ctx := log.WithIdempotencyKey(r.Context(), key)
// All logs in this context will include the idempotency key
slog.InfoContext(ctx, "processing request")
// Output: ... msg="processing request" idempotency_key=req-123
processPayment(ctx)
}
func processPayment(ctx context.Context) {
slog.InfoContext(ctx, "payment processed")
// Output: ... msg="payment processed" idempotency_key=req-123
}
Types
ContextHandler
Wraps an slog.Handler to inject request-scoped values from the context into every log record.
type ContextHandler struct {
slog.Handler
}
Methods:
func (h *ContextHandler) Handle(ctx context.Context, r slog.Record) error
Logs a slog.Record with request-scoped values extracted from the context. Currently supports:
idempotency_key - Injected when context contains an idempotency key
Configuration
Log Level
Set the log level using the LOG_LEVEL environment variable:
Supported values:
debug - Show all logs including debug messages
info (default) - Show info, warn, and error logs
warn or warning - Show only warnings and errors
error - Show only errors
Example:
# Development
LOG_LEVEL=debug
# Production
LOG_LEVEL=info
Color Output
Colors are automatically enabled when:
- Writing to a TTY (terminal)
- Using Windows: Colors work via
go-colorable
Colors are disabled when:
- Output is redirected to a file
- Running in a non-TTY environment (e.g., CI/CD)
Logs are formatted with tint’s colorized, structured output:
Mon, Jan 2 2006, 3:04:05 pm MST INF server started port=8080
Mon, Jan 2 2006, 3:04:06 pm MST DBG debug message module=main
Mon, Jan 2 2006, 3:04:07 pm MST WRN warning message
Mon, Jan 2 2006, 3:04:08 pm MST ERR error occurred error="connection failed"
With context values:
Mon, Jan 2 2006, 3:04:09 pm MST INF processing request idempotency_key=req-123
Usage Examples
Basic Structured Logging
import "log/slog"
// Simple message
slog.Info("application started")
// With attributes
slog.Info("user logged in",
slog.String("user_id", "123"),
slog.String("ip", "192.168.1.1"),
)
// Grouped attributes
slog.Info("request completed",
slog.Group("request",
slog.String("method", "POST"),
slog.String("path", "/api/users"),
),
slog.Int("status", 201),
)
HTTP Middleware
func LoggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Add idempotency key to context
ctx := r.Context()
if key := r.Header.Get("Idempotency-Key"); key != "" {
ctx = log.WithIdempotencyKey(ctx, key)
}
// Log the request
slog.InfoContext(ctx, "incoming request",
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
Error Logging
func processData(ctx context.Context) error {
data, err := fetchData()
if err != nil {
slog.ErrorContext(ctx, "failed to fetch data",
slog.String("error", err.Error()),
)
return err
}
slog.InfoContext(ctx, "data processed", slog.Int("records", len(data)))
return nil
}
Creating a Logger with Additional Context
// Create a logger with persistent attributes
logger := slog.With(
slog.String("service", "payment-processor"),
slog.String("version", "1.0.0"),
)
// All logs from this logger include the attributes
logger.Info("service started") // Includes service=payment-processor version=1.0.0
logger.Error("payment failed", slog.String("error", "insufficient funds"))
Dependencies
The package uses:
Best Practices
- Use structured logging: Prefer key-value attributes over string formatting
// Good
slog.Info("user created", slog.String("user_id", id))
// Avoid
slog.Info(fmt.Sprintf("user %s created", id))
- Use context-aware logging: Pass context through your application
func HandleRequest(ctx context.Context) {
slog.InfoContext(ctx, "processing") // Includes context values
}
-
Set appropriate log levels: Use debug for development, info for production
-
Add persistent context: Create loggers with common attributes
logger := slog.With(slog.String("module", "database"))