Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Cache GraphQL attributes #867

Original file line number Diff line number Diff line change
Expand Up @@ -86,24 +86,60 @@ def 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
{}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a frozen hash and a constant. That will mean only allocating one hash for all "misses"

end
end

def attr_cache
arielvalentin marked this conversation as resolved.
Show resolved Hide resolved
cache_h = Hash.new do |h, k|
h[k] = yield(k)
end
attributes
cache_h.compare_by_identity
cache_h
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@
it 'omits nil attributes for execute_query' do
expected_attributes = {
'graphql.operation.type' => 'query',
'graphql.document' => '{ simpleField }'
'graphql.document' => '{ simpleField }',
'graphql.operation.name' => 'anonymous'
}

SomeGraphQLAppSchema.execute('{ simpleField }')
Expand Down Expand Up @@ -141,7 +142,7 @@
it 'includes attributes using platform types' do
skip if uses_platform_interfaces?
expected_attributes = {
'graphql.field.parent' => 'Car', # type name, not interface
'graphql.field.parent' => 'Vehicle', # interface name, not type
'graphql.field.name' => 'model',
'graphql.lazy' => false
}
Expand Down