lib/elastic_apm/graphql.rb (55 lines of code) (raw):
# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# frozen_string_literal: true
module ElasticAPM
# @api private
module GraphQL
TYPE = 'app'
SUBTYPE = 'graphql'
PREFIX = 'GraphQL: '
UNNAMED = '[unnamed]'
MULTIPLE_QUERIES = '[multiple-queries]'
CONCATENATOR = '+'
MAX_NUMBER_OF_QUERIES_FOR_NAME = 5
KEYS_TO_NAME = {
'lex' => 'graphql.lex',
'parse' => 'graphql.parse',
'validate' => 'graphql.validate',
'analyze_multiplex' => 'graphql.analyze_multiplex',
'analyze_query' => 'graphql.analyze_query',
'execute_multiplex' => 'graphql.execute_multiplex',
'execute_query' => 'graphql.execute_query',
'execute_query_lazy' => 'graphql.execute_query_lazy',
'authorized_lazy' => 'graphql.authorized_lazy',
'resolve_type' => 'graphql.resolve_type',
'resolve_type_lazy' => 'graphql.resolve_type_lazy'
# These are available but deliberately left out as they are mostly noise.
# "execute_field" => "graphql.execute_field",
# "execute_field_lazy" => "graphql.execute_field_lazy",
# "authorized" => "graphql.authorized",
}.freeze
# rubocop:disable Style/ExplicitBlockArgument
def self.trace(key, data)
return yield unless KEYS_TO_NAME.key?(key)
return yield unless (transaction = ElasticAPM.current_transaction)
if key == 'execute_query'
transaction.name =
"#{PREFIX}#{query_name(data[:query])}"
end
results =
ElasticAPM.with_span(
KEYS_TO_NAME.fetch(key, key),
TYPE, subtype: SUBTYPE, action: key
) { yield }
if key == 'execute_multiplex'
transaction.name = "#{PREFIX}#{concat_names(results)}"
end
results
end
# rubocop:enable Style/ExplicitBlockArgument
class << self
private
def query_name(query)
query.operation_name || UNNAMED
end
def concat_names(results)
if results.length > MAX_NUMBER_OF_QUERIES_FOR_NAME
return MULTIPLE_QUERIES
end
results.map do |result|
query_name(result.query)
end.join(CONCATENATOR)
end
end
end
end