Module: LogStruct::SemanticLogger::Setup

Extended by:
T::Sig
Defined in:
lib/log_struct/semantic_logger/setup.rb

Overview

Handles setup and configuration of SemanticLogger for Rails applications

This module provides the core integration between LogStruct and SemanticLogger, configuring appenders, formatters, and logger replacement to provide optimal logging performance while maintaining full compatibility with Rails conventions.

Class Method Summary collapse

Class Method Details

.add_appenders(app) ⇒ void

This method returns an undefined value.

Parameters:

  • app (T.untyped)


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/log_struct/semantic_logger/setup.rb', line 116

def self.add_appenders(app)
  config = LogStruct.config

  # Determine output destination
  io = determine_output(app)

  if Rails.env.development?
    if config.prefer_json_in_development
      # Default to production-style JSON in development when enabled
      ::SemanticLogger.add_appender(
        io: io,
        formatter: LogStruct::SemanticLogger::Formatter.new,
        filter: determine_filter
      )
    elsif config.enable_color_output
      # Opt-in colorful human formatter in development
      ::SemanticLogger.add_appender(
        io: io,
        formatter: LogStruct::SemanticLogger::ColorFormatter.new(
          color_map: config.color_map
        ),
        filter: determine_filter
      )
    else
      ::SemanticLogger.add_appender(
        io: io,
        formatter: LogStruct::SemanticLogger::Formatter.new,
        filter: determine_filter
      )
    end
  else
    # Use our custom JSON formatter in non-development environments
    ::SemanticLogger.add_appender(
      io: io,
      formatter: LogStruct::SemanticLogger::Formatter.new,
      filter: determine_filter
    )
  end

  # Add file appender if Rails has a log path configured (normal Rails behavior)
  if app.config.paths["log"].first
    ::SemanticLogger.add_appender(
      file_name: app.config.paths["log"].first,
      formatter: LogStruct::SemanticLogger::Formatter.new,
      filter: determine_filter
    )
  end
end

.configure_semantic_logger(app) ⇒ void

This method returns an undefined value.

Configures SemanticLogger as the primary logging engine for the Rails application

This method replaces Rails' default logger with SemanticLogger, providing:

  • 10-100x performance improvement for high-volume logging
  • Non-blocking I/O through background thread processing
  • Enhanced reliability with graceful error handling
  • Multiple output destinations (files, STDOUT, cloud services)
  • Structured metadata including process/thread IDs and timing

The configuration automatically:

  • Determines optimal log levels based on environment
  • Sets up appropriate appenders (console, file, etc.)
  • Enables colorized output in development
  • Replaces Rails.logger and component loggers
  • Preserves full Rails.logger API compatibility

Parameters:

  • app (T.untyped)

    The Rails application instance



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/log_struct/semantic_logger/setup.rb', line 83

def self.configure_semantic_logger(app)
  # Set SemanticLogger configuration
  ::SemanticLogger.application = Rails.application.class.module_parent_name
  ::SemanticLogger.environment = Rails.env

  # Determine log level from Rails config
  log_level = determine_log_level(app)
  ::SemanticLogger.default_level = log_level

  # Clear existing appenders
  ::SemanticLogger.clear_appenders!

  # Add appropriate appenders based on environment
  add_appenders(app)

  # Replace Rails.logger with SemanticLogger
  replace_rails_logger(app)
end

.determine_filterRegexp?

Returns:

  • (Regexp, nil)


180
181
182
183
184
185
186
187
# File 'lib/log_struct/semantic_logger/setup.rb', line 180

def self.determine_filter
  # Filter out noisy loggers if configured
  config = LogStruct.config
  return nil unless config.filter_noisy_loggers

  # Common noisy loggers to filter
  /\A(ActionView|ActionController::RoutingError|ActiveRecord::SchemaMigration)/
end

.determine_log_level(app) ⇒ Symbol

Parameters:

  • app (T.untyped)

Returns:

  • (Symbol)


103
104
105
106
107
108
109
110
111
112
113
# File 'lib/log_struct/semantic_logger/setup.rb', line 103

def self.determine_log_level(app)
  if app.config.log_level
    app.config.log_level
  elsif Rails.env.production?
    :info
  elsif Rails.env.test?
    :debug
  else
    :debug
  end
end

.determine_output(app) ⇒ T.untyped

Parameters:

  • app (T.untyped)

Returns:

  • (T.untyped)


166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/log_struct/semantic_logger/setup.rb', line 166

def self.determine_output(app)
  # Always honor explicit STDOUT directive
  return $stdout if ENV["RAILS_LOG_TO_STDOUT"].present?

  if Rails.env.test?
    # Use StringIO in test to keep stdout clean
    StringIO.new
  else
    # Use STDOUT for app logs in dev/production
    $stdout
  end
end

.replace_rails_logger(app) ⇒ void

This method returns an undefined value.

Replaces Rails.logger and all component loggers with LogStruct's SemanticLogger

This method provides seamless integration by replacing the default Rails logger throughout the entire Rails stack, ensuring all logging flows through the high-performance SemanticLogger system.

Benefits of Complete Logger Replacement:

  • Consistent performance: All Rails components benefit from SemanticLogger speed
  • Unified formatting: All logs use the same structured JSON format
  • Centralized configuration: Single point of control for all logging
  • Complete compatibility: Maintains all Rails.logger API contracts

Components Updated:

  • Rails.logger (framework core)
  • ActiveRecord::Base.logger (database queries)
  • ActionController::Base.logger (request processing)
  • ActionMailer::Base.logger (email delivery)
  • ActiveJob::Base.logger (background jobs)
  • ActionView::Base.logger (template rendering)
  • ActionCable.server.config.logger (WebSocket connections)

After replacement, all Rails logging maintains API compatibility while gaining SemanticLogger's performance, reliability, and feature benefits.

Parameters:

  • app (T.untyped)

    The Rails application instance



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/log_struct/semantic_logger/setup.rb', line 215

def self.replace_rails_logger(app)
  # Create new SemanticLogger instance
  logger = LogStruct::SemanticLogger::Logger.new("Rails")

  # Replace Rails.logger
  Rails.logger = logger

  # Also replace various component loggers
  ActiveRecord::Base.logger = logger if defined?(ActiveRecord::Base)
  ActionController::Base.logger = logger if defined?(ActionController::Base)
  if defined?(ActionMailer::Base)
    ActionMailer::Base.logger = logger
    # Ensure ActionMailer.logger is also set (it might be accessed directly)
    T.unsafe(::ActionMailer).logger = logger if T.unsafe(::ActionMailer).respond_to?(:logger=)
  end
  ActiveJob::Base.logger = logger if defined?(ActiveJob::Base)
  ActionView::Base.logger = logger if defined?(ActionView::Base)
  ActionCable.server.config.logger = logger if defined?(ActionCable)

  # Store reference in app config
  app.config.logger = logger
end