newrelic_rpm 3.6.7.159 → 3.6.8.164
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +14 -0
- data/lib/new_relic/agent/agent.rb +38 -35
- data/lib/new_relic/agent/agent_logger.rb +6 -47
- data/lib/new_relic/agent/beacon_configuration.rb +10 -4
- data/lib/new_relic/agent/browser_monitoring.rb +39 -33
- data/lib/new_relic/agent/commands/agent_command.rb +4 -4
- data/lib/new_relic/agent/commands/agent_command_router.rb +72 -10
- data/lib/new_relic/agent/commands/thread_profiler_session.rb +110 -0
- data/lib/new_relic/agent/commands/xray_session.rb +55 -0
- data/lib/new_relic/agent/commands/xray_session_collection.rb +158 -0
- data/lib/new_relic/agent/configuration/default_source.rb +61 -24
- data/lib/new_relic/agent/configuration/mask_defaults.rb +2 -2
- data/lib/new_relic/agent/configuration/server_source.rb +1 -1
- data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +2 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +4 -10
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +10 -11
- data/lib/new_relic/agent/memory_logger.rb +52 -0
- data/lib/new_relic/agent/new_relic_service.rb +4 -0
- data/lib/new_relic/agent/request_sampler.rb +32 -13
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +6 -3
- data/lib/new_relic/agent/threading/agent_thread.rb +2 -1
- data/lib/new_relic/agent/threading/backtrace_node.rb +80 -27
- data/lib/new_relic/agent/threading/backtrace_service.rb +264 -0
- data/lib/new_relic/agent/threading/thread_profile.rb +79 -118
- data/lib/new_relic/agent/transaction/developer_mode_sample_buffer.rb +56 -0
- data/lib/new_relic/agent/transaction/force_persist_sample_buffer.rb +25 -0
- data/lib/new_relic/agent/transaction/slowest_sample_buffer.rb +25 -0
- data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +86 -0
- data/lib/new_relic/agent/transaction/xray_sample_buffer.rb +64 -0
- data/lib/new_relic/agent/transaction.rb +25 -4
- data/lib/new_relic/agent/transaction_sample_builder.rb +6 -10
- data/lib/new_relic/agent/transaction_sampler.rb +47 -202
- data/lib/new_relic/agent/worker_loop.rb +47 -39
- data/lib/new_relic/agent.rb +1 -1
- data/lib/new_relic/build.rb +2 -2
- data/lib/new_relic/coerce.rb +8 -0
- data/lib/new_relic/control/instance_methods.rb +1 -0
- data/lib/new_relic/rack/browser_monitoring.rb +15 -1
- data/lib/new_relic/rack/developer_mode.rb +1 -1
- data/lib/new_relic/transaction_sample.rb +20 -5
- data/lib/new_relic/version.rb +1 -1
- data/newrelic.yml +4 -6
- data/newrelic_rpm.gemspec +1 -1
- data/test/agent_helper.rb +11 -0
- data/test/environments/lib/environments/runner.rb +5 -1
- data/test/environments/rails21/Gemfile +2 -2
- data/test/environments/rails22/Gemfile +2 -2
- data/test/environments/rails23/Gemfile +2 -2
- data/test/environments/rails31/Gemfile +2 -2
- data/test/environments/rails32/Gemfile +2 -2
- data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -1
- data/test/multiverse/suites/agent_only/testing_app.rb +6 -0
- data/test/multiverse/suites/agent_only/thread_profiling_test.rb +5 -5
- data/test/multiverse/suites/agent_only/xray_sessions_test.rb +163 -0
- data/test/multiverse/suites/rails/request_statistics_test.rb +2 -2
- data/test/multiverse/suites/rails/view_instrumentation_test.rb +20 -21
- data/test/new_relic/agent/agent/connect_test.rb +0 -10
- data/test/new_relic/agent/agent_test.rb +27 -44
- data/test/new_relic/agent/browser_monitoring_test.rb +0 -52
- data/test/new_relic/agent/commands/agent_command_router_test.rb +150 -12
- data/test/new_relic/agent/commands/{thread_profiler_test.rb → thread_profiler_session_test.rb} +58 -19
- data/test/new_relic/agent/commands/xray_session_collection_test.rb +332 -0
- data/test/new_relic/agent/commands/xray_session_test.rb +42 -0
- data/test/new_relic/agent/configuration/manager_test.rb +2 -1
- data/test/new_relic/agent/configuration/server_source_test.rb +10 -10
- data/test/new_relic/agent/cpu_sampler_test.rb +50 -0
- data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +31 -0
- data/test/new_relic/agent/instrumentation/queue_time_test.rb +0 -1
- data/test/new_relic/agent/instrumentation/sequel_test.rb +1 -1
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +0 -1
- data/test/new_relic/agent/memory_logger_test.rb +53 -0
- data/test/new_relic/agent/new_relic_service_test.rb +1 -1
- data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -5
- data/test/new_relic/agent/request_sampler_test.rb +70 -20
- data/test/new_relic/agent/rules_engine_test.rb +6 -0
- data/test/new_relic/agent/threading/agent_thread_test.rb +2 -2
- data/test/new_relic/agent/threading/backtrace_node_test.rb +110 -17
- data/test/new_relic/agent/threading/backtrace_service_test.rb +567 -0
- data/test/new_relic/agent/threading/fake_thread.rb +4 -0
- data/test/new_relic/agent/threading/thread_profile_test.rb +141 -217
- data/test/new_relic/agent/threading/threaded_test_case.rb +3 -8
- data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +69 -0
- data/test/new_relic/agent/transaction/force_persist_sample_buffer_test.rb +52 -0
- data/test/new_relic/agent/transaction/slowest_sample_buffer_test.rb +67 -0
- data/test/new_relic/agent/transaction/xray_sample_buffer_test.rb +71 -0
- data/test/new_relic/agent/transaction_sampler_test.rb +171 -307
- data/test/new_relic/agent/transaction_test.rb +33 -5
- data/test/new_relic/agent/worker_loop_test.rb +33 -11
- data/test/new_relic/coerce_test.rb +13 -0
- data/test/new_relic/fake_collector.rb +26 -3
- data/test/new_relic/multiverse_helpers.rb +2 -0
- data/test/new_relic/rack/browser_monitoring_test.rb +12 -0
- data/test/new_relic/rack/developer_mode_test.rb +2 -2
- data/test/new_relic/transaction_sample_test.rb +19 -2
- data/test/performance/lib/performance/console_reporter.rb +1 -1
- data/test/performance/lib/performance/test_case.rb +7 -3
- data/test/performance/script/runner +3 -0
- data/test/performance/suites/thread_profiling.rb +83 -0
- data/test/test_helper.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +32 -32
- metadata.gz.sig +1 -1
- data/lib/new_relic/agent/commands/thread_profiler.rb +0 -80
@@ -2,11 +2,11 @@
|
|
2
2
|
# This file is distributed under New Relic's license terms.
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
4
|
|
5
|
+
require 'set'
|
5
6
|
require 'new_relic/agent/worker_loop'
|
6
7
|
require 'new_relic/agent/threading/backtrace_node'
|
7
8
|
|
8
|
-
#
|
9
|
-
# TODO: Get rid of the running/sampling in this class, externalize it elsewhere
|
9
|
+
# Data structure for representing a thread profile
|
10
10
|
|
11
11
|
module NewRelic
|
12
12
|
module Agent
|
@@ -14,156 +14,117 @@ module NewRelic
|
|
14
14
|
|
15
15
|
class ThreadProfile
|
16
16
|
|
17
|
-
attr_reader :profile_id,
|
18
|
-
:
|
19
|
-
:profile_agent_code
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@
|
27
|
-
@profile_agent_code =
|
28
|
-
|
29
|
-
@duration = arguments.fetch('duration', 120)
|
30
|
-
@worker_loop = NewRelic::Agent::WorkerLoop.new(:duration => duration)
|
31
|
-
@interval = arguments.fetch('sample_period', 0.1)
|
17
|
+
attr_reader :profile_id, :traces, :sample_period,
|
18
|
+
:duration, :poll_count, :backtrace_count, :failure_count,
|
19
|
+
:created_at, :xray_id, :command_arguments, :profile_agent_code
|
20
|
+
attr_accessor :finished_at
|
21
|
+
|
22
|
+
def initialize(command_arguments={})
|
23
|
+
@command_arguments = command_arguments
|
24
|
+
@profile_id = command_arguments.fetch('profile_id', -1)
|
25
|
+
@duration = command_arguments.fetch('duration', 120)
|
26
|
+
@sample_period = command_arguments.fetch('sample_period', 0.1)
|
27
|
+
@profile_agent_code = command_arguments.fetch('profile_agent_code', false)
|
28
|
+
@xray_id = command_arguments.fetch('x_ray_id', nil)
|
32
29
|
@finished = false
|
33
30
|
|
34
31
|
@traces = {
|
35
|
-
:agent
|
36
|
-
:background =>
|
37
|
-
:other
|
38
|
-
:request
|
32
|
+
:agent => BacktraceNode.new(nil),
|
33
|
+
:background => BacktraceNode.new(nil),
|
34
|
+
:other => BacktraceNode.new(nil),
|
35
|
+
:request => BacktraceNode.new(nil)
|
39
36
|
}
|
40
|
-
@flattened_nodes = []
|
41
37
|
|
42
38
|
@poll_count = 0
|
43
|
-
@
|
39
|
+
@backtrace_count = 0
|
44
40
|
@failure_count = 0
|
41
|
+
@unique_threads = []
|
42
|
+
|
43
|
+
@created_at = Time.now
|
45
44
|
end
|
46
45
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
Threading::AgentThread.new('Thread Profiler') do
|
51
|
-
@start_time = now_in_millis
|
52
|
-
|
53
|
-
@worker_loop.run(@interval) do
|
54
|
-
NewRelic::Agent.instance.stats_engine.
|
55
|
-
record_supportability_metric_timed("ThreadProfiler/PollingTime") do
|
56
|
-
|
57
|
-
@poll_count += 1
|
58
|
-
Threading::AgentThread.list.each do |t|
|
59
|
-
bucket = Threading::AgentThread.bucket_thread(t, @profile_agent_code)
|
60
|
-
if bucket != :ignore
|
61
|
-
backtrace = Threading::AgentThread.scrub_backtrace(t, @profile_agent_code)
|
62
|
-
if backtrace.nil?
|
63
|
-
@failure_count += 1
|
64
|
-
else
|
65
|
-
@sample_count += 1
|
66
|
-
aggregate(backtrace, @traces[bucket])
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
mark_done
|
74
|
-
NewRelic::Agent.logger.debug("Finished thread profile. #{@sample_count} backtraces, #{@failure_count} failures. Will send with next harvest.")
|
75
|
-
NewRelic::Agent.instance.stats_engine.
|
76
|
-
record_supportability_metric_count("ThreadProfiler/BacktraceFailures", @failure_count)
|
77
|
-
end
|
46
|
+
def requested_period
|
47
|
+
@sample_period
|
78
48
|
end
|
79
49
|
|
80
|
-
def
|
81
|
-
@
|
82
|
-
mark_done
|
83
|
-
NewRelic::Agent.logger.debug("Stopping thread profile.")
|
50
|
+
def increment_poll_count
|
51
|
+
@poll_count += 1
|
84
52
|
end
|
85
53
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
existing = trees.find {|n| n == node}
|
54
|
+
def sample_count
|
55
|
+
xray? ? @backtrace_count : @poll_count
|
56
|
+
end
|
90
57
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
58
|
+
def xray?
|
59
|
+
!!@xray_id
|
60
|
+
end
|
95
61
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
trees << node unless trees.include? node
|
100
|
-
end
|
62
|
+
def empty?
|
63
|
+
@backtrace_count == 0
|
64
|
+
end
|
101
65
|
|
102
|
-
|
103
|
-
|
66
|
+
def unique_thread_count
|
67
|
+
return 0 if @unique_threads.nil?
|
68
|
+
@unique_threads.length
|
69
|
+
end
|
104
70
|
|
105
|
-
|
71
|
+
def aggregate(backtrace, bucket, thread)
|
72
|
+
if backtrace.nil?
|
73
|
+
@failure_count += 1
|
74
|
+
else
|
75
|
+
@backtrace_count += 1
|
76
|
+
@traces[bucket].aggregate(backtrace)
|
77
|
+
@unique_threads << thread unless @unique_threads.include?(thread)
|
78
|
+
end
|
106
79
|
end
|
107
80
|
|
108
|
-
def
|
109
|
-
@
|
81
|
+
def truncate_to_node_count!(count_to_keep)
|
82
|
+
all_nodes = @traces.values.map { |n| n.flatten }.flatten
|
110
83
|
|
111
84
|
NewRelic::Agent.instance.stats_engine.
|
112
|
-
record_supportability_metric_count("ThreadProfiler/NodeCount",
|
85
|
+
record_supportability_metric_count("ThreadProfiler/NodeCount", all_nodes.size)
|
113
86
|
|
114
|
-
|
115
|
-
|
116
|
-
traces.each { |
|
87
|
+
all_nodes.sort!
|
88
|
+
nodes_to_prune = Set.new(all_nodes[count_to_keep..-1] || [])
|
89
|
+
traces.values.each { |root| root.prune!(nodes_to_prune) }
|
117
90
|
end
|
118
91
|
|
119
92
|
THREAD_PROFILER_NODES = 20_000
|
120
93
|
|
121
94
|
include NewRelic::Coerce
|
122
95
|
|
123
|
-
def
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
"
|
128
|
-
"
|
129
|
-
"
|
130
|
-
"BACKGROUND" => @traces[:background].map{|t| t.to_array }
|
96
|
+
def generate_traces
|
97
|
+
truncate_to_node_count!(THREAD_PROFILER_NODES)
|
98
|
+
{
|
99
|
+
"OTHER" => @traces[:other].to_array,
|
100
|
+
"REQUEST" => @traces[:request].to_array,
|
101
|
+
"AGENT" => @traces[:agent].to_array,
|
102
|
+
"BACKGROUND" => @traces[:background].to_array
|
131
103
|
}
|
132
|
-
|
133
|
-
[[
|
134
|
-
int(@profile_id),
|
135
|
-
float(@start_time),
|
136
|
-
float(@stop_time),
|
137
|
-
int(@poll_count),
|
138
|
-
string(encoder.encode(traces)),
|
139
|
-
int(@sample_count),
|
140
|
-
0
|
141
|
-
]]
|
142
|
-
end
|
143
|
-
|
144
|
-
def now_in_millis
|
145
|
-
Time.now.to_f * 1_000
|
146
104
|
end
|
147
105
|
|
148
|
-
def
|
149
|
-
|
106
|
+
def to_collector_array(encoder)
|
107
|
+
result = [
|
108
|
+
int(self.profile_id),
|
109
|
+
float(self.created_at),
|
110
|
+
float(self.finished_at),
|
111
|
+
int(self.sample_count),
|
112
|
+
string(encoder.encode(generate_traces)),
|
113
|
+
int(self.unique_thread_count),
|
114
|
+
0 # runnable thread count, which we don't track
|
115
|
+
]
|
116
|
+
result << int(@xray_id) if xray?
|
117
|
+
result
|
150
118
|
end
|
151
119
|
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
120
|
+
def to_log_description
|
121
|
+
id = if xray?
|
122
|
+
"@xray_id: #{xray_id}"
|
123
|
+
else
|
124
|
+
"@profile_id: #{profile_id}"
|
125
|
+
end
|
156
126
|
|
157
|
-
|
158
|
-
to_prune = nodes[count_to_keep..-1] || []
|
159
|
-
to_prune.each { |n| n.to_prune = true }
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.parse_backtrace(trace)
|
163
|
-
trace.map do |line|
|
164
|
-
line =~ /(.*)\:(\d+)\:in `(.*)'/
|
165
|
-
{ :method => $3, :line_no => $2.to_i, :file => $1 }
|
166
|
-
end
|
127
|
+
"#<ThreadProfile:#{object_id} #{id} @command_arguments=#{@command_arguments.inspect}>"
|
167
128
|
end
|
168
129
|
|
169
130
|
end
|
@@ -0,0 +1,56 @@
|
|
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 DeveloperModeSampleBuffer < TransactionSampleBuffer
|
11
|
+
|
12
|
+
MAX_SAMPLES = 100
|
13
|
+
|
14
|
+
def max_samples
|
15
|
+
MAX_SAMPLES
|
16
|
+
end
|
17
|
+
|
18
|
+
def harvest_samples
|
19
|
+
NO_SAMPLES
|
20
|
+
end
|
21
|
+
|
22
|
+
def enabled?
|
23
|
+
Agent.config[:developer_mode]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Truncate to the last max_samples we've received
|
27
|
+
def truncate_samples
|
28
|
+
@samples = @samples.last(max_samples)
|
29
|
+
end
|
30
|
+
|
31
|
+
# We don't hold onto previously trapped transactions on harvest
|
32
|
+
# We've already got all the traces we want, thank you!
|
33
|
+
def store_previous(*)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Captures the stack trace for a segment
|
37
|
+
# This is expensive and not for production mode
|
38
|
+
def visit_segment(segment)
|
39
|
+
return unless enabled? && segment
|
40
|
+
|
41
|
+
trace = strip_newrelic_frames(caller)
|
42
|
+
trace = trace.first(40) if trace.length > 40
|
43
|
+
segment[:backtrace] = trace
|
44
|
+
end
|
45
|
+
|
46
|
+
def strip_newrelic_frames(trace)
|
47
|
+
while trace.first =~/\/lib\/new_relic\/agent\//
|
48
|
+
trace.shift
|
49
|
+
end
|
50
|
+
trace
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -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 ForcePersistSampleBuffer < TransactionSampleBuffer
|
11
|
+
|
12
|
+
MAX_SAMPLES = 10
|
13
|
+
|
14
|
+
def max_samples
|
15
|
+
MAX_SAMPLES
|
16
|
+
end
|
17
|
+
|
18
|
+
def allow_sample?(sample)
|
19
|
+
sample.force_persist
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -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 SlowestSampleBuffer < TransactionSampleBuffer
|
11
|
+
|
12
|
+
MAX_SAMPLES = 1
|
13
|
+
|
14
|
+
def max_samples
|
15
|
+
MAX_SAMPLES
|
16
|
+
end
|
17
|
+
|
18
|
+
def allow_sample?(sample)
|
19
|
+
sample.threshold && sample.duration >= sample.threshold
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,86 @@
|
|
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
|
+
module NewRelic
|
6
|
+
module Agent
|
7
|
+
class Transaction
|
8
|
+
class TransactionSampleBuffer
|
9
|
+
attr_reader :samples
|
10
|
+
|
11
|
+
NO_SAMPLES = [].freeze
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@samples = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def enabled?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset!
|
22
|
+
@samples = []
|
23
|
+
end
|
24
|
+
|
25
|
+
def harvest_samples
|
26
|
+
@samples
|
27
|
+
ensure
|
28
|
+
reset!
|
29
|
+
end
|
30
|
+
|
31
|
+
def allow_sample?(sample)
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def store(sample)
|
36
|
+
return unless enabled?
|
37
|
+
if allow_sample?(sample)
|
38
|
+
add_sample(sample)
|
39
|
+
truncate_samples_if_needed
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def store_previous(previous_samples)
|
44
|
+
return unless enabled?
|
45
|
+
previous_samples.each do |sample|
|
46
|
+
add_sample(sample) if allow_sample?(sample)
|
47
|
+
end
|
48
|
+
truncate_samples_if_needed
|
49
|
+
end
|
50
|
+
|
51
|
+
def truncate_samples_if_needed
|
52
|
+
truncate_samples if full?
|
53
|
+
end
|
54
|
+
|
55
|
+
def full?
|
56
|
+
@samples.length >= max_samples
|
57
|
+
end
|
58
|
+
|
59
|
+
# Our default truncation strategy is to keep max_samples worth of the
|
60
|
+
# longest samples. Override this method for alternate behavior.
|
61
|
+
#
|
62
|
+
# This doesn't use the more convenient #last and #sort_by to avoid
|
63
|
+
# additional array allocations (and abundant alliteration)
|
64
|
+
def truncate_samples
|
65
|
+
@samples.sort!{|a,b| a.duration <=> b.duration}
|
66
|
+
@samples.slice!(0..-(max_samples + 1))
|
67
|
+
end
|
68
|
+
|
69
|
+
# When pushing a scope different sample buffers potentially want to
|
70
|
+
# know about what's happening to annotate the incoming segments
|
71
|
+
def visit_segment(*)
|
72
|
+
# no-op
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
# If a buffer needs to modify an added sample, override this method.
|
78
|
+
# Bounds checking, allowing samples and truncation belongs elsewhere.
|
79
|
+
def add_sample(sample)
|
80
|
+
@samples << sample
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,64 @@
|
|
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 XraySampleBuffer < TransactionSampleBuffer
|
11
|
+
|
12
|
+
attr_writer :xray_session_collection
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
|
17
|
+
# Memoize the config setting since this happens per request
|
18
|
+
@enabled = NewRelic::Agent.config[:'xray_session.allow_traces']
|
19
|
+
NewRelic::Agent.config.register_callback(:'xray_session.allow_traces') do |new_value|
|
20
|
+
@enabled = new_value
|
21
|
+
end
|
22
|
+
|
23
|
+
@max_samples = NewRelic::Agent.config[:'xray_session.max_samples']
|
24
|
+
NewRelic::Agent.config.register_callback(:'xray_session.max_samples') do |new_value|
|
25
|
+
@max_samples = new_value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def xray_session_collection
|
30
|
+
@xray_session_collection ||= NewRelic::Agent.instance.agent_command_router.xray_session_collection
|
31
|
+
end
|
32
|
+
|
33
|
+
def max_samples
|
34
|
+
@max_samples
|
35
|
+
end
|
36
|
+
|
37
|
+
def truncate_samples
|
38
|
+
# First in wins, so stop on allow_sample? instead of truncating
|
39
|
+
end
|
40
|
+
|
41
|
+
def allow_sample?(sample)
|
42
|
+
!full? && !lookup_session_id(sample).nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
def enabled?
|
46
|
+
@enabled
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def add_sample(sample)
|
53
|
+
super(sample)
|
54
|
+
sample.xray_session_id = lookup_session_id(sample)
|
55
|
+
end
|
56
|
+
|
57
|
+
def lookup_session_id(sample)
|
58
|
+
xray_session_collection.session_id_for_transaction_name(sample.transaction_name)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|