diff --git a/instrumentation/grape/lib/opentelemetry/instrumentation/grape/event_handler.rb b/instrumentation/grape/lib/opentelemetry/instrumentation/grape/event_handler.rb index 1e5d2b9e2d..052ee1a538 100644 --- a/instrumentation/grape/lib/opentelemetry/instrumentation/grape/event_handler.rb +++ b/instrumentation/grape/lib/opentelemetry/instrumentation/grape/event_handler.rb @@ -93,7 +93,8 @@ def path(endpoint) return '' unless endpoint.routes namespace = endpoint.routes.first.namespace - version = endpoint.routes.first.options[:version]&.to_s + version = endpoint.routes.first.options[:version] + version = config[:version_format].call(version) prefix = endpoint.routes.first.options[:prefix]&.to_s parts = [prefix, version] + namespace.split('/') + endpoint.options[:path] parts.reject { |p| p.nil? || p.empty? || p.eql?('/') }.join('/').prepend('/') @@ -110,6 +111,10 @@ def formatter_type(formatter) def built_in_grape_formatter?(formatter) formatter.respond_to?(:name) && formatter.name.include?('Grape::Formatter') end + + def config + Grape::Instrumentation.instance.config + end end end end diff --git a/instrumentation/grape/lib/opentelemetry/instrumentation/grape/instrumentation.rb b/instrumentation/grape/lib/opentelemetry/instrumentation/grape/instrumentation.rb index 66c89c23a5..5b2d62e392 100644 --- a/instrumentation/grape/lib/opentelemetry/instrumentation/grape/instrumentation.rb +++ b/instrumentation/grape/lib/opentelemetry/instrumentation/grape/instrumentation.rb @@ -38,6 +38,7 @@ class Instrumentation < OpenTelemetry::Instrumentation::Base option :ignored_events, default: [], validate: :array option :install_rack, default: true, validate: :boolean + option :version_format, default: ->(version) { version&.to_s }, validate: :callable private diff --git a/instrumentation/grape/test/opentelemetry/instrumentation/grape_test.rb b/instrumentation/grape/test/opentelemetry/instrumentation/grape_test.rb index 782dcc8d5a..75341bc89f 100644 --- a/instrumentation/grape/test/opentelemetry/instrumentation/grape_test.rb +++ b/instrumentation/grape/test/opentelemetry/instrumentation/grape_test.rb @@ -469,5 +469,76 @@ class BasicAPI < Grape::API end end end + + describe 'when with multiple version in api' do + class BasicAPI < Grape::API + version 'v5', 'v6', 'v7', using: :path + format :json + + get :hello do + { message: 'Hello, world!' } + end + end + + let(:app) do + builder = Rack::Builder.app do + run BasicAPI + end + Rack::MockRequest.new(builder) + end + + let(:request_path) { '/v5/hello' } + let(:expected_span_name) { 'HTTP GET /hello' } + + describe 'default version_format' do + let(:config) { { install_rack: false } } + + let(:app) do + build_rack_app(BasicAPI) + end + + before do + OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.install + end + + it 'creates a span' do + app.get request_path + _(exporter.finished_spans.first.attributes).must_equal( + 'code.namespace' => 'BasicAPI', + 'http.method' => 'GET', + 'http.host' => 'unknown', + 'http.scheme' => 'http', + 'http.target' => '/v5/hello', + 'http.route' => '/["v5", "v6", "v7"]/hello', + 'http.status_code' => 200 + ) + end + end + + describe 'customized version_format' do + let(:config) { { install_rack: false, version_format: ->(version) { version.is_a?(Array) ? "{#{version.join('|')}}" : version.to_s } } } + + let(:app) do + build_rack_app(BasicAPI) + end + + before do + OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.install + end + + it 'creates a span' do + app.get request_path + _(exporter.finished_spans.first.attributes).must_equal( + 'code.namespace' => 'BasicAPI', + 'http.method' => 'GET', + 'http.host' => 'unknown', + 'http.scheme' => 'http', + 'http.target' => '/v5/hello', + 'http.route' => '/{v5|v6|v7}/hello', + 'http.status_code' => 200 + ) + end + end + end end end