Skip to content

Latest commit

 

History

History
640 lines (462 loc) · 14.8 KB

File metadata and controls

640 lines (462 loc) · 14.8 KB

Formatting

The Bash Logging Module allows you to customize the format of log messages using special placeholders.

Table of Contents

Default Format

The default log message format is:

%d [%l] [%s] %m

Which produces output like:

2026-01-16 14:30:45 [INFO] [myscript.sh] Application started

Format Placeholders

Placeholder Description Example
%d Date and time 2026-01-16 14:30:45
%l Log level INFO, ERROR, DEBUG
%s Script name myscript.sh
%m Log message Application started
%z Timezone UTC or LOCAL

Setting Format at Initialization

Use the --format option when initializing the logger:

# Custom format
init_logger --format "[%l] %d %z [%s] %m"

# Minimal format
init_logger --format "%l: %m"

# Detailed format
init_logger --format "%d %z [%l] %s: %m"

Format Examples

Minimal Format

init_logger --format "%l: %m"

Output:

INFO: Application started
ERROR: Failed to open file
DEBUG: Variable value: count=42

When to use:

  • Quick debugging
  • When context is obvious
  • Console-only logging
  • Minimal output requirements

Standard Format (Default)

init_logger --format "%d [%l] [%s] %m"

Output:

2026-01-16 14:30:45 [INFO] [myscript.sh] Application started
2026-01-16 14:30:46 [ERROR] [myscript.sh] Failed to open file

When to use:

  • General purpose logging
  • File logging
  • Production environments
  • Most use cases

Detailed Format with Timezone

init_logger --format "%d %z [%l] [%s] %m"

Output:

2026-01-16 14:30:45 UTC [INFO] [myscript.sh] Application started
2026-01-16 14:30:46 UTC [ERROR] [myscript.sh] Failed to open file

When to use:

  • Multi-timezone deployments
  • Coordinated operations
  • Compliance/audit requirements
  • When UTC timestamps are used

Syslog-Style Format

init_logger --format "%d %s[$$]: [%l] %m"

Output:

2026-01-16 14:30:45 myscript.sh[12345]: [INFO] Application started

Note: $$ is a Bash variable for the current process ID.

When to use:

  • System logs
  • Service logs
  • Process tracking
  • Syslog integration

Compact Format

init_logger --format "[%l] %m"

Output:

[INFO] Application started
[ERROR] Failed to open file

When to use:

  • Development
  • Short-lived scripts
  • When timestamp isn't needed
  • Interactive use

Time-Only Format

init_logger --format "$(date +%H:%M:%S) [%l] %m"

Output:

14:30:45 [INFO] Application started
14:30:46 [ERROR] Failed to open file

When to use:

  • Same-day logs
  • Performance monitoring
  • Short-term debugging
  • When date is implied

Timezone Display

The %z placeholder shows the timezone mode:

# Local time (default)
init_logger --format "%d %z [%l] %m"
# Output: 2026-01-16 14:30:45 LOCAL [INFO] Message

# UTC time
init_logger --utc --format "%d %z [%l] %m"
# Output: 2026-01-16 19:30:45 UTC [INFO] Message

Without Timezone Placeholder

If you don't include %z, the timezone isn't displayed (but timestamps are still affected by the --utc flag):

# Local time without indicator
init_logger --format "%d [%l] %m"
# Output: 2026-01-16 14:30:45 [INFO] Message

# UTC time without indicator
init_logger --utc --format "%d [%l] %m"
# Output: 2026-01-16 19:30:45 [INFO] Message

Configuration File Format Setting

Set format in configuration files:

[logging]
# Standard format
format = %d [%l] [%s] %m

# Detailed format
format = %d %z [%l] [%s] %m

# Minimal format
format = [%l] %m

# Custom format
format = %d [%s] %l: %m

See Configuration for more details.

Changing Format at Runtime

Use the set_log_format function to change format during script execution:

#!/bin/bash
source /path/to/logging.sh

# Start with default format
init_logger

log_info "Starting processing"

# Switch to minimal format for detailed debug output
set_log_format "[%l] %m"
log_debug "Processing item 1"
log_debug "Processing item 2"

# Return to detailed format
set_log_format "%d [%l] [%s] %m"
log_info "Processing complete"

See Runtime Configuration for more details.

Format Best Practices

1. Include Timestamp for File Logs

Always include %d when logging to files:

init_logger --log "/var/log/app.log" --format "%d [%l] [%s] %m"

2. Include Script Name for Multi-Script Logs

Use %s when multiple scripts log to the same file:

init_logger --log "/var/log/shared.log" --format "%d [%l] [%s] %m"

3. Include Timezone for Distributed Systems

Use %z for systems spanning multiple timezones:

init_logger --utc --format "%d %z [%l] [%s] %m"

4. Minimal Format for Console Debugging

Keep it simple for interactive development:

init_logger --format "[%l] %m"

5. Consistent Format Across Applications

Standardize format across your organization:

# Company standard format
init_logger --format "%d [%l] [%s] %m"

6. Consider Log Parsing Tools

If using log analysis tools, choose a format they can parse:

# JSON-like format for structured logging
# Note: This module doesn't produce actual JSON, but you can make it parseable
init_logger --format '%d|%l|%s|%m'

Format Examples by Use Case

Development Script

# Quick debugging - minimal format
init_logger --format "[%l] %m"

Production Application

# Comprehensive logging with timezone
init_logger --log "/var/log/app/app.log" \
  --format "%d %z [%l] [%s] %m" \
  --utc

System Service

# Syslog-style format with process ID
init_logger --journal --format "%d %s[$$]: %m"

Multi-Timezone Deployment

# Clear timezone indication
init_logger --utc --format "%d %z [%l] [%s] %m"

Shared Log File

# Include script name to distinguish sources
init_logger --log "/var/log/shared/all.log" --format "%d [%s] [%l] %m"

CLI Tool

# Minimal format, all to stderr
init_logger --stderr-level DEBUG --format "%l: %m"

Cloud and Structured Logging Formats

Modern cloud platforms and log aggregation services often prefer structured or semi-structured log formats. Here are examples for common platforms:

AWS CloudWatch Logs Format

CloudWatch Logs works well with structured formats that can be parsed:

# CloudWatch-friendly format with clear structure
init_logger --format "%d [%l] [%s] %m" --utc

# CloudWatch with key-value pairs for easy parsing
init_logger --format "timestamp=%d level=%l script=%s message=%m" --utc

Output:

2026-01-16 14:30:45 [INFO] [myscript.sh] Application started
timestamp=2026-01-16 14:30:45 level=INFO script=myscript.sh message=Application started

When to use:

  • AWS Lambda functions
  • EC2 instances with CloudWatch agent
  • ECS/Fargate containers
  • Any AWS service that sends logs to CloudWatch

Best practices for CloudWatch:

  • Always use UTC time (--utc)
  • Include log level for filtering
  • Keep format consistent across services
  • Consider adding request IDs in the message for tracing

JSON-Like Format

While the logging module doesn't produce true JSON, you can create a JSON-like format for log parsers:

# JSON-like format
init_logger --format '{"timestamp":"%d", "level":"%l", "script":"%s", "message":"%m"}' --utc

Output:

{"timestamp":"2026-01-16 14:30:45", "level":"INFO", "script":"myscript.sh", "message":"Application started"}

When to use:

  • Log aggregation platforms (ELK, Splunk, Datadog)
  • When logs need to be parsed programmatically
  • Cloud-native applications
  • Microservices architectures

Note: This creates JSON-like output but is not guaranteed to be valid JSON if the message contains special characters like quotes. For production use with strict JSON requirements, consider post-processing logs or using dedicated JSON logging tools.

Pipe-Delimited Format

A simpler structured format that's easier to parse:

# Pipe-delimited format
init_logger --format "%d|%l|%s|%m" --utc

Output:

2026-01-16 14:30:45|INFO|myscript.sh|Application started
2026-01-16 14:30:46|ERROR|myscript.sh|Failed to open file

When to use:

  • Easy parsing with cut or awk
  • CSV-like log analysis
  • Simple log aggregation
  • When JSON is overkill

Kubernetes/Container Logs Format

For containerized applications, a format that works well with container log drivers:

# Container-friendly format
init_logger --format "%d %z %l %s: %m" --utc

# With structured fields
init_logger --format "time=%d tz=%z level=%l source=%s msg=%m" --utc

Output:

2026-01-16 14:30:45 UTC INFO myscript.sh: Application started
time=2026-01-16 14:30:45 tz=UTC level=INFO source=myscript.sh msg=Application started

When to use:

  • Docker containers
  • Kubernetes pods
  • Container orchestration platforms
  • When logs are collected by container runtime

Splunk-Friendly Format

Format optimized for Splunk ingestion:

# Splunk-friendly format with clear field extraction
init_logger --format "%d source=\"%s\" level=%l %m" --utc

Output:

2026-01-16 14:30:45 source="myscript.sh" level=INFO Application started

When to use:

  • Splunk log ingestion
  • When using Splunk Universal Forwarder
  • Enterprise log management with Splunk

Example: Multi-Environment Format Selection

Choose format based on deployment environment:

#!/bin/bash
source /path/to/logging.sh

# Determine environment
ENV="${DEPLOY_ENV:-development}"

case "$ENV" in
    aws|cloudwatch)
        # AWS CloudWatch format
        init_logger \
            --format "timestamp=%d level=%l script=%s message=%m" \
            --utc \
            --log "/var/log/app.log"
        ;;
    kubernetes|k8s)
        # Kubernetes format
        init_logger \
            --format "time=%d tz=%z level=%l source=%s msg=%m" \
            --utc \
            --stderr-level DEBUG
        ;;
    json)
        # JSON-like format
        init_logger \
            --format '{"timestamp":"%d", "level":"%l", "script":"%s", "message":"%m"}' \
            --utc \
            --log "/var/log/app.json"
        ;;
    development)
        # Human-readable format
        init_logger \
            --format "[%l] %d - %m" \
            --color
        ;;
    *)
        # Default format
        init_logger \
            --format "%d [%l] [%s] %m" \
            --log "/var/log/app.log"
        ;;
esac

log_info "Application started in $ENV environment"

Special Characters in Messages

The logging module handles special characters in log messages:

log_info "Processing file: /path/to/file.txt"
log_info "Status: 100% complete"
log_info "Command: grep -r 'pattern' /dir/"
log_info "Line break test\nSecond line"

Most special characters are displayed as-is. For complex formatting in messages, consider using printf-style formatting:

# Format numbers, padding, etc. before logging
formatted_msg=$(printf "Processing: %-20s [%3d%%]" "$filename" "$percent")
log_info "$formatted_msg"

Escaping in Format Strings

Format placeholders are literal strings. If you need to include a literal % character, you can work around it:

# This works - % not followed by a format letter
init_logger --format "%d [%l] %m (100% complete)"

# This is interpreted as format string
# init_logger --format "%d [%l] %m %d" # Second %d would be replaced

Testing Your Format

Create a test script to see how your format looks:

#!/bin/bash
source /path/to/logging.sh

# Test your format
init_logger --format "[%l] %d %z - %s: %m"

log_debug "Debug message"
log_info "Info message"
log_notice "Notice message"
log_warn "Warning message"
log_error "Error message"
log_critical "Critical message"

Format and Color Output

Format and color codes work together. Colors are applied to the entire line based on log level:

init_logger --format "[%l] %m" --color

log_info "This line will be colored"
log_error "This line will be colored differently"

Color codes are automatically stripped when output is redirected to a file:

./script.sh > output.log  # No color codes in file

Related Documentation