Class: EzLogsAgent::Middleware::HttpRequest

Inherits:
Object
  • Object
show all
Defined in:
lib/ez_logs_agent/middleware/http_request.rb

Overview

Rack middleware for capturing HTTP requests as Events.

Responsibilities:

  • Wrap request lifecycle

  • Measure duration

  • Extract HTTP metadata

  • Build Events via EventBuilder

  • Push Events into Buffer

  • Never crash host application

This middleware is purely additive and defensive. It NEVER swallows exceptions from downstream.

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ HttpRequest

Returns a new instance of HttpRequest.



18
19
20
# File 'lib/ez_logs_agent/middleware/http_request.rb', line 18

def initialize(app)
  @app = app
end

Instance Method Details

#call(env) ⇒ Array

Rack interface: call(env)

Parameters:

  • env (Hash)

    Rack environment

Returns:

  • (Array)

    Rack response tuple [status, headers, body]



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
# File 'lib/ez_logs_agent/middleware/http_request.rb', line 25

def call(env)
  # Skip capturing if disabled or path excluded
  return @app.call(env) unless should_capture?(env)

  # Generate correlation_id at request entry
  # This establishes the correlation context for all downstream operations
  # (model callbacks, job enqueues, nested service calls, etc.)
  setup_correlation

  start_time = current_time_ms
  status = nil
  exception = nil
  graphql_response_errors = nil

  begin
    # Call downstream app
    status, headers, body = @app.call(env)

    # SAFETY CRITICAL: We NEVER touch, modify, reassign, or interfere with
    # the response body in any way. The body variable flows through untouched.
    #
    # For GraphQL error detection, we use a READ-ONLY extraction that:
    # - Never reassigns the body variable
    # - Never calls any methods on the body object
    # - Only reads if body is a plain Array of plain Strings (already buffered)
    # - Returns nil on ANY doubt
    #
    # This sacrifices some error detection for absolute safety.
    if graphql_request?(env) && status == 200
      graphql_response_errors = safely_read_graphql_errors(body)
    end

    [status, headers, body]
  rescue => e
    # Capture exception but re-raise after
    exception = e
    raise
  ensure
    # Extract actor after request completes (when controller context is available)
    # This sets Actor.current for inclusion in event context
    extract_and_set_actor(env)

    # Always capture event (success or failure)
    capture_event(env, start_time, status, exception, graphql_response_errors)

    # Clean up correlation and actor context after request completes
    clear_correlation
    clear_actor
  end
end