graphql 1.13.24 → 2.5.11

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 (427) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
  3. data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
  4. data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
  5. data/lib/generators/graphql/install_generator.rb +50 -1
  6. data/lib/generators/graphql/mutation_delete_generator.rb +1 -1
  7. data/lib/generators/graphql/mutation_update_generator.rb +1 -1
  8. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  9. data/lib/generators/graphql/relay.rb +21 -18
  10. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  11. data/lib/generators/graphql/templates/base_connection.erb +2 -0
  12. data/lib/generators/graphql/templates/base_edge.erb +2 -0
  13. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  14. data/lib/generators/graphql/templates/base_field.erb +2 -0
  15. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  16. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  17. data/lib/generators/graphql/templates/base_object.erb +2 -0
  18. data/lib/generators/graphql/templates/base_resolver.erb +8 -0
  19. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  20. data/lib/generators/graphql/templates/base_union.erb +2 -0
  21. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  22. data/lib/generators/graphql/templates/loader.erb +2 -0
  23. data/lib/generators/graphql/templates/mutation.erb +2 -0
  24. data/lib/generators/graphql/templates/node_type.erb +2 -0
  25. data/lib/generators/graphql/templates/query_type.erb +2 -0
  26. data/lib/generators/graphql/templates/schema.erb +8 -0
  27. data/lib/generators/graphql/type_generator.rb +1 -1
  28. data/lib/graphql/analysis/analyzer.rb +90 -0
  29. data/lib/graphql/analysis/field_usage.rb +65 -28
  30. data/lib/graphql/analysis/max_query_complexity.rb +11 -17
  31. data/lib/graphql/analysis/max_query_depth.rb +13 -19
  32. data/lib/graphql/analysis/query_complexity.rb +236 -61
  33. data/lib/graphql/analysis/query_depth.rb +38 -23
  34. data/lib/graphql/analysis/visitor.rb +280 -0
  35. data/lib/graphql/analysis.rb +93 -6
  36. data/lib/graphql/autoload.rb +38 -0
  37. data/lib/graphql/backtrace/table.rb +118 -73
  38. data/lib/graphql/backtrace.rb +2 -25
  39. data/lib/graphql/coercion_error.rb +1 -9
  40. data/lib/graphql/current.rb +57 -0
  41. data/lib/graphql/dashboard/detailed_traces.rb +47 -0
  42. data/lib/graphql/dashboard/installable.rb +22 -0
  43. data/lib/graphql/dashboard/limiters.rb +93 -0
  44. data/lib/graphql/dashboard/operation_store.rb +199 -0
  45. data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
  46. data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
  47. data/lib/graphql/dashboard/statics/charts.min.css +1 -0
  48. data/lib/graphql/dashboard/statics/dashboard.css +30 -0
  49. data/lib/graphql/dashboard/statics/dashboard.js +143 -0
  50. data/lib/graphql/dashboard/statics/header-icon.png +0 -0
  51. data/lib/graphql/dashboard/statics/icon.png +0 -0
  52. data/lib/graphql/dashboard/subscriptions.rb +96 -0
  53. data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
  54. data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
  55. data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
  56. data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
  57. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +23 -0
  58. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
  59. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
  60. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
  61. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
  62. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
  63. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
  64. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
  65. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
  66. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
  67. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
  68. data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
  69. data/lib/graphql/dashboard.rb +158 -0
  70. data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
  71. data/lib/graphql/dataloader/active_record_source.rb +47 -0
  72. data/lib/graphql/dataloader/async_dataloader.rb +101 -0
  73. data/lib/graphql/dataloader/null_dataloader.rb +11 -2
  74. data/lib/graphql/dataloader/request.rb +5 -0
  75. data/lib/graphql/dataloader/source.rb +103 -47
  76. data/lib/graphql/dataloader.rb +174 -148
  77. data/lib/graphql/dig.rb +3 -2
  78. data/lib/graphql/duration_encoding_error.rb +16 -0
  79. data/lib/graphql/execution/errors.rb +12 -82
  80. data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
  81. data/lib/graphql/execution/interpreter/arguments.rb +1 -1
  82. data/lib/graphql/execution/interpreter/arguments_cache.rb +30 -35
  83. data/lib/graphql/execution/interpreter/resolve.rb +32 -2
  84. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +215 -0
  85. data/lib/graphql/execution/interpreter/runtime.rb +525 -502
  86. data/lib/graphql/execution/interpreter.rb +127 -81
  87. data/lib/graphql/execution/lazy.rb +7 -21
  88. data/lib/graphql/execution/lookahead.rb +133 -55
  89. data/lib/graphql/execution/multiplex.rb +6 -176
  90. data/lib/graphql/execution.rb +11 -4
  91. data/lib/graphql/introspection/directive_location_enum.rb +1 -1
  92. data/lib/graphql/introspection/directive_type.rb +1 -1
  93. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  94. data/lib/graphql/introspection/entry_points.rb +10 -17
  95. data/lib/graphql/introspection/field_type.rb +1 -1
  96. data/lib/graphql/introspection/schema_type.rb +8 -11
  97. data/lib/graphql/introspection/type_type.rb +13 -6
  98. data/lib/graphql/introspection.rb +4 -3
  99. data/lib/graphql/invalid_name_error.rb +1 -1
  100. data/lib/graphql/invalid_null_error.rb +20 -17
  101. data/lib/graphql/language/block_string.rb +34 -18
  102. data/lib/graphql/language/cache.rb +13 -0
  103. data/lib/graphql/language/comment.rb +18 -0
  104. data/lib/graphql/language/definition_slice.rb +1 -1
  105. data/lib/graphql/language/document_from_schema_definition.rb +114 -80
  106. data/lib/graphql/language/lexer.rb +375 -1489
  107. data/lib/graphql/language/nodes.rb +189 -104
  108. data/lib/graphql/language/parser.rb +807 -1941
  109. data/lib/graphql/language/printer.rb +366 -163
  110. data/lib/graphql/language/sanitized_printer.rb +21 -23
  111. data/lib/graphql/language/static_visitor.rb +171 -0
  112. data/lib/graphql/language/visitor.rb +189 -138
  113. data/lib/graphql/language.rb +62 -1
  114. data/lib/graphql/load_application_object_failed_error.rb +5 -1
  115. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  116. data/lib/graphql/pagination/array_connection.rb +8 -6
  117. data/lib/graphql/pagination/connection.rb +61 -7
  118. data/lib/graphql/pagination/connections.rb +3 -28
  119. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
  120. data/lib/graphql/pagination/relation_connection.rb +2 -0
  121. data/lib/graphql/query/context/scoped_context.rb +101 -0
  122. data/lib/graphql/query/context.rb +131 -225
  123. data/lib/graphql/query/input_validation_result.rb +1 -1
  124. data/lib/graphql/query/null_context.rb +11 -33
  125. data/lib/graphql/query/partial.rb +179 -0
  126. data/lib/graphql/query/validation_pipeline.rb +14 -37
  127. data/lib/graphql/query/variable_validation_error.rb +1 -1
  128. data/lib/graphql/query/variables.rb +6 -19
  129. data/lib/graphql/query.rb +162 -98
  130. data/lib/graphql/railtie.rb +15 -109
  131. data/lib/graphql/rake_task/validate.rb +1 -1
  132. data/lib/graphql/rake_task.rb +30 -11
  133. data/lib/graphql/relay/range_add.rb +9 -20
  134. data/lib/graphql/relay.rb +0 -15
  135. data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
  136. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
  137. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
  138. data/lib/graphql/rubocop.rb +2 -0
  139. data/lib/graphql/schema/addition.rb +70 -33
  140. data/lib/graphql/schema/always_visible.rb +15 -0
  141. data/lib/graphql/schema/argument.rb +104 -59
  142. data/lib/graphql/schema/base_64_encoder.rb +3 -5
  143. data/lib/graphql/schema/build_from_definition.rb +154 -74
  144. data/lib/graphql/schema/directive/flagged.rb +4 -2
  145. data/lib/graphql/schema/directive/one_of.rb +24 -0
  146. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  147. data/lib/graphql/schema/directive/transform.rb +1 -1
  148. data/lib/graphql/schema/directive.rb +47 -24
  149. data/lib/graphql/schema/enum.rb +137 -65
  150. data/lib/graphql/schema/enum_value.rb +11 -26
  151. data/lib/graphql/schema/field/connection_extension.rb +6 -16
  152. data/lib/graphql/schema/field/scope_extension.rb +8 -1
  153. data/lib/graphql/schema/field.rb +399 -404
  154. data/lib/graphql/schema/field_extension.rb +2 -5
  155. data/lib/graphql/schema/find_inherited_value.rb +2 -7
  156. data/lib/graphql/schema/has_single_input_argument.rb +160 -0
  157. data/lib/graphql/schema/input_object.rb +144 -99
  158. data/lib/graphql/schema/interface.rb +34 -51
  159. data/lib/graphql/schema/introspection_system.rb +12 -26
  160. data/lib/graphql/schema/late_bound_type.rb +12 -2
  161. data/lib/graphql/schema/list.rb +3 -9
  162. data/lib/graphql/schema/loader.rb +4 -6
  163. data/lib/graphql/schema/member/base_dsl_methods.rb +32 -18
  164. data/lib/graphql/schema/member/build_type.rb +15 -9
  165. data/lib/graphql/schema/member/has_arguments.rb +192 -96
  166. data/lib/graphql/schema/member/has_ast_node.rb +12 -0
  167. data/lib/graphql/schema/member/has_dataloader.rb +62 -0
  168. data/lib/graphql/schema/member/has_deprecation_reason.rb +18 -4
  169. data/lib/graphql/schema/member/has_directives.rb +81 -61
  170. data/lib/graphql/schema/member/has_fields.rb +119 -39
  171. data/lib/graphql/schema/member/has_interfaces.rb +66 -23
  172. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  173. data/lib/graphql/schema/member/has_validators.rb +32 -6
  174. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  175. data/lib/graphql/schema/member/scoped.rb +19 -0
  176. data/lib/graphql/schema/member/type_system_helpers.rb +32 -2
  177. data/lib/graphql/schema/member/validates_input.rb +4 -4
  178. data/lib/graphql/schema/member.rb +1 -6
  179. data/lib/graphql/schema/mutation.rb +7 -9
  180. data/lib/graphql/schema/non_null.rb +1 -7
  181. data/lib/graphql/schema/object.rb +42 -49
  182. data/lib/graphql/schema/printer.rb +12 -8
  183. data/lib/graphql/schema/ractor_shareable.rb +79 -0
  184. data/lib/graphql/schema/relay_classic_mutation.rb +12 -124
  185. data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
  186. data/lib/graphql/schema/resolver.rb +96 -81
  187. data/lib/graphql/schema/scalar.rb +10 -30
  188. data/lib/graphql/schema/subscription.rb +60 -14
  189. data/lib/graphql/schema/timeout.rb +44 -31
  190. data/lib/graphql/schema/type_expression.rb +2 -2
  191. data/lib/graphql/schema/type_membership.rb +3 -0
  192. data/lib/graphql/schema/union.rb +12 -19
  193. data/lib/graphql/schema/unique_within_type.rb +1 -1
  194. data/lib/graphql/schema/validator/all_validator.rb +62 -0
  195. data/lib/graphql/schema/validator/required_validator.rb +60 -10
  196. data/lib/graphql/schema/validator.rb +5 -3
  197. data/lib/graphql/schema/visibility/migration.rb +188 -0
  198. data/lib/graphql/schema/visibility/profile.rb +445 -0
  199. data/lib/graphql/schema/visibility/visit.rb +190 -0
  200. data/lib/graphql/schema/visibility.rb +311 -0
  201. data/lib/graphql/schema/warden.rb +318 -94
  202. data/lib/graphql/schema/wrapper.rb +0 -5
  203. data/lib/graphql/schema.rb +1148 -1085
  204. data/lib/graphql/static_validation/all_rules.rb +4 -3
  205. data/lib/graphql/static_validation/base_visitor.rb +11 -27
  206. data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
  207. data/lib/graphql/static_validation/error.rb +2 -2
  208. data/lib/graphql/static_validation/literal_validator.rb +24 -7
  209. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  210. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
  211. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
  212. data/lib/graphql/static_validation/rules/directives_are_defined.rb +13 -7
  213. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -12
  214. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
  215. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +48 -6
  216. data/lib/graphql/static_validation/rules/fields_will_merge.rb +90 -27
  217. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
  218. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  219. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
  220. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  221. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  222. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
  223. data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
  224. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  225. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  226. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  227. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -5
  228. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
  229. data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
  230. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +19 -9
  231. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  232. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
  233. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  234. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
  235. data/lib/graphql/static_validation/validation_context.rb +21 -5
  236. data/lib/graphql/static_validation/validator.rb +12 -26
  237. data/lib/graphql/static_validation.rb +0 -3
  238. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +14 -6
  239. data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
  240. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +40 -1
  241. data/lib/graphql/subscriptions/event.rb +24 -12
  242. data/lib/graphql/subscriptions/serialize.rb +3 -1
  243. data/lib/graphql/subscriptions.rb +48 -32
  244. data/lib/graphql/testing/helpers.rb +158 -0
  245. data/lib/graphql/testing.rb +2 -0
  246. data/lib/graphql/tracing/active_support_notifications_trace.rb +27 -0
  247. data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
  248. data/lib/graphql/tracing/appoptics_trace.rb +259 -0
  249. data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
  250. data/lib/graphql/tracing/appsignal_trace.rb +54 -0
  251. data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
  252. data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
  253. data/lib/graphql/tracing/data_dog_trace.rb +71 -0
  254. data/lib/graphql/tracing/data_dog_tracing.rb +3 -0
  255. data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
  256. data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
  257. data/lib/graphql/tracing/detailed_trace.rb +93 -0
  258. data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +11 -28
  259. data/lib/graphql/tracing/legacy_trace.rb +12 -0
  260. data/lib/graphql/tracing/monitor_trace.rb +283 -0
  261. data/lib/graphql/tracing/new_relic_trace.rb +68 -0
  262. data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
  263. data/lib/graphql/tracing/notifications_trace.rb +195 -0
  264. data/lib/graphql/tracing/notifications_tracing.rb +2 -0
  265. data/lib/graphql/tracing/null_trace.rb +9 -0
  266. data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
  267. data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
  268. data/lib/graphql/tracing/perfetto_trace.rb +734 -0
  269. data/lib/graphql/tracing/platform_trace.rb +123 -0
  270. data/lib/graphql/tracing/platform_tracing.rb +28 -41
  271. data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +6 -2
  272. data/lib/graphql/tracing/prometheus_trace.rb +93 -0
  273. data/lib/graphql/tracing/prometheus_tracing.rb +5 -3
  274. data/lib/graphql/tracing/scout_trace.rb +49 -0
  275. data/lib/graphql/tracing/scout_tracing.rb +2 -0
  276. data/lib/graphql/tracing/sentry_trace.rb +80 -0
  277. data/lib/graphql/tracing/statsd_trace.rb +48 -0
  278. data/lib/graphql/tracing/statsd_tracing.rb +2 -0
  279. data/lib/graphql/tracing/trace.rb +186 -0
  280. data/lib/graphql/tracing.rb +32 -52
  281. data/lib/graphql/type_kinds.rb +8 -4
  282. data/lib/graphql/types/iso_8601_date.rb +4 -1
  283. data/lib/graphql/types/iso_8601_date_time.rb +4 -0
  284. data/lib/graphql/types/iso_8601_duration.rb +77 -0
  285. data/lib/graphql/types/relay/base_connection.rb +16 -6
  286. data/lib/graphql/types/relay/connection_behaviors.rb +65 -23
  287. data/lib/graphql/types/relay/edge_behaviors.rb +33 -5
  288. data/lib/graphql/types/relay/node_behaviors.rb +12 -2
  289. data/lib/graphql/types/relay/page_info_behaviors.rb +11 -2
  290. data/lib/graphql/types/relay.rb +0 -3
  291. data/lib/graphql/types/string.rb +1 -1
  292. data/lib/graphql/types.rb +18 -10
  293. data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
  294. data/lib/graphql/version.rb +1 -1
  295. data/lib/graphql.rb +76 -123
  296. data/readme.md +13 -3
  297. metadata +225 -142
  298. data/lib/graphql/analysis/analyze_query.rb +0 -98
  299. data/lib/graphql/analysis/ast/analyzer.rb +0 -84
  300. data/lib/graphql/analysis/ast/field_usage.rb +0 -55
  301. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -23
  302. data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
  303. data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
  304. data/lib/graphql/analysis/ast/query_depth.rb +0 -56
  305. data/lib/graphql/analysis/ast/visitor.rb +0 -269
  306. data/lib/graphql/analysis/ast.rb +0 -91
  307. data/lib/graphql/analysis/reducer_state.rb +0 -48
  308. data/lib/graphql/argument.rb +0 -131
  309. data/lib/graphql/authorization.rb +0 -82
  310. data/lib/graphql/backtrace/inspect_result.rb +0 -50
  311. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  312. data/lib/graphql/backtrace/tracer.rb +0 -81
  313. data/lib/graphql/backwards_compatibility.rb +0 -61
  314. data/lib/graphql/base_type.rb +0 -232
  315. data/lib/graphql/boolean_type.rb +0 -2
  316. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  317. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  318. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  319. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  320. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  321. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  322. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  323. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  324. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  325. data/lib/graphql/compatibility.rb +0 -5
  326. data/lib/graphql/define/assign_argument.rb +0 -12
  327. data/lib/graphql/define/assign_connection.rb +0 -13
  328. data/lib/graphql/define/assign_enum_value.rb +0 -18
  329. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  330. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  331. data/lib/graphql/define/assign_object_field.rb +0 -42
  332. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  333. data/lib/graphql/define/instance_definable.rb +0 -255
  334. data/lib/graphql/define/no_definition_error.rb +0 -7
  335. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  336. data/lib/graphql/define/type_definer.rb +0 -31
  337. data/lib/graphql/define.rb +0 -31
  338. data/lib/graphql/deprecated_dsl.rb +0 -55
  339. data/lib/graphql/deprecation.rb +0 -9
  340. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  341. data/lib/graphql/directive/include_directive.rb +0 -2
  342. data/lib/graphql/directive/skip_directive.rb +0 -2
  343. data/lib/graphql/directive.rb +0 -107
  344. data/lib/graphql/enum_type.rb +0 -133
  345. data/lib/graphql/execution/execute.rb +0 -333
  346. data/lib/graphql/execution/flatten.rb +0 -40
  347. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  348. data/lib/graphql/execution/typecast.rb +0 -50
  349. data/lib/graphql/field/resolve.rb +0 -59
  350. data/lib/graphql/field.rb +0 -226
  351. data/lib/graphql/filter.rb +0 -53
  352. data/lib/graphql/float_type.rb +0 -2
  353. data/lib/graphql/function.rb +0 -128
  354. data/lib/graphql/id_type.rb +0 -2
  355. data/lib/graphql/input_object_type.rb +0 -138
  356. data/lib/graphql/int_type.rb +0 -2
  357. data/lib/graphql/interface_type.rb +0 -72
  358. data/lib/graphql/internal_representation/document.rb +0 -27
  359. data/lib/graphql/internal_representation/node.rb +0 -206
  360. data/lib/graphql/internal_representation/print.rb +0 -51
  361. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  362. data/lib/graphql/internal_representation/scope.rb +0 -88
  363. data/lib/graphql/internal_representation/visit.rb +0 -36
  364. data/lib/graphql/internal_representation.rb +0 -7
  365. data/lib/graphql/language/lexer.rl +0 -260
  366. data/lib/graphql/language/parser.y +0 -550
  367. data/lib/graphql/language/token.rb +0 -34
  368. data/lib/graphql/list_type.rb +0 -80
  369. data/lib/graphql/non_null_type.rb +0 -71
  370. data/lib/graphql/object_type.rb +0 -130
  371. data/lib/graphql/query/arguments.rb +0 -189
  372. data/lib/graphql/query/arguments_cache.rb +0 -24
  373. data/lib/graphql/query/executor.rb +0 -52
  374. data/lib/graphql/query/literal_input.rb +0 -136
  375. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  376. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  377. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  378. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  379. data/lib/graphql/query/serial_execution.rb +0 -40
  380. data/lib/graphql/relay/array_connection.rb +0 -83
  381. data/lib/graphql/relay/base_connection.rb +0 -189
  382. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  383. data/lib/graphql/relay/connection_resolve.rb +0 -43
  384. data/lib/graphql/relay/connection_type.rb +0 -54
  385. data/lib/graphql/relay/edge.rb +0 -27
  386. data/lib/graphql/relay/edge_type.rb +0 -19
  387. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  388. data/lib/graphql/relay/global_id_resolve.rb +0 -17
  389. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  390. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  391. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  392. data/lib/graphql/relay/mutation/result.rb +0 -38
  393. data/lib/graphql/relay/mutation.rb +0 -106
  394. data/lib/graphql/relay/node.rb +0 -39
  395. data/lib/graphql/relay/page_info.rb +0 -7
  396. data/lib/graphql/relay/relation_connection.rb +0 -188
  397. data/lib/graphql/relay/type_extensions.rb +0 -32
  398. data/lib/graphql/scalar_type.rb +0 -91
  399. data/lib/graphql/schema/base_64_bp.rb +0 -26
  400. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  401. data/lib/graphql/schema/default_parse_error.rb +0 -10
  402. data/lib/graphql/schema/default_type_error.rb +0 -17
  403. data/lib/graphql/schema/invalid_type_error.rb +0 -7
  404. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  405. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  406. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  407. data/lib/graphql/schema/middleware_chain.rb +0 -82
  408. data/lib/graphql/schema/null_mask.rb +0 -11
  409. data/lib/graphql/schema/possible_types.rb +0 -44
  410. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  411. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  412. data/lib/graphql/schema/traversal.rb +0 -228
  413. data/lib/graphql/schema/validation.rb +0 -313
  414. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  415. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  416. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
  417. data/lib/graphql/static_validation/type_stack.rb +0 -216
  418. data/lib/graphql/string_type.rb +0 -2
  419. data/lib/graphql/subscriptions/instrumentation.rb +0 -79
  420. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  421. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  422. data/lib/graphql/types/relay/default_relay.rb +0 -31
  423. data/lib/graphql/types/relay/node_field.rb +0 -24
  424. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  425. data/lib/graphql/union_type.rb +0 -115
  426. data/lib/graphql/upgrader/member.rb +0 -937
  427. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -0,0 +1,734 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Tracing
4
+ # This produces a trace file for inspecting in the [Perfetto Trace Viewer](https://ui.perfetto.dev).
5
+ #
6
+ # To get the file, call {#write} on the trace.
7
+ #
8
+ # Use "trace modes" to configure this to run on command or on a sample of traffic.
9
+ #
10
+ # @example Writing trace output
11
+ #
12
+ # result = MySchema.execute(...)
13
+ # result.query.trace.write(file: "tmp/trace.dump")
14
+ #
15
+ # @example Running this instrumenter when `trace: true` is present in the request
16
+ #
17
+ # class MySchema < GraphQL::Schema
18
+ # # Only run this tracer when `context[:trace_mode]` is `:trace`
19
+ # trace_with GraphQL::Tracing::Perfetto, mode: :trace
20
+ # end
21
+ #
22
+ # # In graphql_controller.rb:
23
+ #
24
+ # context[:trace_mode] = params[:trace] ? :trace : nil
25
+ # result = MySchema.execute(query_str, context: context, variables: variables, ...)
26
+ # if context[:trace_mode] == :trace
27
+ # result.trace.write(file: ...)
28
+ # end
29
+ #
30
+ module PerfettoTrace
31
+ # TODOs:
32
+ # - Make debug annotations visible on both parts when dataloader is involved
33
+
34
+ PROTOBUF_AVAILABLE = begin
35
+ require "google/protobuf"
36
+ true
37
+ rescue LoadError
38
+ false
39
+ end
40
+
41
+ if PROTOBUF_AVAILABLE
42
+ require "graphql/tracing/perfetto_trace/trace_pb"
43
+ end
44
+
45
+ def self.included(_trace_class)
46
+ if !PROTOBUF_AVAILABLE
47
+ raise "#{self} can't be used because the `google-protobuf` gem wasn't available. Add it to your project, then try again."
48
+ end
49
+ end
50
+
51
+ DATALOADER_CATEGORY_IIDS = [5]
52
+ FIELD_EXECUTE_CATEGORY_IIDS = [6]
53
+ ACTIVE_SUPPORT_NOTIFICATIONS_CATEGORY_IIDS = [7]
54
+ AUTHORIZED_CATEGORY_IIDS = [8]
55
+ RESOLVE_TYPE_CATEGORY_IIDS = [9]
56
+
57
+ DA_OBJECT_IID = 10
58
+ DA_RESULT_IID = 11
59
+ DA_ARGUMENTS_IID = 12
60
+ DA_FETCH_KEYS_IID = 13
61
+ DA_STR_VAL_NIL_IID = 14
62
+
63
+ # @param active_support_notifications_pattern [String, RegExp, false] A filter for `ActiveSupport::Notifications`, if it's present. Or `false` to skip subscribing.
64
+ def initialize(active_support_notifications_pattern: nil, save_profile: false, **_rest)
65
+ super
66
+ @active_support_notifications_pattern = active_support_notifications_pattern
67
+ @save_profile = save_profile
68
+ Fiber[:graphql_flow_stack] = nil
69
+ @sequence_id = object_id
70
+ @pid = Process.pid
71
+ @flow_ids = Hash.new { |h, source_inst| h[source_inst] = [] }.compare_by_identity
72
+ @new_interned_event_names = {}
73
+ @interned_event_name_iids = Hash.new { |h, k|
74
+ new_id = 100 + h.size
75
+ @new_interned_event_names[k] = new_id
76
+ h[k] = new_id
77
+ }
78
+
79
+ @source_name_iids = Hash.new do |h, source_class|
80
+ h[source_class] = @interned_event_name_iids[source_class.name]
81
+ end.compare_by_identity
82
+
83
+ @auth_name_iids = Hash.new do |h, graphql_type|
84
+ h[graphql_type] = @interned_event_name_iids["Authorize: #{graphql_type.graphql_name}"]
85
+ end.compare_by_identity
86
+
87
+ @resolve_type_name_iids = Hash.new do |h, graphql_type|
88
+ h[graphql_type] = @interned_event_name_iids["Resolve Type: #{graphql_type.graphql_name}"]
89
+ end.compare_by_identity
90
+
91
+ @new_interned_da_names = {}
92
+ @interned_da_name_ids = Hash.new { |h, k|
93
+ next_id = 100 + h.size
94
+ @new_interned_da_names[k] = next_id
95
+ h[k] = next_id
96
+ }
97
+
98
+ @new_interned_da_string_values = {}
99
+ @interned_da_string_values = Hash.new do |h, k|
100
+ new_id = 100 + h.size
101
+ @new_interned_da_string_values[k] = new_id
102
+ h[k] = new_id
103
+ end
104
+
105
+ @class_name_iids = Hash.new do |h, k|
106
+ h[k] = @interned_da_string_values[k.name]
107
+ end.compare_by_identity
108
+
109
+ @starting_objects = GC.stat(:total_allocated_objects)
110
+ @objects_counter_id = :objects_counter.object_id
111
+ @fibers_counter_id = :fibers_counter.object_id
112
+ @fields_counter_id = :fields_counter.object_id
113
+ @begin_validate = nil
114
+ @begin_time = nil
115
+ @packets = []
116
+ @packets << TracePacket.new(
117
+ track_descriptor: TrackDescriptor.new(
118
+ uuid: tid,
119
+ name: "Main Thread",
120
+ child_ordering: TrackDescriptor::ChildTracksOrdering::CHRONOLOGICAL,
121
+ ),
122
+ first_packet_on_sequence: true,
123
+ previous_packet_dropped: true,
124
+ trusted_packet_sequence_id: @sequence_id,
125
+ sequence_flags: 3,
126
+ )
127
+ @packets << TracePacket.new(
128
+ interned_data: InternedData.new(
129
+ event_categories: [
130
+ EventCategory.new(name: "Dataloader", iid: DATALOADER_CATEGORY_IIDS.first),
131
+ EventCategory.new(name: "Field Execution", iid: FIELD_EXECUTE_CATEGORY_IIDS.first),
132
+ EventCategory.new(name: "ActiveSupport::Notifications", iid: ACTIVE_SUPPORT_NOTIFICATIONS_CATEGORY_IIDS.first),
133
+ EventCategory.new(name: "Authorized", iid: AUTHORIZED_CATEGORY_IIDS.first),
134
+ EventCategory.new(name: "Resolve Type", iid: RESOLVE_TYPE_CATEGORY_IIDS.first),
135
+ ],
136
+ 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),
141
+ ],
142
+ debug_annotation_string_values: [
143
+ InternedString.new(str: "(nil)", iid: DA_STR_VAL_NIL_IID),
144
+ ],
145
+ ),
146
+ trusted_packet_sequence_id: @sequence_id,
147
+ sequence_flags: 2,
148
+ )
149
+ @main_fiber_id = fid
150
+ @packets << track_descriptor_packet(tid, fid, "Main Fiber")
151
+ @packets << track_descriptor_packet(tid, @objects_counter_id, "Allocated Objects", counter: {})
152
+ @packets << trace_packet(
153
+ type: TrackEvent::Type::TYPE_COUNTER,
154
+ track_uuid: @objects_counter_id,
155
+ counter_value: count_allocations,
156
+ )
157
+ @packets << track_descriptor_packet(tid, @fibers_counter_id, "Active Fibers", counter: {})
158
+ @fibers_count = 0
159
+ @packets << trace_packet(
160
+ type: TrackEvent::Type::TYPE_COUNTER,
161
+ track_uuid: @fibers_counter_id,
162
+ counter_value: count_fibers(0),
163
+ )
164
+
165
+ @packets << track_descriptor_packet(tid, @fields_counter_id, "Resolved Fields", counter: {})
166
+ @fields_count = -1
167
+ @packets << trace_packet(
168
+ type: TrackEvent::Type::TYPE_COUNTER,
169
+ track_uuid: @fields_counter_id,
170
+ counter_value: count_fields,
171
+ )
172
+ end
173
+
174
+ def execute_multiplex(multiplex:)
175
+ if defined?(ActiveSupport::Notifications) && @active_support_notifications_pattern != false
176
+ subscribe_to_active_support_notifications(@active_support_notifications_pattern)
177
+ end
178
+ @operation_name = multiplex.queries.map { |q| q.selected_operation_name || "anonymous" }.join(",")
179
+ @begin_time = Time.now
180
+ @packets << trace_packet(
181
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
182
+ 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
+ )
188
+ result = super
189
+
190
+ @packets << trace_packet(
191
+ type: TrackEvent::Type::TYPE_SLICE_END,
192
+ track_uuid: fid,
193
+ )
194
+
195
+ result
196
+ ensure
197
+ unsubscribe_from_active_support_notifications
198
+ if @save_profile
199
+ begin_ts = (@begin_time.to_f * 1000).round
200
+ end_ts = (Time.now.to_f * 1000).round
201
+ duration_ms = end_ts - begin_ts
202
+ multiplex.schema.detailed_trace.save_trace(@operation_name, duration_ms, begin_ts, Trace.encode(Trace.new(packet: @packets)))
203
+ end
204
+ end
205
+
206
+ def begin_execute_field(field, object, arguments, query)
207
+ packet = trace_packet(
208
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
209
+ track_uuid: fid,
210
+ name: query.context.current_path.join("."),
211
+ category_iids: FIELD_EXECUTE_CATEGORY_IIDS,
212
+ extra_counter_track_uuids: [@objects_counter_id],
213
+ extra_counter_values: [count_allocations],
214
+ )
215
+ @packets << packet
216
+ fiber_flow_stack << packet
217
+ super
218
+ end
219
+
220
+ def end_execute_field(field, object, arguments, query, app_result)
221
+ 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
+ })
229
+
230
+ @packets << trace_packet(
231
+ type: TrackEvent::Type::TYPE_SLICE_END,
232
+ track_uuid: fid,
233
+ extra_counter_track_uuids: [@objects_counter_id, @fields_counter_id],
234
+ extra_counter_values: [count_allocations, count_fields],
235
+ )
236
+ super
237
+ end
238
+
239
+ def begin_analyze_multiplex(m, analyzers)
240
+ @packets << trace_packet(
241
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
242
+ track_uuid: fid,
243
+ extra_counter_track_uuids: [@objects_counter_id],
244
+ 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
+ )
251
+ super
252
+ end
253
+
254
+ def end_analyze_multiplex(m, analyzers)
255
+ @packets << trace_packet(
256
+ type: TrackEvent::Type::TYPE_SLICE_END,
257
+ track_uuid: fid,
258
+ extra_counter_track_uuids: [@objects_counter_id],
259
+ extra_counter_values: [count_allocations],
260
+ )
261
+ super
262
+ end
263
+
264
+ def parse(query_string:)
265
+ @packets << trace_packet(
266
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
267
+ track_uuid: fid,
268
+ extra_counter_track_uuids: [@objects_counter_id],
269
+ extra_counter_values: [count_allocations],
270
+ name: "Parse"
271
+ )
272
+ result = super
273
+ @packets << trace_packet(
274
+ type: TrackEvent::Type::TYPE_SLICE_END,
275
+ track_uuid: fid,
276
+ extra_counter_track_uuids: [@objects_counter_id],
277
+ extra_counter_values: [count_allocations],
278
+ )
279
+ result
280
+ end
281
+
282
+ def begin_validate(query, validate)
283
+ @packets << @begin_validate = trace_packet(
284
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
285
+ track_uuid: fid,
286
+ extra_counter_track_uuids: [@objects_counter_id],
287
+ extra_counter_values: [count_allocations],
288
+ name: "Validate",
289
+ debug_annotations: [
290
+ payload_to_debug("validate?", validate),
291
+ ]
292
+ )
293
+ super
294
+ end
295
+
296
+ def end_validate(query, validate, validation_errors)
297
+ @packets << trace_packet(
298
+ type: TrackEvent::Type::TYPE_SLICE_END,
299
+ track_uuid: fid,
300
+ extra_counter_track_uuids: [@objects_counter_id],
301
+ extra_counter_values: [count_allocations],
302
+ )
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
+ )
312
+ super
313
+ end
314
+
315
+ def dataloader_spawn_execution_fiber(jobs)
316
+ @packets << trace_packet(
317
+ type: TrackEvent::Type::TYPE_INSTANT,
318
+ track_uuid: fid,
319
+ name: "Create Execution Fiber",
320
+ category_iids: DATALOADER_CATEGORY_IIDS,
321
+ extra_counter_track_uuids: [@fibers_counter_id, @objects_counter_id],
322
+ extra_counter_values: [count_fibers(1), count_allocations]
323
+ )
324
+ @packets << track_descriptor_packet(@did, fid, "Exec Fiber ##{fid}")
325
+ super
326
+ end
327
+
328
+ def dataloader_spawn_source_fiber(pending_sources)
329
+ @packets << trace_packet(
330
+ type: TrackEvent::Type::TYPE_INSTANT,
331
+ track_uuid: fid,
332
+ name: "Create Source Fiber",
333
+ category_iids: DATALOADER_CATEGORY_IIDS,
334
+ extra_counter_track_uuids: [@fibers_counter_id, @objects_counter_id],
335
+ extra_counter_values: [count_fibers(1), count_allocations]
336
+ )
337
+ @packets << track_descriptor_packet(@did, fid, "Source Fiber ##{fid}")
338
+ super
339
+ end
340
+
341
+ def dataloader_fiber_yield(source)
342
+ ls = fiber_flow_stack.last
343
+ if (flow_id = ls.track_event.flow_ids.first)
344
+ # got it
345
+ else
346
+ flow_id = ls.track_event.name.object_id
347
+ ls.track_event = dup_with(ls.track_event, {flow_ids: [flow_id] }, delete_counters: true)
348
+ end
349
+ @flow_ids[source] << flow_id
350
+ @packets << trace_packet(
351
+ type: TrackEvent::Type::TYPE_SLICE_END,
352
+ track_uuid: fid,
353
+ )
354
+ @packets << trace_packet(
355
+ type: TrackEvent::Type::TYPE_INSTANT,
356
+ track_uuid: fid,
357
+ name: "Fiber Yield",
358
+ category_iids: DATALOADER_CATEGORY_IIDS,
359
+ )
360
+ super
361
+ end
362
+
363
+ def dataloader_fiber_resume(source)
364
+ @packets << trace_packet(
365
+ type: TrackEvent::Type::TYPE_INSTANT,
366
+ track_uuid: fid,
367
+ name: "Fiber Resume",
368
+ category_iids: DATALOADER_CATEGORY_IIDS,
369
+ )
370
+
371
+ ls = fiber_flow_stack.pop
372
+ @packets << packet = TracePacket.new(
373
+ timestamp: ts,
374
+ track_event: dup_with(ls.track_event, { type: TrackEvent::Type::TYPE_SLICE_BEGIN }),
375
+ trusted_packet_sequence_id: @sequence_id,
376
+ )
377
+ fiber_flow_stack << packet
378
+
379
+ super
380
+ end
381
+
382
+ def dataloader_fiber_exit
383
+ @packets << trace_packet(
384
+ type: TrackEvent::Type::TYPE_INSTANT,
385
+ track_uuid: fid,
386
+ name: "Fiber Exit",
387
+ category_iids: DATALOADER_CATEGORY_IIDS,
388
+ extra_counter_track_uuids: [@fibers_counter_id],
389
+ extra_counter_values: [count_fibers(-1)],
390
+ )
391
+ super
392
+ end
393
+
394
+ def begin_dataloader(dl)
395
+ @packets << trace_packet(
396
+ type: TrackEvent::Type::TYPE_COUNTER,
397
+ track_uuid: @fibers_counter_id,
398
+ counter_value: count_fibers(1),
399
+ )
400
+ @did = fid
401
+ @packets << track_descriptor_packet(@main_fiber_id, @did, "Dataloader Fiber ##{@did}")
402
+ super
403
+ end
404
+
405
+ def end_dataloader(dl)
406
+ @packets << trace_packet(
407
+ type: TrackEvent::Type::TYPE_COUNTER,
408
+ track_uuid: @fibers_counter_id,
409
+ counter_value: count_fibers(-1),
410
+ )
411
+ super
412
+ end
413
+
414
+ def begin_dataloader_source(source)
415
+ fds = @flow_ids[source]
416
+ fds_copy = fds.dup
417
+ fds.clear
418
+ packet = trace_packet(
419
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
420
+ track_uuid: fid,
421
+ name_iid: @source_name_iids[source.class],
422
+ category_iids: DATALOADER_CATEGORY_IIDS,
423
+ 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
+ )
433
+ @packets << packet
434
+ fiber_flow_stack << packet
435
+ super
436
+ end
437
+
438
+ def end_dataloader_source(source)
439
+ @packets << trace_packet(
440
+ type: TrackEvent::Type::TYPE_SLICE_END,
441
+ track_uuid: fid,
442
+ extra_counter_track_uuids: [@objects_counter_id],
443
+ extra_counter_values: [count_allocations],
444
+ )
445
+ fiber_flow_stack.pop
446
+ super
447
+ end
448
+
449
+ def begin_authorized(type, obj, ctx)
450
+ packet = trace_packet(
451
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
452
+ track_uuid: fid,
453
+ category_iids: AUTHORIZED_CATEGORY_IIDS,
454
+ extra_counter_track_uuids: [@objects_counter_id],
455
+ extra_counter_values: [count_allocations],
456
+ name_iid: @auth_name_iids[type],
457
+ )
458
+ @packets << packet
459
+ fiber_flow_stack << packet
460
+ super
461
+ end
462
+
463
+ def end_authorized(type, obj, ctx, is_authorized)
464
+ @packets << trace_packet(
465
+ type: TrackEvent::Type::TYPE_SLICE_END,
466
+ track_uuid: fid,
467
+ extra_counter_track_uuids: [@objects_counter_id],
468
+ extra_counter_values: [count_allocations],
469
+ )
470
+ 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)] })
472
+ super
473
+ end
474
+
475
+ def begin_resolve_type(type, value, context)
476
+ packet = trace_packet(
477
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
478
+ track_uuid: fid,
479
+ category_iids: RESOLVE_TYPE_CATEGORY_IIDS,
480
+ extra_counter_track_uuids: [@objects_counter_id],
481
+ extra_counter_values: [count_allocations],
482
+ name_iid: @resolve_type_name_iids[type],
483
+ )
484
+ @packets << packet
485
+ fiber_flow_stack << packet
486
+ super
487
+ end
488
+
489
+ def end_resolve_type(type, value, context, resolved_type)
490
+ @packets << trace_packet(
491
+ type: TrackEvent::Type::TYPE_SLICE_END,
492
+ track_uuid: fid,
493
+ extra_counter_track_uuids: [@objects_counter_id],
494
+ extra_counter_values: [count_allocations],
495
+ )
496
+ 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)] })
498
+ super
499
+ end
500
+
501
+ # Dump protobuf output in the specified file.
502
+ # @param file [String] path to a file in a directory that already exists
503
+ # @param debug_json [Boolean] True to print JSON instead of binary
504
+ # @return [nil, String, Hash] If `file` was given, `nil`. If `file` was `nil`, a Hash if `debug_json: true`, else binary data.
505
+ def write(file:, debug_json: false)
506
+ trace = Trace.new(
507
+ packet: @packets,
508
+ )
509
+ data = if debug_json
510
+ small_json = Trace.encode_json(trace)
511
+ JSON.pretty_generate(JSON.parse(small_json))
512
+ else
513
+ Trace.encode(trace)
514
+ end
515
+
516
+ if file
517
+ File.write(file, data, mode: 'wb')
518
+ nil
519
+ else
520
+ data
521
+ end
522
+ end
523
+
524
+ private
525
+
526
+ def ts
527
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
528
+ end
529
+
530
+ def tid
531
+ Thread.current.object_id
532
+ end
533
+
534
+ def fid
535
+ Fiber.current.object_id
536
+ end
537
+
538
+ def debug_annotation(iid, value_key, value)
539
+ if iid
540
+ DebugAnnotation.new(name_iid: iid, value_key => value)
541
+ else
542
+ DebugAnnotation.new(value_key => value)
543
+ end
544
+ end
545
+
546
+ def payload_to_debug(k, v, iid: nil, intern_value: false)
547
+ if iid.nil?
548
+ iid = @interned_da_name_ids[k]
549
+ k = nil
550
+ end
551
+ case v
552
+ when String
553
+ if intern_value
554
+ v = @interned_da_string_values[v]
555
+ debug_annotation(iid, :string_value_iid, v)
556
+ else
557
+ debug_annotation(iid, :string_value, v)
558
+ end
559
+ when Float
560
+ debug_annotation(iid, :double_value, v)
561
+ when Integer
562
+ debug_annotation(iid, :int_value, v)
563
+ when true, false
564
+ debug_annotation(iid, :bool_value, v)
565
+ when nil
566
+ if iid
567
+ DebugAnnotation.new(name_iid: iid, string_value_iid: DA_STR_VAL_NIL_IID)
568
+ else
569
+ DebugAnnotation.new(name: k, string_value_iid: DA_STR_VAL_NIL_IID)
570
+ end
571
+ when Module
572
+ if intern_value
573
+ val_iid = @class_name_iids[v]
574
+ debug_annotation(iid, :string_value_iid, val_iid)
575
+ else
576
+ debug_annotation(iid, :string_value, v.name)
577
+ end
578
+ when Symbol
579
+ debug_annotation(iid, :string_value, v.inspect)
580
+ when Array
581
+ debug_annotation(iid, :array_values, v.map { |v2| payload_to_debug(nil, v2, intern_value: intern_value) }.compact)
582
+ when Hash
583
+ debug_annotation(iid, :dict_entries, v.map { |k2, v2| payload_to_debug(k2, v2, intern_value: intern_value) }.compact)
584
+ 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
589
+ end
590
+ if intern_value
591
+ str_iid = @interned_da_string_values[debug_str]
592
+ debug_annotation(iid, :string_value_iid, str_iid)
593
+ else
594
+ debug_annotation(iid, :string_value, debug_str)
595
+ end
596
+ end
597
+ end
598
+
599
+ def count_allocations
600
+ GC.stat(:total_allocated_objects) - @starting_objects
601
+ end
602
+
603
+ def count_fibers(diff)
604
+ @fibers_count += diff
605
+ end
606
+
607
+ def count_fields
608
+ @fields_count += 1
609
+ end
610
+
611
+ def dup_with(message, attrs, delete_counters: false)
612
+ new_attrs = message.to_h
613
+ if delete_counters
614
+ new_attrs.delete(:extra_counter_track_uuids)
615
+ new_attrs.delete(:extra_counter_values)
616
+ end
617
+ new_attrs.merge!(attrs)
618
+ message.class.new(**new_attrs)
619
+ end
620
+
621
+ def fiber_flow_stack
622
+ Fiber[:graphql_flow_stack] ||= []
623
+ end
624
+
625
+ def trace_packet(event_attrs)
626
+ TracePacket.new(
627
+ timestamp: ts,
628
+ track_event: TrackEvent.new(event_attrs),
629
+ trusted_packet_sequence_id: @sequence_id,
630
+ sequence_flags: 2,
631
+ interned_data: new_interned_data
632
+ )
633
+ end
634
+
635
+ def new_interned_data
636
+ if !@new_interned_da_names.empty?
637
+ da_names = @new_interned_da_names.map { |(name, iid)| DebugAnnotationName.new(iid: iid, name: name) }
638
+ @new_interned_da_names.clear
639
+ end
640
+
641
+ if !@new_interned_event_names.empty?
642
+ ev_names = @new_interned_event_names.map { |(name, iid)| EventName.new(iid: iid, name: name) }
643
+ @new_interned_event_names.clear
644
+ end
645
+
646
+ if !@new_interned_da_string_values.empty?
647
+ str_vals = @new_interned_da_string_values.map { |name, iid| InternedString.new(iid: iid, str: name.b) }
648
+ @new_interned_da_string_values.clear
649
+ end
650
+
651
+ if ev_names || da_names || str_vals
652
+ InternedData.new(
653
+ event_names: ev_names,
654
+ debug_annotation_names: da_names,
655
+ debug_annotation_string_values: str_vals,
656
+ )
657
+ else
658
+ nil
659
+ end
660
+ end
661
+
662
+ def track_descriptor_packet(parent_uuid, uuid, name, counter: nil)
663
+ td = if counter
664
+ TrackDescriptor.new(
665
+ parent_uuid: parent_uuid,
666
+ uuid: uuid,
667
+ name: name,
668
+ counter: counter
669
+ )
670
+ else
671
+ TrackDescriptor.new(
672
+ parent_uuid: parent_uuid,
673
+ uuid: uuid,
674
+ name: name,
675
+ child_ordering: TrackDescriptor::ChildTracksOrdering::CHRONOLOGICAL,
676
+ )
677
+ end
678
+ TracePacket.new(
679
+ track_descriptor: td,
680
+ trusted_packet_sequence_id: @sequence_id,
681
+ sequence_flags: 2,
682
+ )
683
+ end
684
+
685
+ def unsubscribe_from_active_support_notifications
686
+ if defined?(@as_subscriber)
687
+ ActiveSupport::Notifications.unsubscribe(@as_subscriber)
688
+ end
689
+ end
690
+
691
+ def subscribe_to_active_support_notifications(pattern)
692
+ @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?
696
+ TrackEvent.new(
697
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
698
+ track_uuid: fid,
699
+ category_iids: ACTIVE_SUPPORT_NOTIFICATIONS_CATEGORY_IIDS,
700
+ name: name,
701
+ )
702
+ else
703
+ TrackEvent.new(
704
+ type: TrackEvent::Type::TYPE_SLICE_BEGIN,
705
+ track_uuid: fid,
706
+ name: name,
707
+ category_iids: ACTIVE_SUPPORT_NOTIFICATIONS_CATEGORY_IIDS,
708
+ debug_annotations: metadata,
709
+ )
710
+ end
711
+ @packets << TracePacket.new(
712
+ timestamp: (start * 1_000_000_000).to_i,
713
+ track_event: te,
714
+ trusted_packet_sequence_id: @sequence_id,
715
+ sequence_flags: 2,
716
+ interned_data: new_interned_data
717
+ )
718
+ @packets << TracePacket.new(
719
+ timestamp: (finish * 1_000_000_000).to_i,
720
+ track_event: TrackEvent.new(
721
+ type: TrackEvent::Type::TYPE_SLICE_END,
722
+ track_uuid: fid,
723
+ name: name,
724
+ extra_counter_track_uuids: [@objects_counter_id],
725
+ extra_counter_values: [count_allocations]
726
+ ),
727
+ trusted_packet_sequence_id: @sequence_id,
728
+ sequence_flags: 2,
729
+ )
730
+ end
731
+ end
732
+ end
733
+ end
734
+ end