graphql 1.8.0.pre1 → 1.8.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/function_generator.rb +1 -1
- data/lib/generators/graphql/loader_generator.rb +1 -1
- data/lib/generators/graphql/mutation_generator.rb +6 -1
- data/lib/generators/graphql/templates/function.erb +2 -2
- data/lib/generators/graphql/templates/loader.erb +2 -2
- data/lib/graphql.rb +1 -0
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution/instrumentation.rb +82 -0
- data/lib/graphql/execution/multiplex.rb +11 -28
- data/lib/graphql/field.rb +5 -0
- data/lib/graphql/internal_representation/node.rb +1 -1
- data/lib/graphql/language.rb +1 -0
- data/lib/graphql/language/document_from_schema_definition.rb +185 -0
- data/lib/graphql/language/lexer.rb +3 -3
- data/lib/graphql/language/lexer.rl +2 -2
- data/lib/graphql/language/token.rb +9 -2
- data/lib/graphql/query.rb +4 -0
- data/lib/graphql/railtie.rb +83 -0
- data/lib/graphql/relay/relation_connection.rb +13 -18
- data/lib/graphql/schema.rb +6 -0
- data/lib/graphql/schema/argument.rb +1 -1
- data/lib/graphql/schema/build_from_definition.rb +2 -0
- data/lib/graphql/schema/field.rb +5 -2
- data/lib/graphql/schema/input_object.rb +2 -2
- data/lib/graphql/schema/member.rb +10 -0
- data/lib/graphql/schema/member/build_type.rb +8 -0
- data/lib/graphql/schema/member/instrumentation.rb +3 -3
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +6 -4
- data/lib/graphql/tracing.rb +1 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +45 -0
- data/lib/graphql/tracing/platform_tracing.rb +20 -7
- data/lib/graphql/upgrader/member.rb +111 -0
- data/lib/graphql/upgrader/schema.rb +37 -0
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/dummy/app/channels/graphql_channel.rb +22 -1
- data/spec/dummy/log/development.log +239 -0
- data/spec/dummy/log/test.log +204 -0
- data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
- data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
- data/spec/generators/graphql/function_generator_spec.rb +26 -0
- data/spec/generators/graphql/loader_generator_spec.rb +24 -0
- data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
- data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
- data/spec/graphql/base_type_spec.rb +12 -0
- data/spec/graphql/boolean_type_spec.rb +3 -3
- data/spec/graphql/execution/execute_spec.rb +1 -1
- data/spec/graphql/execution/instrumentation_spec.rb +165 -0
- data/spec/graphql/execution/multiplex_spec.rb +1 -1
- data/spec/graphql/float_type_spec.rb +2 -2
- data/spec/graphql/id_type_spec.rb +1 -1
- data/spec/graphql/input_object_type_spec.rb +2 -2
- data/spec/graphql/int_type_spec.rb +2 -2
- data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
- data/spec/graphql/introspection/schema_type_spec.rb +1 -0
- data/spec/graphql/language/document_from_schema_definition_spec.rb +337 -0
- data/spec/graphql/language/lexer_spec.rb +12 -1
- data/spec/graphql/language/parser_spec.rb +1 -1
- data/spec/graphql/query/arguments_spec.rb +3 -3
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/query_spec.rb +4 -4
- data/spec/graphql/relay/base_connection_spec.rb +1 -1
- data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
- data/spec/graphql/relay/connection_type_spec.rb +1 -1
- data/spec/graphql/relay/mutation_spec.rb +3 -3
- data/spec/graphql/relay/relation_connection_spec.rb +58 -0
- data/spec/graphql/schema/build_from_definition_spec.rb +14 -0
- data/spec/graphql/schema/field_spec.rb +5 -1
- data/spec/graphql/schema/instrumentation_spec.rb +39 -0
- data/spec/graphql/schema/validation_spec.rb +1 -1
- data/spec/graphql/schema/warden_spec.rb +11 -11
- data/spec/graphql/schema_spec.rb +8 -1
- data/spec/graphql/string_type_spec.rb +3 -3
- data/spec/graphql/subscriptions_spec.rb +1 -1
- data/spec/graphql/tracing/platform_tracing_spec.rb +59 -0
- data/spec/graphql/upgrader/member_spec.rb +222 -0
- data/spec/graphql/upgrader/schema_spec.rb +82 -0
- data/spec/support/dummy/schema.rb +19 -0
- data/spec/support/jazz.rb +14 -14
- data/spec/support/star_wars/data.rb +1 -2
- metadata +18 -2
@@ -387,7 +387,7 @@ def self.run_lexer(query_string)
|
|
387
387
|
begin
|
388
388
|
te = p+1;
|
389
389
|
begin
|
390
|
-
emit_string(ts + 1, te
|
390
|
+
emit_string(ts + 1, te, meta)
|
391
391
|
end
|
392
392
|
|
393
393
|
end
|
@@ -791,7 +791,7 @@ def self.run_lexer(query_string)
|
|
791
791
|
begin
|
792
792
|
p = ((te))-1;
|
793
793
|
begin
|
794
|
-
emit_string(ts + 1, te
|
794
|
+
emit_string(ts + 1, te, meta)
|
795
795
|
end
|
796
796
|
|
797
797
|
end
|
@@ -1304,7 +1304,7 @@ PACK_DIRECTIVE = "c*"
|
|
1304
1304
|
UTF_8_ENCODING = "UTF-8"
|
1305
1305
|
|
1306
1306
|
def self.emit_string(ts, te, meta)
|
1307
|
-
value = meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
1307
|
+
value = meta[:data][ts...te - 1].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
1308
1308
|
if value !~ VALID_STRING
|
1309
1309
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
1310
1310
|
name: :BAD_UNICODE_ESCAPE,
|
@@ -75,7 +75,7 @@
|
|
75
75
|
RBRACKET => { emit(:RBRACKET, ts, te, meta) };
|
76
76
|
LBRACKET => { emit(:LBRACKET, ts, te, meta) };
|
77
77
|
COLON => { emit(:COLON, ts, te, meta) };
|
78
|
-
QUOTED_STRING => { emit_string(ts + 1, te
|
78
|
+
QUOTED_STRING => { emit_string(ts + 1, te, meta) };
|
79
79
|
VAR_SIGN => { emit(:VAR_SIGN, ts, te, meta) };
|
80
80
|
DIR_SIGN => { emit(:DIR_SIGN, ts, te, meta) };
|
81
81
|
ELLIPSIS => { emit(:ELLIPSIS, ts, te, meta) };
|
@@ -189,7 +189,7 @@ module GraphQL
|
|
189
189
|
UTF_8_ENCODING = "UTF-8"
|
190
190
|
|
191
191
|
def self.emit_string(ts, te, meta)
|
192
|
-
value = meta[:data][ts...te].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
192
|
+
value = meta[:data][ts...te - 1].pack(PACK_DIRECTIVE).force_encoding(UTF_8_ENCODING)
|
193
193
|
if value !~ VALID_STRING
|
194
194
|
meta[:tokens] << token = GraphQL::Language::Token.new(
|
195
195
|
name: :BAD_UNICODE_ESCAPE,
|
@@ -5,7 +5,10 @@ module GraphQL
|
|
5
5
|
# Contains type, value and position data.
|
6
6
|
class Token
|
7
7
|
# @return [Symbol] The kind of token this is
|
8
|
-
attr_reader :name
|
8
|
+
attr_reader :name
|
9
|
+
# @return [String] The text of this token
|
10
|
+
attr_reader :value
|
11
|
+
attr_reader :prev_token, :line, :col
|
9
12
|
|
10
13
|
def initialize(value:, name:, line:, col:, prev_token:)
|
11
14
|
@name = name
|
@@ -15,13 +18,17 @@ module GraphQL
|
|
15
18
|
@prev_token = prev_token
|
16
19
|
end
|
17
20
|
|
18
|
-
|
21
|
+
alias to_s value
|
19
22
|
def to_i; @value.to_i; end
|
20
23
|
def to_f; @value.to_f; end
|
21
24
|
|
22
25
|
def line_and_column
|
23
26
|
[@line, @col]
|
24
27
|
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
"(#{@name} #{@value.inspect} [#{@line}:#{@col}])"
|
31
|
+
end
|
25
32
|
end
|
26
33
|
end
|
27
34
|
end
|
data/lib/graphql/query.rb
CHANGED
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './upgrader/member'
|
4
|
+
require_relative './upgrader/schema'
|
5
|
+
|
6
|
+
module GraphQL
|
7
|
+
class Railtie < Rails::Railtie
|
8
|
+
rake_tasks do
|
9
|
+
namespace :graphql do
|
10
|
+
task :upgrade, [:dir] do |t, args|
|
11
|
+
unless (dir = args[:dir])
|
12
|
+
fail 'You have to give me a directory where your GraphQL schema and types live. ' \
|
13
|
+
'For example: `bin/rake graphql:upgrade[app/graphql/**/*]`'
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir[dir].each do |file|
|
17
|
+
# Members (types, interfaces, etc.)
|
18
|
+
if file =~ /.*_(type|interface|enum|union|)\.rb$/
|
19
|
+
Rake::Task["graphql:upgrade:member"].execute(Struct.new(:member_file).new(file))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
namespace :upgrade do
|
25
|
+
task :create_base_objects, [:base_dir] do |t, args|
|
26
|
+
base_dir = args.base_dir
|
27
|
+
|
28
|
+
destination_file = File.join(base_dir, "types", "base_enum.rb")
|
29
|
+
unless File.exists?(destination_file)
|
30
|
+
FileUtils.mkdir_p(File.dirname(destination_file))
|
31
|
+
File.open(destination_file, 'w') do |f|
|
32
|
+
f.write "class Types::BaseEnum < GraphQL::Schema::Enum; end"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
destination_file = File.join(base_dir, "types", "base_union.rb")
|
37
|
+
unless File.exists?(destination_file)
|
38
|
+
FileUtils.mkdir_p(File.dirname(destination_file))
|
39
|
+
File.open(destination_file, 'w') do |f|
|
40
|
+
f.write "class Types::BaseUnion < GraphQL::Schema::Union; end"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
destination_file = File.join(base_dir, "types", "base_interface.rb")
|
45
|
+
unless File.exists?(destination_file)
|
46
|
+
FileUtils.mkdir_p(File.dirname(destination_file))
|
47
|
+
File.open(destination_file, 'w') do |f|
|
48
|
+
f.write "class Types::BaseInterface < GraphQL::Schema::Interface; end"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
destination_file = File.join(base_dir, "types", "base_object.rb")
|
53
|
+
unless File.exists?(destination_file)
|
54
|
+
File.open(destination_file, 'w') do |f|
|
55
|
+
f.write "class Types::BaseObject < GraphQL::Schema::Object; end"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
task :schema, [:schema_file] do |t, args|
|
61
|
+
schema_file = args.schema_file
|
62
|
+
|
63
|
+
upgrader = GraphQL::Upgrader::Schema.new File.read(schema_file)
|
64
|
+
|
65
|
+
puts "- Transforming schema #{schema_file}"
|
66
|
+
File.open(schema_file, 'w') { |f| f.write upgrader.upgrade }
|
67
|
+
end
|
68
|
+
|
69
|
+
task :member, [:member_file] do |t, args|
|
70
|
+
member_file = args.member_file
|
71
|
+
|
72
|
+
upgrader = GraphQL::Upgrader::Member.new File.read(member_file)
|
73
|
+
next unless upgrader.upgradeable?
|
74
|
+
|
75
|
+
puts "- Transforming member #{member_file}"
|
76
|
+
File.open(member_file, 'w') { |f| f.write upgrader.upgrade }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
@@ -7,11 +7,11 @@ module GraphQL
|
|
7
7
|
# - `Sequel::Dataset`
|
8
8
|
class RelationConnection < BaseConnection
|
9
9
|
def cursor_from_node(item)
|
10
|
-
item_index =
|
10
|
+
item_index = paged_nodes.index(item)
|
11
11
|
if item_index.nil?
|
12
12
|
raise("Can't generate cursor, item not found in connection: #{item}")
|
13
13
|
else
|
14
|
-
offset = item_index + 1 + ((
|
14
|
+
offset = item_index + 1 + ((paged_nodes_offset || 0) - (relation_offset(sliced_nodes) || 0))
|
15
15
|
|
16
16
|
if after
|
17
17
|
offset += offset_from_cursor(after)
|
@@ -25,7 +25,7 @@ module GraphQL
|
|
25
25
|
|
26
26
|
def has_next_page
|
27
27
|
if first
|
28
|
-
|
28
|
+
paged_nodes.length >= first && sliced_nodes_count > first
|
29
29
|
elsif GraphQL::Relay::ConnectionType.bidirectional_pagination && last
|
30
30
|
sliced_nodes_count > last
|
31
31
|
else
|
@@ -35,7 +35,7 @@ module GraphQL
|
|
35
35
|
|
36
36
|
def has_previous_page
|
37
37
|
if last
|
38
|
-
|
38
|
+
paged_nodes.length >= last && sliced_nodes_count > last
|
39
39
|
elsif GraphQL::Relay::ConnectionType.bidirectional_pagination && after
|
40
40
|
# We've already paginated through the collection a bit,
|
41
41
|
# there are nodes behind us
|
@@ -64,6 +64,7 @@ module GraphQL
|
|
64
64
|
private
|
65
65
|
|
66
66
|
# apply first / last limit results
|
67
|
+
# @return [Array]
|
67
68
|
def paged_nodes
|
68
69
|
return @paged_nodes if defined? @paged_nodes
|
69
70
|
|
@@ -94,7 +95,14 @@ module GraphQL
|
|
94
95
|
end
|
95
96
|
end
|
96
97
|
|
97
|
-
|
98
|
+
# Store this here so we can convert the relation to an Array
|
99
|
+
# (this avoids an extra DB call on Sequel)
|
100
|
+
@paged_nodes_offset = relation_offset(items)
|
101
|
+
@paged_nodes = items.to_a
|
102
|
+
end
|
103
|
+
|
104
|
+
def paged_nodes_offset
|
105
|
+
paged_nodes && @paged_nodes_offset
|
98
106
|
end
|
99
107
|
|
100
108
|
def relation_offset(relation)
|
@@ -166,19 +174,6 @@ module GraphQL
|
|
166
174
|
def offset_from_cursor(cursor)
|
167
175
|
decode(cursor).to_i
|
168
176
|
end
|
169
|
-
|
170
|
-
def paged_nodes_array
|
171
|
-
return @paged_nodes_array if defined?(@paged_nodes_array)
|
172
|
-
@paged_nodes_array = paged_nodes.to_a
|
173
|
-
end
|
174
|
-
|
175
|
-
def paged_nodes_length
|
176
|
-
if paged_nodes.respond_to?(:length)
|
177
|
-
paged_nodes.length
|
178
|
-
else
|
179
|
-
paged_nodes_array.length
|
180
|
-
end
|
181
|
-
end
|
182
177
|
end
|
183
178
|
|
184
179
|
if defined?(ActiveRecord::Relation)
|
data/lib/graphql/schema.rb
CHANGED
@@ -570,6 +570,12 @@ module GraphQL
|
|
570
570
|
GraphQL::Schema::Printer.print_schema(self, only: only, except: except, context: context)
|
571
571
|
end
|
572
572
|
|
573
|
+
# Return the GraphQL::Language::Document IDL AST for the schema
|
574
|
+
# @return [GraphQL::Language::Document]
|
575
|
+
def to_document
|
576
|
+
GraphQL::Language::DocumentFromSchemaDefinition.new(self).document
|
577
|
+
end
|
578
|
+
|
573
579
|
# Return the Hash response of {Introspection::INTROSPECTION_QUERY}.
|
574
580
|
# @param context [Hash]
|
575
581
|
# @param only [<#call(member, ctx)>]
|
data/lib/graphql/schema/field.rb
CHANGED
@@ -16,7 +16,7 @@ module GraphQL
|
|
16
16
|
def initialize(name, return_type_expr = nil, desc = nil, null: nil, field: nil, function: nil, deprecation_reason: nil, method: nil, connection: nil, max_page_size: nil, resolve: nil, &args_block)
|
17
17
|
if !(field || function)
|
18
18
|
if return_type_expr.nil?
|
19
|
-
raise ArgumentError "missing
|
19
|
+
raise ArgumentError, "missing positional argument `type`"
|
20
20
|
end
|
21
21
|
if null.nil?
|
22
22
|
raise ArgumentError, "missing keyword argument null:"
|
@@ -47,7 +47,8 @@ module GraphQL
|
|
47
47
|
else
|
48
48
|
GraphQL::Field.new
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
|
+
field_defn.name = Member::BuildType.camelize(name)
|
51
52
|
|
52
53
|
if @return_type_expr
|
53
54
|
return_type_name = Member::BuildType.to_type_name(@return_type_expr)
|
@@ -96,6 +97,8 @@ module GraphQL
|
|
96
97
|
field_defn
|
97
98
|
end
|
98
99
|
|
100
|
+
private
|
101
|
+
|
99
102
|
class << self
|
100
103
|
def argument_class(new_arg_class = nil)
|
101
104
|
if new_arg_class
|
@@ -20,7 +20,7 @@ module GraphQL
|
|
20
20
|
def argument(*args)
|
21
21
|
argument = GraphQL::Schema::Argument.new(*args)
|
22
22
|
own_arguments << argument
|
23
|
-
arg_name = argument.name
|
23
|
+
arg_name = argument.graphql_definition.name
|
24
24
|
# Add a method access
|
25
25
|
define_method(Member::BuildType.underscore(arg_name)) do
|
26
26
|
@arguments.public_send(arg_name)
|
@@ -47,7 +47,7 @@ module GraphQL
|
|
47
47
|
type_defn.name = graphql_name
|
48
48
|
type_defn.description = description
|
49
49
|
arguments.each do |arg|
|
50
|
-
type_defn.arguments[arg.name] = arg.graphql_definition
|
50
|
+
type_defn.arguments[arg.graphql_definition.name] = arg.graphql_definition
|
51
51
|
end
|
52
52
|
# Make a reference to a classic-style Arguments class
|
53
53
|
self.arguments_class = GraphQL::Query::Arguments.construct_arguments_class(type_defn)
|
@@ -62,6 +62,16 @@ module GraphQL
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
# Just a convenience method to point out that people should use graphql_name instead
|
66
|
+
def name(new_name = nil)
|
67
|
+
return super() if new_name.nil?
|
68
|
+
|
69
|
+
fail(
|
70
|
+
"The new name override method is `graphql_name`, not `name`. Usage: "\
|
71
|
+
"graphql_name \"#{new_name}\""
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
65
75
|
# Call this method to provide a new description; OR
|
66
76
|
# call it without an argument to get the description
|
67
77
|
# @param new_description [String]
|
@@ -94,6 +94,14 @@ module GraphQL
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
+
def camelize(string)
|
98
|
+
return string unless string.include?('_')
|
99
|
+
|
100
|
+
string.split('_').map(&:capitalize).join.tap do |camelized|
|
101
|
+
camelized[0] = camelized[0].downcase
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
97
105
|
def underscore(string)
|
98
106
|
string
|
99
107
|
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') # URLDecoder -> URL_Decoder
|
@@ -85,10 +85,10 @@ module GraphQL
|
|
85
85
|
private
|
86
86
|
|
87
87
|
def proxy_to_depth(obj, depth, type, ctx)
|
88
|
-
if
|
89
|
-
obj.map { |inner_obj| proxy_to_depth(inner_obj, depth - 1, type, ctx) }
|
90
|
-
elsif obj.nil?
|
88
|
+
if obj.nil?
|
91
89
|
obj
|
90
|
+
elsif depth > 0
|
91
|
+
obj.map { |inner_obj| proxy_to_depth(inner_obj, depth - 1, type, ctx) }
|
92
92
|
else
|
93
93
|
concrete_type = case type
|
94
94
|
when GraphQL::UnionType, GraphQL::InterfaceType
|
@@ -62,19 +62,21 @@ module GraphQL
|
|
62
62
|
class ActionCableSubscriptions < GraphQL::Subscriptions
|
63
63
|
SUBSCRIPTION_PREFIX = "graphql-subscription:"
|
64
64
|
EVENT_PREFIX = "graphql-event:"
|
65
|
-
|
65
|
+
|
66
|
+
# @param serializer [<#dump(obj), #load(string)] Used for serializing messages before handing them to `.broadcast(msg)`
|
67
|
+
def initialize(serializer: Serialize, **rest)
|
66
68
|
# A per-process map of subscriptions to deliver.
|
67
69
|
# This is provided by Rails, so let's use it
|
68
70
|
@subscriptions = Concurrent::Map.new
|
71
|
+
@serializer = serializer
|
69
72
|
super
|
70
73
|
end
|
71
74
|
|
72
75
|
# An event was triggered; Push the data over ActionCable.
|
73
76
|
# Subscribers will re-evaluate locally.
|
74
|
-
# TODO: this method name is a smell
|
75
77
|
def execute_all(event, object)
|
76
78
|
stream = EVENT_PREFIX + event.topic
|
77
|
-
message =
|
79
|
+
message = @serializer.dump(object)
|
78
80
|
ActionCable.server.broadcast(stream, message)
|
79
81
|
end
|
80
82
|
|
@@ -97,7 +99,7 @@ module GraphQL
|
|
97
99
|
@subscriptions[subscription_id] = query
|
98
100
|
events.each do |event|
|
99
101
|
channel.stream_from(EVENT_PREFIX + event.topic, coder: ActiveSupport::JSON) do |message|
|
100
|
-
execute(subscription_id, event,
|
102
|
+
execute(subscription_id, event, @serializer.load(message))
|
101
103
|
nil
|
102
104
|
end
|
103
105
|
end
|
data/lib/graphql/tracing.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require "graphql/tracing/active_support_notifications_tracing"
|
3
3
|
require "graphql/tracing/platform_tracing"
|
4
4
|
require "graphql/tracing/appsignal_tracing"
|
5
|
+
require "graphql/tracing/data_dog_tracing"
|
5
6
|
require "graphql/tracing/new_relic_tracing"
|
6
7
|
require "graphql/tracing/scout_tracing"
|
7
8
|
require "graphql/tracing/skylight_tracing"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Tracing
|
5
|
+
class DataDogTracing < PlatformTracing
|
6
|
+
self.platform_keys = {
|
7
|
+
'lex' => 'lex.graphql',
|
8
|
+
'parse' => 'parse.graphql',
|
9
|
+
'validate' => 'validate.graphql',
|
10
|
+
'analyze_query' => 'analyze.graphql',
|
11
|
+
'analyze_multiplex' => 'analyze.graphql',
|
12
|
+
'execute_multiplex' => 'execute.graphql',
|
13
|
+
'execute_query' => 'execute.graphql',
|
14
|
+
'execute_query_lazy' => 'execute.graphql',
|
15
|
+
}
|
16
|
+
|
17
|
+
def platform_trace(platform_key, key, data)
|
18
|
+
service = options.fetch(:service, 'ruby-graphql')
|
19
|
+
|
20
|
+
pin = Datadog::Pin.get_from(self)
|
21
|
+
unless pin
|
22
|
+
pin = Datadog::Pin.new(service)
|
23
|
+
pin.onto(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
pin.tracer.trace(platform_key, service: pin.service) do |span|
|
27
|
+
if key == 'execute_multiplex'
|
28
|
+
span.resource = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
|
29
|
+
end
|
30
|
+
|
31
|
+
if key == 'execute_query'
|
32
|
+
span.set_tag(:selected_operation_name, data[:query].selected_operation_name)
|
33
|
+
span.set_tag(:selected_operation_type, data[:query].selected_operation.operation_type)
|
34
|
+
span.set_tag(:query_string, data[:query].query_string)
|
35
|
+
end
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def platform_field_key(type, field)
|
41
|
+
"#{type.name}.#{field.name}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|