graphql 2.4.15 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/dashboard/detailed_traces.rb +47 -0
  3. data/lib/graphql/dashboard/installable.rb +22 -0
  4. data/lib/graphql/dashboard/limiters.rb +93 -0
  5. data/lib/graphql/dashboard/operation_store.rb +199 -0
  6. data/lib/graphql/dashboard/statics/charts.min.css +1 -0
  7. data/lib/graphql/dashboard/statics/dashboard.css +27 -0
  8. data/lib/graphql/dashboard/statics/dashboard.js +74 -9
  9. data/lib/graphql/dashboard/subscriptions.rb +96 -0
  10. data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
  11. data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
  12. data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
  13. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +23 -0
  14. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
  15. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
  16. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
  17. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
  18. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
  19. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
  20. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
  21. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
  22. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
  23. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
  24. data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +49 -1
  25. data/lib/graphql/dashboard.rb +45 -29
  26. data/lib/graphql/execution/interpreter.rb +3 -5
  27. data/lib/graphql/execution/multiplex.rb +1 -1
  28. data/lib/graphql/language/parser.rb +13 -6
  29. data/lib/graphql/query.rb +2 -4
  30. data/lib/graphql/static_validation/all_rules.rb +1 -1
  31. data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
  32. data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
  33. data/lib/graphql/tracing/active_support_notifications_trace.rb +7 -0
  34. data/lib/graphql/tracing/appoptics_tracing.rb +5 -0
  35. data/lib/graphql/tracing/appsignal_trace.rb +26 -61
  36. data/lib/graphql/tracing/data_dog_trace.rb +41 -164
  37. data/lib/graphql/tracing/monitor_trace.rb +285 -0
  38. data/lib/graphql/tracing/new_relic_trace.rb +34 -166
  39. data/lib/graphql/tracing/notifications_trace.rb +181 -37
  40. data/lib/graphql/tracing/perfetto_trace.rb +15 -18
  41. data/lib/graphql/tracing/prometheus_trace.rb +47 -74
  42. data/lib/graphql/tracing/scout_trace.rb +25 -59
  43. data/lib/graphql/tracing/sentry_trace.rb +57 -99
  44. data/lib/graphql/tracing/statsd_trace.rb +24 -47
  45. data/lib/graphql/tracing/trace.rb +0 -17
  46. data/lib/graphql/tracing.rb +1 -0
  47. data/lib/graphql/version.rb +1 -1
  48. metadata +25 -4
  49. data/lib/graphql/dashboard/views/graphql/dashboard/traces/index.html.erb +0 -63
  50. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "graphql/tracing/platform_trace"
3
+ require "graphql/tracing/monitor_trace"
4
4
 
5
5
  module GraphQL
6
6
  module Tracing
@@ -16,184 +16,52 @@ module GraphQL
16
16
  #
17
17
  # @example Installing without trace events for `authorized?` or `resolve_type` calls
18
18
  # trace_with GraphQL::Tracing::NewRelicTrace, trace_authorized: false, trace_resolve_type: false
19
+ NewRelicTrace = MonitorTrace.create_module("newrelic")
19
20
  module NewRelicTrace
20
- # @param set_transaction_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
21
- # This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
22
- # It can also be specified per-query with `context[:set_new_relic_transaction_name]`.
23
- # @param trace_authorized [Boolean] If `false`, skip tracing `authorized?` calls
24
- # @param trace_resolve_type [Boolean] If `false`, skip tracing `resolve_type?` calls
25
- # @param trace_scalars [Boolean] If `true`, Enum and Scalar fields will be traced by default
26
- def initialize(set_transaction_name: false, trace_authorized: true, trace_resolve_type: true, trace_scalars: false, **_rest)
27
- @set_transaction_name = set_transaction_name
28
- @trace_authorized = trace_authorized
29
- @trace_resolve_type = trace_resolve_type
30
- @trace_scalars = trace_scalars
31
- @nr_field_names = Hash.new do |h, field|
32
- h[field] = "GraphQL/#{field.owner.graphql_name}/#{field.graphql_name}"
33
- end.compare_by_identity
34
-
35
- @nr_authorized_names = Hash.new do |h, type|
36
- h[type] = "GraphQL/Authorized/#{type.graphql_name}"
37
- end.compare_by_identity
38
-
39
- @nr_resolve_type_names = Hash.new do |h, type|
40
- h[type] = "GraphQL/ResolveType/#{type.graphql_name}"
41
- end.compare_by_identity
42
-
43
- @nr_source_names = Hash.new do |h, source_inst|
44
- h[source_inst] = "GraphQL/Source/#{source_inst.class.name}"
45
- end.compare_by_identity
46
-
47
- @nr_parse = @nr_validate = @nr_analyze = @nr_execute = nil
48
- super
49
- end
50
-
51
- def begin_parse(query_str)
52
- @nr_parse = NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: "GraphQL/parse", category: :web)
53
- super
54
- end
55
-
56
- def end_parse(query_str)
57
- @nr_parse.finish
58
- super
59
- end
60
-
61
- def begin_validate(query, validate)
62
- @nr_validate = NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: "GraphQL/validate", category: :web)
63
- super
64
- end
65
-
66
- def end_validate(query, validate, validation_errors)
67
- @nr_validate.finish
68
- super
69
- end
70
-
71
- def begin_analyze_multiplex(multiplex, analyzers)
72
- @nr_analyze = NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: "GraphQL/analyze", category: :web)
73
- super
74
- end
75
-
76
- def end_analyze_multiplex(multiplex, analyzers)
77
- @nr_analyze.finish
78
- super
79
- end
80
-
81
- def begin_execute_multiplex(multiplex)
82
- query = multiplex.queries.first
83
- set_this_txn_name = query.context[:set_new_relic_transaction_name]
84
- if set_this_txn_name || (set_this_txn_name.nil? && @set_transaction_name)
85
- NewRelic::Agent.set_transaction_name(transaction_name(query))
21
+ class NewrelicMonitor < MonitorTrace::Monitor
22
+ PARSE_NAME = "GraphQL/parse"
23
+ LEX_NAME = "GraphQL/lex"
24
+ VALIDATE_NAME = "GraphQL/validate"
25
+ EXECUTE_NAME = "GraphQL/execute"
26
+ ANALYZE_NAME = "GraphQL/analyze"
27
+
28
+ def instrument(keyword, payload, &block)
29
+ if keyword == :execute
30
+ query = payload.queries.first
31
+ set_this_txn_name = query.context[:set_new_relic_transaction_name]
32
+ if set_this_txn_name || (set_this_txn_name.nil? && @set_transaction_name)
33
+ NewRelic::Agent.set_transaction_name(transaction_name(query))
34
+ end
35
+ end
36
+ ::NewRelic::Agent::MethodTracerHelpers.trace_execution_scoped(name_for(keyword, payload), &block)
86
37
  end
87
- @nr_execute = NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: "GraphQL/execute", category: :web)
88
- super
89
- end
90
-
91
- def end_execute_multiplex(multiplex)
92
- @nr_execute.finish
93
- super
94
- end
95
38
 
96
- def begin_execute_field(field, object, arguments, query)
97
- return_type = field.type.unwrap
98
- trace_field = if return_type.kind.scalar? || return_type.kind.enum?
99
- (field.trace.nil? && @trace_scalars) || field.trace
100
- else
101
- true
39
+ def platform_source_class_key(source_class)
40
+ "GraphQL/Source/#{source_class.name}"
102
41
  end
103
- if trace_field
104
- start_segment(partial_name: @nr_field_names[field], category: :web)
105
- end
106
- super
107
- end
108
42
 
109
- def end_execute_field(field, objects, arguments, query, result)
110
- finish_segment
111
- super
112
- end
113
-
114
- def begin_authorized(type, obj, ctx)
115
- if @trace_authorized
116
- start_segment(partial_name: @nr_authorized_names[type], category: :web)
117
- end
118
- super
119
- end
120
-
121
- def end_authorized(type, obj, ctx, is_authed)
122
- if @trace_authorized
123
- finish_segment
43
+ def platform_field_key(field)
44
+ "GraphQL/#{field.owner.graphql_name}/#{field.graphql_name}"
124
45
  end
125
- super
126
- end
127
46
 
128
- def begin_resolve_type(type, value, context)
129
- if @trace_resolve_type
130
- start_segment(partial_name: @nr_resolve_type_names[type], category: :web)
47
+ def platform_authorized_key(type)
48
+ "GraphQL/Authorized/#{type.graphql_name}"
131
49
  end
132
- super
133
- end
134
50
 
135
- def end_resolve_type(type, value, context, resolved_type)
136
- if @trace_resolve_type
137
- finish_segment
51
+ def platform_resolve_type_key(type)
52
+ "GraphQL/ResolveType/#{type.graphql_name}"
138
53
  end
139
- super
140
- end
141
-
142
- def begin_dataloader_source(source)
143
- start_segment(partial_name: @nr_source_names[source], category: :web)
144
- super
145
- end
146
54
 
147
- def end_dataloader_source(source)
148
- finish_segment
149
- super
150
- end
151
-
152
- def dataloader_fiber_yield(source)
153
- prev_segment = finish_segment
154
- Fiber[:graphql_nr_previous_segment] = prev_segment
155
- super
156
- end
55
+ class Event < MonitorTrace::Monitor::Event
56
+ def start
57
+ name = @monitor.name_for(keyword, object)
58
+ @nr_ev = NewRelic::Agent::Tracer.start_transaction_or_segment(partial_name: name, category: :web)
59
+ end
157
60
 
158
- def dataloader_fiber_resume(source)
159
- prev_segment = Fiber[:graphql_nr_previous_segment]
160
- Fiber[:graphql_nr_previous_segment] = nil
161
- if prev_segment
162
- seg_partial_name = prev_segment.name.sub(/^.*(GraphQL.*)$/, '\1')
163
- start_segment(partial_name: seg_partial_name, category: :web)
61
+ def finish
62
+ @nr_ev.finish
63
+ end
164
64
  end
165
- super
166
- end
167
-
168
- private
169
-
170
- def start_segment(...)
171
- Fiber[:graphql_nr_segment] = NewRelic::Agent::Tracer.start_transaction_or_segment(...)
172
- end
173
-
174
- def finish_segment
175
- segment = Fiber[:graphql_nr_segment]
176
- if segment
177
- segment.finish
178
- Fiber[:graphql_nr_segment] = nil
179
- segment
180
- end
181
- end
182
-
183
- def transaction_name(query)
184
- selected_op = query.selected_operation
185
- txn_name = if selected_op
186
- op_type = selected_op.operation_type
187
- op_name = selected_op.name || fallback_transaction_name(query.context) || "anonymous"
188
- "#{op_type}.#{op_name}"
189
- else
190
- "query.anonymous"
191
- end
192
- "GraphQL/#{txn_name}"
193
- end
194
-
195
- def fallback_transaction_name(context)
196
- context[:tracing_fallback_transaction_name]
197
65
  end
198
66
  end
199
67
  end
@@ -1,49 +1,193 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "graphql/tracing/platform_trace"
4
-
5
3
  module GraphQL
6
4
  module Tracing
7
- # This implementation forwards events to a notification handler (i.e.
8
- # ActiveSupport::Notifications or Dry::Monitor::Notifications)
9
- # with a `graphql` suffix.
5
+ # This implementation forwards events to a notification handler
6
+ # (i.e. ActiveSupport::Notifications or Dry::Monitor::Notifications) with a `graphql` suffix.
7
+ #
8
+ # @see ActiveSupportNotificationsTrace ActiveSupport::Notifications integration
10
9
  module NotificationsTrace
11
- # Initialize a new NotificationsTracing instance
12
- #
13
- # @param engine [#instrument(key, metadata, block)] The notifications engine to use
14
- def initialize(engine:, **rest)
15
- @notifications_engine = engine
16
- super
17
- end
18
-
19
- # rubocop:disable Development/NoEvalCop This eval takes static inputs at load-time
20
-
21
- {
22
- "lex" => "lex.graphql",
23
- "parse" => "parse.graphql",
24
- "validate" => "validate.graphql",
25
- "analyze_multiplex" => "analyze_multiplex.graphql",
26
- "analyze_query" => "analyze_query.graphql",
27
- "execute_multiplex" => "execute_multiplex.graphql",
28
- "execute_query" => "execute_query.graphql",
29
- "execute_query_lazy" => "execute_query_lazy.graphql",
30
- "execute_field" => "execute_field.graphql",
31
- "execute_field_lazy" => "execute_field_lazy.graphql",
32
- "authorized" => "authorized.graphql",
33
- "authorized_lazy" => "authorized_lazy.graphql",
34
- "resolve_type" => "resolve_type.graphql",
35
- "resolve_type_lazy" => "resolve_type.graphql",
36
- }.each do |trace_method, platform_key|
37
- module_eval <<-RUBY, __FILE__, __LINE__
38
- def #{trace_method}(**metadata, &block)
39
- @notifications_engine.instrument("#{platform_key}", metadata) { super(**metadata, &block) }
10
+ # @api private
11
+ class Adapter
12
+ def instrument(keyword, payload, &block)
13
+ raise "Implement #{self.class}#instrument to measure the block"
14
+ end
15
+
16
+ def start_event(keyword, payload)
17
+ ev = self.class::Event.new(keyword, payload)
18
+ ev.start
19
+ ev
20
+ end
21
+
22
+ class Event
23
+ def initialize(name, payload)
24
+ @name = name
25
+ @payload = payload
26
+ end
27
+
28
+ attr_reader :name, :payload
29
+
30
+ def start
31
+ raise "Implement #{self.class}#start to begin a new event (#{inspect})"
40
32
  end
41
- RUBY
33
+
34
+ def finish
35
+ raise "Implement #{self.class}#finish to end this event (#{inspect})"
36
+ end
37
+ end
42
38
  end
43
39
 
44
- # rubocop:enable Development/NoEvalCop
40
+ # @api private
41
+ class DryMonitorAdapter < Adapter
42
+ def instrument(...)
43
+ Dry::Monitor.instrument(...)
44
+ end
45
45
 
46
- include PlatformTrace
46
+ class Event < Adapter::Event
47
+ def start
48
+ Dry::Monitor.start(@name, @payload)
49
+ end
50
+
51
+ def finish
52
+ Dry::Monitor.stop(@name, @payload)
53
+ end
54
+ end
55
+ end
56
+
57
+ # @api private
58
+ class ActiveSupportNotificationsAdapter < Adapter
59
+ def instrument(...)
60
+ ActiveSupport::Notifications.instrument(...)
61
+ end
62
+
63
+ class Event < Adapter::Event
64
+ def start
65
+ @asn_event = ActiveSupport::Notifications.instrumenter.new_event(@name, @payload)
66
+ @asn_event.start!
67
+ end
68
+
69
+ def finish
70
+ @asn_event.finish!
71
+ ActiveSupport::Notifications.publish_event(@asn_event)
72
+ end
73
+ end
74
+ end
75
+
76
+ # @param engine [Class] The notifications engine to use, eg `Dry::Monitor` or `ActiveSupport::Notifications`
77
+ def initialize(engine:, **rest)
78
+ adapter = if defined?(Dry::Monitor) && engine == Dry::Monitor
79
+ DryMonitoringAdapter
80
+ elsif defined?(ActiveSupport::Notifications) && engine == ActiveSupport::Notifications
81
+ ActiveSupportNotificationsAdapter
82
+ else
83
+ engine
84
+ end
85
+ @notifications = adapter.new
86
+ super
87
+ end
88
+
89
+ def parse(**payload)
90
+ @notifications.instrument("parse.graphql", payload) do
91
+ super
92
+ end
93
+ end
94
+
95
+ def lex(**payload)
96
+ @notifications.instrument("lex.graphql", payload) do
97
+ super
98
+ end
99
+ end
100
+
101
+ def validate(**payload)
102
+ @notifications.instrument("validate.graphql", payload) do
103
+ super
104
+ end
105
+ end
106
+
107
+ def begin_analyze_multiplex(multiplex, analyzers)
108
+ begin_notifications_event("analyze.graphql", {multiplex: multiplex, analyzers: analyzers})
109
+ super
110
+ end
111
+
112
+ def end_analyze_multiplex(_multiplex, _analyzers)
113
+ finish_notifications_event
114
+ super
115
+ end
116
+
117
+ def execute_multiplex(**payload)
118
+ @notifications.instrument("execute.graphql", payload) do
119
+ super
120
+ end
121
+ end
122
+
123
+ def begin_execute_field(field, object, arguments, query)
124
+ begin_notifications_event("execute_field.graphql", {field: field, object: object, arguments: arguments, query: query})
125
+ super
126
+ end
127
+
128
+ def end_execute_field(_field, _object, _arguments, _query, _result)
129
+ finish_notifications_event
130
+ super
131
+ end
132
+
133
+ def dataloader_fiber_yield(source)
134
+ Fiber[PREVIOUS_EV_KEY] = finish_notifications_event
135
+ super
136
+ end
137
+
138
+ def dataloader_fiber_resume(source)
139
+ prev_ev = Fiber[PREVIOUS_EV_KEY]
140
+ begin_notifications_event(prev_ev.name, prev_ev.payload)
141
+ super
142
+ end
143
+
144
+ def begin_authorized(type, object, context)
145
+ begin_notifications_event("authorized.graphql", {type: type, object: object, context: context})
146
+ super
147
+ end
148
+
149
+ def end_authorized(type, object, context, result)
150
+ finish_notifications_event
151
+ super
152
+ end
153
+
154
+ def begin_resolve_type(type, object, context)
155
+ begin_notifications_event("resolve_type.graphql", {type: type, object: object, context: context})
156
+ super
157
+ end
158
+
159
+ def end_resolve_type(type, object, context, resolved_type)
160
+ finish_notifications_event
161
+ super
162
+ end
163
+
164
+ def begin_dataloader_source(source)
165
+ begin_notifications_event("dataloader_source.graphql", { source: source })
166
+ super
167
+ end
168
+
169
+ def end_dataloader_source(source)
170
+ finish_notifications_event
171
+ super
172
+ end
173
+
174
+ CURRENT_EV_KEY = :__notifications_graphql_trace_event
175
+ PREVIOUS_EV_KEY = :__notifications_graphql_trace_previous_event
176
+
177
+ private
178
+
179
+ def begin_notifications_event(name, payload)
180
+ Fiber[CURRENT_EV_KEY] = @notifications.start_event(name, payload)
181
+ end
182
+
183
+ def finish_notifications_event
184
+ if ev = Fiber[CURRENT_EV_KEY]
185
+ ev.finish
186
+ # Use `false` to prevent grabbing an event from a parent fiber
187
+ Fiber[CURRENT_EV_KEY] = false
188
+ ev
189
+ end
190
+ end
47
191
  end
48
192
  end
49
193
  end
@@ -63,6 +63,7 @@ module GraphQL
63
63
  # @param active_support_notifications_pattern [String, RegExp, false] A filter for `ActiveSupport::Notifications`, if it's present. Or `false` to skip subscribing.
64
64
  def initialize(active_support_notifications_pattern: nil, save_profile: false, **_rest)
65
65
  super
66
+ @active_support_notifications_pattern = active_support_notifications_pattern
66
67
  @save_profile = save_profile
67
68
  Fiber[:graphql_flow_stack] = nil
68
69
  @sequence_id = object_id
@@ -168,39 +169,38 @@ module GraphQL
168
169
  track_uuid: @fields_counter_id,
169
170
  counter_value: count_fields,
170
171
  )
171
-
172
- if defined?(ActiveSupport::Notifications) && active_support_notifications_pattern != false
173
- subscribe_to_active_support_notifications(active_support_notifications_pattern)
174
- end
175
172
  end
176
173
 
177
- def begin_execute_multiplex(m)
178
- @operation_name = m.queries.map { |q| q.selected_operation_name || "anonymous" }.join(",")
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
179
  @begin_time = Time.now
180
180
  @packets << trace_packet(
181
181
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
182
182
  track_uuid: fid,
183
183
  name: "Multiplex",
184
184
  debug_annotations: [
185
- payload_to_debug("query_string", m.queries.map(&:sanitized_query_string).join("\n\n"))
185
+ payload_to_debug("query_string", multiplex.queries.map(&:sanitized_query_string).join("\n\n"))
186
186
  ]
187
187
  )
188
- super
189
- end
188
+ result = super
190
189
 
191
- def end_execute_multiplex(m)
192
190
  @packets << trace_packet(
193
191
  type: TrackEvent::Type::TYPE_SLICE_END,
194
192
  track_uuid: fid,
195
193
  )
194
+
195
+ result
196
+ ensure
196
197
  unsubscribe_from_active_support_notifications
197
198
  if @save_profile
198
199
  begin_ts = (@begin_time.to_f * 1000).round
199
200
  end_ts = (Time.now.to_f * 1000).round
200
201
  duration_ms = end_ts - begin_ts
201
- m.schema.detailed_trace.save_trace(@operation_name, duration_ms, begin_ts, Trace.encode(Trace.new(packet: @packets)))
202
+ multiplex.schema.detailed_trace.save_trace(@operation_name, duration_ms, begin_ts, Trace.encode(Trace.new(packet: @packets)))
202
203
  end
203
- super
204
204
  end
205
205
 
206
206
  def begin_execute_field(field, object, arguments, query)
@@ -261,7 +261,7 @@ module GraphQL
261
261
  super
262
262
  end
263
263
 
264
- def begin_parse(str)
264
+ def parse(query_string:)
265
265
  @packets << trace_packet(
266
266
  type: TrackEvent::Type::TYPE_SLICE_BEGIN,
267
267
  track_uuid: fid,
@@ -269,17 +269,14 @@ module GraphQL
269
269
  extra_counter_values: [count_allocations],
270
270
  name: "Parse"
271
271
  )
272
- super
273
- end
274
-
275
- def end_parse(str)
272
+ result = super
276
273
  @packets << trace_packet(
277
274
  type: TrackEvent::Type::TYPE_SLICE_END,
278
275
  track_uuid: fid,
279
276
  extra_counter_track_uuids: [@objects_counter_id],
280
277
  extra_counter_values: [count_allocations],
281
278
  )
282
- super
279
+ result
283
280
  end
284
281
 
285
282
  def begin_validate(query, validate)