Class: OpenTelemetry::Instrumentation::Rack::Middlewares::EventHandler

Inherits:
Object
  • Object
show all
Includes:
Rack::Events::Abstract
Defined in:
lib/opentelemetry/instrumentation/rack/middlewares/event_handler.rb

Overview

OTel Rack Event Handler

This seeds the root context for this service with the server span as the current_span allowing for callers later in the stack to reference it using Trace.current_span

It also registers the server span in a context dedicated to this instrumentation that users may look up using OpenTelemetry::Instrumentation::Rack.current_span, which makes it possible for users to mutate the span, e.g. add events or update the span name like in the ActionPack instrumentation.

Examples:

Rack App Using BodyProxy

GLOBAL_LOGGER = Logger.new($stderr)
APP_TRACER = OpenTelemetry.tracer_provider.tracer('my-app', '1.0.0')

Rack::Builder.new do
  use Rack::Events, [OpenTelemetry::Instrumentation::Rack::Middlewares::EventHandler.new]
  run lambda { |_arg|
    APP_TRACER.in_span('hello-world') do |_span|
      body = Rack::BodyProxy.new(['hello world!']) do
        rack_span = OpenTelemetry::Instrumentation::Rack.current_span
        GLOBAL_LOGGER.info("otel.trace_id=#{rack_span.context.hex_trace_id} otel.span_id=#{rack_span.context.hex_span_id}")
      end
      [200, { 'Content-Type' => 'text/plain' }, body]
    end
  }
end

See Also:

  • Rack::Events
  • OpenTelemetry::Instrumentation::Rack.current_span

Constant Summary collapse

TOKENS_KEY =
'otel.context.tokens'
GOOD_HTTP_STATUSES =
(100..499)

Instance Method Summary collapse

Instance Method Details

#on_commit(request, response) ⇒ void

This method returns an undefined value.

Optionally adds debugging response headers injected from #response_propagators

Parameters:

  • The (Rack::Request)

    current HTTP request

  • This (Rack::Response)

    current HTTP response



69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/opentelemetry/instrumentation/rack/middlewares/event_handler.rb', line 69

def on_commit(request, response)
  span = OpenTelemetry::Instrumentation::Rack.current_span
  return unless span.recording?

  response_propagators&.each do |propagator|
    propagator.inject(response.headers)
  rescue StandardError => e
    OpenTelemetry.handle_error(message: 'Unable to inject response propagation headers', exception: e)
  end
rescue StandardError => e
  OpenTelemetry.handle_error(exception: e)
end

#on_error(request, _, error) ⇒ Object

Note:

does nothing if the span is a non-recording span

Records Unexpected Exceptions on the Rack span and set the Span Status to Error

Parameters:

  • The (Rack::Request)

    current HTTP request

  • The (Rack::Response)

    current HTTP response

  • An (Exception)

    unxpected error raised by the application



88
89
90
91
92
93
94
95
96
# File 'lib/opentelemetry/instrumentation/rack/middlewares/event_handler.rb', line 88

def on_error(request, _, error)
  span = OpenTelemetry::Instrumentation::Rack.current_span
  return unless span.recording?

  span.record_exception(error)
  span.status = OpenTelemetry::Trace::Status.error(error.class.name)
rescue StandardError => e
  OpenTelemetry.handle_error(exception: e)
end

#on_finish(request, response) ⇒ Object

Note:

does nothing if the span is a non-recording span

Finishes the span making it eligible to be exported and cleans up existing contexts

Parameters:

  • The (Rack::Request)

    current HTTP request

  • The (Rack::Response)

    current HTTP response



103
104
105
106
107
108
109
110
111
112
# File 'lib/opentelemetry/instrumentation/rack/middlewares/event_handler.rb', line 103

def on_finish(request, response)
  span = OpenTelemetry::Instrumentation::Rack.current_span
  return unless span.recording?

  add_response_attributes(span, response) if response
rescue StandardError => e
  OpenTelemetry.handle_error(exception: e)
ensure
  detach_contexts(request)
end

#on_start(request, _) ⇒ void

This method returns an undefined value.

Creates a server span for this current request using the incoming parent context and registers them as the current_span

Parameters:

  • The (Rack::Request)

    current HTTP request

  • This (Rack::Response)

    is nil in practice



54
55
56
57
58
59
60
61
62
# File 'lib/opentelemetry/instrumentation/rack/middlewares/event_handler.rb', line 54

def on_start(request, _)
  return if untraced_request?(request.env)

  parent_context = extract_remote_context(request)
  span = create_span(parent_context, request)
  request.env[TOKENS_KEY] = register_current_span(span)
rescue StandardError => e
  OpenTelemetry.handle_error(exception: e)
end