newrelic_rpm 5.7.0.350 → 6.0.0.351

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/.yardopts +1 -0
  4. data/CHANGELOG.md +41 -0
  5. data/lib/new_relic/agent.rb +3 -3
  6. data/lib/new_relic/agent/agent.rb +4 -4
  7. data/lib/new_relic/agent/configuration/default_source.rb +3 -1
  8. data/lib/new_relic/agent/cross_app_monitor.rb +3 -3
  9. data/lib/new_relic/agent/datastores.rb +6 -8
  10. data/lib/new_relic/agent/datastores/metric_helper.rb +1 -2
  11. data/lib/new_relic/agent/distributed_trace_monitor.rb +1 -2
  12. data/lib/new_relic/agent/error_collector.rb +1 -1
  13. data/lib/new_relic/agent/external.rb +6 -4
  14. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +8 -5
  15. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +12 -8
  16. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +1 -1
  17. data/lib/new_relic/agent/instrumentation/active_job.rb +6 -7
  18. data/lib/new_relic/agent/instrumentation/active_record.rb +2 -2
  19. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +2 -2
  20. data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +1 -1
  21. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +1 -1
  22. data/lib/new_relic/agent/instrumentation/bunny.rb +1 -1
  23. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +9 -3
  24. data/lib/new_relic/agent/instrumentation/data_mapper.rb +1 -1
  25. data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +1 -1
  26. data/lib/new_relic/agent/instrumentation/excon/connection.rb +1 -1
  27. data/lib/new_relic/agent/instrumentation/grape.rb +4 -2
  28. data/lib/new_relic/agent/instrumentation/middleware_proxy.rb +1 -1
  29. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +11 -4
  30. data/lib/new_relic/agent/instrumentation/net.rb +1 -1
  31. data/lib/new_relic/agent/instrumentation/rake.rb +2 -3
  32. data/lib/new_relic/agent/instrumentation/typhoeus.rb +3 -3
  33. data/lib/new_relic/agent/javascript_instrumentor.rb +1 -1
  34. data/lib/new_relic/agent/messaging.rb +9 -8
  35. data/lib/new_relic/agent/method_tracer_helpers.rb +2 -2
  36. data/lib/new_relic/agent/sql_sampler.rb +3 -3
  37. data/lib/new_relic/agent/stats_engine.rb +2 -2
  38. data/lib/new_relic/agent/synthetics_monitor.rb +1 -2
  39. data/lib/new_relic/agent/threading/agent_thread.rb +1 -1
  40. data/lib/new_relic/agent/tracer.rb +462 -0
  41. data/lib/new_relic/agent/transaction.rb +40 -87
  42. data/lib/new_relic/agent/transaction/abstract_segment.rb +1 -1
  43. data/lib/new_relic/agent/transaction/distributed_tracing.rb +1 -2
  44. data/lib/new_relic/agent/transaction/tracing.rb +0 -99
  45. data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -2
  46. data/lib/new_relic/control/frameworks/rails6.rb +14 -0
  47. data/lib/new_relic/rack/agent_middleware.rb +1 -1
  48. data/lib/new_relic/version.rb +2 -2
  49. data/test/agent_helper.rb +2 -2
  50. metadata +4 -3
  51. data/lib/new_relic/agent/transaction_state.rb +0 -186
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 625a0434dacaefcf0902757f00bc9da4d6076c6060599b696a582e90187fc883
4
- data.tar.gz: fac2ce2e4f4d293a123c93bebbfc62093f2c02ae1580b9a1a24df3c901ad09db
3
+ metadata.gz: 91ab526e3b85c3d323b557163c7213681e1783c0c6ac9f29bf53dad5dd421a92
4
+ data.tar.gz: ba03925e985ecaf44b0b56375cb0c38532c2473cf87440c2b7f2c4fccea3d744
5
5
  SHA512:
6
- metadata.gz: 579cab156bcd049477932f8411b028d83469e21aa6404a6c9a66a7e2289849a78dade9d723bd43233f3889069581217e067c951c42a5ff63f59c5f9213957072
7
- data.tar.gz: 62e685079a4f023713ad7a3e520a9b7519b957b762a84dcc5857d2024a52f3180d783e12a9992b0d4696eaa636866d8bf56d1dc130a75a5b32ead180ab1a75e9
6
+ metadata.gz: 811d5a9f971f18d5e66a2b0826d003603b5771b8378906ee1594ec95834593f31a668e8d8084cbd84db8f0e3d367d93620ed87b86e047c31d20b115cd4c8cfb6
7
+ data.tar.gz: 115f4a4d0c6186546cdd6d698279e5d60b26a67d7749bd2959c44f0478f594621e78e4785a8b6508d78c986e5a19d6dcb5df145f9891eb323432141336e72845
@@ -11,7 +11,6 @@ sudo: required
11
11
  before_install:
12
12
  # RUBY-2072 Prevent Travis setup failure before our test even starts
13
13
  - sudo rm -f /etc/apt/sources.list.d/travis_ci_zeromq3.list
14
-
15
14
  - gem --version
16
15
  - ./test/script/before_install/update_rubygems.sh
17
16
  - gem uninstall bundler -a -x
data/.yardopts CHANGED
@@ -12,6 +12,7 @@ lib/new_relic/agent/stats_engine/metric_stats.rb
12
12
  lib/new_relic/agent/datastores.rb
13
13
  lib/new_relic/agent/messaging.rb
14
14
  lib/new_relic/agent/sql_sampler.rb
15
+ lib/new_relic/agent/tracer.rb
15
16
  lib/new_relic/agent/transaction.rb
16
17
  lib/new_relic/agent/transaction_sampler.rb
17
18
  lib/new_relic/rack/agent_hooks.rb
@@ -1,5 +1,46 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
+ ## v6.0.0
4
+
5
+ * Tracer API for flexible custom instrumentation
6
+
7
+ With agent version 6.0, we are introducing the `Tracer` class, an
8
+ officially supported public API for more flexible custom
9
+ instrumentation. By calling its `in_transaction` method, you can
10
+ instrument an arbitrary section of Ruby code without needing to
11
+ juggle any explicit state. Behind the scenes, the agent will
12
+ make sure that the measured code results in an APM segment inside
13
+ a transaction.
14
+
15
+ The same API contains additional methods for creating
16
+ transactions and segments, and for interacting with the current
17
+ transaction. For more details, see the [custom instrumentation
18
+ documentation](https://docs.newrelic.com/docs/agents/ruby-agent/api-guides/ruby-custom-instrumentation).
19
+
20
+ If you were previously using any of the agent's private,
21
+ undocumented APIs, such as `Transaction.wrap` or
22
+ `Transaction.start/stop`, you will need to update your code to
23
+ use the Tracer API.
24
+
25
+ The full list of APIs that were removed or deprecated are:
26
+ * `External.start_segment`
27
+ * `Transaction.create_segment`
28
+ * `Transaction.start`
29
+ * `Transaction.stop`
30
+ * `Transaction.start_datastore_segment`
31
+ * `Transaction.start_segment`
32
+ * `Transaction.wrap`
33
+ * `TransactionState.current_transaction`
34
+
35
+ If are you using any of these APIs, please see the [upgrade guide](https://docs.newrelic.com/docs/agents/ruby-agent/troubleshooting/update-private-api-calls-public-tracer-api) for a list of replacements.
36
+
37
+ * Agent detects Rails 6.0
38
+
39
+ The agent properly detects Rails 6.0 and no longer logs an error when
40
+ started in a Rails 6.0 environment. This does not include full Rails 6.0
41
+ support, which will be coming in a future release. Thanks to Jacob Bednarz
42
+ for the contribution.
43
+
3
44
  ## v5.7.0
4
45
 
5
46
  * Ruby 2.6 support
@@ -487,7 +487,7 @@ module NewRelic
487
487
  # Yield to the block without collecting any metrics or traces in
488
488
  # any of the subsequent calls. If executed recursively, will keep
489
489
  # track of the first entry point and turn on tracing again after
490
- # leaving that block. This uses the thread local TransactionState.
490
+ # leaving that block. This uses the thread local Tracer::State.
491
491
  #
492
492
  # @api public
493
493
  #
@@ -544,13 +544,13 @@ module NewRelic
544
544
 
545
545
  # Check to see if we are capturing metrics currently on this thread.
546
546
  def tl_is_execution_traced?
547
- NewRelic::Agent::TransactionState.tl_get.is_execution_traced?
547
+ NewRelic::Agent::Tracer.state.is_execution_traced?
548
548
  end
549
549
 
550
550
  # helper method to check the thread local to determine whether sql
551
551
  # is being recorded or not
552
552
  def tl_is_sql_recorded?
553
- NewRelic::Agent::TransactionState.tl_get.is_sql_recorded?
553
+ NewRelic::Agent::Tracer.state.is_sql_recorded?
554
554
  end
555
555
 
556
556
  # @!group Adding custom attributes to traces
@@ -262,7 +262,7 @@ module NewRelic
262
262
  # should not record sql in the current thread. Returns the
263
263
  # previous value, if there is one
264
264
  def set_record_sql(should_record) #THREAD_LOCAL_ACCESS
265
- state = TransactionState.tl_get
265
+ state = Tracer.state
266
266
  prev = state.record_sql
267
267
  state.record_sql = should_record
268
268
  prev.nil? || prev
@@ -273,13 +273,13 @@ module NewRelic
273
273
  # children of a transaction without affecting the tracing of
274
274
  # the whole transaction
275
275
  def push_trace_execution_flag(should_trace=false) #THREAD_LOCAL_ACCESS
276
- TransactionState.tl_get.push_traced(should_trace)
276
+ Tracer.state.push_traced(should_trace)
277
277
  end
278
278
 
279
279
  # Pop the current trace execution status. Restore trace execution status
280
280
  # to what it was before we pushed the current flag.
281
281
  def pop_trace_execution_flag #THREAD_LOCAL_ACCESS
282
- TransactionState.tl_get.pop_traced
282
+ Tracer.state.pop_traced
283
283
  end
284
284
 
285
285
  # Herein lies the corpse of the former 'start' method. May
@@ -543,7 +543,7 @@ module NewRelic
543
543
  @sql_sampler.reset!
544
544
 
545
545
  if Agent.config[:clear_transaction_state_after_fork]
546
- TransactionState.tl_clear
546
+ Tracer.clear_state
547
547
  end
548
548
  end
549
549
 
@@ -95,6 +95,8 @@ module NewRelic
95
95
  :rails4
96
96
  when 5
97
97
  :rails5
98
+ when 6
99
+ :rails6
98
100
  else
99
101
  ::NewRelic::Agent.logger.error "Detected unsupported Rails version #{Rails::VERSION::STRING}"
100
102
  end
@@ -1735,7 +1737,7 @@ module NewRelic
1735
1737
  :public => true,
1736
1738
  :type => Boolean,
1737
1739
  :allowed_from_server => false,
1738
- :description => 'If <code>true</code>, the agent will clear <code>TransactionState</code> in <code>Agent.drop_buffered_data</code>.'
1740
+ :description => 'If <code>true</code>, the agent will clear <code>Tracer::State</code> in <code>Agent.drop_buffered_data</code>.'
1739
1741
  },
1740
1742
  :account_id => {
1741
1743
  :default => nil,
@@ -6,7 +6,7 @@ require 'digest'
6
6
  require 'json'
7
7
 
8
8
  require 'new_relic/agent/inbound_request_monitor'
9
- require 'new_relic/agent/transaction_state'
9
+ require 'new_relic/agent/tracer'
10
10
  require 'new_relic/agent/threading/agent_thread'
11
11
  require 'new_relic/agent/cross_app_payload'
12
12
 
@@ -44,7 +44,7 @@ module NewRelic
44
44
 
45
45
  events.subscribe(:before_call) do |env| #THREAD_LOCAL_ACCESS
46
46
  if id = decoded_id(env) and should_process_request?(id)
47
- state = NewRelic::Agent::TransactionState.tl_get
47
+ state = NewRelic::Agent::Tracer.state
48
48
 
49
49
  if (transaction = state.current_transaction)
50
50
  transaction_info = referring_transaction_info(state, env)
@@ -58,7 +58,7 @@ module NewRelic
58
58
  end
59
59
 
60
60
  events.subscribe(:after_call) do |env, (_status_code, headers, _body)| #THREAD_LOCAL_ACCESS
61
- state = NewRelic::Agent::TransactionState.tl_get
61
+ state = NewRelic::Agent::Tracer.state
62
62
 
63
63
  insert_response_header(state, env, headers)
64
64
  end
@@ -47,7 +47,7 @@ module NewRelic
47
47
  alias_method method_name_without_newrelic, method_name
48
48
 
49
49
  define_method(method_name) do |*args, &blk|
50
- segment = NewRelic::Agent::Transaction.start_datastore_segment(
50
+ segment = NewRelic::Agent::Tracer.start_datastore_segment(
51
51
  product: product,
52
52
  operation: operation
53
53
  )
@@ -112,7 +112,7 @@ module NewRelic
112
112
 
113
113
  return yield unless operation
114
114
 
115
- segment = NewRelic::Agent::Transaction.start_datastore_segment(
115
+ segment = NewRelic::Agent::Tracer.start_datastore_segment(
116
116
  product: product,
117
117
  operation: operation,
118
118
  collection: collection
@@ -123,8 +123,8 @@ module NewRelic
123
123
  ensure
124
124
  begin
125
125
  if callback
126
- elapsed_time = (Time.now - segment.start_time).to_f
127
- callback.call(result, segment.name, elapsed_time)
126
+ elapsed_time = (Time.now - segment.start_time).to_f
127
+ callback.call(result, segment.name, elapsed_time)
128
128
  end
129
129
  ensure
130
130
  segment.finish if segment
@@ -163,8 +163,7 @@ module NewRelic
163
163
  def self.notice_sql(query, scoped_metric, elapsed)
164
164
  NewRelic::Agent.record_api_supportability_metric(:notice_sql)
165
165
 
166
- state = TransactionState.tl_get
167
- if (txn = state.current_transaction) && (segment = txn.current_segment) && segment.respond_to?(:notice_sql)
166
+ if (txn = Tracer.current_transaction) && (segment = txn.current_segment) && segment.respond_to?(:notice_sql)
168
167
  segment.notice_sql(query)
169
168
  end
170
169
  nil
@@ -198,8 +197,7 @@ module NewRelic
198
197
 
199
198
  # Settings may change eventually, but for now we follow the same
200
199
  # capture rules as SQL for non-SQL statements.
201
- state = TransactionState.tl_get
202
- if (txn = state.current_transaction) && (segment = txn.current_segment) && segment.respond_to?(:notice_nosql_statement)
200
+ if (txn = Tracer.current_transaction) && (segment = txn.current_segment) && segment.respond_to?(:notice_nosql_statement)
203
201
  segment.notice_nosql_statement(statement)
204
202
  end
205
203
  nil
@@ -107,8 +107,7 @@ module NewRelic
107
107
  # Allow Transaction#with_database_metric_name to override our
108
108
  # collection and operation
109
109
  def self.overridden_operation_and_collection #THREAD_LOCAL_ACCESS
110
- state = NewRelic::Agent::TransactionState.tl_get
111
- txn = state.current_transaction
110
+ txn = Tracer.current_transaction
112
111
  txn ? txn.instrumentation_state[:datastore_override] : nil
113
112
  end
114
113
 
@@ -18,9 +18,8 @@ module NewRelic
18
18
  def on_before_call(request)
19
19
  return unless NewRelic::Agent.config[:'distributed_tracing.enabled']
20
20
  return unless payload = request[NEWRELIC_TRACE_KEY]
21
+ return unless txn = Tracer.current_transaction
21
22
 
22
- state = NewRelic::Agent::TransactionState.tl_get
23
- txn = state.current_transaction
24
23
  if txn.accept_distributed_trace_payload payload
25
24
  txn.distributed_trace_payload.caller_transport_type = transport_type(request)
26
25
  end
@@ -197,7 +197,7 @@ module NewRelic
197
197
 
198
198
  tag_exception(exception)
199
199
 
200
- state = ::NewRelic::Agent::TransactionState.tl_get
200
+ state = ::NewRelic::Agent::Tracer.state
201
201
 
202
202
  unless options[:expected]
203
203
  increment_error_count!(state, exception, options)
@@ -34,13 +34,16 @@ module NewRelic
34
34
  #
35
35
  # @api public
36
36
  def start_segment(library: nil, uri: nil, procedure: nil)
37
+ Deprecator.deprecate 'External.start_segment',
38
+ 'Tracer#start_external_request_segment'
39
+
37
40
  raise ArgumentError, 'Argument `library` is required' if library.nil?
38
41
  raise ArgumentError, 'Argument `uri` is required' if uri.nil?
39
42
  raise ArgumentError, 'Argument `procedure` is required' if procedure.nil?
40
43
 
41
44
  ::NewRelic::Agent.record_api_supportability_metric(:start_segment)
42
45
 
43
- ::NewRelic::Agent::Transaction.start_external_request_segment(
46
+ ::NewRelic::Agent::Tracer.start_external_request_segment(
44
47
  library: library,
45
48
  uri: uri,
46
49
  procedure: procedure
@@ -64,7 +67,7 @@ module NewRelic
64
67
  NewRelic::Agent.record_api_supportability_metric(:process_request_metadata)
65
68
  return unless CrossAppTracing.cross_app_enabled?
66
69
 
67
- state = NewRelic::Agent::TransactionState.tl_get
70
+ state = NewRelic::Agent::Tracer.state
68
71
  if transaction = state.current_transaction
69
72
  rmd = ::JSON.parse obfuscator.deobfuscate(request_metadata)
70
73
 
@@ -109,8 +112,7 @@ module NewRelic
109
112
  NewRelic::Agent.record_api_supportability_metric(:get_response_metadata)
110
113
  return unless CrossAppTracing.cross_app_enabled?
111
114
 
112
- state = NewRelic::Agent::TransactionState.tl_get
113
- return unless (transaction = state.current_transaction)
115
+ return unless (transaction = Tracer.current_transaction)
114
116
  return unless (cross_app_payload = transaction.cross_app_payload)
115
117
 
116
118
  # must freeze the name since we're responding with it
@@ -27,7 +27,7 @@ module NewRelic
27
27
  event = super
28
28
  notice_error payload if payload.key? :exception
29
29
  if event.name == PERFORM_ACTION
30
- finish_transaction
30
+ finish_transaction event
31
31
  else
32
32
  stop_recording_metrics event
33
33
  end
@@ -38,15 +38,18 @@ module NewRelic
38
38
  private
39
39
 
40
40
  def start_transaction event
41
- Transaction.start(state, :action_cable, :transaction_name => transaction_name_from_event(event))
41
+ event.payload[:finishable] = Tracer.start_transaction_or_segment(
42
+ name: transaction_name_from_event(event),
43
+ category: :action_cable
44
+ )
42
45
  end
43
46
 
44
- def finish_transaction
45
- Transaction.stop(state)
47
+ def finish_transaction event
48
+ (finishable = event.payload[:finishable]) && finishable.finish
46
49
  end
47
50
 
48
51
  def start_recording_metrics event
49
- event.payload[:segment] = Transaction.start_segment name: metric_name_from_event(event)
52
+ event.payload[:segment] = Tracer.start_segment name: metric_name_from_event(event)
50
53
  end
51
54
 
52
55
  def stop_recording_metrics event
@@ -43,17 +43,21 @@ module NewRelic
43
43
  end
44
44
 
45
45
  def start_transaction(event)
46
- Transaction.start(state, :controller,
47
- :request => event.request,
48
- :filtered_params => filter(event.payload[:params]),
49
- :apdex_start_time => event.queue_start,
50
- :transaction_name => event.metric_name,
51
- :ignore_apdex => event.apdex_ignored?,
52
- :ignore_enduser => event.enduser_ignored?)
46
+ event.payload[:finishable] = Tracer.start_transaction_or_segment(
47
+ name: event.metric_name,
48
+ category: :controller,
49
+ options: {
50
+ request: event.request,
51
+ filtered_params: filter(event.payload[:params]),
52
+ apdex_start_time: event.queue_start,
53
+ ignore_apdex: event.apdex_ignored?,
54
+ ignore_enduser: event.enduser_ignored?
55
+ }
56
+ )
53
57
  end
54
58
 
55
59
  def stop_transaction(event)
56
- Transaction.stop(state)
60
+ (finishable = event.payload[:finishable]) && finishable.finish
57
61
  end
58
62
 
59
63
  def filter(params)
@@ -14,7 +14,7 @@ module NewRelic
14
14
  event = RenderEvent.new(name, Time.now, nil, id, payload)
15
15
  push_event(event)
16
16
  if state.is_execution_traced? && event.recordable?
17
- event.segment = NewRelic::Agent::Transaction.start_segment name: event.metric_name
17
+ event.segment = NewRelic::Agent::Tracer.start_segment name: event.metric_name
18
18
  end
19
19
  rescue => e
20
20
  log_notification_error(e, name, 'start')
@@ -39,7 +39,7 @@ module NewRelic
39
39
  end
40
40
 
41
41
  def self.perform(job, block)
42
- state = ::NewRelic::Agent::TransactionState.tl_get
42
+ state = ::NewRelic::Agent::Tracer.state
43
43
  txn = state.current_transaction
44
44
 
45
45
  # Don't nest transactions if we're already in a web transaction.
@@ -52,7 +52,7 @@ module NewRelic
52
52
  transaction_category)
53
53
  block.call
54
54
  else
55
- run_in_transaction(state, job, block)
55
+ run_in_transaction(job, block)
56
56
  end
57
57
  end
58
58
 
@@ -62,11 +62,10 @@ module NewRelic
62
62
  end
63
63
  end
64
64
 
65
- def self.run_in_transaction(state, job, block)
66
- ::NewRelic::Agent::Transaction.wrap(state,
67
- transaction_name_for_job(job),
68
- :other,
69
- &block)
65
+ def self.run_in_transaction(job, block)
66
+ ::NewRelic::Agent::Tracer.in_transaction(name: transaction_name_for_job(job),
67
+ category: :other,
68
+ &block)
70
69
  end
71
70
 
72
71
  def self.transaction_category
@@ -44,7 +44,7 @@ module NewRelic
44
44
  end
45
45
 
46
46
  def log_with_newrelic_instrumentation(*args, &block) #THREAD_LOCAL_ACCESS
47
- state = NewRelic::Agent::TransactionState.tl_get
47
+ state = NewRelic::Agent::Tracer.state
48
48
 
49
49
  if !state.is_execution_traced?
50
50
  return log_without_newrelic_instrumentation(*args, &block)
@@ -67,7 +67,7 @@ module NewRelic
67
67
  database = @config && @config[:database]
68
68
  end
69
69
 
70
- segment = NewRelic::Agent::Transaction.start_datastore_segment(
70
+ segment = NewRelic::Agent::Tracer.start_datastore_segment(
71
71
  product: product,
72
72
  operation: operation,
73
73
  collection: collection,
@@ -114,7 +114,7 @@ module NewRelic
114
114
  database = @config && @config[:database]
115
115
  end
116
116
 
117
- segment = Transaction.start_datastore_segment product: product,
117
+ segment = Tracer.start_datastore_segment product: product,
118
118
  operation: operation,
119
119
  collection: collection,
120
120
  host: host,
@@ -130,7 +130,7 @@ module NewRelic
130
130
  end
131
131
 
132
132
  def state
133
- @state ||= NewRelic::Agent::TransactionState.tl_get
133
+ @state ||= NewRelic::Agent::Tracer.state
134
134
  end
135
135
 
136
136
  def sql
@@ -22,7 +22,7 @@ module NewRelic
22
22
  end
23
23
 
24
24
  def start_segment name, id, payload
25
- segment = Transaction.start_segment name: metric_name(name, payload)
25
+ segment = Tracer.start_segment name: metric_name(name, payload)
26
26
  segment.params[:key] = payload[:key]
27
27
  segment.params[:exist] = payload[:exist] if payload.key? :exist
28
28
  event_stack[id].push segment