newrelic_rpm 3.14.1.311 → 3.14.2.312

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +174 -11
  3. data/CHANGELOG +22 -0
  4. data/Rakefile +5 -0
  5. data/lib/new_relic/agent/agent.rb +22 -7
  6. data/lib/new_relic/agent/aws_info.rb +1 -1
  7. data/lib/new_relic/agent/custom_event_aggregator.rb +19 -44
  8. data/lib/new_relic/agent/error_event_aggregator.rb +11 -103
  9. data/lib/new_relic/agent/event_aggregator.rb +130 -0
  10. data/lib/new_relic/agent/event_buffer.rb +7 -0
  11. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +18 -2
  12. data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +12 -4
  13. data/lib/new_relic/agent/new_relic_service.rb +6 -4
  14. data/lib/new_relic/agent/sampled_buffer.rb +9 -6
  15. data/lib/new_relic/agent/stats_engine/metric_stats.rb +1 -2
  16. data/lib/new_relic/agent/stats_engine/stats_hash.rb +2 -1
  17. data/lib/new_relic/agent/supported_versions.rb +1 -1
  18. data/lib/new_relic/agent/synthetics_event_aggregator.rb +52 -0
  19. data/lib/new_relic/agent/synthetics_event_buffer.rb +0 -2
  20. data/lib/new_relic/agent/transaction.rb +14 -7
  21. data/lib/new_relic/agent/transaction/request_attributes.rb +7 -2
  22. data/lib/new_relic/agent/transaction_error_primitive.rb +72 -0
  23. data/lib/new_relic/agent/transaction_event_aggregator.rb +33 -210
  24. data/lib/new_relic/agent/transaction_event_primitive.rb +106 -0
  25. data/lib/new_relic/agent/transaction_event_recorder.rb +48 -0
  26. data/lib/new_relic/agent/transaction_metrics.rb +9 -1
  27. data/lib/new_relic/agent/transction_event_recorder.rb +35 -0
  28. data/lib/new_relic/recipes/capistrano3.rb +1 -1
  29. data/lib/new_relic/version.rb +1 -1
  30. data/lib/tasks/versions.html.erb +13 -11
  31. data/lib/tasks/versions.postface.html +8 -0
  32. data/lib/tasks/versions.preface.html +3 -0
  33. data/lib/tasks/versions.rake +15 -5
  34. data/test/agent_helper.rb +1 -1
  35. data/test/environments/rails31/Gemfile +2 -0
  36. data/test/environments/rails32/Gemfile +2 -0
  37. data/test/environments/rails32/Rakefile +2 -1
  38. data/test/environments/rails32/config/database.yml +1 -6
  39. data/test/multiverse/suites/active_record/Envfile +1 -0
  40. data/test/multiverse/suites/agent_only/agent_attributes_test.rb +18 -0
  41. data/test/multiverse/suites/agent_only/custom_analytics_events_test.rb +21 -6
  42. data/test/multiverse/suites/agent_only/error_events_test.rb +14 -6
  43. data/test/multiverse/suites/agent_only/transaction_events_test.rb +31 -0
  44. data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +2 -0
  45. data/test/multiverse/suites/capistrano/Envfile +9 -3
  46. data/test/multiverse/suites/capistrano2/Envfile +4 -0
  47. data/test/multiverse/suites/config_file_loading/Envfile +1 -1
  48. data/test/multiverse/suites/curb/Envfile +1 -1
  49. data/test/multiverse/suites/datamapper/Envfile +3 -0
  50. data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +7 -3
  51. data/test/multiverse/suites/grape/grape_test.rb +2 -0
  52. data/test/multiverse/suites/padrino/Envfile +4 -3
  53. data/test/multiverse/suites/padrino/config/newrelic.yml +2 -0
  54. data/test/multiverse/suites/rack/config/newrelic.yml +18 -0
  55. data/test/multiverse/suites/rack/nested_non_rack_app_test.rb +1 -1
  56. data/test/multiverse/suites/rack/puma_rack_builder_test.rb +17 -14
  57. data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +16 -13
  58. data/test/multiverse/suites/rack/rack_unsupported_version_test.rb +1 -1
  59. data/test/multiverse/suites/rails/Envfile +5 -0
  60. data/test/multiverse/suites/rails/parameter_capture_test.rb +9 -0
  61. data/test/multiverse/suites/rake/Envfile +2 -1
  62. data/test/multiverse/suites/redis/redis_instrumentation_test.rb +1 -1
  63. data/test/multiverse/suites/sidekiq/Envfile +18 -0
  64. data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +11 -10
  65. data/test/multiverse/suites/sidekiq/test_model.rb +12 -0
  66. data/test/multiverse/suites/sinatra/ignoring_test.rb +43 -25
  67. data/test/multiverse/suites/sinatra/nested_middleware_test.rb +10 -2
  68. data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +4 -0
  69. data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +8 -2
  70. data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +4 -0
  71. data/test/multiverse/suites/sinatra/sinatra_parameter_capture_test.rb +2 -0
  72. data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +79 -10
  73. data/test/new_relic/agent/agent_test.rb +3 -3
  74. data/test/new_relic/agent/aws_info_test.rb +1 -2
  75. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +2 -0
  76. data/test/new_relic/agent/custom_event_aggregator_test.rb +43 -4
  77. data/test/new_relic/agent/error_collector_test.rb +1 -1
  78. data/test/new_relic/agent/error_event_aggregator_test.rb +13 -81
  79. data/test/new_relic/agent/event_aggregator_test.rb +178 -0
  80. data/test/new_relic/agent/event_buffer_test_cases.rb +16 -0
  81. data/test/new_relic/agent/instrumentation/sinatra/transaction_namer_test.rb +7 -0
  82. data/test/new_relic/agent/new_relic_service_test.rb +7 -1
  83. data/test/new_relic/agent/pipe_channel_manager_test.rb +45 -3
  84. data/test/new_relic/agent/rpm_agent_test.rb +1 -0
  85. data/test/new_relic/agent/stats_engine/stats_hash_test.rb +2 -2
  86. data/test/new_relic/agent/synthetics_event_aggregator_test.rb +179 -0
  87. data/test/new_relic/agent/transaction/request_attributes_test.rb +8 -0
  88. data/test/new_relic/agent/transaction_error_primitive_test.rb +117 -0
  89. data/test/new_relic/agent/transaction_event_aggregator_test.rb +148 -374
  90. data/test/new_relic/agent/transaction_event_primitive_test.rb +195 -0
  91. data/test/new_relic/agent/transaction_event_recorder_test.rb +80 -0
  92. data/test/new_relic/agent/transaction_metrics_test.rb +7 -7
  93. data/test/new_relic/agent/transaction_test.rb +4 -4
  94. data/test/new_relic/agent/utilization_data_test.rb +7 -7
  95. data/test/new_relic/fake_collector.rb +10 -17
  96. data/test/new_relic/license_test.rb +2 -0
  97. data/test/new_relic/marshalling_test_cases.rb +1 -1
  98. data/test/nullverse/default_source_require_test.rb +21 -0
  99. data/test/nullverse/nullverse_helper.rb +10 -0
  100. data/test/performance/suites/active_record.rb +1 -1
  101. data/test/performance/suites/sql_obfuscation.rb +7 -6
  102. data/test/script/ci.sh +10 -165
  103. data/test/script/install_mongodb.sh +6 -0
  104. metadata +21 -6
  105. data/test/script/build_test_gem.sh +0 -57
  106. data/test/script/ci_agent-tests_runner.sh +0 -82
  107. data/test/script/ci_bench.sh +0 -52
  108. data/test/script/ci_multiverse_runner.sh +0 -63
@@ -8,8 +8,8 @@ module NewRelic
8
8
  module Agent
9
9
  class Transaction
10
10
  class RequestAttributes
11
- attr_reader :request_path, :referer, :accept, :content_length, :host,
12
- :port, :user_agent, :request_method
11
+ attr_reader :request_path, :referer, :accept, :content_length, :content_type,
12
+ :host, :port, :user_agent, :request_method
13
13
 
14
14
  HTTP_ACCEPT_HEADER_KEY = "HTTP_ACCEPT".freeze
15
15
 
@@ -18,6 +18,7 @@ module NewRelic
18
18
  @referer = referer_from_request request
19
19
  @accept = attribute_from_env request, HTTP_ACCEPT_HEADER_KEY
20
20
  @content_length = content_length_from_request request
21
+ @content_type = attribute_from_request request, :content_type
21
22
  @host = attribute_from_request request, :host
22
23
  @port = port_from_request request
23
24
  @user_agent = attribute_from_request request, :user_agent
@@ -41,6 +42,10 @@ module NewRelic
41
42
  txn.add_agent_attribute :'request.headers.contentLength', content_length, default_destinations
42
43
  end
43
44
 
45
+ if content_type
46
+ txn.add_agent_attribute :'request.headers.contentType', content_type, default_destinations
47
+ end
48
+
44
49
  if host
45
50
  txn.add_agent_attribute :'request.headers.host', host, default_destinations
46
51
  end
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ # This module was introduced and largely extracted from the transaction event aggregator
6
+ # when the synthetics container was extracted from it. Its purpose is to create the data
7
+ # necessary for creating a transaction event and to facilitate transfer of events between
8
+ # the transaction event aggregator and the synthetics container.
9
+
10
+ require 'new_relic/agent/payload_metric_mapping'
11
+
12
+ module NewRelic
13
+ module Agent
14
+ module TransactionErrorPrimitive
15
+ extend self
16
+
17
+ SAMPLE_TYPE = 'TransactionError'.freeze
18
+ TYPE_KEY = 'type'.freeze
19
+ ERROR_CLASS_KEY = 'error.class'.freeze
20
+ ERROR_MESSAGE_KEY = 'error.message'.freeze
21
+ TIMESTAMP_KEY = 'timestamp'.freeze
22
+ PORT_KEY = 'port'.freeze
23
+ NAME_KEY = 'transactionName'.freeze
24
+ DURATION_KEY = 'duration'.freeze
25
+ GUID_KEY = 'nr.transactionGuid'.freeze
26
+ REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'.freeze
27
+ SYNTHETICS_RESOURCE_ID_KEY = "nr.syntheticsResourceId".freeze
28
+ SYNTHETICS_JOB_ID_KEY = "nr.syntheticsJobId".freeze
29
+ SYNTHETICS_MONITOR_ID_KEY = "nr.syntheticsMonitorId".freeze
30
+
31
+ def create noticed_error, payload
32
+ [
33
+ intrinsic_attributes_for(noticed_error, payload),
34
+ noticed_error.custom_attributes,
35
+ noticed_error.agent_attributes
36
+ ]
37
+ end
38
+
39
+ def intrinsic_attributes_for noticed_error, payload
40
+ attrs = {
41
+ TYPE_KEY => SAMPLE_TYPE,
42
+ ERROR_CLASS_KEY => noticed_error.exception_class_name,
43
+ ERROR_MESSAGE_KEY => noticed_error.message,
44
+ TIMESTAMP_KEY => noticed_error.timestamp.to_f
45
+ }
46
+
47
+ attrs[PORT_KEY] = noticed_error.request_port if noticed_error.request_port
48
+
49
+ if payload
50
+ attrs[NAME_KEY] = payload[:name]
51
+ attrs[DURATION_KEY] = payload[:duration]
52
+ append_synthetics payload, attrs
53
+ append_cat payload, attrs
54
+ PayloadMetricMapping.append_mapped_metrics payload[:metrics], attrs
55
+ end
56
+
57
+ attrs
58
+ end
59
+
60
+ def append_synthetics payload, sample
61
+ sample[SYNTHETICS_RESOURCE_ID_KEY] = payload[:synthetics_resource_id] if payload[:synthetics_resource_id]
62
+ sample[SYNTHETICS_JOB_ID_KEY] = payload[:synthetics_job_id] if payload[:synthetics_job_id]
63
+ sample[SYNTHETICS_MONITOR_ID_KEY] = payload[:synthetics_monitor_id] if payload[:synthetics_monitor_id]
64
+ end
65
+
66
+ def append_cat payload, sample
67
+ sample[GUID_KEY] = payload[:guid] if payload[:guid]
68
+ sample[REFERRING_TRANSACTION_GUID_KEY] = payload[:referring_transaction_guid] if payload[:referring_transaction_guid]
69
+ end
70
+ end
71
+ end
72
+ end
@@ -3,226 +3,49 @@
3
3
  # This file is distributed under New Relic's license terms.
4
4
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
5
5
 
6
- require 'monitor'
7
-
8
6
  require 'newrelic_rpm' unless defined?( NewRelic )
9
7
  require 'new_relic/agent' unless defined?( NewRelic::Agent )
10
- require 'new_relic/agent/payload_metric_mapping'
11
-
12
- class NewRelic::Agent::TransactionEventAggregator
13
- include NewRelic::Coerce,
14
- MonitorMixin
15
-
16
- # The type field of the sample
17
- SAMPLE_TYPE = 'Transaction'.freeze
18
-
19
- # Strings for static keys of the sample structure
20
- TYPE_KEY = 'type'.freeze
21
- TIMESTAMP_KEY = 'timestamp'.freeze
22
- NAME_KEY = 'name'.freeze
23
- DURATION_KEY = 'duration'.freeze
24
- ERROR_KEY = 'error'.freeze
25
- GUID_KEY = 'nr.guid'.freeze
26
- REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'.freeze
27
- CAT_TRIP_ID_KEY = 'nr.tripId'.freeze
28
- CAT_PATH_HASH_KEY = 'nr.pathHash'.freeze
29
- CAT_REFERRING_PATH_HASH_KEY = 'nr.referringPathHash'.freeze
30
- CAT_ALTERNATE_PATH_HASHES_KEY = 'nr.alternatePathHashes'.freeze
31
- APDEX_PERF_ZONE_KEY = 'nr.apdexPerfZone'.freeze
32
- SYNTHETICS_RESOURCE_ID_KEY = "nr.syntheticsResourceId".freeze
33
- SYNTHETICS_JOB_ID_KEY = "nr.syntheticsJobId".freeze
34
- SYNTHETICS_MONITOR_ID_KEY = "nr.syntheticsMonitorId".freeze
35
-
36
- # To avoid allocations when we have empty custom or agent attributes
37
- EMPTY_HASH = {}.freeze
38
-
39
- def initialize( event_listener )
40
- super()
41
-
42
- @enabled = false
43
- @notified_full = false
44
-
45
- @samples = ::NewRelic::Agent::SampledBuffer.new(NewRelic::Agent.config[:'analytics_events.max_samples_stored'])
46
- @synthetics_samples = ::NewRelic::Agent::SyntheticsEventBuffer.new(NewRelic::Agent.config[:'synthetics.events_limit'])
47
-
48
- event_listener.subscribe( :transaction_finished, &method(:on_transaction_finished) )
49
- self.register_config_callbacks
50
- end
51
-
52
-
53
- ######
54
- public
55
- ######
56
-
57
- # Fetch a copy of the sampler's gathered samples. (Synchronized)
58
- def samples
59
- return self.synchronize { @samples.to_a.concat(@synthetics_samples.to_a) }
60
- end
61
-
62
- def reset!
63
- sample_count, request_count, synthetics_dropped = 0
64
- old_samples = nil
8
+ require 'new_relic/agent/event_aggregator'
65
9
 
66
- self.synchronize do
67
- sample_count = @samples.size
68
- request_count = @samples.num_seen
10
+ module NewRelic
11
+ module Agent
12
+ class TransactionEventAggregator < EventAggregator
69
13
 
70
- synthetics_dropped = @synthetics_samples.num_dropped
14
+ named :TransactionEventAggregator
15
+ capacity_key :'analytics_events.max_samples_stored'
16
+ enabled_key :'analytics_events.enabled'
71
17
 
72
- old_samples = @samples.to_a + @synthetics_samples.to_a
73
- @samples.reset!
74
- @synthetics_samples.reset!
18
+ def append event=nil, &blk
19
+ raise ArgumentError, "Expected argument or block, but received both" if event && blk
20
+ return unless enabled?
75
21
 
76
- @notified_full = false
77
- end
78
-
79
- [old_samples, sample_count, request_count, synthetics_dropped]
80
- end
81
-
82
- # Clear any existing samples, reset the last sample time, and return the
83
- # previous set of samples. (Synchronized)
84
- def harvest!
85
- old_samples, sample_count, request_count, synthetics_dropped = reset!
86
- record_sampling_rate(request_count, sample_count) if @enabled
87
- record_dropped_synthetics(synthetics_dropped)
88
- old_samples
89
- end
90
-
91
- # Merge samples back into the buffer, for example after a failed
92
- # transmission to the collector. (Synchronized)
93
- def merge!(old_samples)
94
- self.synchronize do
95
- old_samples.each { |s| append_event(s) }
96
- end
97
- end
98
-
99
- def record_sampling_rate(request_count, sample_count) #THREAD_LOCAL_ACCESS
100
- request_count_lifetime = @samples.seen_lifetime
101
- sample_count_lifetime = @samples.captured_lifetime
102
- NewRelic::Agent.logger.debug("Sampled %d / %d (%.1f %%) requests this cycle, %d / %d (%.1f %%) since startup" % [
103
- sample_count,
104
- request_count,
105
- (sample_count.to_f / request_count * 100.0),
106
- sample_count_lifetime,
107
- request_count_lifetime,
108
- (sample_count_lifetime.to_f / request_count_lifetime * 100.0)
109
- ])
110
-
111
- engine = NewRelic::Agent.instance.stats_engine
112
- engine.tl_record_supportability_metric_count("TransactionEventAggregator/requests", request_count)
113
- engine.tl_record_supportability_metric_count("TransactionEventAggregator/samples", sample_count)
114
- end
115
-
116
- def record_dropped_synthetics(synthetics_dropped)
117
- return unless synthetics_dropped > 0
118
-
119
- NewRelic::Agent.logger.debug("Synthetics transaction event limit (#{@samples.capacity}) reached. Further synthetics events this harvest period dropped.")
120
-
121
- engine = NewRelic::Agent.instance.stats_engine
122
- engine.tl_record_supportability_metric_count("TransactionEventAggregator/synthetics_events_dropped", synthetics_dropped)
123
- end
124
-
125
- def register_config_callbacks
126
- NewRelic::Agent.config.register_callback(:'analytics_events.max_samples_stored') do |max_samples|
127
- NewRelic::Agent.logger.debug "TransactionEventAggregator max_samples set to #{max_samples}"
128
- self.synchronize { @samples.capacity = max_samples }
129
- end
130
-
131
- NewRelic::Agent.config.register_callback(:'synthetics.events_limit') do |max_samples|
132
- NewRelic::Agent.logger.debug "TransactionEventAggregator limit for synthetics events set to #{max_samples}"
133
- self.synchronize { @synthetics_samples.capacity = max_samples }
134
- end
135
-
136
- NewRelic::Agent.config.register_callback(:'analytics_events.enabled') do |enabled|
137
- @enabled = enabled
138
- end
139
- end
140
-
141
- def notify_full
142
- NewRelic::Agent.logger.debug "Transaction event capacity of #{@samples.capacity} reached, beginning sampling"
143
- @notified_full = true
144
- end
145
-
146
- # Event handler for the :transaction_finished event.
147
- def on_transaction_finished(payload)
148
- return unless @enabled
149
-
150
- attributes = payload[:attributes]
151
- main_event = create_main_event(payload)
152
- custom_attributes = create_custom_attributes(attributes)
153
- agent_attributes = create_agent_attributes(attributes)
154
-
155
- self.synchronize { append_event([main_event, custom_attributes, agent_attributes]) }
156
- notify_full if !@notified_full && @samples.full?
157
- end
158
-
159
- def append_event(event)
160
- main_event, _ = event
161
-
162
- if main_event.include?(SYNTHETICS_RESOURCE_ID_KEY)
163
- # Try adding to synthetics buffer. If anything is rejected, give it a
164
- # shot in the main transaction events (where it may get sampled)
165
- _, rejected = @synthetics_samples.append_with_reject(event)
166
-
167
- if rejected
168
- @samples.append(rejected)
22
+ @lock.synchronize do
23
+ @buffer.append event, &blk
24
+ notify_if_full
25
+ end
169
26
  end
170
- else
171
- @samples.append(event)
172
- end
173
- end
174
-
175
- def create_main_event(payload)
176
- sample = {
177
- TIMESTAMP_KEY => float(payload[:start_timestamp]),
178
- NAME_KEY => string(payload[:name]),
179
- DURATION_KEY => float(payload[:duration]),
180
- TYPE_KEY => SAMPLE_TYPE,
181
- ERROR_KEY => payload[:error]
182
- }
183
- NewRelic::Agent::PayloadMetricMapping.append_mapped_metrics(payload[:metrics], sample)
184
- optionally_append(GUID_KEY, :guid, sample, payload)
185
- optionally_append(REFERRING_TRANSACTION_GUID_KEY, :referring_transaction_guid, sample, payload)
186
- optionally_append(CAT_TRIP_ID_KEY, :cat_trip_id, sample, payload)
187
- optionally_append(CAT_PATH_HASH_KEY, :cat_path_hash, sample, payload)
188
- optionally_append(CAT_REFERRING_PATH_HASH_KEY, :cat_referring_path_hash, sample, payload)
189
- optionally_append(APDEX_PERF_ZONE_KEY, :apdex_perf_zone, sample, payload)
190
- optionally_append(SYNTHETICS_RESOURCE_ID_KEY, :synthetics_resource_id, sample, payload)
191
- optionally_append(SYNTHETICS_JOB_ID_KEY, :synthetics_job_id, sample, payload)
192
- optionally_append(SYNTHETICS_MONITOR_ID_KEY, :synthetics_monitor_id, sample, payload)
193
- append_cat_alternate_path_hashes(sample, payload)
194
- sample
195
- end
196
-
197
- def append_cat_alternate_path_hashes(sample, payload)
198
- if payload.include?(:cat_alternate_path_hashes)
199
- sample[CAT_ALTERNATE_PATH_HASHES_KEY] = payload[:cat_alternate_path_hashes].sort.join(',')
200
- end
201
- end
202
27
 
203
- def optionally_append(sample_key, payload_key, sample, payload)
204
- if payload.include?(payload_key)
205
- sample[sample_key] = string(payload[payload_key])
206
- end
207
- end
28
+ private
208
29
 
209
- def create_custom_attributes(attributes)
210
- if attributes
211
- custom_attributes = attributes.custom_attributes_for(NewRelic::Agent::AttributeFilter::DST_TRANSACTION_EVENTS)
212
- custom_attributes = custom_attributes
213
- custom_attributes.freeze
214
- else
215
- EMPTY_HASH
216
- end
217
- end
30
+ def after_harvest metadata
31
+ return unless enabled?
32
+ record_sampling_rate metadata
33
+ end
218
34
 
219
- def create_agent_attributes(attributes)
220
- if attributes
221
- agent_attributes = attributes.agent_attributes_for(NewRelic::Agent::AttributeFilter::DST_TRANSACTION_EVENTS)
222
- agent_attributes = agent_attributes
223
- agent_attributes.freeze
224
- else
225
- EMPTY_HASH
35
+ def record_sampling_rate(metadata) #THREAD_LOCAL_ACCESS
36
+ NewRelic::Agent.logger.debug("Sampled %d / %d (%.1f %%) requests this cycle, %d / %d (%.1f %%) since startup" % [
37
+ metadata[:captured],
38
+ metadata[:seen],
39
+ (metadata[:captured].to_f / metadata[:seen] * 100.0),
40
+ metadata[:captured_lifetime],
41
+ metadata[:seen_lifetime],
42
+ (metadata[:captured_lifetime].to_f / metadata[:seen_lifetime] * 100.0)
43
+ ])
44
+
45
+ engine = NewRelic::Agent.instance.stats_engine
46
+ engine.tl_record_supportability_metric_count("TransactionEventAggregator/requests", metadata[:seen])
47
+ engine.tl_record_supportability_metric_count("TransactionEventAggregator/samples", metadata[:captured])
48
+ end
226
49
  end
227
50
  end
228
51
  end
@@ -0,0 +1,106 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+
5
+ # This module was introduced and largely extracted from the transaction event aggregator
6
+ # when the synthetics container was extracted from it. Its purpose is to create the data
7
+ # necessary for creating a transaction event and to facilitate transfer of events between
8
+ # the transaction event aggregator and the synthetics container.
9
+
10
+ require 'new_relic/agent/payload_metric_mapping'
11
+
12
+ module NewRelic
13
+ module Agent
14
+ module TransactionEventPrimitive
15
+ include NewRelic::Coerce
16
+ extend self
17
+
18
+ # The type field of the sample
19
+ SAMPLE_TYPE = 'Transaction'.freeze
20
+
21
+ # Strings for static keys of the sample structure
22
+ TYPE_KEY = 'type'.freeze
23
+ TIMESTAMP_KEY = 'timestamp'.freeze
24
+ NAME_KEY = 'name'.freeze
25
+ DURATION_KEY = 'duration'.freeze
26
+ ERROR_KEY = 'error'.freeze
27
+ GUID_KEY = 'nr.guid'.freeze
28
+ REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'.freeze
29
+ CAT_TRIP_ID_KEY = 'nr.tripId'.freeze
30
+ CAT_PATH_HASH_KEY = 'nr.pathHash'.freeze
31
+ CAT_REFERRING_PATH_HASH_KEY = 'nr.referringPathHash'.freeze
32
+ CAT_ALTERNATE_PATH_HASHES_KEY = 'nr.alternatePathHashes'.freeze
33
+ APDEX_PERF_ZONE_KEY = 'nr.apdexPerfZone'.freeze
34
+ SYNTHETICS_RESOURCE_ID_KEY = "nr.syntheticsResourceId".freeze
35
+ SYNTHETICS_JOB_ID_KEY = "nr.syntheticsJobId".freeze
36
+ SYNTHETICS_MONITOR_ID_KEY = "nr.syntheticsMonitorId".freeze
37
+
38
+ # To avoid allocations when we have empty custom or agent attributes
39
+ EMPTY_HASH = {}.freeze
40
+
41
+ def create(payload)
42
+ intrinsics = {
43
+ TIMESTAMP_KEY => float(payload[:start_timestamp]),
44
+ NAME_KEY => string(payload[:name]),
45
+ DURATION_KEY => float(payload[:duration]),
46
+ TYPE_KEY => SAMPLE_TYPE,
47
+ ERROR_KEY => payload[:error]
48
+ }
49
+
50
+ NewRelic::Agent::PayloadMetricMapping.append_mapped_metrics(payload[:metrics], intrinsics)
51
+ append_optional_attributes(intrinsics, payload)
52
+
53
+ attributes = payload[:attributes]
54
+
55
+ [intrinsics, custom_attributes(attributes), agent_attributes(attributes)]
56
+ end
57
+
58
+ private
59
+
60
+ def append_optional_attributes(sample, payload)
61
+ optionally_append(GUID_KEY, :guid, sample, payload)
62
+ optionally_append(REFERRING_TRANSACTION_GUID_KEY, :referring_transaction_guid, sample, payload)
63
+ optionally_append(CAT_TRIP_ID_KEY, :cat_trip_id, sample, payload)
64
+ optionally_append(CAT_PATH_HASH_KEY, :cat_path_hash, sample, payload)
65
+ optionally_append(CAT_REFERRING_PATH_HASH_KEY, :cat_referring_path_hash, sample, payload)
66
+ optionally_append(APDEX_PERF_ZONE_KEY, :apdex_perf_zone, sample, payload)
67
+ optionally_append(SYNTHETICS_RESOURCE_ID_KEY, :synthetics_resource_id, sample, payload)
68
+ optionally_append(SYNTHETICS_JOB_ID_KEY, :synthetics_job_id, sample, payload)
69
+ optionally_append(SYNTHETICS_MONITOR_ID_KEY, :synthetics_monitor_id, sample, payload)
70
+ append_cat_alternate_path_hashes(sample, payload)
71
+ end
72
+
73
+ COMMA = ','.freeze
74
+
75
+ def append_cat_alternate_path_hashes(sample, payload)
76
+ if payload.include?(:cat_alternate_path_hashes)
77
+ sample[CAT_ALTERNATE_PATH_HASHES_KEY] = payload[:cat_alternate_path_hashes].sort.join(COMMA)
78
+ end
79
+ end
80
+
81
+ def optionally_append(sample_key, payload_key, sample, payload)
82
+ if payload.include?(payload_key)
83
+ sample[sample_key] = string(payload[payload_key])
84
+ end
85
+ end
86
+
87
+ def custom_attributes attributes
88
+ if attributes
89
+ result = attributes.custom_attributes_for(NewRelic::Agent::AttributeFilter::DST_TRANSACTION_EVENTS)
90
+ result.freeze
91
+ else
92
+ EMPTY_HASH
93
+ end
94
+ end
95
+
96
+ def agent_attributes attributes
97
+ if attributes
98
+ result = attributes.agent_attributes_for(NewRelic::Agent::AttributeFilter::DST_TRANSACTION_EVENTS)
99
+ result.freeze
100
+ else
101
+ EMPTY_HASH
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end