Class: EzLogsAgent::Railtie
- Inherits:
-
Rails::Railtie
- Object
- Rails::Railtie
- EzLogsAgent::Railtie
- Defined in:
- lib/ez_logs_agent/railtie.rb
Overview
Rails Railtie for automatic zero-config runtime integration.
This Railtie is the ONLY orchestrator in EzLogs Agent. It handles:
-
Starting/stopping the FlushScheduler
-
Auto-registering HTTP middleware
-
Auto-registering Sidekiq middleware (client + server)
-
Auto-installing ActiveJob capturer
-
Auto-installing Database capturer
All integrations are:
-
Defensive (wrapped in begin/rescue, never crash host app)
-
Configuration-gated (respect capture_http, capture_jobs, capture_database)
-
Framework-aware (check defined?(Sidekiq), defined?(ActiveRecord), etc.)
-
Idempotent (safe to boot multiple times)
-
Explicitly logged (log what’s enabled/skipped and why)
Class Attribute Summary collapse
-
.activejob_installed ⇒ Object
Returns the value of attribute activejob_installed.
-
.database_capturer_installed ⇒ Object
Returns the value of attribute database_capturer_installed.
-
.sidekiq_client_registered ⇒ Object
Returns the value of attribute sidekiq_client_registered.
-
.sidekiq_server_registered ⇒ Object
Returns the value of attribute sidekiq_server_registered.
Class Method Summary collapse
-
.install_activejob_capturer ⇒ void
Install ActiveJob capturer.
-
.install_database_capturer ⇒ void
Install Database capturer.
-
.log_configuration_summary ⇒ void
Log configuration summary at boot time.
-
.register_sidekiq_client_middleware ⇒ void
Register Sidekiq client middleware.
-
.register_sidekiq_middleware ⇒ void
Register Sidekiq client and server middleware.
-
.register_sidekiq_server_middleware ⇒ void
Register Sidekiq server middleware.
-
.reset_registration_state! ⇒ Object
Reset registration state (for testing).
-
.setup_flush_scheduler ⇒ void
Setup FlushScheduler with fork-aware initialization.
-
.start_flush_scheduler ⇒ void
Start the FlushScheduler.
-
.validate_configuration ⇒ Boolean
Validate configuration at boot time.
Class Attribute Details
.activejob_installed ⇒ Object
Returns the value of attribute activejob_installed.
30 31 32 |
# File 'lib/ez_logs_agent/railtie.rb', line 30 def activejob_installed @activejob_installed end |
.database_capturer_installed ⇒ Object
Returns the value of attribute database_capturer_installed.
30 31 32 |
# File 'lib/ez_logs_agent/railtie.rb', line 30 def database_capturer_installed @database_capturer_installed end |
.sidekiq_client_registered ⇒ Object
Returns the value of attribute sidekiq_client_registered.
30 31 32 |
# File 'lib/ez_logs_agent/railtie.rb', line 30 def sidekiq_client_registered @sidekiq_client_registered end |
.sidekiq_server_registered ⇒ Object
Returns the value of attribute sidekiq_server_registered.
30 31 32 |
# File 'lib/ez_logs_agent/railtie.rb', line 30 def sidekiq_server_registered @sidekiq_server_registered end |
Class Method Details
.install_activejob_capturer ⇒ void
This method returns an undefined value.
Install ActiveJob capturer
ActiveJob capturer handles correlation propagation and job capture for non-Sidekiq adapters (async, inline, etc.).
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/ez_logs_agent/railtie.rb', line 195 def self.install_activejob_capturer # Check if ActiveJob is present unless defined?(ActiveJob) EzLogsAgent::Logger.debug("[Railtie] ActiveJob not detected, skipping ActiveJob capturer") return end # Check if job capture is enabled unless EzLogsAgent.configuration.capture_jobs # Already logged in register_sidekiq_middleware if Sidekiq present # Only log here if Sidekiq is NOT present unless defined?(Sidekiq) EzLogsAgent::Logger.debug("[Railtie] Job capture disabled (capture_jobs = false)") end return end return if @activejob_installed EzLogsAgent::Capturers::ActiveJobCapturer.install @activejob_installed = true EzLogsAgent::Logger.debug("[Railtie] ActiveJob capturer installed") rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to install ActiveJob capturer: #{e.class} - #{e.}") end |
.install_database_capturer ⇒ void
This method returns an undefined value.
Install Database capturer
Database capturer installs ActiveRecord lifecycle callbacks (after_create, after_update, after_destroy) for all models.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/ez_logs_agent/railtie.rb', line 227 def self.install_database_capturer # Check if ActiveRecord is present unless defined?(ActiveRecord) EzLogsAgent::Logger.debug("[Railtie] ActiveRecord not detected, skipping database capture") return end # Check if database capture is enabled unless EzLogsAgent.configuration.capture_database EzLogsAgent::Logger.debug("[Railtie] Database capture disabled (capture_database = false)") return end return if @database_capturer_installed EzLogsAgent::Capturers::DatabaseCapturer.install @database_capturer_installed = true EzLogsAgent::Logger.debug("[Railtie] Database capture installed") rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to install database capturer: #{e.class} - #{e.}") end |
.log_configuration_summary ⇒ void
This method returns an undefined value.
Log configuration summary at boot time
Shows what’s enabled/disabled to help with debugging and visibility.
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/ez_logs_agent/railtie.rb', line 327 def self.log_configuration_summary config = EzLogsAgent.configuration EzLogsAgent::Logger.info("[Railtie] Configuration:") EzLogsAgent::Logger.info("[Railtie] Server: #{config.server_url}") EzLogsAgent::Logger.info("[Railtie] Capture HTTP: #{config.capture_http}") EzLogsAgent::Logger.info("[Railtie] Capture Jobs: #{config.capture_jobs}") EzLogsAgent::Logger.info("[Railtie] Capture Database: #{config.capture_database}") # Show optional configuration if present if config.actor_from_request EzLogsAgent::Logger.info("[Railtie] Actor Extraction: enabled") end if config.display_name_for && config.display_name_for.any? EzLogsAgent::Logger.info("[Railtie] Display Names: configured for #{config.display_name_for.keys.join(', ')}") end rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to log configuration summary: #{e.class} - #{e.}") end |
.register_sidekiq_client_middleware ⇒ void
This method returns an undefined value.
Register Sidekiq client middleware
Client middleware runs in ALL processes (web, worker, console) and injects correlation_id into job payloads at enqueue-time.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/ez_logs_agent/railtie.rb', line 148 def self.register_sidekiq_client_middleware return if @sidekiq_client_registered Sidekiq.configure_client do |config| config.client_middleware do |chain| chain.add EzLogsAgent::Capturers::JobCapturer::ClientMiddleware end end @sidekiq_client_registered = true EzLogsAgent::Logger.debug("[Railtie] Sidekiq client middleware registered") rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to register Sidekiq client middleware: #{e.class} - #{e.}") end |
.register_sidekiq_middleware ⇒ void
This method returns an undefined value.
Register Sidekiq client and server middleware
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/ez_logs_agent/railtie.rb', line 120 def self.register_sidekiq_middleware # Check if Sidekiq is present unless defined?(Sidekiq) EzLogsAgent::Logger.debug("[Railtie] Sidekiq not detected, skipping job capture middleware") return end # Check if job capture is enabled unless EzLogsAgent.configuration.capture_jobs EzLogsAgent::Logger.debug("[Railtie] Job capture disabled (capture_jobs = false)") return end # Register client middleware (correlation propagation) register_sidekiq_client_middleware # Register server middleware (job execution capture) register_sidekiq_server_middleware rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to register Sidekiq middleware: #{e.class} - #{e.}") end |
.register_sidekiq_server_middleware ⇒ void
This method returns an undefined value.
Register Sidekiq server middleware
Server middleware runs ONLY in Sidekiq worker processes and captures job execution as background_job events.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/ez_logs_agent/railtie.rb', line 169 def self.register_sidekiq_server_middleware return if @sidekiq_server_registered Sidekiq.configure_server do |config| # Also register client middleware in server process (for job-enqueues-job scenarios) config.client_middleware do |chain| chain.add EzLogsAgent::Capturers::JobCapturer::ClientMiddleware end config.server_middleware do |chain| chain.add EzLogsAgent::Capturers::JobCapturer::ServerMiddleware end end @sidekiq_server_registered = true EzLogsAgent::Logger.debug("[Railtie] Sidekiq server middleware registered") rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to register Sidekiq server middleware: #{e.class} - #{e.}") end |
.reset_registration_state! ⇒ Object
Reset registration state (for testing)
34 35 36 37 38 39 |
# File 'lib/ez_logs_agent/railtie.rb', line 34 def reset_registration_state! @sidekiq_client_registered = false @sidekiq_server_registered = false @activejob_installed = false @database_capturer_installed = false end |
.setup_flush_scheduler ⇒ void
This method returns an undefined value.
Setup FlushScheduler with fork-aware initialization
Background threads don’t survive fork(). In forking servers like Puma cluster mode or Unicorn, we must start FlushScheduler AFTER the fork in each worker process.
Strategy:
-
Always register ActiveSupport::ForkTracker hook (handles all forking cases)
-
Also start immediately (for non-forking servers or single-process mode)
-
FlushScheduler.start is idempotent, so calling it multiple times is safe
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/ez_logs_agent/railtie.rb', line 261 def self.setup_flush_scheduler # Register fork hook for Puma cluster mode, Unicorn, etc. # ActiveSupport::ForkTracker (Rails 6.1+) is the most reliable way if defined?(ActiveSupport::ForkTracker) ActiveSupport::ForkTracker.after_fork do start_flush_scheduler end EzLogsAgent::Logger.debug("[Railtie] Registered ActiveSupport::ForkTracker hook for FlushScheduler") end # Always start FlushScheduler now (for non-forking servers or master process) # In forking servers, this runs in master (will be killed on fork) # then ForkTracker restarts it in each worker start_flush_scheduler rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to setup FlushScheduler: #{e.class} - #{e.}") end |
.start_flush_scheduler ⇒ void
This method returns an undefined value.
Start the FlushScheduler
282 283 284 285 286 287 |
# File 'lib/ez_logs_agent/railtie.rb', line 282 def self.start_flush_scheduler EzLogsAgent::FlushScheduler.start EzLogsAgent::Logger.debug("[Railtie] FlushScheduler started (PID: #{Process.pid})") rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to start FlushScheduler: #{e.class} - #{e.}") end |
.validate_configuration ⇒ Boolean
Validate configuration at boot time
Logs errors and warnings from configuration validation. If configuration is invalid, logs errors and returns false to skip initialization. If configuration has warnings, logs them but continues.
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/ez_logs_agent/railtie.rb', line 296 def self.validate_configuration result = EzLogsAgent::ConfigurationValidator.validate(EzLogsAgent.configuration) # Log errors if result.errors.any? EzLogsAgent::Logger.error("[Railtie] Configuration validation failed:") result.errors.each do |error| EzLogsAgent::Logger.error("[Railtie] - #{error}") end EzLogsAgent::Logger.error("[Railtie] Agent initialization skipped. Please fix configuration errors.") return false end # Log warnings if result.warnings.any? result.warnings.each do |warning| EzLogsAgent::Logger.warn("[Railtie] ⚠ #{warning}") end end true rescue StandardError => e EzLogsAgent::Logger.error("[Railtie] Failed to validate configuration: #{e.class} - #{e.}") false end |