Class: DeadBro::SqlTrackingMiddleware
- Inherits:
-
Object
- Object
- DeadBro::SqlTrackingMiddleware
- Defined in:
- lib/dead_bro/sql_tracking_middleware.rb
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app) ⇒ SqlTrackingMiddleware
constructor
A new instance of SqlTrackingMiddleware.
Constructor Details
#initialize(app) ⇒ SqlTrackingMiddleware
Returns a new instance of SqlTrackingMiddleware.
5 6 7 |
# File 'lib/dead_bro/sql_tracking_middleware.rb', line 5 def initialize(app) @app = app end |
Instance Method Details
#call(env) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/dead_bro/sql_tracking_middleware.rb', line 9 def call(env) return @app.call(env) if DeadBro.configuration.skip_tracking? # Capture rack entry time before any setup so middleware overhead is accurately measured. rack_entry = Time.now Thread.current[DeadBro::TRACKING_START_TIME_KEY] = rack_entry # Queue time: gap between when the upstream proxy accepted the connection and when a Rack # worker picked it up. Heroku sets X-Request-Start as "t=<microseconds>"; nginx typically # uses "t=<seconds.ms>". Both are parsed below. Thread.current[:dead_bro_queue_duration_ms] = parse_queue_start(env, rack_entry) # Clear logs for this request DeadBro.logger.clear # Start SQL tracking for this request if defined?(DeadBro::SqlSubscriber) DeadBro::SqlSubscriber.start_request_tracking end # Start cache tracking for this request if defined?(DeadBro::CacheSubscriber) DeadBro::CacheSubscriber.start_request_tracking end # Start Redis tracking for this request if defined?(DeadBro::RedisSubscriber) DeadBro::RedisSubscriber.start_request_tracking end # Start view rendering tracking for this request if defined?(DeadBro::ViewRenderingSubscriber) DeadBro::ViewRenderingSubscriber.start_request_tracking end # Start lightweight memory tracking for this request if defined?(DeadBro::LightweightMemoryTracker) DeadBro::LightweightMemoryTracker.start_request_tracking end # Decide once whether this request pays for heavy allocation tracking # (flag + per-request sampling). Cache the decision so the matching stop # in Subscriber agrees with this start. alloc_active = DeadBro.configuration.allocation_tracking_active? Thread.current[:dead_bro_alloc_active] = alloc_active # Start detailed memory + allocation-source tracking when active if alloc_active DeadBro::MemoryTrackingSubscriber.start_request_tracking if defined?(DeadBro::MemoryTrackingSubscriber) DeadBro::AllocationSourceSampler.start if defined?(DeadBro::AllocationSourceSampler) end # Start Elasticsearch tracking for this request if defined?(DeadBro::ElasticsearchSubscriber) DeadBro::ElasticsearchSubscriber.start_request_tracking end # Start DB connection pool wait tracking if defined?(DeadBro::DbConnectionSubscriber) DeadBro::DbConnectionSubscriber.start_request_tracking end # Start GC pressure tracking — snapshot before any app code runs DeadBro::GcTracker.start_request_tracking if defined?(DeadBro::GcTracker) # Start per-phase allocation attribution (~0.1ms; under memory tracking) if DeadBro.configuration.memory_tracking_enabled && defined?(DeadBro::MemoryPhaseTracker) DeadBro::MemoryPhaseTracker.start_request_tracking end # Start AR object instantiation counting for this request DeadBro::ArObjectTracker.start_request_tracking if defined?(DeadBro::ArObjectTracker) # Start CPU time tracking for this request (thread-local clock) DeadBro::CpuTracker.start_request_tracking if defined?(DeadBro::CpuTracker) # Start outgoing HTTP accumulation for this request Thread.current[:dead_bro_http_events] = [] @app.call(env) ensure # Clean up thread-local storage if defined?(DeadBro::SqlSubscriber) Thread.current[:dead_bro_sql_queries] Thread.current[:dead_bro_sql_queries] = nil end if defined?(DeadBro::CacheSubscriber) Thread.current[:dead_bro_cache_events] Thread.current[:dead_bro_cache_events] = nil end if defined?(DeadBro::RedisSubscriber) Thread.current[:dead_bro_redis_events] Thread.current[:dead_bro_redis_events] = nil end if defined?(DeadBro::ViewRenderingSubscriber) Thread.current[:dead_bro_view_events] Thread.current[:dead_bro_view_events] = nil end if defined?(DeadBro::LightweightMemoryTracker) Thread.current[:dead_bro_lightweight_memory] Thread.current[:dead_bro_lightweight_memory] = nil end # Clean up HTTP events, ES events, DB connection tracking, and tracking start time Thread.current[:dead_bro_elasticsearch_events] = nil Thread.current[:dead_bro_http_events] = nil Thread.current[:dead_bro_queue_duration_ms] = nil DeadBro::DbConnectionSubscriber.stop_request_tracking if defined?(DeadBro::DbConnectionSubscriber) Thread.current[DeadBro::GcTracker::THREAD_KEY] = nil if defined?(DeadBro::GcTracker) # Bypass stop_request_tracking intentionally — cleanup only, no return value needed here. Thread.current[DeadBro::ArObjectTracker::THREAD_KEY] = nil if defined?(DeadBro::ArObjectTracker) Thread.current[DeadBro::CpuTracker::THREAD_KEY] = nil if defined?(DeadBro::CpuTracker) Thread.current[DeadBro::MemoryPhaseTracker::THREAD_KEY] = nil if defined?(DeadBro::MemoryPhaseTracker) # Safety net: ensure allocation tracing is never left running across # requests (Subscriber normally stops it after analyzing). if Thread.current[:dead_bro_alloc_active] DeadBro::AllocationSourceSampler.stop if defined?(DeadBro::AllocationSourceSampler) end Thread.current[:dead_bro_alloc_active] = nil Thread.current[DeadBro::TRACKING_START_TIME_KEY] = nil end |