diff --git a/lib/graphql/tracing.rb b/lib/graphql/tracing.rb index e962e9cde1..04ecb58524 100644 --- a/lib/graphql/tracing.rb +++ b/lib/graphql/tracing.rb @@ -1,38 +1,36 @@ # frozen_string_literal: true -require "graphql/tracing/trace" -require "graphql/tracing/legacy_trace" -require "graphql/tracing/legacy_hooks_trace" -# Legacy tracing: -require "graphql/tracing/active_support_notifications_tracing" -require "graphql/tracing/platform_tracing" -require "graphql/tracing/appoptics_tracing" -require "graphql/tracing/appsignal_tracing" -require "graphql/tracing/data_dog_tracing" -require "graphql/tracing/new_relic_tracing" -require "graphql/tracing/scout_tracing" -require "graphql/tracing/statsd_tracing" -require "graphql/tracing/prometheus_tracing" - -# New Tracing: -require "graphql/tracing/active_support_notifications_trace" -require "graphql/tracing/platform_trace" -require "graphql/tracing/appoptics_trace" -require "graphql/tracing/appsignal_trace" -require "graphql/tracing/data_dog_trace" -require "graphql/tracing/new_relic_trace" -require "graphql/tracing/notifications_trace" -require "graphql/tracing/sentry_trace" -require "graphql/tracing/scout_trace" -require "graphql/tracing/statsd_trace" -require "graphql/tracing/prometheus_trace" -if defined?(PrometheusExporter::Server) - require "graphql/tracing/prometheus_trace/graphql_collector" -end module GraphQL module Tracing - NullTrace = Trace.new + autoload :Trace, "graphql/tracing/trace" + autoload :CallLegacyTracers, "graphql/tracing/call_legacy_tracers" + autoload :LegacyTrace, "graphql/tracing/legacy_trace" + autoload :LegacyHooksTrace, "graphql/tracing/legacy_hooks_trace" + autoload :NullTrace, "graphql/tracing/null_trace" + + autoload :ActiveSupportNotificationsTracing, "graphql/tracing/active_support_notifications_tracing" + autoload :PlatformTracing, "graphql/tracing/platform_tracing" + autoload :AppOpticsTracing, "graphql/tracing/appoptics_tracing" + autoload :AppsignalTracing, "graphql/tracing/appsignal_tracing" + autoload :DataDogTracing, "graphql/tracing/data_dog_tracing" + autoload :NewRelicTracing, "graphql/tracing/new_relic_tracing" + autoload :NotificationsTracing, "graphql/tracing/notifications_tracing" + autoload :ScoutTracing, "graphql/tracing/scout_tracing" + autoload :StatsdTracing, "graphql/tracing/statsd_tracing" + autoload :PrometheusTracing, "graphql/tracing/prometheus_tracing" + + autoload :ActiveSupportNotificationsTrace, "graphql/tracing/active_support_notifications_trace" + autoload :PlatformTrace, "graphql/tracing/platform_trace" + autoload :AppOpticsTrace, "graphql/tracing/appoptics_trace" + autoload :AppsignalTrace, "graphql/tracing/appsignal_trace" + autoload :DataDogTrace, "graphql/tracing/data_dog_trace" + autoload :NewRelicTrace, "graphql/tracing/new_relic_trace" + autoload :NotificationsTrace, "graphql/tracing/notifications_trace" + autoload :SentryTrace, "graphql/tracing/sentry_trace" + autoload :ScoutTrace, "graphql/tracing/scout_trace" + autoload :StatsdTrace, "graphql/tracing/statsd_trace" + autoload :PrometheusTrace, "graphql/tracing/prometheus_trace" # Objects may include traceable to gain a `.trace(...)` method. # The object must have a `@tracers` ivar of type `Array<<#trace(k, d, &b)>>`. diff --git a/lib/graphql/tracing/active_support_notifications_trace.rb b/lib/graphql/tracing/active_support_notifications_trace.rb index 57b2ed3004..26b6ce6844 100644 --- a/lib/graphql/tracing/active_support_notifications_trace.rb +++ b/lib/graphql/tracing/active_support_notifications_trace.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'graphql/tracing/notifications_trace' +require "graphql/tracing/notifications_trace" module GraphQL module Tracing diff --git a/lib/graphql/tracing/active_support_notifications_tracing.rb b/lib/graphql/tracing/active_support_notifications_tracing.rb index 52fbc23c5e..4f60c63a34 100644 --- a/lib/graphql/tracing/active_support_notifications_tracing.rb +++ b/lib/graphql/tracing/active_support_notifications_tracing.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'graphql/tracing/notifications_tracing' +require "graphql/tracing/notifications_tracing" module GraphQL module Tracing diff --git a/lib/graphql/tracing/appoptics_trace.rb b/lib/graphql/tracing/appoptics_trace.rb index 2ea36c59be..4a950ecb61 100644 --- a/lib/graphql/tracing/appoptics_trace.rb +++ b/lib/graphql/tracing/appoptics_trace.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing diff --git a/lib/graphql/tracing/appoptics_tracing.rb b/lib/graphql/tracing/appoptics_tracing.rb index e24d1a06d1..3ecebcfbfe 100644 --- a/lib/graphql/tracing/appoptics_tracing.rb +++ b/lib/graphql/tracing/appoptics_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing diff --git a/lib/graphql/tracing/appsignal_trace.rb b/lib/graphql/tracing/appsignal_trace.rb index 0f639dc1da..980ee12805 100644 --- a/lib/graphql/tracing/appsignal_trace.rb +++ b/lib/graphql/tracing/appsignal_trace.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing module AppsignalTrace diff --git a/lib/graphql/tracing/appsignal_tracing.rb b/lib/graphql/tracing/appsignal_tracing.rb index 413cd9711e..cd552ee71a 100644 --- a/lib/graphql/tracing/appsignal_tracing.rb +++ b/lib/graphql/tracing/appsignal_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing class AppsignalTracing < PlatformTracing diff --git a/lib/graphql/tracing/call_legacy_tracers.rb b/lib/graphql/tracing/call_legacy_tracers.rb new file mode 100644 index 0000000000..c42b99fa18 --- /dev/null +++ b/lib/graphql/tracing/call_legacy_tracers.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module GraphQL + module Tracing + # This trace class calls legacy-style tracer with payload hashes. + # New-style `trace_with` modules significantly reduce the overhead of tracing, + # but that advantage is lost when legacy-style tracers are also used (since the payload hashes are still constructed). + module CallLegacyTracers + def lex(query_string:) + (@multiplex || @query).trace("lex", { query_string: query_string }) { super } + end + + def parse(query_string:) + (@multiplex || @query).trace("parse", { query_string: query_string }) { super } + end + + def validate(query:, validate:) + query.trace("validate", { validate: validate, query: query }) { super } + end + + def analyze_multiplex(multiplex:) + multiplex.trace("analyze_multiplex", { multiplex: multiplex }) { super } + end + + def analyze_query(query:) + query.trace("analyze_query", { query: query }) { super } + end + + def execute_multiplex(multiplex:) + multiplex.trace("execute_multiplex", { multiplex: multiplex }) { super } + end + + def execute_query(query:) + query.trace("execute_query", { query: query }) { super } + end + + def execute_query_lazy(query:, multiplex:) + multiplex.trace("execute_query_lazy", { multiplex: multiplex, query: query }) { super } + end + + def execute_field(field:, query:, ast_node:, arguments:, object:) + query.trace("execute_field", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super } + end + + def execute_field_lazy(field:, query:, ast_node:, arguments:, object:) + query.trace("execute_field_lazy", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super } + end + + def authorized(query:, type:, object:) + query.trace("authorized", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } + end + + def authorized_lazy(query:, type:, object:) + query.trace("authorized_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } + end + + def resolve_type(query:, type:, object:) + query.trace("resolve_type", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } + end + + def resolve_type_lazy(query:, type:, object:) + query.trace("resolve_type_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } + end + end + end +end diff --git a/lib/graphql/tracing/data_dog_trace.rb b/lib/graphql/tracing/data_dog_trace.rb index 33c08850a3..c37d2aa4a4 100644 --- a/lib/graphql/tracing/data_dog_trace.rb +++ b/lib/graphql/tracing/data_dog_trace.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing module DataDogTrace diff --git a/lib/graphql/tracing/data_dog_tracing.rb b/lib/graphql/tracing/data_dog_tracing.rb index ef3d2fc975..b764c2ba26 100644 --- a/lib/graphql/tracing/data_dog_tracing.rb +++ b/lib/graphql/tracing/data_dog_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing class DataDogTracing < PlatformTracing diff --git a/lib/graphql/tracing/legacy_hooks_trace.rb b/lib/graphql/tracing/legacy_hooks_trace.rb index ee488019a0..d23fe190a1 100644 --- a/lib/graphql/tracing/legacy_hooks_trace.rb +++ b/lib/graphql/tracing/legacy_hooks_trace.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + module GraphQL module Tracing module LegacyHooksTrace diff --git a/lib/graphql/tracing/legacy_trace.rb b/lib/graphql/tracing/legacy_trace.rb index 0663d37922..e4b8207440 100644 --- a/lib/graphql/tracing/legacy_trace.rb +++ b/lib/graphql/tracing/legacy_trace.rb @@ -1,67 +1,10 @@ # frozen_string_literal: true -module GraphQL - module Tracing - # This trace class calls legacy-style tracer with payload hashes. - # New-style `trace_with` modules significantly reduce the overhead of tracing, - # but that advantage is lost when legacy-style tracers are also used (since the payload hashes are still constructed). - module CallLegacyTracers - def lex(query_string:) - (@multiplex || @query).trace("lex", { query_string: query_string }) { super } - end - - def parse(query_string:) - (@multiplex || @query).trace("parse", { query_string: query_string }) { super } - end - - def validate(query:, validate:) - query.trace("validate", { validate: validate, query: query }) { super } - end - - def analyze_multiplex(multiplex:) - multiplex.trace("analyze_multiplex", { multiplex: multiplex }) { super } - end - - def analyze_query(query:) - query.trace("analyze_query", { query: query }) { super } - end - - def execute_multiplex(multiplex:) - multiplex.trace("execute_multiplex", { multiplex: multiplex }) { super } - end - - def execute_query(query:) - query.trace("execute_query", { query: query }) { super } - end - - def execute_query_lazy(query:, multiplex:) - multiplex.trace("execute_query_lazy", { multiplex: multiplex, query: query }) { super } - end - def execute_field(field:, query:, ast_node:, arguments:, object:) - query.trace("execute_field", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super } - end - - def execute_field_lazy(field:, query:, ast_node:, arguments:, object:) - query.trace("execute_field_lazy", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super } - end - - def authorized(query:, type:, object:) - query.trace("authorized", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } - end - - def authorized_lazy(query:, type:, object:) - query.trace("authorized_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } - end - - def resolve_type(query:, type:, object:) - query.trace("resolve_type", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } - end - - def resolve_type_lazy(query:, type:, object:) - query.trace("resolve_type_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super } - end - end +require "graphql/tracing/trace" +require "graphql/tracing/call_legacy_tracers" +module GraphQL + module Tracing class LegacyTrace < Trace include CallLegacyTracers end diff --git a/lib/graphql/tracing/new_relic_trace.rb b/lib/graphql/tracing/new_relic_trace.rb index 0b455d5231..386ff5d745 100644 --- a/lib/graphql/tracing/new_relic_trace.rb +++ b/lib/graphql/tracing/new_relic_trace.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing module NewRelicTrace diff --git a/lib/graphql/tracing/new_relic_tracing.rb b/lib/graphql/tracing/new_relic_tracing.rb index cf7431728e..a2d05b5203 100644 --- a/lib/graphql/tracing/new_relic_tracing.rb +++ b/lib/graphql/tracing/new_relic_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing class NewRelicTracing < PlatformTracing diff --git a/lib/graphql/tracing/notifications_tracing.rb b/lib/graphql/tracing/notifications_tracing.rb index 9e50f18e46..c8ad4f8861 100644 --- a/lib/graphql/tracing/notifications_tracing.rb +++ b/lib/graphql/tracing/notifications_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing # This implementation forwards events to a notification handler (i.e. diff --git a/lib/graphql/tracing/null_trace.rb b/lib/graphql/tracing/null_trace.rb new file mode 100644 index 0000000000..26e2b27695 --- /dev/null +++ b/lib/graphql/tracing/null_trace.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require "graphql/tracing/trace" + +module GraphQL + module Tracing + NullTrace = Trace.new + end +end diff --git a/lib/graphql/tracing/prometheus_trace.rb b/lib/graphql/tracing/prometheus_trace.rb index 8b7f8a57d9..8d33156a94 100644 --- a/lib/graphql/tracing/prometheus_trace.rb +++ b/lib/graphql/tracing/prometheus_trace.rb @@ -1,8 +1,13 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing module PrometheusTrace + if defined?(PrometheusExporter::Server) + autoload :GraphQLCollector, "graphql/tracing/prometheus_trace/graphql_collector" + end include PlatformTrace def initialize(client: PrometheusExporter::Client.default, keys_whitelist: ["execute_field", "execute_field_lazy"], collector_type: "graphql", **rest) diff --git a/lib/graphql/tracing/prometheus_trace/graphql_collector.rb b/lib/graphql/tracing/prometheus_trace/graphql_collector.rb index e351a639c5..87304af015 100644 --- a/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +++ b/lib/graphql/tracing/prometheus_trace/graphql_collector.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing" + module GraphQL module Tracing module PrometheusTrace diff --git a/lib/graphql/tracing/prometheus_tracing.rb b/lib/graphql/tracing/prometheus_tracing.rb index e76da521c1..a10a0bc600 100644 --- a/lib/graphql/tracing/prometheus_tracing.rb +++ b/lib/graphql/tracing/prometheus_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing class PrometheusTracing < PlatformTracing diff --git a/lib/graphql/tracing/scout_trace.rb b/lib/graphql/tracing/scout_trace.rb index ac42d795e1..d35819f63b 100644 --- a/lib/graphql/tracing/scout_trace.rb +++ b/lib/graphql/tracing/scout_trace.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing module ScoutTrace diff --git a/lib/graphql/tracing/scout_tracing.rb b/lib/graphql/tracing/scout_tracing.rb index 2b5fecaf6a..c3b20b7ee9 100644 --- a/lib/graphql/tracing/scout_tracing.rb +++ b/lib/graphql/tracing/scout_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing class ScoutTracing < PlatformTracing diff --git a/lib/graphql/tracing/sentry_trace.rb b/lib/graphql/tracing/sentry_trace.rb index f37cea19c2..262cd25eb7 100644 --- a/lib/graphql/tracing/sentry_trace.rb +++ b/lib/graphql/tracing/sentry_trace.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing module SentryTrace diff --git a/lib/graphql/tracing/statsd_trace.rb b/lib/graphql/tracing/statsd_trace.rb index b5121b5753..56ce54631f 100644 --- a/lib/graphql/tracing/statsd_trace.rb +++ b/lib/graphql/tracing/statsd_trace.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_trace" + module GraphQL module Tracing module StatsdTrace diff --git a/lib/graphql/tracing/statsd_tracing.rb b/lib/graphql/tracing/statsd_tracing.rb index 28e1a30772..2b1ff10c8d 100644 --- a/lib/graphql/tracing/statsd_tracing.rb +++ b/lib/graphql/tracing/statsd_tracing.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "graphql/tracing/platform_tracing" + module GraphQL module Tracing class StatsdTracing < PlatformTracing diff --git a/lib/graphql/tracing/trace.rb b/lib/graphql/tracing/trace.rb index 8834c2d59c..ef9a3722a8 100644 --- a/lib/graphql/tracing/trace.rb +++ b/lib/graphql/tracing/trace.rb @@ -1,4 +1,7 @@ # frozen_string_literal: true + +require "graphql/tracing" + module GraphQL module Tracing # This is the base class for a `trace` instance whose methods are called during query execution. diff --git a/spec/graphql/autoload_spec.rb b/spec/graphql/autoload_spec.rb index f9313acb0f..fd58b8e9f4 100644 --- a/spec/graphql/autoload_spec.rb +++ b/spec/graphql/autoload_spec.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "spec_helper" +require "open3" describe GraphQL::Autoload do module LazyModule @@ -45,4 +46,18 @@ def self.eager_load! assert EagerModule::NestedEagerModule::NestedEagerClass end end + + describe "loading nested files in the repo" do + it "can load them individually" do + files_to_load = Dir.glob("lib/**/tracing/*.rb") + assert_equal 26, files_to_load.size, "It found all the expected files" + files_to_load.each do |file| + require_path = file.sub("lib/", "").sub(".rb", "") + stderr_and_stdout, _status = Open3.capture2e("ruby -Ilib -e 'require \"#{require_path}\"'") + assert_equal "", stderr_and_stdout, "It loads #{require_path.inspect} in isolation" + stderr_and_stdout, _status = Open3.capture2e("ruby -Ilib -e 'require \"graphql\"; require \"#{require_path}\"'") + assert_equal "", stderr_and_stdout, "It loads #{require_path.inspect} after loading graphql" + end + end + end end