Logging Section API Reference

Comprehensive logging configuration for CLI applications

Sections

Terminology & Glossary
📖 Documentation
Navigation
77 sectionsv0.1
📄 Logging Section API Reference — glaze help logging-section-reference
logging-section-reference

Logging Section API Reference

Comprehensive logging configuration for CLI applications

Topicreferenceloggingapiclay

Logging Section API Reference

Overview

The Glazed logging section provides comprehensive logging configuration for CLI applications through command-line fields, environment variables, and configuration files. The section handles setup for console output and file logging while supporting multiple output formats and verbosity levels.

Key Capabilities

  • Multiple output targets: Console and file
  • Structured logging: JSON and text formats with contextual fields
  • Automatic configuration: Single function call for complete setup
  • Production features: Log rotation, performance optimization

Architecture

graph TD
    A[CLI Fields] --> B[Logging Section]
    B --> C[Console Output]
    B --> D[File Output]
    
    C --> F[Human-readable text]
    D --> G[Rotating log files]

The logging section transforms command-line fields into configured log outputs, supporting development, testing, and production deployment scenarios.

Implementation

Basic Integration

Add the logging section to any Glazed command:

import (
    "github.com/go-go-golems/glazed/pkg/cmds/logging"
    "github.com/rs/zerolog/log"
)

func NewMyCommand() (*MyCommand, error) {
    loggingSection, err := logging.NewLoggingSection()
    if err != nil {
        return nil, fmt.Errorf("failed to create logging section: %w", err)
    }
    
    cmdDesc := cmds.NewCommandDescription(
        "my-command",
        cmds.WithShort("Command with logging support"),
        cmds.WithSectionsList(loggingSection),
    )
    
    return &MyCommand{CommandDescription: cmdDesc}, nil
}

func (c *MyCommand) RunIntoGlazeProcessor(
    ctx context.Context,
    parsedSections *values.Values,
    gp middlewares.Processor,
) error {
    // Initialize logging settings from parsed sections
    var settings logging.LoggingSettings
    if err := parsedSections.DecodeSectionInto(logging.LoggingSectionSlug, &settings); err != nil {
        return fmt.Errorf("failed to get logging settings: %w", err)
    }
    
    if err := logging.InitLoggerFromSettings(&settings); err != nil {
        return fmt.Errorf("failed to initialize logger: %w", err)
    }
    
    log.Info().Msg("Processing started")
    // Command implementation
    return nil
}

Structured Logging Patterns

Use structured fields for effective logging:

func processFile(fileName string) error {
    start := time.Now()
    
    log.Debug().
        Str("file", fileName).
        Msg("Starting file processing")
    
    data, err := os.ReadFile(fileName)
    if err != nil {
        log.Error().
            Str("file", fileName).
            Err(err).
            Msg("Failed to read file")
        return fmt.Errorf("reading file %s: %w", fileName, err)
    }
    
    log.Info().
        Str("file", fileName).
        Int("bytes_processed", len(data)).
        Dur("duration", time.Since(start)).
        Msg("File processed successfully")
    
    return nil
}

Contextual Loggers

Create loggers with persistent context for complex operations:

func processUser(userID string) error {
    userLogger := log.With().
        Str("user_id", userID).
        Str("operation", "user_processing").
        Logger()
    
    userLogger.Info().Msg("Starting user processing")
    
    if err := validateUser(userID); err != nil {
        userLogger.Error().
            Err(err).
            Msg("User validation failed")
        return err
    }
    
    userLogger.Info().Msg("User processing completed")
    return nil
}

Configuration Fields

Command-Line Flags

FieldTypeDefaultDescription
--log-levelchoiceinfoVerbosity level (trace, debug, info, warn, error, fatal)
--log-formatchoicetextOutput format (text, json)
--log-filestring""Output file path with automatic rotation
--with-callerboolfalseInclude source file and line number
--log-to-stdoutboolfalseForce output to stdout regardless of other settings
--log-configstring list[]Additional logcopter profile/config files, loaded in command-line order
--log-areakey-value{}Per-area log level override, for example app.view:debug or app.db=warn
--strict-log-areasboolfalseFail if configured areas do not match known generated logcopter areas

Area-scoped log levels with logcopter

Glazed configures logcopter's default manager in-place. Applications keep using github.com/go-go-golems/glazed/pkg/cmds/logging; generated package loggers use github.com/go-go-golems/logcopter/pkg/logcopter.

Application YAML can use a canonical logging.areas map:

logging:
  log-level: info
  log-format: text
  areas:
    app.view.render: trace
    app.db: warn
    lib.protocol: debug

CLI overrides accept both colon and equals syntax:

myapp serve \
  --log-area app.view:debug \
  --log-area app.db=warn

--log-area is a repeatable key-value flag. Cobra/pflag also accepts comma splitting for StringSlice flags:

myapp serve --log-area app.view=debug,app.db=warn

Reusable logcopter profile files can be loaded explicitly with --log-config:

myapp serve --log-config ~/.config/logcopter/profiles/dev.yaml

Glazed supports both application-style wrapped profiles:

logging:
  log-level: info
  areas:
    app.view.render: trace
    app.db: warn

and direct logcopter-only profiles:

level: info
format: text
areas:
  app.view.render: trace
  app.db: warn

In the Cobra initialization path, merge order is:

  1. defaults;
  2. explicit --log-config files, in command-line order;
  3. direct CLI flags such as --log-level and --log-area.

Logcopter uses per-area child logger levels. Glazed therefore keeps zerolog's global level permissive enough not to suppress a trace-enabled area while the conventional global logger remains filtered at --log-level.

Log Levels

LevelPurposeUsage
traceExtremely detailed execution flowPerformance debugging
debugDetailed diagnostic informationDevelopment troubleshooting
infoGeneral application progressDefault production level
warnUnexpected conditions that don't halt executionMonitoring degraded performance
errorError conditions with continued executionProblem tracking
fatalCritical errors requiring application terminationSystem failures

Output Formats

Text format (human-readable):

INFO  2023-12-07T10:30:00Z Processing started
DEBUG 2023-12-07T10:30:01Z File loaded file=data.csv rows=1000

JSON format (machine-readable):

{"level":"info","time":"2023-12-07T10:30:00Z","message":"Processing started"}
{"level":"debug","time":"2023-12-07T10:30:01Z","message":"File loaded","file":"data.csv","rows":1000}

Production Deployment

File Logging

Configure automatic log rotation for production:

myapp process-data \
    --log-level info \
    --log-format json \
    --log-file /var/log/myapp/application.log

File logging features:

  • Rotation: 10MB maximum file size
  • Retention: 3 backup files, 28-day retention
  • Thread safety: Atomic writes for concurrent operations

Environment Variables

Configure logging through environment variables:

export MYAPP_LOG_LEVEL=info
export MYAPP_LOG_FORMAT=json
export MYAPP_LOG_FILE=/var/log/myapp.log

API Reference

Core Types

LoggingSettings

type LoggingSettings struct {
    WithCaller     bool              `glazed:"with-caller"`
    LogLevel       string            `glazed:"log-level"`
    LogFormat      string            `glazed:"log-format"`
    LogFile        string            `glazed:"log-file"`
    LogToStdout    bool              `glazed:"log-to-stdout"`
    LogConfigFiles []string          `glazed:"log-config"`
    LogAreas       map[string]string `glazed:"log-area"`
    Areas          map[string]string `glazed:"areas"`
    StrictAreas    bool              `glazed:"strict-log-areas"`
}

Functions

Working with Logging Settings

To initialize logging from parsed sections, use the standard pattern:

// Extract logging settings from parsed sections
var settings logging.LoggingSettings
if err := parsedSections.DecodeSectionInto(logging.LoggingSectionSlug, &settings); err != nil {
    return fmt.Errorf("failed to get logging settings: %w", err)
}

// Initialize logger from settings
if err := logging.InitLoggerFromSettings(&settings); err != nil {
    return fmt.Errorf("failed to initialize logger: %w", err)
}

InitLoggerFromSettings

func InitLoggerFromSettings(settings *LoggingSettings) error

Configures global logger from logging settings struct.

Usage:

if err := logging.InitLoggerFromSettings(&settings); err != nil {
    return fmt.Errorf("failed to initialize logger: %w", err)
}

Custom Validation Pattern

For custom validation of logging settings:

var settings logging.LoggingSettings
if err := parsedSections.DecodeSectionInto(logging.LoggingSectionSlug, &settings); err != nil {
    return fmt.Errorf("failed to extract logging settings: %w", err)
}

// Custom validation


return logging.SetupLogging(settings)

NewLoggingSection

func NewLoggingSection() (schema.Section, error)

Creates field section for command definitions.

Usage:

loggingSection, err := logging.NewLoggingSection()
if err != nil {
    return nil, err
}

cmdDesc := cmds.NewCommandDescription(
    "my-command",
    cmds.WithSectionsList(loggingSection),
)

Performance Optimization

Conditional Expensive Operations

Avoid performance penalties for debug logging:

// Efficient: Check if debug is enabled before expensive operations
if log.Debug().Enabled() {
    expensiveData := calculateComplexDebuggingInfo()
    log.Debug().
        Interface("debug_data", expensiveData).
        Msg("Detailed debug information")
}

// Always efficient: Simple field logging
log.Info().
    Str("user", userID).
    Int("count", itemCount).
    Dur("elapsed", duration).
    Msg("Operation completed")

Configuration Examples

Development Configuration

logging:
  log-level: debug
  log-format: text
  with-caller: true

Production Configuration

logging:
  log-level: info
  log-format: json
  log-file: /var/log/application.log

Common Issues

No Log Output

Symptoms: Application runs but produces no log output

Solutions:

  1. Verify logging initialization is called before logging:
    var settings logging.LoggingSettings
    parsedSections.DecodeSectionInto(logging.LoggingSectionSlug, &settings)
    logging.InitLoggerFromSettings(&settings)
    
  2. Check log level filtering: use --log-level debug
  3. Verify file permissions for --log-file destinations

Incorrect Format

Symptoms: Unexpected output format (JSON instead of text or vice versa)

Solutions:

  1. Explicitly set format: --log-format json or --log-format text
  2. Check environment variables: LOG_FORMAT may override settings
  3. Verify configuration file format settings

See Also