newrelic_rpm 3.9.6.257 → 3.9.7.266
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +45 -0
- data/lib/new_relic/agent.rb +0 -1
- data/lib/new_relic/agent/agent.rb +61 -22
- data/lib/new_relic/agent/agent_logger.rb +11 -9
- data/lib/new_relic/agent/configuration/default_source.rb +25 -2
- data/lib/new_relic/agent/cross_app_monitor.rb +15 -53
- data/lib/new_relic/agent/cross_app_tracing.rb +11 -3
- data/lib/new_relic/agent/custom_event_aggregator.rb +98 -0
- data/lib/new_relic/agent/event_buffer.rb +84 -0
- data/lib/new_relic/agent/harvester.rb +4 -15
- data/lib/new_relic/agent/hostname.rb +1 -9
- data/lib/new_relic/agent/inbound_request_monitor.rb +41 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +2 -2
- data/lib/new_relic/agent/instrumentation/queue_time.rb +0 -5
- data/lib/new_relic/agent/instrumentation/resque.rb +4 -9
- data/lib/new_relic/agent/javascript_instrumentor.rb +0 -12
- data/lib/new_relic/agent/method_tracer_helpers.rb +3 -1
- data/lib/new_relic/agent/new_relic_service.rb +1 -1
- data/lib/new_relic/agent/sampled_buffer.rb +13 -41
- data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +52 -24
- data/lib/new_relic/agent/sized_buffer.rb +23 -0
- data/lib/new_relic/agent/synthetics_monitor.rb +50 -0
- data/lib/new_relic/agent/system_info.rb +28 -0
- data/lib/new_relic/agent/transaction.rb +78 -9
- data/lib/new_relic/agent/transaction/synthetics_sample_buffer.rb +25 -0
- data/lib/new_relic/agent/{request_sampler.rb → transaction_event_aggregator.rb} +53 -19
- data/lib/new_relic/agent/transaction_sample_builder.rb +3 -1
- data/lib/new_relic/agent/transaction_sampler.rb +10 -0
- data/lib/new_relic/agent/transaction_state.rb +1 -9
- data/lib/new_relic/coerce.rb +8 -2
- data/lib/new_relic/control.rb +0 -1
- data/lib/new_relic/local_environment.rb +12 -8
- data/lib/new_relic/metric_spec.rb +11 -2
- data/lib/new_relic/rack/developer_mode.rb +9 -1
- data/lib/new_relic/transaction_sample.rb +4 -10
- data/lib/new_relic/version.rb +1 -1
- data/newrelic_rpm.gemspec +1 -0
- data/test/agent_helper.rb +15 -2
- data/test/environments/norails/Gemfile +1 -0
- data/test/environments/rails21/Gemfile +1 -0
- data/test/environments/rails22/Gemfile +1 -0
- data/test/environments/rails23/Gemfile +1 -0
- data/test/environments/rails30/Gemfile +1 -0
- data/test/environments/rails31/Gemfile +1 -0
- data/test/environments/rails32/Gemfile +2 -1
- data/test/environments/rails40/Gemfile +2 -1
- data/test/environments/rails41/Gemfile +3 -1
- data/test/environments/rails42/Gemfile +3 -1
- data/test/fixtures/cross_agent_tests/README.md +6 -2
- data/test/fixtures/cross_agent_tests/docker_container_id/README.md +6 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/cases.json +22 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-0.9.1.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.0.0.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.3.txt +9 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/empty.txt +0 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/lxc-containers-without-docker.txt +10 -0
- data/test/fixtures/cross_agent_tests/proc_meminfo/README.md +7 -0
- data/test/fixtures/cross_agent_tests/proc_meminfo/meminfo_4096MB.txt +47 -0
- data/test/fixtures/cross_agent_tests/rum_client_config.json +0 -80
- data/test/fixtures/cross_agent_tests/synthetics/synthetics.json +317 -0
- data/test/multiverse/lib/multiverse/runner.rb +1 -1
- data/test/multiverse/lib/multiverse/suite.rb +1 -0
- data/test/multiverse/suites/active_record/Envfile +42 -8
- data/test/multiverse/suites/active_record/ar_method_aliasing.rb +8 -4
- data/test/multiverse/suites/agent_only/audit_log_test.rb +0 -2
- data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +1 -2
- data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +5 -5
- data/test/multiverse/suites/agent_only/encoding_handling_test.rb +2 -0
- data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +8 -0
- data/test/multiverse/suites/agent_only/synthetics_test.rb +139 -0
- data/test/multiverse/suites/delayed_job/Envfile +79 -0
- data/test/multiverse/suites/delayed_job/before_suite.rb +33 -0
- data/test/multiverse/suites/delayed_job/config/newrelic.yml +18 -0
- data/test/multiverse/suites/delayed_job/delayed_job_sampler_test.rb +131 -0
- data/test/multiverse/suites/delayed_job/unsupported_backend_test.rb +24 -0
- data/test/multiverse/suites/high_security/high_security_test.rb +3 -10
- data/test/multiverse/suites/rails/Envfile +4 -4
- data/test/multiverse/suites/rails/request_statistics_test.rb +4 -4
- data/test/new_relic/agent/agent_test.rb +32 -4
- data/test/new_relic/agent/configuration/default_source_test.rb +6 -0
- data/test/new_relic/agent/cross_app_monitor_test.rb +23 -29
- data/test/new_relic/agent/custom_event_aggregator_test.rb +88 -0
- data/test/new_relic/agent/event_buffer_test_cases.rb +152 -0
- data/test/new_relic/agent/harvester_test.rb +5 -25
- data/test/new_relic/agent/hostname_test.rb +1 -1
- data/test/new_relic/agent/inbound_request_monitor_test.rb +49 -0
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +9 -9
- data/test/new_relic/agent/instrumentation/queue_time_test.rb +0 -19
- data/test/new_relic/agent/javascript_instrumentor_test.rb +0 -45
- data/test/new_relic/agent/new_relic_service_test.rb +17 -12
- data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -4
- data/test/new_relic/agent/sampled_buffer_test.rb +73 -145
- data/test/new_relic/agent/sized_buffer_test.rb +29 -0
- data/test/new_relic/agent/synthetics_monitor_test.rb +96 -0
- data/test/new_relic/agent/system_info_test.rb +19 -3
- data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +14 -8
- data/test/new_relic/agent/transaction/synthetics_sample_buffer_test.rb +38 -0
- data/test/new_relic/agent/{request_sampler_test.rb → transaction_event_aggregator_test.rb} +55 -4
- data/test/new_relic/agent/transaction_sampler_test.rb +33 -11
- data/test/new_relic/agent/transaction_state_test.rb +0 -1
- data/test/new_relic/agent/transaction_test.rb +121 -19
- data/test/new_relic/coerce_test.rb +38 -3
- data/test/new_relic/control_test.rb +1 -0
- data/test/new_relic/fake_collector.rb +6 -2
- data/test/new_relic/fake_external_server.rb +2 -6
- data/test/new_relic/fake_server.rb +46 -29
- data/test/new_relic/http_client_test_cases.rb +71 -2
- data/test/new_relic/local_environment_test.rb +78 -0
- data/test/new_relic/metric_parser/metric_parser_test.rb +2 -0
- data/test/new_relic/metric_spec_test.rb +43 -0
- data/test/new_relic/multiverse_helpers.rb +11 -18
- data/test/new_relic/rack/browser_monitoring_test.rb +1 -18
- data/test/new_relic/rack/developer_mode_test.rb +1 -1
- data/test/new_relic/transaction_sample_test.rb +14 -4
- data/test/performance/suites/rack_middleware.rb +3 -1
- data/test/test_helper.rb +33 -0
- metadata +48 -7
- metadata.gz.sig +0 -0
- data/lib/new_relic/agent/browser_token.rb +0 -41
- data/test/multiverse/suites/agent_only/before_suite.rb +0 -7
- data/test/new_relic/agent/browser_token_test.rb +0 -56
@@ -18,9 +18,16 @@ module NewRelic
|
|
18
18
|
class DelayedJobSampler < NewRelic::Agent::Sampler
|
19
19
|
named :delayed_job
|
20
20
|
|
21
|
+
# DelayedJob supports multiple backends, only some of which we can
|
22
|
+
# handle. Check whether we think we've got what we need here.
|
23
|
+
def self.supported_backend?
|
24
|
+
::Delayed::Worker.backend.to_s == "Delayed::Backend::ActiveRecord::Job"
|
25
|
+
end
|
26
|
+
|
21
27
|
def initialize
|
22
|
-
raise Unsupported, "DJ
|
23
|
-
raise Unsupported, "
|
28
|
+
raise Unsupported, "DJ queue sampler disabled" if Agent.config[:disable_dj]
|
29
|
+
raise Unsupported, "DJ queue sampling unsupported with backend '#{::Delayed::Worker.backend}'" unless self.class.supported_backend?
|
30
|
+
raise Unsupported, "No DJ worker present. Skipping DJ queue sampler" unless NewRelic::DelayedJobInjection.worker_name
|
24
31
|
end
|
25
32
|
|
26
33
|
def record_failed_jobs(value)
|
@@ -31,51 +38,72 @@ module NewRelic
|
|
31
38
|
NewRelic::Agent.record_metric("Workers/DelayedJob/locked_jobs", value)
|
32
39
|
end
|
33
40
|
|
41
|
+
FAILED_QUERY = 'failed_at is not NULL'.freeze
|
42
|
+
LOCKED_QUERY = 'locked_by is not NULL'.freeze
|
43
|
+
|
34
44
|
def failed_jobs
|
35
|
-
|
45
|
+
count(FAILED_QUERY)
|
36
46
|
end
|
37
47
|
|
38
48
|
def locked_jobs
|
39
|
-
|
49
|
+
count(LOCKED_QUERY)
|
50
|
+
end
|
51
|
+
|
52
|
+
def count(query)
|
53
|
+
if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
54
|
+
::Delayed::Job.count(query)
|
55
|
+
else
|
56
|
+
::Delayed::Job.where(query).count
|
57
|
+
end
|
40
58
|
end
|
41
59
|
|
42
60
|
def self.supported_on_this_platform?
|
43
|
-
defined?(Delayed::Job)
|
61
|
+
defined?(::Delayed::Job)
|
44
62
|
end
|
45
63
|
|
46
64
|
def poll
|
47
65
|
record_failed_jobs(failed_jobs)
|
48
66
|
record_locked_jobs(locked_jobs)
|
49
|
-
|
50
|
-
if @queue
|
51
|
-
record_queue_length_across_dimension('queue')
|
52
|
-
else
|
53
|
-
record_queue_length_across_dimension('priority')
|
54
|
-
end
|
67
|
+
record_queue_length_metrics
|
55
68
|
end
|
56
69
|
|
57
70
|
private
|
58
71
|
|
59
|
-
def
|
72
|
+
def record_queue_length_metrics
|
73
|
+
counts = []
|
74
|
+
counts << record_counts_by("queue", "name") if ::Delayed::Job.instance_methods.include?(:queue)
|
75
|
+
counts << record_counts_by("priority")
|
76
|
+
|
77
|
+
all_metric = "Workers/DelayedJob/queue_length/all"
|
78
|
+
NewRelic::Agent.record_metric(all_metric, counts.max)
|
79
|
+
end
|
80
|
+
|
81
|
+
QUEUE_QUERY_CONDITION = 'run_at <= ? and failed_at is NULL'.freeze
|
82
|
+
|
83
|
+
def record_counts_by(column_name, metric_segment = column_name)
|
60
84
|
all_count = 0
|
61
|
-
|
85
|
+
queue_counts(column_name).each do |column_val, count|
|
62
86
|
all_count += count
|
63
|
-
|
87
|
+
column_val = "default" if column_val.nil? || column_val == ""
|
88
|
+
metric = "Workers/DelayedJob/queue_length/#{metric_segment}/#{column_val}"
|
64
89
|
NewRelic::Agent.record_metric(metric, count)
|
65
90
|
end
|
66
|
-
|
67
|
-
NewRelic::Agent.record_metric(all_metric, all_count)
|
91
|
+
all_count
|
68
92
|
end
|
69
93
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
94
|
+
def queue_counts(column_name)
|
95
|
+
now = ::Delayed::Job.db_time_now
|
96
|
+
# There is not an ActiveRecord syntax for what we're trying to do
|
97
|
+
# here that's valid on 2.x through 4.1, so split it up.
|
98
|
+
result = if ::ActiveRecord::VERSION::MAJOR.to_i < 4
|
99
|
+
::Delayed::Job.count(:group => column_name,
|
100
|
+
:conditions => [QUEUE_QUERY_CONDITION, now])
|
101
|
+
else
|
102
|
+
::Delayed::Job.where(QUEUE_QUERY_CONDITION, now).
|
103
|
+
group(column_name).
|
104
|
+
count
|
77
105
|
end
|
78
|
-
|
106
|
+
result.to_a
|
79
107
|
end
|
80
108
|
end
|
81
109
|
end
|
@@ -0,0 +1,23 @@
|
|
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
|
+
require 'new_relic/agent/event_buffer'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
class SizedBuffer < EventBuffer
|
10
|
+
|
11
|
+
def append_event(x)
|
12
|
+
if @items.size < @capacity
|
13
|
+
@items << x
|
14
|
+
return x
|
15
|
+
else
|
16
|
+
return nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,50 @@
|
|
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
|
+
require 'new_relic/agent/inbound_request_monitor'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
class SyntheticsMonitor < InboundRequestMonitor
|
10
|
+
SYNTHETICS_HEADER_KEY = 'HTTP_X_NEWRELIC_SYNTHETICS'.freeze
|
11
|
+
|
12
|
+
SUPPORTED_VERSION = 1
|
13
|
+
EXPECTED_PAYLOAD_LENGTH = 5
|
14
|
+
|
15
|
+
def on_finished_configuring(events)
|
16
|
+
events.subscribe(:before_call, &method(:on_before_call))
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_before_call(request) #THREAD_LOCAL_ACCESS
|
20
|
+
encoded_header = request[SYNTHETICS_HEADER_KEY]
|
21
|
+
return unless encoded_header
|
22
|
+
|
23
|
+
incoming_payload = deserialize_header(encoded_header, SYNTHETICS_HEADER_KEY)
|
24
|
+
|
25
|
+
return unless incoming_payload &&
|
26
|
+
is_valid_payload?(incoming_payload) &&
|
27
|
+
is_supported_version?(incoming_payload) &&
|
28
|
+
is_trusted?(incoming_payload)
|
29
|
+
|
30
|
+
state = NewRelic::Agent::TransactionState.tl_get
|
31
|
+
txn = state.current_transaction
|
32
|
+
txn.raw_synthetics_header = encoded_header
|
33
|
+
txn.synthetics_payload = incoming_payload
|
34
|
+
end
|
35
|
+
|
36
|
+
def is_supported_version?(incoming_payload)
|
37
|
+
incoming_payload.first == SUPPORTED_VERSION
|
38
|
+
end
|
39
|
+
|
40
|
+
def is_trusted?(incoming_payload)
|
41
|
+
account_id = incoming_payload[1]
|
42
|
+
NewRelic::Agent.config[:trusted_account_ids].include?(account_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def is_valid_payload?(incoming_payload)
|
46
|
+
incoming_payload.length == EXPECTED_PAYLOAD_LENGTH
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -124,6 +124,34 @@ module NewRelic
|
|
124
124
|
proc_try_read('/proc/version')
|
125
125
|
end
|
126
126
|
|
127
|
+
def self.docker_container_id
|
128
|
+
return unless ruby_os_identifier =~ /linux/
|
129
|
+
|
130
|
+
cgroup_info = proc_try_read('/proc/self/cgroup')
|
131
|
+
return unless cgroup_info
|
132
|
+
|
133
|
+
parse_docker_container_id(cgroup_info)
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.parse_docker_container_id(cgroup_info)
|
137
|
+
cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu']
|
138
|
+
return unless cpu_cgroup && cpu_cgroup =~ %r{^/docker/(.*)}
|
139
|
+
return $1
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.parse_cgroup_ids(cgroup_info)
|
143
|
+
cgroup_ids = {}
|
144
|
+
|
145
|
+
cgroup_info.split("\n").each do |line|
|
146
|
+
parts = line.split(':')
|
147
|
+
next unless parts.size == 3
|
148
|
+
_, type, cgroup_id = parts
|
149
|
+
cgroup_ids[type] = cgroup_id
|
150
|
+
end
|
151
|
+
|
152
|
+
cgroup_ids
|
153
|
+
end
|
154
|
+
|
127
155
|
# A File.read against /(proc|sysfs)/* can hang with some older Linuxes.
|
128
156
|
# See https://bugzilla.redhat.com/show_bug.cgi?id=604887, RUBY-736, and
|
129
157
|
# https://github.com/opscode/ohai/commit/518d56a6cb7d021b47ed3d691ecf7fba7f74a6a7
|
@@ -63,6 +63,9 @@ module NewRelic
|
|
63
63
|
# Populated with the trace sample once this transaction is completed.
|
64
64
|
attr_reader :transaction_trace
|
65
65
|
|
66
|
+
# Fields for tracking synthetics requests
|
67
|
+
attr_accessor :raw_synthetics_header, :synthetics_payload
|
68
|
+
|
66
69
|
# Return the currently active transaction, or nil.
|
67
70
|
def self.tl_current
|
68
71
|
TransactionState.tl_get.current_transaction
|
@@ -357,9 +360,24 @@ module NewRelic
|
|
357
360
|
transaction_sampler.ignore_transaction(state)
|
358
361
|
end
|
359
362
|
|
363
|
+
WEB_SUMMARY_METRIC = 'HttpDispatcher'.freeze
|
364
|
+
OTHER_SUMMARY_METRIC = 'OtherTransaction/all'.freeze
|
365
|
+
|
360
366
|
def summary_metrics
|
361
|
-
|
362
|
-
|
367
|
+
if @frozen_name.start_with?(CONTROLLER_PREFIX)
|
368
|
+
[WEB_SUMMARY_METRIC]
|
369
|
+
else
|
370
|
+
background_summary_metrics
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def background_summary_metrics
|
375
|
+
segments = @frozen_name.split('/')
|
376
|
+
if segments.size > 2
|
377
|
+
["OtherTransaction/#{segments[1]}/all", OTHER_SUMMARY_METRIC]
|
378
|
+
else
|
379
|
+
[]
|
380
|
+
end
|
363
381
|
end
|
364
382
|
|
365
383
|
def needs_middleware_summary_metrics?(name)
|
@@ -402,6 +420,7 @@ module NewRelic
|
|
402
420
|
end
|
403
421
|
|
404
422
|
def user_defined_rules_ignore?
|
423
|
+
return unless uri
|
405
424
|
return if (rules = NewRelic::Agent.config[:"rules.ignore_url_regexes"]).empty?
|
406
425
|
|
407
426
|
parsed = NewRelic::Agent::HTTPClients::URIUtil.parse_url(uri)
|
@@ -422,7 +441,7 @@ module NewRelic
|
|
422
441
|
|
423
442
|
record_summary_metrics(outermost_segment_name, end_time)
|
424
443
|
record_apdex(state, end_time) unless ignore_apdex?
|
425
|
-
|
444
|
+
record_queue_time
|
426
445
|
|
427
446
|
record_exceptions
|
428
447
|
merge_metrics
|
@@ -451,6 +470,7 @@ module NewRelic
|
|
451
470
|
}
|
452
471
|
append_cat_info(state, duration, payload)
|
453
472
|
append_apdex_perf_zone(duration, payload)
|
473
|
+
append_synthetics_to(state, payload)
|
454
474
|
append_referring_transaction_guid_to(state, payload)
|
455
475
|
append_http_response_code(payload)
|
456
476
|
|
@@ -462,8 +482,7 @@ module NewRelic
|
|
462
482
|
end
|
463
483
|
|
464
484
|
def include_guid?(state, duration)
|
465
|
-
state.is_cross_app? ||
|
466
|
-
(state.request_token && duration > apdex_t)
|
485
|
+
state.is_cross_app? || is_synthetics_request?
|
467
486
|
end
|
468
487
|
|
469
488
|
def cat_trip_id(state)
|
@@ -489,6 +508,35 @@ module NewRelic
|
|
489
508
|
NewRelic::Agent.instance.cross_app_monitor.client_referring_transaction_path_hash(state)
|
490
509
|
end
|
491
510
|
|
511
|
+
def is_synthetics_request?
|
512
|
+
synthetics_payload != nil && raw_synthetics_header != nil
|
513
|
+
end
|
514
|
+
|
515
|
+
def synthetics_version
|
516
|
+
info = synthetics_payload or return nil
|
517
|
+
info[0]
|
518
|
+
end
|
519
|
+
|
520
|
+
def synthetics_account_id
|
521
|
+
info = synthetics_payload or return nil
|
522
|
+
info[1]
|
523
|
+
end
|
524
|
+
|
525
|
+
def synthetics_resource_id
|
526
|
+
info = synthetics_payload or return nil
|
527
|
+
info[2]
|
528
|
+
end
|
529
|
+
|
530
|
+
def synthetics_job_id
|
531
|
+
info = synthetics_payload or return nil
|
532
|
+
info[3]
|
533
|
+
end
|
534
|
+
|
535
|
+
def synthetics_monitor_id
|
536
|
+
info = synthetics_payload or return nil
|
537
|
+
info[4]
|
538
|
+
end
|
539
|
+
|
492
540
|
APDEX_S = 'S'.freeze
|
493
541
|
APDEX_T = 'T'.freeze
|
494
542
|
APDEX_F = 'F'.freeze
|
@@ -528,6 +576,14 @@ module NewRelic
|
|
528
576
|
end
|
529
577
|
end
|
530
578
|
|
579
|
+
def append_synthetics_to(state, payload)
|
580
|
+
return unless is_synthetics_request?
|
581
|
+
|
582
|
+
payload[:synthetics_resource_id] = synthetics_resource_id
|
583
|
+
payload[:synthetics_job_id] = synthetics_job_id
|
584
|
+
payload[:synthetics_monitor_id] = synthetics_monitor_id
|
585
|
+
end
|
586
|
+
|
531
587
|
def append_referring_transaction_guid_to(state, payload)
|
532
588
|
referring_guid = NewRelic::Agent.instance.cross_app_monitor.client_referring_transaction_guid(state)
|
533
589
|
if referring_guid
|
@@ -595,6 +651,23 @@ module NewRelic
|
|
595
651
|
end
|
596
652
|
end
|
597
653
|
|
654
|
+
QUEUE_TIME_METRIC = 'WebFrontend/QueueTime'.freeze
|
655
|
+
|
656
|
+
def queue_time
|
657
|
+
@apdex_start ? @start_time - @apdex_start : 0
|
658
|
+
end
|
659
|
+
|
660
|
+
def record_queue_time
|
661
|
+
value = queue_time
|
662
|
+
if value > 0.0
|
663
|
+
if value < MethodTracerHelpers::MAX_ALLOWED_METRIC_DURATION
|
664
|
+
@metrics.record_unscoped(QUEUE_TIME_METRIC, value)
|
665
|
+
else
|
666
|
+
::NewRelic::Agent.logger.log_once(:warn, :too_high_queue_time, "Not recording unreasonably large queue time of #{value} s")
|
667
|
+
end
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
598
671
|
APDEX_METRIC = 'Apdex'.freeze
|
599
672
|
|
600
673
|
def had_error?
|
@@ -669,10 +742,6 @@ module NewRelic
|
|
669
742
|
alias_method :user_attributes, :custom_parameters
|
670
743
|
alias_method :set_user_attributes, :add_custom_parameters
|
671
744
|
|
672
|
-
def queue_time
|
673
|
-
@apdex_start ? @start_time - @apdex_start : 0
|
674
|
-
end
|
675
|
-
|
676
745
|
# Returns truthy if the current in-progress transaction is considered a
|
677
746
|
# a web transaction (as opposed to, e.g., a background transaction).
|
678
747
|
#
|
@@ -0,0 +1,25 @@
|
|
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
|
+
require 'new_relic/agent/transaction/transaction_sample_buffer'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
class Transaction
|
10
|
+
class SyntheticsSampleBuffer < TransactionSampleBuffer
|
11
|
+
def capacity
|
12
|
+
NewRelic::Agent.config[:'synthetics.traces_limit']
|
13
|
+
end
|
14
|
+
|
15
|
+
def allow_sample?(sample)
|
16
|
+
sample.synthetics_resource_id != nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def truncate_samples
|
20
|
+
@samples.slice!(max_capacity..-1)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -8,7 +8,7 @@ require 'monitor'
|
|
8
8
|
require 'newrelic_rpm' unless defined?( NewRelic )
|
9
9
|
require 'new_relic/agent' unless defined?( NewRelic::Agent )
|
10
10
|
|
11
|
-
class NewRelic::Agent::
|
11
|
+
class NewRelic::Agent::TransactionEventAggregator
|
12
12
|
include NewRelic::Coerce,
|
13
13
|
MonitorMixin
|
14
14
|
|
@@ -28,14 +28,19 @@ class NewRelic::Agent::RequestSampler
|
|
28
28
|
CAT_REFERRING_PATH_HASH_KEY = 'nr.referringPathHash'.freeze
|
29
29
|
CAT_ALTERNATE_PATH_HASHES_KEY = 'nr.alternatePathHashes'.freeze
|
30
30
|
APDEX_PERF_ZONE_KEY = 'nr.apdexPerfZone'.freeze
|
31
|
+
SYNTHETICS_RESOURCE_ID_KEY = "nr.syntheticsResourceId".freeze
|
32
|
+
SYNTHETICS_JOB_ID_KEY = "nr.syntheticsJobId".freeze
|
33
|
+
SYNTHETICS_MONITOR_ID_KEY = "nr.syntheticsMonitorId".freeze
|
31
34
|
|
32
35
|
def initialize( event_listener )
|
33
36
|
super()
|
34
37
|
|
35
38
|
@enabled = false
|
36
|
-
@samples = ::NewRelic::Agent::SampledBuffer.new(NewRelic::Agent.config[:'analytics_events.max_samples_stored'])
|
37
39
|
@notified_full = false
|
38
40
|
|
41
|
+
@samples = ::NewRelic::Agent::SampledBuffer.new(NewRelic::Agent.config[:'analytics_events.max_samples_stored'])
|
42
|
+
@synthetics_samples = ::NewRelic::Agent::SizedBuffer.new(NewRelic::Agent.config[:'synthetics.events_limit'])
|
43
|
+
|
39
44
|
event_listener.subscribe( :transaction_finished, &method(:on_transaction_finished) )
|
40
45
|
self.register_config_callbacks
|
41
46
|
end
|
@@ -47,31 +52,35 @@ class NewRelic::Agent::RequestSampler
|
|
47
52
|
|
48
53
|
# Fetch a copy of the sampler's gathered samples. (Synchronized)
|
49
54
|
def samples
|
50
|
-
return self.synchronize { @samples.to_a }
|
55
|
+
return self.synchronize { @samples.to_a.concat(@synthetics_samples.to_a) }
|
51
56
|
end
|
52
57
|
|
53
58
|
def reset!
|
54
|
-
|
55
|
-
|
56
|
-
sample_count, request_count = 0
|
59
|
+
sample_count, request_count, synthetics_dropped = 0
|
57
60
|
old_samples = nil
|
58
61
|
|
59
62
|
self.synchronize do
|
60
63
|
sample_count = @samples.size
|
61
|
-
request_count = @samples.
|
62
|
-
|
63
|
-
@
|
64
|
+
request_count = @samples.num_seen
|
65
|
+
|
66
|
+
synthetics_dropped = @synthetics_samples.num_dropped
|
67
|
+
|
68
|
+
old_samples = @samples.to_a + @synthetics_samples.to_a
|
69
|
+
@samples.reset!
|
70
|
+
@synthetics_samples.reset!
|
71
|
+
|
64
72
|
@notified_full = false
|
65
73
|
end
|
66
74
|
|
67
|
-
[old_samples, sample_count, request_count]
|
75
|
+
[old_samples, sample_count, request_count, synthetics_dropped]
|
68
76
|
end
|
69
77
|
|
70
78
|
# Clear any existing samples, reset the last sample time, and return the
|
71
79
|
# previous set of samples. (Synchronized)
|
72
80
|
def harvest!
|
73
|
-
old_samples, sample_count, request_count = reset!
|
81
|
+
old_samples, sample_count, request_count, synthetics_dropped = reset!
|
74
82
|
record_sampling_rate(request_count, sample_count) if @enabled
|
83
|
+
record_dropped_synthetics(synthetics_dropped)
|
75
84
|
old_samples
|
76
85
|
end
|
77
86
|
|
@@ -79,7 +88,7 @@ class NewRelic::Agent::RequestSampler
|
|
79
88
|
# transmission to the collector. (Synchronized)
|
80
89
|
def merge!(old_samples)
|
81
90
|
self.synchronize do
|
82
|
-
old_samples.each { |s|
|
91
|
+
old_samples.each { |s| append_event(s) }
|
83
92
|
end
|
84
93
|
end
|
85
94
|
|
@@ -96,15 +105,28 @@ class NewRelic::Agent::RequestSampler
|
|
96
105
|
])
|
97
106
|
|
98
107
|
engine = NewRelic::Agent.instance.stats_engine
|
99
|
-
engine.tl_record_supportability_metric_count("
|
100
|
-
engine.tl_record_supportability_metric_count("
|
108
|
+
engine.tl_record_supportability_metric_count("TransactionEventAggregator/requests", request_count)
|
109
|
+
engine.tl_record_supportability_metric_count("TransactionEventAggregator/samples", sample_count)
|
110
|
+
end
|
111
|
+
|
112
|
+
def record_dropped_synthetics(synthetics_dropped)
|
113
|
+
return unless synthetics_dropped > 0
|
114
|
+
|
115
|
+
NewRelic::Agent.logger.debug("Synthetics transaction event limit (#{@samples.capacity}) reached. Further synthetics events this harvest period dropped.")
|
116
|
+
|
117
|
+
engine = NewRelic::Agent.instance.stats_engine
|
118
|
+
engine.tl_record_supportability_metric_count("TransactionEventAggregator/synthetics_events_dropped", synthetics_dropped)
|
101
119
|
end
|
102
120
|
|
103
121
|
def register_config_callbacks
|
104
122
|
NewRelic::Agent.config.register_callback(:'analytics_events.max_samples_stored') do |max_samples|
|
105
|
-
NewRelic::Agent.logger.debug "
|
123
|
+
NewRelic::Agent.logger.debug "TransactionEventAggregator max_samples set to #{max_samples}"
|
106
124
|
self.synchronize { @samples.capacity = max_samples }
|
107
|
-
|
125
|
+
end
|
126
|
+
|
127
|
+
NewRelic::Agent.config.register_callback(:'synthetics.events_limit') do |max_samples|
|
128
|
+
NewRelic::Agent.logger.debug "TransactionEventAggregator limit for synthetics events set to #{max_samples}"
|
129
|
+
self.synchronize { @synthetics_samples.capacity = max_samples }
|
108
130
|
end
|
109
131
|
|
110
132
|
NewRelic::Agent.config.register_callback(:'analytics_events.enabled') do |enabled|
|
@@ -113,7 +135,7 @@ class NewRelic::Agent::RequestSampler
|
|
113
135
|
end
|
114
136
|
|
115
137
|
def notify_full
|
116
|
-
NewRelic::Agent.logger.debug "
|
138
|
+
NewRelic::Agent.logger.debug "Transaction event capacity of #{@samples.capacity} reached, beginning sampling"
|
117
139
|
@notified_full = true
|
118
140
|
end
|
119
141
|
|
@@ -124,8 +146,17 @@ class NewRelic::Agent::RequestSampler
|
|
124
146
|
main_event = create_main_event(payload)
|
125
147
|
custom_params = create_custom_parameters(payload)
|
126
148
|
|
127
|
-
|
128
|
-
notify_full if
|
149
|
+
self.synchronize { append_event([main_event, custom_params]) }
|
150
|
+
notify_full if !@notified_full && @samples.full?
|
151
|
+
end
|
152
|
+
|
153
|
+
def append_event(event)
|
154
|
+
main_event, _ = event
|
155
|
+
if main_event.include?(SYNTHETICS_RESOURCE_ID_KEY)
|
156
|
+
@synthetics_samples.append(event)
|
157
|
+
else
|
158
|
+
@samples.append(event)
|
159
|
+
end
|
129
160
|
end
|
130
161
|
|
131
162
|
def self.map_metric(metric_name, to_add={})
|
@@ -186,6 +217,9 @@ class NewRelic::Agent::RequestSampler
|
|
186
217
|
optionally_append(CAT_PATH_HASH_KEY, :cat_path_hash, sample, payload)
|
187
218
|
optionally_append(CAT_REFERRING_PATH_HASH_KEY, :cat_referring_path_hash, sample, payload)
|
188
219
|
optionally_append(APDEX_PERF_ZONE_KEY, :apdex_perf_zone, sample, payload)
|
220
|
+
optionally_append(SYNTHETICS_RESOURCE_ID_KEY, :synthetics_resource_id, sample, payload)
|
221
|
+
optionally_append(SYNTHETICS_JOB_ID_KEY, :synthetics_job_id, sample, payload)
|
222
|
+
optionally_append(SYNTHETICS_MONITOR_ID_KEY, :synthetics_monitor_id, sample, payload)
|
189
223
|
append_http_response_code(sample, payload)
|
190
224
|
append_cat_alternate_path_hashes(sample, payload)
|
191
225
|
sample
|