graphql 2.5.11 → 2.5.19

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/detailed_trace_generator.rb +77 -0
  3. data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
  4. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +1 -0
  5. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +2 -2
  6. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +1 -1
  7. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +1 -1
  8. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +1 -1
  9. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +1 -1
  10. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +1 -1
  11. data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +7 -7
  12. data/lib/graphql/dashboard.rb +5 -2
  13. data/lib/graphql/dataloader/async_dataloader.rb +22 -11
  14. data/lib/graphql/dataloader/null_dataloader.rb +44 -10
  15. data/lib/graphql/dataloader.rb +75 -23
  16. data/lib/graphql/date_encoding_error.rb +1 -1
  17. data/lib/graphql/execution/interpreter/resolve.rb +7 -13
  18. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +13 -0
  19. data/lib/graphql/execution/interpreter/runtime.rb +21 -16
  20. data/lib/graphql/execution/interpreter.rb +2 -13
  21. data/lib/graphql/language/document_from_schema_definition.rb +2 -1
  22. data/lib/graphql/language.rb +21 -12
  23. data/lib/graphql/schema/argument.rb +7 -0
  24. data/lib/graphql/schema/build_from_definition.rb +3 -1
  25. data/lib/graphql/schema/directive.rb +22 -4
  26. data/lib/graphql/schema/field.rb +6 -47
  27. data/lib/graphql/schema/member/has_arguments.rb +43 -14
  28. data/lib/graphql/schema/member/has_fields.rb +76 -4
  29. data/lib/graphql/schema/validator/required_validator.rb +33 -2
  30. data/lib/graphql/schema/visibility.rb +2 -2
  31. data/lib/graphql/schema.rb +20 -3
  32. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +2 -2
  33. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -0
  34. data/lib/graphql/testing/helpers.rb +12 -9
  35. data/lib/graphql/testing/mock_action_cable.rb +111 -0
  36. data/lib/graphql/testing.rb +1 -0
  37. data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
  38. data/lib/graphql/tracing/detailed_trace.rb +70 -7
  39. data/lib/graphql/tracing/perfetto_trace.rb +208 -78
  40. data/lib/graphql/tracing/sentry_trace.rb +3 -1
  41. data/lib/graphql/version.rb +1 -1
  42. data/lib/graphql.rb +5 -2
  43. metadata +7 -3
@@ -60,11 +60,52 @@ module GraphQL
60
60
  DA_FETCH_KEYS_IID = 13
61
61
  DA_STR_VAL_NIL_IID = 14
62
62
 
63
+ REVERSE_DEBUG_NAME_LOOKUP = {
64
+ DA_OBJECT_IID => "object",
65
+ DA_RESULT_IID => "result",
66
+ DA_ARGUMENTS_IID => "arguments",
67
+ DA_FETCH_KEYS_IID => "fetch keys",
68
+ }
69
+
70
+ DEBUG_INSPECT_CATEGORY_IIDS = [15]
71
+ DA_DEBUG_INSPECT_CLASS_IID = 16
72
+ DEBUG_INSPECT_EVENT_NAME_IID = 17
73
+ DA_DEBUG_INSPECT_FOR_IID = 18
74
+
63
75
  # @param active_support_notifications_pattern [String, RegExp, false] A filter for `ActiveSupport::Notifications`, if it's present. Or `false` to skip subscribing.
64
76
  def initialize(active_support_notifications_pattern: nil, save_profile: false, **_rest)
65
77
  super
66
78
  @active_support_notifications_pattern = active_support_notifications_pattern
67
79
  @save_profile = save_profile
80
+
81
+ query = if @multiplex
82
+ @multiplex.queries.first
83
+ else
84
+ @query # could still be nil in some initializations
85
+ end
86
+
87
+ @detailed_trace = query&.schema&.detailed_trace || DetailedTrace
88
+ @create_debug_annotations = if (ctx = query&.context).nil? || (ctx_debug = ctx[:detailed_trace_debug]).nil?
89
+ @detailed_trace.debug?
90
+ else
91
+ ctx_debug
92
+ end
93
+
94
+ @arguments_filter = if (ctx = query&.context) && (dtf = ctx[:detailed_trace_filter])
95
+ dtf
96
+ elsif defined?(ActiveSupport::ParameterFilter)
97
+ fp = if defined?(Rails) && Rails.application && (app_config = Rails.application.config.filter_parameters).present? && !app_config.empty?
98
+ app_config
99
+ elsif ActiveSupport.respond_to?(:filter_parameters)
100
+ ActiveSupport.filter_parameters
101
+ else
102
+ EmptyObjects::EMPTY_ARRAY
103
+ end
104
+ ActiveSupport::ParameterFilter.new(fp, mask: ArgumentsFilter::FILTERED)
105
+ else
106
+ ArgumentsFilter.new
107
+ end
108
+
68
109
  Fiber[:graphql_flow_stack] = nil
69
110
  @sequence_id = object_id
70
111
  @pid = Process.pid
@@ -110,6 +151,10 @@ module GraphQL
110
151
  @objects_counter_id = :objects_counter.object_id
111
152
  @fibers_counter_id = :fibers_counter.object_id
112
153
  @fields_counter_id = :fields_counter.object_id
154
+ @counts_objects = [@objects_counter_id]
155
+ @counts_objects_and_fields = [@objects_counter_id, @fields_counter_id]
156
+ @counts_fibers = [@fibers_counter_id]
157
+ @counts_fibers_and_objects = [@fibers_counter_id, @objects_counter_id]
113
158
  @begin_validate = nil
114
159
  @begin_time = nil
115
160
  @packets = []
@@ -132,16 +177,19 @@ module GraphQL
132
177
  EventCategory.new(name: "ActiveSupport::Notifications", iid: ACTIVE_SUPPORT_NOTIFICATIONS_CATEGORY_IIDS.first),
133
178
  EventCategory.new(name: "Authorized", iid: AUTHORIZED_CATEGORY_IIDS.first),
134
179
  EventCategory.new(name: "Resolve Type", iid: RESOLVE_TYPE_CATEGORY_IIDS.first),
180
+ EventCategory.new(name: "Debug Inspect", iid: DEBUG_INSPECT_CATEGORY_IIDS.first),
135
181
  ],
136
182
  debug_annotation_names: [
137
- DebugAnnotationName.new(name: "object", iid: DA_OBJECT_IID),
138
- DebugAnnotationName.new(name: "arguments", iid: DA_ARGUMENTS_IID),
139
- DebugAnnotationName.new(name: "result", iid: DA_RESULT_IID),
140
- DebugAnnotationName.new(name: "fetch keys", iid: DA_FETCH_KEYS_IID),
183
+ *REVERSE_DEBUG_NAME_LOOKUP.map { |(iid, name)| DebugAnnotationName.new(name: name, iid: iid) },
184
+ DebugAnnotationName.new(name: "inspect instance of", iid: DA_DEBUG_INSPECT_CLASS_IID),
185
+ DebugAnnotationName.new(name: "inspecting for", iid: DA_DEBUG_INSPECT_FOR_IID)
141
186
  ],
142
187
  debug_annotation_string_values: [
143
188
  InternedString.new(str: "(nil)", iid: DA_STR_VAL_NIL_IID),
144
189
  ],
190
+ event_names: [
191
+ EventName.new(name: "#{(@detailed_trace.is_a?(Class) ? @detailed_trace : @detailed_trace.class).name}#inspect_object", iid: DEBUG_INSPECT_EVENT_NAME_IID)
192
+ ],
145
193
  ),
146
194
  trusted_packet_sequence_id: @sequence_id,
147
195
  sequence_flags: 2,
@@ -180,11 +228,9 @@ module GraphQL
180
228
  @packets << trace_packet(
181
229
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
182
230
  track_uuid: fid,
183
- name: "Multiplex",
184
- debug_annotations: [
185
- payload_to_debug("query_string", multiplex.queries.map(&:sanitized_query_string).join("\n\n"))
186
- ]
187
- )
231
+ name: "Multiplex"
232
+ ) { [ payload_to_debug("query_string", multiplex.queries.map(&:sanitized_query_string).join("\n\n")) ] }
233
+
188
234
  result = super
189
235
 
190
236
  @packets << trace_packet(
@@ -209,7 +255,7 @@ module GraphQL
209
255
  track_uuid: fid,
210
256
  name: query.context.current_path.join("."),
211
257
  category_iids: FIELD_EXECUTE_CATEGORY_IIDS,
212
- extra_counter_track_uuids: [@objects_counter_id],
258
+ extra_counter_track_uuids: @counts_objects,
213
259
  extra_counter_values: [count_allocations],
214
260
  )
215
261
  @packets << packet
@@ -218,19 +264,23 @@ module GraphQL
218
264
  end
219
265
 
220
266
  def end_execute_field(field, object, arguments, query, app_result)
267
+ end_ts = ts
221
268
  start_field = fiber_flow_stack.pop
222
- start_field.track_event = dup_with(start_field.track_event, {
223
- debug_annotations: [
224
- payload_to_debug(nil, object.object, iid: DA_OBJECT_IID, intern_value: true),
225
- payload_to_debug(nil, arguments, iid: DA_ARGUMENTS_IID),
226
- payload_to_debug(nil, app_result, iid: DA_RESULT_IID, intern_value: true)
227
- ]
228
- })
269
+ if @create_debug_annotations
270
+ start_field.track_event = dup_with(start_field.track_event,{
271
+ debug_annotations: [
272
+ payload_to_debug(nil, object.object, iid: DA_OBJECT_IID, intern_value: true),
273
+ payload_to_debug(nil, arguments, iid: DA_ARGUMENTS_IID),
274
+ payload_to_debug(nil, app_result, iid: DA_RESULT_IID, intern_value: true)
275
+ ]
276
+ })
277
+ end
229
278
 
230
279
  @packets << trace_packet(
280
+ timestamp: end_ts,
231
281
  type: TrackEvent::Type::TYPE_SLICE_END,
232
282
  track_uuid: fid,
233
- extra_counter_track_uuids: [@objects_counter_id, @fields_counter_id],
283
+ extra_counter_track_uuids: @counts_objects_and_fields,
234
284
  extra_counter_values: [count_allocations, count_fields],
235
285
  )
236
286
  super
@@ -240,22 +290,24 @@ module GraphQL
240
290
  @packets << trace_packet(
241
291
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
242
292
  track_uuid: fid,
243
- extra_counter_track_uuids: [@objects_counter_id],
293
+ extra_counter_track_uuids: @counts_objects,
244
294
  extra_counter_values: [count_allocations],
245
- name: "Analysis",
246
- debug_annotations: [
247
- payload_to_debug("analyzers_count", analyzers.size),
248
- payload_to_debug("analyzers", analyzers),
249
- ]
250
- )
295
+ name: "Analysis") {
296
+ [
297
+ payload_to_debug("analyzers_count", analyzers.size),
298
+ payload_to_debug("analyzers", analyzers),
299
+ ]
300
+ }
251
301
  super
252
302
  end
253
303
 
254
304
  def end_analyze_multiplex(m, analyzers)
305
+ end_ts = ts
255
306
  @packets << trace_packet(
307
+ timestamp: end_ts,
256
308
  type: TrackEvent::Type::TYPE_SLICE_END,
257
309
  track_uuid: fid,
258
- extra_counter_track_uuids: [@objects_counter_id],
310
+ extra_counter_track_uuids: @counts_objects,
259
311
  extra_counter_values: [count_allocations],
260
312
  )
261
313
  super
@@ -265,50 +317,57 @@ module GraphQL
265
317
  @packets << trace_packet(
266
318
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
267
319
  track_uuid: fid,
268
- extra_counter_track_uuids: [@objects_counter_id],
320
+ extra_counter_track_uuids: @counts_objects,
269
321
  extra_counter_values: [count_allocations],
270
322
  name: "Parse"
271
323
  )
272
324
  result = super
325
+ end_ts = ts
273
326
  @packets << trace_packet(
327
+ timestamp: end_ts,
274
328
  type: TrackEvent::Type::TYPE_SLICE_END,
275
329
  track_uuid: fid,
276
- extra_counter_track_uuids: [@objects_counter_id],
330
+ extra_counter_track_uuids: @counts_objects,
277
331
  extra_counter_values: [count_allocations],
278
332
  )
279
333
  result
280
334
  end
281
335
 
282
336
  def begin_validate(query, validate)
283
- @packets << @begin_validate = trace_packet(
337
+ @begin_validate = trace_packet(
284
338
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
285
339
  track_uuid: fid,
286
- extra_counter_track_uuids: [@objects_counter_id],
340
+ extra_counter_track_uuids: @counts_objects,
287
341
  extra_counter_values: [count_allocations],
288
- name: "Validate",
289
- debug_annotations: [
290
- payload_to_debug("validate?", validate),
291
- ]
292
- )
342
+ name: "Validate") {
343
+ [payload_to_debug("validate?", validate)]
344
+ }
345
+
346
+ @packets << @begin_validate
293
347
  super
294
348
  end
295
349
 
296
350
  def end_validate(query, validate, validation_errors)
351
+ end_ts = ts
297
352
  @packets << trace_packet(
353
+ timestamp: end_ts,
298
354
  type: TrackEvent::Type::TYPE_SLICE_END,
299
355
  track_uuid: fid,
300
- extra_counter_track_uuids: [@objects_counter_id],
356
+ extra_counter_track_uuids: @counts_objects,
301
357
  extra_counter_values: [count_allocations],
302
358
  )
303
- @begin_validate.track_event = dup_with(
304
- @begin_validate.track_event,
305
- {
306
- debug_annotations: [
307
- @begin_validate.track_event.debug_annotations.first,
308
- payload_to_debug("valid?", validation_errors.empty?)
309
- ]
310
- }
311
- )
359
+
360
+ if @create_debug_annotations
361
+ new_bv_track_event = dup_with(
362
+ @begin_validate.track_event, {
363
+ debug_annotations: [
364
+ @begin_validate.track_event.debug_annotations.first,
365
+ payload_to_debug("valid?", validation_errors.empty?)
366
+ ]
367
+ }
368
+ )
369
+ @begin_validate.track_event = new_bv_track_event
370
+ end
312
371
  super
313
372
  end
314
373
 
@@ -318,7 +377,7 @@ module GraphQL
318
377
  track_uuid: fid,
319
378
  name: "Create Execution Fiber",
320
379
  category_iids: DATALOADER_CATEGORY_IIDS,
321
- extra_counter_track_uuids: [@fibers_counter_id, @objects_counter_id],
380
+ extra_counter_track_uuids: @counts_fibers_and_objects,
322
381
  extra_counter_values: [count_fibers(1), count_allocations]
323
382
  )
324
383
  @packets << track_descriptor_packet(@did, fid, "Exec Fiber ##{fid}")
@@ -331,7 +390,7 @@ module GraphQL
331
390
  track_uuid: fid,
332
391
  name: "Create Source Fiber",
333
392
  category_iids: DATALOADER_CATEGORY_IIDS,
334
- extra_counter_track_uuids: [@fibers_counter_id, @objects_counter_id],
393
+ extra_counter_track_uuids: @counts_fibers_and_objects,
335
394
  extra_counter_values: [count_fibers(1), count_allocations]
336
395
  )
337
396
  @packets << track_descriptor_packet(@did, fid, "Source Fiber ##{fid}")
@@ -385,7 +444,7 @@ module GraphQL
385
444
  track_uuid: fid,
386
445
  name: "Fiber Exit",
387
446
  category_iids: DATALOADER_CATEGORY_IIDS,
388
- extra_counter_track_uuids: [@fibers_counter_id],
447
+ extra_counter_track_uuids: @counts_fibers,
389
448
  extra_counter_values: [count_fibers(-1)],
390
449
  )
391
450
  super
@@ -415,31 +474,34 @@ module GraphQL
415
474
  fds = @flow_ids[source]
416
475
  fds_copy = fds.dup
417
476
  fds.clear
477
+
418
478
  packet = trace_packet(
419
479
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
420
480
  track_uuid: fid,
421
481
  name_iid: @source_name_iids[source.class],
422
482
  category_iids: DATALOADER_CATEGORY_IIDS,
423
483
  flow_ids: fds_copy,
424
- extra_counter_track_uuids: [@objects_counter_id],
425
- extra_counter_values: [count_allocations],
426
- debug_annotations: [
427
- payload_to_debug(nil, source.pending.values, iid: DA_FETCH_KEYS_IID, intern_value: true),
428
- *(source.instance_variables - [:@pending, :@fetching, :@results, :@dataloader]).map { |iv|
429
- payload_to_debug(iv.to_s, source.instance_variable_get(iv), intern_value: true)
430
- }
431
- ]
432
- )
484
+ extra_counter_track_uuids: @counts_objects,
485
+ extra_counter_values: [count_allocations]) {
486
+ [
487
+ payload_to_debug(nil, source.pending.values, iid: DA_FETCH_KEYS_IID, intern_value: true),
488
+ *(source.instance_variables - [:@pending, :@fetching, :@results, :@dataloader]).map { |iv|
489
+ payload_to_debug(iv.to_s, source.instance_variable_get(iv), intern_value: true)
490
+ }
491
+ ]
492
+ }
433
493
  @packets << packet
434
494
  fiber_flow_stack << packet
435
495
  super
436
496
  end
437
497
 
438
498
  def end_dataloader_source(source)
499
+ end_ts = ts
439
500
  @packets << trace_packet(
501
+ timestamp: end_ts,
440
502
  type: TrackEvent::Type::TYPE_SLICE_END,
441
503
  track_uuid: fid,
442
- extra_counter_track_uuids: [@objects_counter_id],
504
+ extra_counter_track_uuids: @counts_objects,
443
505
  extra_counter_values: [count_allocations],
444
506
  )
445
507
  fiber_flow_stack.pop
@@ -451,7 +513,7 @@ module GraphQL
451
513
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
452
514
  track_uuid: fid,
453
515
  category_iids: AUTHORIZED_CATEGORY_IIDS,
454
- extra_counter_track_uuids: [@objects_counter_id],
516
+ extra_counter_track_uuids: @counts_objects,
455
517
  extra_counter_values: [count_allocations],
456
518
  name_iid: @auth_name_iids[type],
457
519
  )
@@ -461,14 +523,18 @@ module GraphQL
461
523
  end
462
524
 
463
525
  def end_authorized(type, obj, ctx, is_authorized)
526
+ end_ts = ts
464
527
  @packets << trace_packet(
528
+ timestamp: end_ts,
465
529
  type: TrackEvent::Type::TYPE_SLICE_END,
466
530
  track_uuid: fid,
467
- extra_counter_track_uuids: [@objects_counter_id],
531
+ extra_counter_track_uuids: @counts_objects,
468
532
  extra_counter_values: [count_allocations],
469
533
  )
470
534
  beg_auth = fiber_flow_stack.pop
471
- beg_auth.track_event = dup_with(beg_auth.track_event, { debug_annotations: [payload_to_debug("authorized?", is_authorized)] })
535
+ if @create_debug_annotations
536
+ beg_auth.track_event = dup_with(beg_auth.track_event, { debug_annotations: [payload_to_debug("authorized?", is_authorized)] })
537
+ end
472
538
  super
473
539
  end
474
540
 
@@ -477,7 +543,7 @@ module GraphQL
477
543
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
478
544
  track_uuid: fid,
479
545
  category_iids: RESOLVE_TYPE_CATEGORY_IIDS,
480
- extra_counter_track_uuids: [@objects_counter_id],
546
+ extra_counter_track_uuids: @counts_objects,
481
547
  extra_counter_values: [count_allocations],
482
548
  name_iid: @resolve_type_name_iids[type],
483
549
  )
@@ -487,14 +553,18 @@ module GraphQL
487
553
  end
488
554
 
489
555
  def end_resolve_type(type, value, context, resolved_type)
556
+ end_ts = ts
490
557
  @packets << trace_packet(
558
+ timestamp: end_ts,
491
559
  type: TrackEvent::Type::TYPE_SLICE_END,
492
560
  track_uuid: fid,
493
- extra_counter_track_uuids: [@objects_counter_id],
561
+ extra_counter_track_uuids: @counts_objects,
494
562
  extra_counter_values: [count_allocations],
495
563
  )
496
564
  rt_begin = fiber_flow_stack.pop
497
- rt_begin.track_event = dup_with(rt_begin.track_event, { debug_annotations: [payload_to_debug("resolved_type", resolved_type, intern_value: true)] })
565
+ if @create_debug_annotations
566
+ rt_begin.track_event = dup_with(rt_begin.track_event, { debug_annotations: [payload_to_debug("resolved_type", resolved_type, intern_value: true)] })
567
+ end
498
568
  super
499
569
  end
500
570
 
@@ -535,6 +605,22 @@ module GraphQL
535
605
  Fiber.current.object_id
536
606
  end
537
607
 
608
+ class ArgumentsFilter
609
+ # From Rails defaults
610
+ # https://github.com/rails/rails/blob/main/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt#L6-L8
611
+ SENSITIVE_KEY = /passw|token|crypt|email|_key|salt|certificate|secret|ssn|cvv|cvc|otp/i
612
+ FILTERED = "[FILTERED]"
613
+
614
+ def filter_param(key, value)
615
+ if (key.is_a?(String) && SENSITIVE_KEY.match?(key)) ||
616
+ (key.is_a?(Symbol) && SENSITIVE_KEY.match?(key.name))
617
+ FILTERED
618
+ else
619
+ value
620
+ end
621
+ end
622
+ end
623
+
538
624
  def debug_annotation(iid, value_key, value)
539
625
  if iid
540
626
  DebugAnnotation.new(name_iid: iid, value_key => value)
@@ -546,7 +632,6 @@ module GraphQL
546
632
  def payload_to_debug(k, v, iid: nil, intern_value: false)
547
633
  if iid.nil?
548
634
  iid = @interned_da_name_ids[k]
549
- k = nil
550
635
  end
551
636
  case v
552
637
  when String
@@ -578,15 +663,56 @@ module GraphQL
578
663
  when Symbol
579
664
  debug_annotation(iid, :string_value, v.inspect)
580
665
  when Array
581
- debug_annotation(iid, :array_values, v.map { |v2| payload_to_debug(nil, v2, intern_value: intern_value) }.compact)
666
+ debug_annotation(iid, :array_values, v.each_with_index.map { |v2, idx| payload_to_debug((k ? "#{k}.#{idx}" : String(idx)), v2, intern_value: intern_value) }.compact)
582
667
  when Hash
583
- debug_annotation(iid, :dict_entries, v.map { |k2, v2| payload_to_debug(k2, v2, intern_value: intern_value) }.compact)
668
+ debug_v = v.map { |k2, v2|
669
+ debug_k = case k2
670
+ when String
671
+ k2
672
+ when Symbol
673
+ k2.name
674
+ else
675
+ String(k2)
676
+ end
677
+ filtered_v2 = @arguments_filter.filter_param(debug_k, v2)
678
+ payload_to_debug(debug_k, filtered_v2, intern_value: intern_value)
679
+ }
680
+ debug_v.compact!
681
+ debug_annotation(iid, :dict_entries, debug_v)
682
+ when GraphQL::Schema::InputObject
683
+ payload_to_debug(k, v.to_h, iid: iid, intern_value: intern_value)
584
684
  else
585
- debug_str = if defined?(ActiveRecord::Relation) && v.is_a?(ActiveRecord::Relation)
586
- "#{v.class}, .to_sql=#{v.to_sql.inspect}"
587
- else
588
- v.inspect
685
+ class_name_iid = @interned_da_string_values[v.class.name]
686
+ da = [
687
+ debug_annotation(DA_DEBUG_INSPECT_CLASS_IID, :string_value_iid, class_name_iid),
688
+ ]
689
+ if k
690
+ k_str_value_iid = @interned_da_string_values[k]
691
+ da << debug_annotation(DA_DEBUG_INSPECT_FOR_IID, :string_value_iid, k_str_value_iid)
692
+ elsif iid
693
+ k = REVERSE_DEBUG_NAME_LOOKUP[iid] || @interned_da_name_ids.key(iid)
694
+ if k.nil?
695
+ da << debug_annotation(DA_DEBUG_INSPECT_FOR_IID, :string_value_iid, DA_STR_VAL_NIL_IID)
696
+ else
697
+ k_str_value_iid = @interned_da_string_values[k]
698
+ da << debug_annotation(DA_DEBUG_INSPECT_FOR_IID, :string_value_iid, k_str_value_iid)
699
+ end
589
700
  end
701
+
702
+ @packets << trace_packet(
703
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
704
+ track_uuid: fid,
705
+ name_iid: DEBUG_INSPECT_EVENT_NAME_IID,
706
+ category_iids: DEBUG_INSPECT_CATEGORY_IIDS,
707
+ extra_counter_track_uuids: @counts_objects,
708
+ extra_counter_values: [count_allocations],
709
+ debug_annotations: da,
710
+ )
711
+ debug_str = @detailed_trace.inspect_object(v)
712
+ @packets << trace_packet(
713
+ type: TrackEvent::Type::TYPE_SLICE_END,
714
+ track_uuid: fid,
715
+ )
590
716
  if intern_value
591
717
  str_iid = @interned_da_string_values[debug_str]
592
718
  debug_annotation(iid, :string_value_iid, str_iid)
@@ -622,10 +748,14 @@ module GraphQL
622
748
  Fiber[:graphql_flow_stack] ||= []
623
749
  end
624
750
 
625
- def trace_packet(event_attrs)
751
+ def trace_packet(timestamp: ts, **event_attrs)
752
+ if @create_debug_annotations && block_given?
753
+ event_attrs[:debug_annotations] = yield
754
+ end
755
+ track_event = TrackEvent.new(event_attrs)
626
756
  TracePacket.new(
627
- timestamp: ts,
628
- track_event: TrackEvent.new(event_attrs),
757
+ timestamp: timestamp,
758
+ track_event: track_event,
629
759
  trusted_packet_sequence_id: @sequence_id,
630
760
  sequence_flags: 2,
631
761
  interned_data: new_interned_data
@@ -690,9 +820,9 @@ module GraphQL
690
820
 
691
821
  def subscribe_to_active_support_notifications(pattern)
692
822
  @as_subscriber = ActiveSupport::Notifications.monotonic_subscribe(pattern) do |name, start, finish, id, payload|
693
- metadata = payload.map { |k, v| payload_to_debug(k, v, intern_value: true) }
694
- metadata.compact!
695
- te = if metadata.empty?
823
+ metadata = @create_debug_annotations ? payload.map { |k, v| payload_to_debug(String(k), v, intern_value: true) } : nil
824
+ metadata&.compact!
825
+ te = if metadata.nil? || metadata.empty?
696
826
  TrackEvent.new(
697
827
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
698
828
  track_uuid: fid,
@@ -721,7 +851,7 @@ module GraphQL
721
851
  type: TrackEvent::Type::TYPE_SLICE_END,
722
852
  track_uuid: fid,
723
853
  name: name,
724
- extra_counter_track_uuids: [@objects_counter_id],
854
+ extra_counter_track_uuids: @counts_objects,
725
855
  extra_counter_values: [count_allocations]
726
856
  ),
727
857
  trusted_packet_sequence_id: @sequence_id,
@@ -41,7 +41,9 @@ module GraphQL
41
41
  if query.selected_operation_name
42
42
  span.set_data('graphql.operation.name', query.selected_operation_name)
43
43
  end
44
- span.set_data('graphql.operation.type', query.selected_operation.operation_type)
44
+ if query.selected_operation
45
+ span.set_data('graphql.operation.type', query.selected_operation.operation_type)
46
+ end
45
47
  end
46
48
  end
47
49
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.5.11"
3
+ VERSION = "2.5.19"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -4,7 +4,7 @@ require "json"
4
4
  require "set"
5
5
  require "singleton"
6
6
  require "forwardable"
7
- require "fiber/storage"
7
+ require "fiber/storage" if RUBY_VERSION < "3.2.0"
8
8
  require "graphql/autoload"
9
9
 
10
10
  module GraphQL
@@ -126,7 +126,10 @@ This is probably a bug in GraphQL-Ruby, please report this error on GitHub: http
126
126
  autoload :Testing, "graphql/testing"
127
127
  autoload :Current, "graphql/current"
128
128
  if defined?(::Rails::Engine)
129
- autoload :Dashboard, 'graphql/dashboard'
129
+ # This needs to be defined before Rails runs `add_routing_paths`,
130
+ # otherwise GraphQL::Dashboard's routes won't have been gathered for loading
131
+ # when that initializer runs.
132
+ require 'graphql/dashboard'
130
133
  end
131
134
  end
132
135
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.11
4
+ version: 2.5.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-07-09 00:00:00.000000000 Z
10
+ date: 2026-02-05 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -383,6 +383,7 @@ files:
383
383
  - ".yardopts"
384
384
  - MIT-LICENSE
385
385
  - lib/generators/graphql/core.rb
386
+ - lib/generators/graphql/detailed_trace_generator.rb
386
387
  - lib/generators/graphql/enum_generator.rb
387
388
  - lib/generators/graphql/field_extractor.rb
388
389
  - lib/generators/graphql/input_generator.rb
@@ -412,6 +413,7 @@ files:
412
413
  - lib/generators/graphql/templates/base_resolver.erb
413
414
  - lib/generators/graphql/templates/base_scalar.erb
414
415
  - lib/generators/graphql/templates/base_union.erb
416
+ - lib/generators/graphql/templates/create_graphql_detailed_traces.erb
415
417
  - lib/generators/graphql/templates/enum.erb
416
418
  - lib/generators/graphql/templates/graphql_controller.erb
417
419
  - lib/generators/graphql/templates/input.erb
@@ -729,6 +731,7 @@ files:
729
731
  - lib/graphql/subscriptions/serialize.rb
730
732
  - lib/graphql/testing.rb
731
733
  - lib/graphql/testing/helpers.rb
734
+ - lib/graphql/testing/mock_action_cable.rb
732
735
  - lib/graphql/tracing.rb
733
736
  - lib/graphql/tracing/active_support_notifications_trace.rb
734
737
  - lib/graphql/tracing/active_support_notifications_tracing.rb
@@ -740,6 +743,7 @@ files:
740
743
  - lib/graphql/tracing/data_dog_trace.rb
741
744
  - lib/graphql/tracing/data_dog_tracing.rb
742
745
  - lib/graphql/tracing/detailed_trace.rb
746
+ - lib/graphql/tracing/detailed_trace/active_record_backend.rb
743
747
  - lib/graphql/tracing/detailed_trace/memory_backend.rb
744
748
  - lib/graphql/tracing/detailed_trace/redis_backend.rb
745
749
  - lib/graphql/tracing/legacy_hooks_trace.rb
@@ -817,7 +821,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
817
821
  - !ruby/object:Gem::Version
818
822
  version: '0'
819
823
  requirements: []
820
- rubygems_version: 3.6.8
824
+ rubygems_version: 3.6.2
821
825
  specification_version: 4
822
826
  summary: A GraphQL language and runtime for Ruby
823
827
  test_files: []