lib/opentelemetry/instrumentation/graphql/tracers/graphql_tracer.rb in opentelemetry-instrumentation-graphql-0.27.0 vs lib/opentelemetry/instrumentation/graphql/tracers/graphql_tracer.rb in opentelemetry-instrumentation-graphql-0.28.0
- old
+ new
@@ -11,10 +11,12 @@
module GraphQL
module Tracers
# GraphQLTracer contains the OpenTelemetry tracer implementation compatible with
# the GraphQL tracer API
class GraphQLTracer < ::GraphQL::Tracing::PlatformTracing
+ DEFAULT_HASH = {}.freeze
+
self.platform_keys = {
'lex' => 'graphql.lex',
'parse' => 'graphql.parse',
'validate' => 'graphql.validate',
'analyze_query' => 'graphql.analyze_query',
@@ -84,27 +86,63 @@
def config
GraphQL::Instrumentation.instance.config
end
def attributes_for(key, data)
- attributes = {}
case key
- when 'execute_field', 'execute_field_lazy'
- attributes['graphql.field.parent'] = data[:owner]&.graphql_name # owner is the concrete type, not interface
- attributes['graphql.field.name'] = data[:field]&.graphql_name
- attributes['graphql.lazy'] = key == 'execute_field_lazy'
- when 'authorized', 'authorized_lazy'
- attributes['graphql.type.name'] = data[:type]&.graphql_name
- attributes['graphql.lazy'] = key == 'authorized_lazy'
- when 'resolve_type', 'resolve_type_lazy'
- attributes['graphql.type.name'] = data[:type]&.graphql_name
- attributes['graphql.lazy'] = key == 'resolve_type_lazy'
+ when 'execute_field'
+ field_attr_cache = data[:query].context.namespace(:otel_attrs)[:execute_field_attrs] ||= attr_cache do |field|
+ attrs = {}
+ attrs['graphql.field.parent'] = field.owner.graphql_name if field.owner.graphql_name
+ attrs['graphql.field.name'] = field.graphql_name if field.graphql_name
+ attrs['graphql.lazy'] = false
+ attrs.freeze
+ end
+ field_attr_cache[data[:field]]
+ when 'execute_field_lazy'
+ lazy_field_attr_cache = data[:query].context.namespace(:otel_attrs)[:execute_field_lazy_attrs] ||= attr_cache do |field|
+ attrs = {}
+ attrs['graphql.field.parent'] = field.owner.graphql_name if field.owner.graphql_name
+ attrs['graphql.field.name'] = field.graphql_name if field.graphql_name
+ attrs['graphql.lazy'] = true
+ attrs.freeze
+ end
+ lazy_field_attr_cache[data[:field]]
+ when 'authorized', 'resolve_type'
+ type_attrs_cache = data[:context].namespace(:otel_attrs)[:type_attrs] ||= attr_cache do |type|
+ attrs = {}
+ attrs['graphql.type.name'] = type.graphql_name if type.graphql_name
+ attrs['graphql.lazy'] = false
+ attrs.freeze
+ end
+ type_attrs_cache[data[:type]]
+ when 'authorized_lazy', 'resolve_type_lazy'
+ type_lazy_attrs_cache = data[:context].namespace(:otel_attrs)[:type_lazy_attrs] ||= attr_cache do |type|
+ attrs = {}
+ attrs['graphql.type.name'] = type.graphql_name if type.graphql_name
+ attrs['graphql.lazy'] = true
+ attrs.freeze
+ end
+ type_lazy_attrs_cache[data[:type]]
when 'execute_query'
- attributes['graphql.operation.name'] = data[:query].selected_operation_name if data[:query].selected_operation_name
- attributes['graphql.operation.type'] = data[:query].selected_operation.operation_type
- attributes['graphql.document'] = data[:query].query_string
+ attrs = {}
+ attrs['graphql.document'] = data[:query].query_string if data[:query].query_string
+ # rubocop:disable Style/SafeNavigation - using safe navigation creates more objects, we want to avoid this
+ attrs['graphql.operation.type'] = data[:query].selected_operation.operation_type if data[:query].selected_operation && data[:query].selected_operation.operation_type
+ # rubocop:enable Style/SafeNavigation
+ attrs['graphql.operation.name'] = data[:query].selected_operation_name || 'anonymous'
+ attrs.freeze
+ else
+ DEFAULT_HASH
end
- attributes
+ end
+
+ def attr_cache
+ cache_h = Hash.new do |h, k|
+ h[k] = yield(k)
+ end
+ cache_h.compare_by_identity
+ cache_h
end
end
end
end
end