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.
- checksums.yaml +4 -4
- data/.travis.yml +174 -11
- data/CHANGELOG +22 -0
- data/Rakefile +5 -0
- data/lib/new_relic/agent/agent.rb +22 -7
- data/lib/new_relic/agent/aws_info.rb +1 -1
- data/lib/new_relic/agent/custom_event_aggregator.rb +19 -44
- data/lib/new_relic/agent/error_event_aggregator.rb +11 -103
- data/lib/new_relic/agent/event_aggregator.rb +130 -0
- data/lib/new_relic/agent/event_buffer.rb +7 -0
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +18 -2
- data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +12 -4
- data/lib/new_relic/agent/new_relic_service.rb +6 -4
- data/lib/new_relic/agent/sampled_buffer.rb +9 -6
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +1 -2
- data/lib/new_relic/agent/stats_engine/stats_hash.rb +2 -1
- data/lib/new_relic/agent/supported_versions.rb +1 -1
- data/lib/new_relic/agent/synthetics_event_aggregator.rb +52 -0
- data/lib/new_relic/agent/synthetics_event_buffer.rb +0 -2
- data/lib/new_relic/agent/transaction.rb +14 -7
- data/lib/new_relic/agent/transaction/request_attributes.rb +7 -2
- data/lib/new_relic/agent/transaction_error_primitive.rb +72 -0
- data/lib/new_relic/agent/transaction_event_aggregator.rb +33 -210
- data/lib/new_relic/agent/transaction_event_primitive.rb +106 -0
- data/lib/new_relic/agent/transaction_event_recorder.rb +48 -0
- data/lib/new_relic/agent/transaction_metrics.rb +9 -1
- data/lib/new_relic/agent/transction_event_recorder.rb +35 -0
- data/lib/new_relic/recipes/capistrano3.rb +1 -1
- data/lib/new_relic/version.rb +1 -1
- data/lib/tasks/versions.html.erb +13 -11
- data/lib/tasks/versions.postface.html +8 -0
- data/lib/tasks/versions.preface.html +3 -0
- data/lib/tasks/versions.rake +15 -5
- data/test/agent_helper.rb +1 -1
- data/test/environments/rails31/Gemfile +2 -0
- data/test/environments/rails32/Gemfile +2 -0
- data/test/environments/rails32/Rakefile +2 -1
- data/test/environments/rails32/config/database.yml +1 -6
- data/test/multiverse/suites/active_record/Envfile +1 -0
- data/test/multiverse/suites/agent_only/agent_attributes_test.rb +18 -0
- data/test/multiverse/suites/agent_only/custom_analytics_events_test.rb +21 -6
- data/test/multiverse/suites/agent_only/error_events_test.rb +14 -6
- data/test/multiverse/suites/agent_only/transaction_events_test.rb +31 -0
- data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +2 -0
- data/test/multiverse/suites/capistrano/Envfile +9 -3
- data/test/multiverse/suites/capistrano2/Envfile +4 -0
- data/test/multiverse/suites/config_file_loading/Envfile +1 -1
- data/test/multiverse/suites/curb/Envfile +1 -1
- data/test/multiverse/suites/datamapper/Envfile +3 -0
- data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +7 -3
- data/test/multiverse/suites/grape/grape_test.rb +2 -0
- data/test/multiverse/suites/padrino/Envfile +4 -3
- data/test/multiverse/suites/padrino/config/newrelic.yml +2 -0
- data/test/multiverse/suites/rack/config/newrelic.yml +18 -0
- data/test/multiverse/suites/rack/nested_non_rack_app_test.rb +1 -1
- data/test/multiverse/suites/rack/puma_rack_builder_test.rb +17 -14
- data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +16 -13
- data/test/multiverse/suites/rack/rack_unsupported_version_test.rb +1 -1
- data/test/multiverse/suites/rails/Envfile +5 -0
- data/test/multiverse/suites/rails/parameter_capture_test.rb +9 -0
- data/test/multiverse/suites/rake/Envfile +2 -1
- data/test/multiverse/suites/redis/redis_instrumentation_test.rb +1 -1
- data/test/multiverse/suites/sidekiq/Envfile +18 -0
- data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +11 -10
- data/test/multiverse/suites/sidekiq/test_model.rb +12 -0
- data/test/multiverse/suites/sinatra/ignoring_test.rb +43 -25
- data/test/multiverse/suites/sinatra/nested_middleware_test.rb +10 -2
- data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +4 -0
- data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +8 -2
- data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +4 -0
- data/test/multiverse/suites/sinatra/sinatra_parameter_capture_test.rb +2 -0
- data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +79 -10
- data/test/new_relic/agent/agent_test.rb +3 -3
- data/test/new_relic/agent/aws_info_test.rb +1 -2
- data/test/new_relic/agent/configuration/orphan_configuration_test.rb +2 -0
- data/test/new_relic/agent/custom_event_aggregator_test.rb +43 -4
- data/test/new_relic/agent/error_collector_test.rb +1 -1
- data/test/new_relic/agent/error_event_aggregator_test.rb +13 -81
- data/test/new_relic/agent/event_aggregator_test.rb +178 -0
- data/test/new_relic/agent/event_buffer_test_cases.rb +16 -0
- data/test/new_relic/agent/instrumentation/sinatra/transaction_namer_test.rb +7 -0
- data/test/new_relic/agent/new_relic_service_test.rb +7 -1
- data/test/new_relic/agent/pipe_channel_manager_test.rb +45 -3
- data/test/new_relic/agent/rpm_agent_test.rb +1 -0
- data/test/new_relic/agent/stats_engine/stats_hash_test.rb +2 -2
- data/test/new_relic/agent/synthetics_event_aggregator_test.rb +179 -0
- data/test/new_relic/agent/transaction/request_attributes_test.rb +8 -0
- data/test/new_relic/agent/transaction_error_primitive_test.rb +117 -0
- data/test/new_relic/agent/transaction_event_aggregator_test.rb +148 -374
- data/test/new_relic/agent/transaction_event_primitive_test.rb +195 -0
- data/test/new_relic/agent/transaction_event_recorder_test.rb +80 -0
- data/test/new_relic/agent/transaction_metrics_test.rb +7 -7
- data/test/new_relic/agent/transaction_test.rb +4 -4
- data/test/new_relic/agent/utilization_data_test.rb +7 -7
- data/test/new_relic/fake_collector.rb +10 -17
- data/test/new_relic/license_test.rb +2 -0
- data/test/new_relic/marshalling_test_cases.rb +1 -1
- data/test/nullverse/default_source_require_test.rb +21 -0
- data/test/nullverse/nullverse_helper.rb +10 -0
- data/test/performance/suites/active_record.rb +1 -1
- data/test/performance/suites/sql_obfuscation.rb +7 -6
- data/test/script/ci.sh +10 -165
- data/test/script/install_mongodb.sh +6 -0
- metadata +21 -6
- data/test/script/build_test_gem.sh +0 -57
- data/test/script/ci_agent-tests_runner.sh +0 -82
- data/test/script/ci_bench.sh +0 -52
- 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, :
|
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/
|
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
|
-
|
67
|
-
|
68
|
-
|
10
|
+
module NewRelic
|
11
|
+
module Agent
|
12
|
+
class TransactionEventAggregator < EventAggregator
|
69
13
|
|
70
|
-
|
14
|
+
named :TransactionEventAggregator
|
15
|
+
capacity_key :'analytics_events.max_samples_stored'
|
16
|
+
enabled_key :'analytics_events.enabled'
|
71
17
|
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
-
|
204
|
-
if payload.include?(payload_key)
|
205
|
-
sample[sample_key] = string(payload[payload_key])
|
206
|
-
end
|
207
|
-
end
|
28
|
+
private
|
208
29
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
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
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
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
|