legion-logging

Logging module for the LegionIO framework. Provides colorized console output via Rainbow, structured JSON logging, multi-output IO, and a consistent logging interface across all Legion gems and extensions.

Version: 1.5.2

Installation

gem install legion-logging

Or add to your Gemfile:

gem 'legion-logging'

Usage

require 'legion/logging'

Legion::Logging.setup(log_file: './legion.log', level: 'debug')
Legion::Logging.setup(level: 'info')  # defaults to stdout when no log_file specified

Legion::Logging.debug('debugging info')
Legion::Logging.info('hello')
Legion::Logging.warn('warning a user')
Legion::Logging.error('something went wrong')
Legion::Logging.fatal('critical failure')

Async Logging

By default, setup enables async logging — log calls push to a background writer thread and return immediately. Fatal calls always bypass the queue and write synchronously.

# Async is on by default
Legion::Logging.setup(level: 'info')

# Disable async (synchronous mode)
Legion::Logging.setup(level: 'info', async: false)

# Configure buffer size via Legion::Settings
# Legion::Settings[:logging, :async, :buffer_size] = 20_000

When the buffer is full, callers block until the writer drains — this preserves log completeness. Use Legion::Logging.stop_async_writer during shutdown to flush and stop the writer thread.

Structured JSON Output

Pass format: :json to disable colorization and emit machine-parseable JSON log lines:

Legion::Logging.setup(level: 'info', format: :json)

This is useful for log aggregation pipelines (Elasticsearch, Splunk, etc.).

Multi-Output IO

Legion::Logging::MultiIO writes to multiple destinations simultaneously — for example, stdout and a file at the same time. Used internally by the Builder when log_file is set alongside console output.

SIEM Export

Legion::Logging::SIEMExporter provides PHI-redacting export helpers for security event pipelines:

# Redact PHI patterns (SSN, phone, MRN, DOB) from a string
clean = Legion::Logging::SIEMExporter.redact_phi(raw_message)

# Export to Splunk HEC
Legion::Logging::SIEMExporter.export_to_splunk(event, hec_url: url, token: token)

# Format for ELK/OpenSearch
Legion::Logging::SIEMExporter.format_for_elk(event, index: 'legion')

PHI patterns redacted: SSN (###-##-####), phone (###-###-####), MRN (XX#######), DOB (##/##/####).

Helper Mixin

Legion::Logging::Helper is an injectable mixin for LEX extensions. It derives logger tags from segments, lex_filename, or class name automatically, and passes through settings[:logger] config when available. Allows LEX gems to use legion-logging directly without requiring the full LegionIO framework.

class MyRunner
  include Legion::Logging::Helper

  def run
    log.info("starting")
    log.debug("details")
  end
end

Exception Logging

log_exception provides a single call for complete exception logging with component context. It writes a human-readable exception line through the configured logger and publishes a structured exception event when an exception_writer is configured.

begin
  runner.call
rescue StandardError => e
  Legion::Logging.log_exception(
    e,
    handled: true,
    component_type: :runner,
    lex: 'my_extension',
    task_id: 'abc-123'
  )
end

The synchronous log line includes the full Ruby backtrace. Legion does not truncate it to a fixed frame count or replace the tail with ... N more, because the missing frames are often the useful part of production failures.

Structured exception events include:

  • exception class and message
  • full backtrace array
  • caller file, line, and function where available
  • log level and handled/unhandled status
  • component type, lex name, gem name, version, and source path metadata
  • task and thread context
  • stable error fingerprint for deduplication

Writer Lambdas

log_writer and exception_writer are pluggable lambda slots that replace the old Hooks system. Assign them to forward events to external systems:

Legion::Logging.exception_writer = lambda do |payload, routing_key:, headers:, properties:|
  publish_to_amqp(payload, routing_key:, headers:, properties:)
end

Legion::Logging.log_writer = lambda do |context, routing_key:|
  publish_log(context, routing_key:)
end

EventBuilder

EventBuilder.build_exception constructs rich structured exception payloads including caller location, lex identity, and gem metadata. EventBuilder.fingerprint produces an MD5 fingerprint of stable error fields for deduplication in log aggregation pipelines.

Redactor

Legion::Logging::Redactor redacts PII/PHI patterns (SSN, email, phone, MRN, DOB, credit card) plus Vault tokens, JWTs, bearer tokens, vault:// URIs, lease:// URIs, and lease IDs from log messages. Redaction is opt-in for text log lines: load the module (for example via require 'legion/logging/redactor') and enable it with logging.redaction.enabled: true. When loaded and enabled, it is wired into all log methods in the write path.

Structured exception events are redacted before publishing when the redactor is loaded. This includes event identity fields such as user, so email-shaped local usernames are not forwarded raw.

Requirements

  • Ruby >= 3.4

License

Apache-2.0