lib/opentelemetry/instrumentation/rack/instrumentation.rb in opentelemetry-instrumentation-rack-0.22.1 vs lib/opentelemetry/instrumentation/rack/instrumentation.rb in opentelemetry-instrumentation-rack-0.23.0

- old
+ new

@@ -10,57 +10,74 @@ module Instrumentation module Rack # The Instrumentation class contains logic to detect and install the Rack # instrumentation class Instrumentation < OpenTelemetry::Instrumentation::Base - install do |config| + install do |_config| require_dependencies - - retain_middleware_names if config[:retain_middleware_names] end present do defined?(::Rack) end option :allowed_request_headers, default: [], validate: :array option :allowed_response_headers, default: [], validate: :array option :application, default: nil, validate: :callable option :record_frontend_span, default: false, validate: :boolean - option :retain_middleware_names, default: false, validate: :boolean option :untraced_endpoints, default: [], validate: :array option :url_quantization, default: nil, validate: :callable option :untraced_requests, default: nil, validate: :callable option :response_propagators, default: [], validate: :array + # This option is only valid for applicaitons using Rack 2.0 or greater + option :use_rack_events, default: false, validate: :boolean + # Temporary Helper for Sinatra and ActionPack middleware to use during installation + # + # @example Default usage + # Rack::Builder.new do + # use *OpenTelemetry::Instrumentation::Rack::Instrumenation.instance.middleware_args + # run lambda { |_arg| [200, { 'Content-Type' => 'text/plain' }, body] } + # end + # @return [Array] consisting of a middleware and arguments used in rack builders + def middleware_args + if config.fetch(:use_rack_events, false) == true && defined?(::Rack::Events) + [::Rack::Events, [OpenTelemetry::Instrumentation::Rack::Middlewares::EventHandler.new]] + else + [OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware] + end + end + private def require_dependencies + require_relative 'middlewares/event_handler' if defined?(Rack::Events) require_relative 'middlewares/tracer_middleware' end - MissingApplicationError = Class.new(StandardError) - - # intercept all middleware-compatible calls, retain class name - def retain_middleware_names - next_middleware = config[:application] - raise MissingApplicationError unless next_middleware - - while next_middleware - if next_middleware.respond_to?(:call) - next_middleware.singleton_class.class_eval do - alias_method :__call, :call - - def call(env) - env['RESPONSE_MIDDLEWARE'] = self.class.to_s - __call(env) - end - end + def config_options(user_config) + config = super(user_config) + config[:allowed_rack_request_headers] = config[:allowed_request_headers].compact.each_with_object({}) do |header, memo| + key = header.to_s.upcase.gsub(/[-\s]/, '_') + case key + when 'CONTENT_TYPE', 'CONTENT_LENGTH' + memo[key] = build_attribute_name('http.request.header.', header) + else + memo["HTTP_#{key}"] = build_attribute_name('http.request.header.', header) end + end - next_middleware = next_middleware.instance_variable_defined?('@app') && - next_middleware.instance_variable_get('@app') + config[:allowed_rack_response_headers] = config[:allowed_response_headers].each_with_object({}) do |header, memo| + memo[header] = build_attribute_name('http.response.header.', header) + memo[header.to_s.upcase] = build_attribute_name('http.response.header.', header) end + + config[:untraced_endpoints]&.compact! + config + end + + def build_attribute_name(prefix, suffix) + prefix + suffix.to_s.downcase.gsub(/[-\s]/, '_') end end end end end