Class: BrainzLab::Rails::Middleware
- Inherits:
-
Object
- Object
- BrainzLab::Rails::Middleware
- Defined in:
- lib/brainzlab/rails/railtie.rb
Overview
Middleware for request context
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app) ⇒ Middleware
constructor
A new instance of Middleware.
- #record_pulse_trace(request, started_at, status) ⇒ Object
- #should_trace_request?(request) ⇒ Boolean
Constructor Details
#initialize(app) ⇒ Middleware
Returns a new instance of Middleware.
200 201 202 |
# File 'lib/brainzlab/rails/railtie.rb', line 200 def initialize(app) @app = app end |
Instance Method Details
#call(env) ⇒ Object
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/brainzlab/rails/railtie.rb', line 204 def call(env) request = ActionDispatch::Request.new(env) started_at = Time.now.utc # Set request context context = BrainzLab::Context.current request_id = request.request_id || env['action_dispatch.request_id'] context.request_id = request_id # Store request_id in thread local for log subscriber Thread.current[:brainzlab_request_id] = request_id # Capture session_id - access session to ensure it's loaded if request.session.respond_to?(:id) # Force session load by accessing it session_id = begin request.session.id rescue StandardError nil end context.session_id = session_id.to_s if session_id.present? end # Capture full request info for Reflex context.request_method = request.request_method context.request_path = request.path context.request_url = request.url context.request_params = begin filter_params(request.params.to_h) rescue ActionDispatch::Http::Parameters::ParseError {} end context.request_headers = extract_headers(env) # Add breadcrumb for request start BrainzLab::Reflex.( "#{request.request_method} #{request.path}", category: 'http.request', level: :info, data: { url: request.url } ) # Add request data to Recall context context.set_context( path: request.path, method: request.request_method, ip: request.remote_ip, user_agent: request.user_agent ) # Extract distributed tracing context from incoming request headers parent_context = BrainzLab::Pulse.extract!(env) # Start Pulse trace if enabled and path not excluded should_trace = should_trace_request?(request) if should_trace # Initialize spans array for this request Thread.current[:brainzlab_pulse_spans] = [] Thread.current[:brainzlab_pulse_breakdown] = nil BrainzLab::Pulse.start_trace( "#{request.request_method} #{request.path}", kind: 'request', parent_context: parent_context ) end status, headers, response = @app.call(env) # Add breadcrumb for response BrainzLab::Reflex.( "Response #{status}", category: 'http.response', level: status >= 400 ? :error : :info, data: { status: status } ) [status, headers, response] rescue StandardError => e # Record error in Pulse trace if should_trace BrainzLab::Pulse.finish_trace( error: true, error_class: e.class.name, error_message: e. ) end raise ensure # Finish Pulse trace for successful requests record_pulse_trace(request, started_at, status) if should_trace && !$ERROR_INFO Thread.current[:brainzlab_request_id] = nil BrainzLab::Context.clear! BrainzLab::Pulse::Propagation.clear! end |
#record_pulse_trace(request, started_at, status) ⇒ Object
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/brainzlab/rails/railtie.rb', line 316 def record_pulse_trace(request, started_at, status) ended_at = Time.now.utc context = BrainzLab::Context.current # Collect spans from instrumentation spans = Thread.current[:brainzlab_pulse_spans] || [] breakdown = Thread.current[:brainzlab_pulse_breakdown] || {} # Format spans for API formatted_spans = spans.map do |span| { span_id: span[:span_id], name: span[:name], kind: span[:kind], started_at: (span[:started_at]), ended_at: (span[:ended_at]), duration_ms: span[:duration_ms], data: span[:data] } end BrainzLab::Pulse.record_trace( "#{request.request_method} #{request.path}", kind: 'request', started_at: started_at, ended_at: ended_at, request_id: context.request_id, request_method: request.request_method, request_path: request.path, controller: context.controller, action: context.action, status: status, error: status.to_i >= 500, view_ms: breakdown[:view_ms], db_ms: breakdown[:db_ms], spans: formatted_spans ) rescue StandardError => e BrainzLab.configuration.logger&.error("[BrainzLab::Pulse] Failed to record trace: #{e.}") ensure # Clean up thread locals Thread.current[:brainzlab_pulse_spans] = nil Thread.current[:brainzlab_pulse_breakdown] = nil end |
#should_trace_request?(request) ⇒ Boolean
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/brainzlab/rails/railtie.rb', line 300 def should_trace_request?(request) return false unless BrainzLab.configuration.pulse_enabled excluded = BrainzLab.configuration.pulse_excluded_paths || [] path = request.path # Check if path matches any excluded pattern excluded.none? do |pattern| if pattern.include?('*') File.fnmatch?(pattern, path) else path.start_with?(pattern) end end end |