graphql 2.4.16 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/graphql/execution/interpreter.rb +0 -3
- data/lib/graphql/query.rb +0 -3
- data/lib/graphql/static_validation/all_rules.rb +1 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +7 -0
- data/lib/graphql/tracing/appoptics_tracing.rb +5 -0
- data/lib/graphql/tracing/appsignal_trace.rb +26 -61
- data/lib/graphql/tracing/data_dog_trace.rb +41 -164
- data/lib/graphql/tracing/monitor_trace.rb +285 -0
- data/lib/graphql/tracing/new_relic_trace.rb +34 -166
- data/lib/graphql/tracing/notifications_trace.rb +181 -37
- data/lib/graphql/tracing/perfetto_trace.rb +11 -14
- data/lib/graphql/tracing/prometheus_trace.rb +47 -74
- data/lib/graphql/tracing/scout_trace.rb +25 -59
- data/lib/graphql/tracing/sentry_trace.rb +57 -99
- data/lib/graphql/tracing/statsd_trace.rb +24 -47
- data/lib/graphql/tracing/trace.rb +0 -17
- data/lib/graphql/tracing.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- metadata +4 -2
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
@@ -1,121 +1,79 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "graphql/tracing/
|
3
|
+
require "graphql/tracing/monitor_trace"
|
4
4
|
|
5
5
|
module GraphQL
|
6
6
|
module Tracing
|
7
7
|
# A tracer for reporting GraphQL-Ruby times to Sentry.
|
8
|
+
#
|
8
9
|
# @example Installing the tracer
|
9
10
|
# class MySchema < GraphQL::Schema
|
10
11
|
# trace_with GraphQL::Tracing::SentryTrace
|
11
12
|
# end
|
13
|
+
# @see MonitorTrace Configuration Options in the parent module
|
14
|
+
SentryTrace = MonitorTrace.create_module("sentry")
|
12
15
|
module SentryTrace
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
16
|
+
class SentryMonitor < MonitorTrace::Monitor
|
17
|
+
def instrument(keyword, object)
|
18
|
+
return yield unless Sentry.initialized?
|
19
|
+
|
20
|
+
platform_key = name_for(keyword, object)
|
21
|
+
|
22
|
+
Sentry.with_child_span(op: platform_key, start_timestamp: Sentry.utc_now.to_f) do |span|
|
23
|
+
result = yield
|
24
|
+
return result unless span
|
25
|
+
|
26
|
+
span.finish
|
27
|
+
if keyword == :execute
|
28
|
+
queries = object.queries
|
29
|
+
operation_names = queries.map{|q| operation_name(q) }
|
30
|
+
span.set_description(operation_names.join(", "))
|
31
|
+
|
32
|
+
if queries.size == 1
|
33
|
+
query = queries.first
|
34
|
+
set_this_txn_name = query.context[:set_sentry_transaction_name]
|
35
|
+
if set_this_txn_name == true || (set_this_txn_name.nil? && @set_transaction_name)
|
36
|
+
Sentry.configure_scope do |scope|
|
37
|
+
scope.set_transaction_name(transaction_name(query))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
span.set_data('graphql.document', query.query_string)
|
41
|
+
if query.selected_operation_name
|
42
|
+
span.set_data('graphql.operation.name', query.selected_operation_name)
|
43
|
+
end
|
44
|
+
span.set_data('graphql.operation.type', query.selected_operation.operation_type)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
result
|
28
49
|
end
|
29
50
|
end
|
30
|
-
instrument_sentry_execution("graphql.execute", "execute_query", data) { super }
|
31
|
-
end
|
32
51
|
|
33
|
-
|
52
|
+
include MonitorTrace::Monitor::GraphQLPrefixNames
|
34
53
|
|
35
|
-
|
36
|
-
"lex" => "graphql.lex",
|
37
|
-
"parse" => "graphql.parse",
|
38
|
-
"validate" => "graphql.validate",
|
39
|
-
"analyze_query" => "graphql.analyze",
|
40
|
-
"analyze_multiplex" => "graphql.analyze_multiplex",
|
41
|
-
"execute_multiplex" => "graphql.execute_multiplex",
|
42
|
-
"execute_query_lazy" => "graphql.execute"
|
43
|
-
}.each do |trace_method, platform_key|
|
44
|
-
module_eval <<-RUBY, __FILE__, __LINE__
|
45
|
-
def #{trace_method}(**data)
|
46
|
-
instrument_sentry_execution("#{platform_key}", "#{trace_method}", data) { super }
|
47
|
-
end
|
48
|
-
RUBY
|
49
|
-
end
|
50
|
-
|
51
|
-
# rubocop:enable Development/NoEvalCop
|
52
|
-
|
53
|
-
def platform_execute_field(platform_key, &block)
|
54
|
-
instrument_sentry_execution(platform_key, "execute_field", &block)
|
55
|
-
end
|
56
|
-
|
57
|
-
def platform_execute_field_lazy(platform_key, &block)
|
58
|
-
instrument_sentry_execution(platform_key, "execute_field_lazy", &block)
|
59
|
-
end
|
60
|
-
|
61
|
-
def platform_authorized(platform_key, &block)
|
62
|
-
instrument_sentry_execution(platform_key, "authorized", &block)
|
63
|
-
end
|
64
|
-
|
65
|
-
def platform_authorized_lazy(platform_key, &block)
|
66
|
-
instrument_sentry_execution(platform_key, "authorized_lazy", &block)
|
67
|
-
end
|
68
|
-
|
69
|
-
def platform_resolve_type(platform_key, &block)
|
70
|
-
instrument_sentry_execution(platform_key, "resolve_type", &block)
|
71
|
-
end
|
54
|
+
private
|
72
55
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
def platform_authorized_key(type)
|
82
|
-
"graphql.authorized.#{type.graphql_name}"
|
83
|
-
end
|
84
|
-
|
85
|
-
def platform_resolve_type_key(type)
|
86
|
-
"graphql.resolve_type.#{type.graphql_name}"
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def instrument_sentry_execution(platform_key, trace_method, data=nil, &block)
|
92
|
-
return yield unless Sentry.initialized?
|
93
|
-
|
94
|
-
Sentry.with_child_span(op: platform_key, start_timestamp: Sentry.utc_now.to_f) do |span|
|
95
|
-
result = yield
|
96
|
-
return result unless span
|
97
|
-
|
98
|
-
span.finish
|
99
|
-
if trace_method == "execute_multiplex" && data.key?(:multiplex)
|
100
|
-
operation_names = data[:multiplex].queries.map{|q| operation_name(q) }
|
101
|
-
span.set_description(operation_names.join(", "))
|
102
|
-
elsif trace_method == "execute_query" && data.key?(:query)
|
103
|
-
span.set_description(operation_name(data[:query]))
|
104
|
-
span.set_data('graphql.document', data[:query].query_string)
|
105
|
-
span.set_data('graphql.operation.name', data[:query].selected_operation_name) if data[:query].selected_operation_name
|
106
|
-
span.set_data('graphql.operation.type', data[:query].selected_operation.operation_type)
|
56
|
+
def operation_name(query)
|
57
|
+
selected_op = query.selected_operation
|
58
|
+
if selected_op
|
59
|
+
[selected_op.operation_type, selected_op.name].compact.join(' ')
|
60
|
+
else
|
61
|
+
'GraphQL Operation'
|
107
62
|
end
|
108
|
-
|
109
|
-
result
|
110
63
|
end
|
111
|
-
end
|
112
64
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
65
|
+
class Event < MonitorTrace::Monitor::Event
|
66
|
+
def start
|
67
|
+
if Sentry.initialized?
|
68
|
+
@span = Sentry.get_current_scope.get_span
|
69
|
+
span_name = @monitor.name_for(@keyword, @object)
|
70
|
+
@span.start_child(op: span_name)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def finish
|
75
|
+
@span&.finish
|
76
|
+
end
|
119
77
|
end
|
120
78
|
end
|
121
79
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "graphql/tracing/
|
3
|
+
require "graphql/tracing/monitor_trace"
|
4
4
|
|
5
5
|
module GraphQL
|
6
6
|
module Tracing
|
7
7
|
# A tracer for reporting GraphQL-Ruby times to Statsd.
|
8
|
-
# Passing any Statsd client that implements `.time(name) { ... }`
|
8
|
+
# Passing any Statsd client that implements `.time(name) { ... }`
|
9
|
+
# and `.timing(name, ms)` will work.
|
9
10
|
#
|
10
11
|
# @example Installing this tracer
|
11
12
|
# # eg:
|
@@ -13,58 +14,34 @@ module GraphQL
|
|
13
14
|
# class MySchema < GraphQL::Schema
|
14
15
|
# use GraphQL::Tracing::StatsdTrace, statsd: $statsd
|
15
16
|
# end
|
17
|
+
StatsdTrace = MonitorTrace.create_module("statsd")
|
16
18
|
module StatsdTrace
|
17
|
-
|
19
|
+
class StatsdMonitor < MonitorTrace::Monitor
|
20
|
+
def initialize(statsd:, **_rest)
|
21
|
+
@statsd = statsd
|
22
|
+
super
|
23
|
+
end
|
18
24
|
|
19
|
-
|
20
|
-
def initialize(statsd:, **rest)
|
21
|
-
@statsd = statsd
|
22
|
-
super(**rest)
|
23
|
-
end
|
24
|
-
|
25
|
-
# rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
|
25
|
+
attr_reader :statsd
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
'validate' => "graphql.validate",
|
31
|
-
'analyze_query' => "graphql.analyze_query",
|
32
|
-
'analyze_multiplex' => "graphql.analyze_multiplex",
|
33
|
-
'execute_multiplex' => "graphql.execute_multiplex",
|
34
|
-
'execute_query' => "graphql.execute_query",
|
35
|
-
'execute_query_lazy' => "graphql.execute_query_lazy",
|
36
|
-
}.each do |trace_method, platform_key|
|
37
|
-
module_eval <<-RUBY, __FILE__, __LINE__
|
38
|
-
def #{trace_method}(**data)
|
39
|
-
@statsd.time("#{platform_key}") do
|
40
|
-
super
|
41
|
-
end
|
27
|
+
def instrument(keyword, object)
|
28
|
+
@statsd.time(name_for(keyword, object)) do
|
29
|
+
yield
|
42
30
|
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
# rubocop:enable Development/NoEvalCop
|
31
|
+
end
|
47
32
|
|
48
|
-
|
49
|
-
@statsd.time(platform_key, &block)
|
50
|
-
end
|
51
|
-
|
52
|
-
def platform_authorized(key, &block)
|
53
|
-
@statsd.time(key, &block)
|
54
|
-
end
|
33
|
+
include MonitorTrace::Monitor::GraphQLPrefixNames
|
55
34
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
def platform_authorized_key(type)
|
63
|
-
"graphql.authorized.#{type.graphql_name}"
|
64
|
-
end
|
35
|
+
class Event < MonitorTrace::Monitor::Event
|
36
|
+
def start
|
37
|
+
@start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
38
|
+
end
|
65
39
|
|
66
|
-
|
67
|
-
|
40
|
+
def finish
|
41
|
+
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - @start_time
|
42
|
+
@monitor.statsd.timing(@monitor.name_for(keyword, object), elapsed)
|
43
|
+
end
|
44
|
+
end
|
68
45
|
end
|
69
46
|
end
|
70
47
|
end
|
@@ -23,12 +23,6 @@ module GraphQL
|
|
23
23
|
yield
|
24
24
|
end
|
25
25
|
|
26
|
-
# @param query_str [String]
|
27
|
-
# @return [void]
|
28
|
-
def begin_parse(query_str); end;
|
29
|
-
# @param query_str [String]
|
30
|
-
# @return [void]
|
31
|
-
def end_parse(query_str); end;
|
32
26
|
# @param query_string [String]
|
33
27
|
# @return [void]
|
34
28
|
def parse(query_string:)
|
@@ -63,17 +57,6 @@ module GraphQL
|
|
63
57
|
yield
|
64
58
|
end
|
65
59
|
|
66
|
-
# This is the first event in the tracing lifecycle.
|
67
|
-
# Every Query is technically run _inside_ a {GraphQL::Multiplex}.
|
68
|
-
# @param multiplex [GraphQL::Execution::Multiplex]
|
69
|
-
# @return [void]
|
70
|
-
def begin_execute_multiplex(multiplex); end;
|
71
|
-
|
72
|
-
# This is the last event of the tracing lifecycle.
|
73
|
-
# @param multiplex [GraphQL::Execution::Multiplex]
|
74
|
-
# @return [void]
|
75
|
-
def end_execute_multiplex(multiplex); end;
|
76
|
-
|
77
60
|
# This wraps an entire `.execute` call.
|
78
61
|
# @param multiplex [GraphQL::Execution::Multiplex]
|
79
62
|
# @return [void]
|
data/lib/graphql/tracing.rb
CHANGED
@@ -25,6 +25,7 @@ module GraphQL
|
|
25
25
|
autoload :AppOpticsTrace, "graphql/tracing/appoptics_trace"
|
26
26
|
autoload :AppsignalTrace, "graphql/tracing/appsignal_trace"
|
27
27
|
autoload :DataDogTrace, "graphql/tracing/data_dog_trace"
|
28
|
+
autoload :MonitorTrace, "graphql/tracing/monitor_trace"
|
28
29
|
autoload :NewRelicTrace, "graphql/tracing/new_relic_trace"
|
29
30
|
autoload :NotificationsTrace, "graphql/tracing/notifications_trace"
|
30
31
|
autoload :SentryTrace, "graphql/tracing/sentry_trace"
|
data/lib/graphql/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
@@ -676,6 +676,7 @@ files:
|
|
676
676
|
- lib/graphql/static_validation/rules/mutation_root_exists_error.rb
|
677
677
|
- lib/graphql/static_validation/rules/no_definitions_are_present.rb
|
678
678
|
- lib/graphql/static_validation/rules/no_definitions_are_present_error.rb
|
679
|
+
- lib/graphql/static_validation/rules/not_single_subscription_error.rb
|
679
680
|
- lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb
|
680
681
|
- lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb
|
681
682
|
- lib/graphql/static_validation/rules/operation_names_are_valid.rb
|
@@ -686,7 +687,7 @@ files:
|
|
686
687
|
- lib/graphql/static_validation/rules/required_arguments_are_present_error.rb
|
687
688
|
- lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb
|
688
689
|
- lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb
|
689
|
-
- lib/graphql/static_validation/rules/
|
690
|
+
- lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb
|
690
691
|
- lib/graphql/static_validation/rules/subscription_root_exists_error.rb
|
691
692
|
- lib/graphql/static_validation/rules/unique_directives_per_location.rb
|
692
693
|
- lib/graphql/static_validation/rules/unique_directives_per_location_error.rb
|
@@ -727,6 +728,7 @@ files:
|
|
727
728
|
- lib/graphql/tracing/detailed_trace/redis_backend.rb
|
728
729
|
- lib/graphql/tracing/legacy_hooks_trace.rb
|
729
730
|
- lib/graphql/tracing/legacy_trace.rb
|
731
|
+
- lib/graphql/tracing/monitor_trace.rb
|
730
732
|
- lib/graphql/tracing/new_relic_trace.rb
|
731
733
|
- lib/graphql/tracing/new_relic_tracing.rb
|
732
734
|
- lib/graphql/tracing/notifications_trace.rb
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module GraphQL
|
3
|
-
module StaticValidation
|
4
|
-
module SubscriptionRootExists
|
5
|
-
def on_operation_definition(node, _parent)
|
6
|
-
if node.operation_type == "subscription" && context.types.subscription_root.nil?
|
7
|
-
add_error(GraphQL::StaticValidation::SubscriptionRootExistsError.new(
|
8
|
-
'Schema is not configured for subscriptions',
|
9
|
-
nodes: node
|
10
|
-
))
|
11
|
-
else
|
12
|
-
super
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|