newrelic_rpm 3.6.8.168 → 3.6.9.171
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.gitignore +1 -0
- data/.yardopts +17 -0
- data/CHANGELOG +48 -0
- data/README.md +8 -6
- data/lib/new_relic/agent.rb +65 -17
- data/lib/new_relic/agent/agent.rb +42 -113
- data/lib/new_relic/agent/browser_monitoring.rb +9 -1
- data/lib/new_relic/agent/configuration/default_source.rb +12 -0
- data/lib/new_relic/agent/error_collector.rb +13 -6
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +5 -5
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +15 -0
- data/lib/new_relic/agent/instrumentation/curb.rb +2 -2
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +2 -2
- data/lib/new_relic/agent/instrumentation/rack.rb +2 -0
- data/lib/new_relic/agent/instrumentation/resque.rb +9 -3
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +5 -0
- data/lib/new_relic/agent/method_tracer.rb +45 -27
- data/lib/new_relic/agent/new_relic_service.rb +14 -6
- data/lib/new_relic/agent/pipe_service.rb +1 -1
- data/lib/new_relic/agent/request_sampler.rb +10 -7
- data/lib/new_relic/agent/rules_engine.rb +5 -0
- data/lib/new_relic/agent/samplers/object_sampler.rb +1 -1
- data/lib/new_relic/agent/sql_sampler.rb +4 -2
- data/lib/new_relic/agent/stats_engine.rb +3 -0
- data/lib/new_relic/agent/stats_engine/gc_profiler.rb +17 -7
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +5 -7
- data/lib/new_relic/agent/stats_engine/stats_hash.rb +2 -0
- data/lib/new_relic/agent/supported_versions.rb +247 -0
- data/lib/new_relic/agent/threading/backtrace_service.rb +1 -1
- data/lib/new_relic/agent/threading/thread_profile.rb +2 -1
- data/lib/new_relic/agent/transaction.rb +7 -6
- data/lib/new_relic/agent/transaction/developer_mode_sample_buffer.rb +11 -5
- data/lib/new_relic/agent/transaction/force_persist_sample_buffer.rb +3 -3
- data/lib/new_relic/agent/transaction/slowest_sample_buffer.rb +3 -3
- data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +23 -4
- data/lib/new_relic/agent/transaction/xray_sample_buffer.rb +4 -4
- data/lib/new_relic/agent/transaction_sampler.rb +14 -18
- data/lib/new_relic/agent/worker_loop.rb +1 -0
- data/lib/new_relic/control.rb +1 -0
- data/lib/new_relic/control/instance_methods.rb +0 -1
- data/lib/new_relic/helper.rb +1 -2
- data/lib/new_relic/language_support.rb +12 -2
- data/lib/new_relic/local_environment.rb +12 -11
- data/lib/new_relic/rack.rb +9 -0
- data/lib/new_relic/rack/agent_hooks.rb +6 -0
- data/lib/new_relic/rack/browser_monitoring.rb +9 -2
- data/lib/new_relic/rack/developer_mode.rb +15 -1
- data/lib/new_relic/rack/error_collector.rb +7 -0
- data/lib/new_relic/recipes.rb +2 -0
- data/lib/new_relic/transaction_sample.rb +39 -48
- data/lib/new_relic/version.rb +1 -1
- data/lib/tasks/install.rake +44 -2
- data/lib/tasks/versions.html.erb +31 -0
- data/lib/tasks/versions.rake +52 -0
- data/lib/tasks/versions.txt.erb +14 -0
- data/newrelic_rpm.gemspec +4 -2
- data/test/agent_helper.rb +21 -1
- data/test/environments/lib/environments/runner.rb +19 -5
- data/test/environments/norails/Gemfile +4 -1
- data/test/environments/rails21/Gemfile +4 -6
- data/test/environments/rails21/Rakefile +4 -0
- data/test/environments/rails21/config/database.yml +2 -7
- data/test/environments/rails22/Gemfile +6 -13
- data/test/environments/rails22/Rakefile +4 -0
- data/test/environments/rails22/config/database.yml +2 -7
- data/test/environments/rails22/config/environment.rb +1 -1
- data/test/environments/rails23/Gemfile +3 -4
- data/test/environments/rails23/Rakefile +4 -0
- data/test/environments/rails23/config/database.yml +2 -7
- data/test/environments/rails30/Gemfile +2 -4
- data/test/environments/rails30/Rakefile +2 -0
- data/test/environments/rails30/config/database.yml +2 -7
- data/test/environments/rails31/Gemfile +2 -4
- data/test/environments/rails31/Rakefile +2 -0
- data/test/environments/rails31/config/database.yml +2 -7
- data/test/environments/rails32/Gemfile +2 -5
- data/test/environments/rails32/Rakefile +2 -0
- data/test/environments/rails32/config/database.yml +1 -1
- data/test/environments/rails40/Gemfile +7 -4
- data/test/environments/rails40/Rakefile +2 -0
- data/test/environments/rails40/config/database.yml +2 -7
- data/test/helpers/runtime_detection.rb +17 -0
- data/test/multiverse/lib/multiverse/suite.rb +20 -4
- data/test/multiverse/suites/agent_only/key_transactions_test.rb +1 -1
- data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -1
- data/test/multiverse/suites/agent_only/thread_profiling_test.rb +32 -7
- data/test/multiverse/suites/agent_only/xray_sessions_test.rb +1 -0
- data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +4 -3
- data/test/multiverse/suites/curb/curb_test.rb +8 -0
- data/test/multiverse/suites/excon/excon_test.rb +8 -0
- data/test/multiverse/suites/httpclient/httpclient_test.rb +8 -0
- data/test/multiverse/suites/net_http/net_http_test.rb +8 -0
- data/test/multiverse/suites/padrino/Envfile +3 -2
- data/test/multiverse/suites/rails/gc_instrumentation_test.rb +17 -8
- data/test/multiverse/suites/resque/Envfile +3 -3
- data/test/multiverse/suites/resque/instrumentation_test.rb +47 -5
- data/test/multiverse/suites/sequel/Envfile +0 -3
- data/test/multiverse/suites/sequel/database.rb +53 -0
- data/test/{new_relic/agent/instrumentation/sequel_test.rb → multiverse/suites/sequel/sequel_instrumentation_test.rb} +12 -53
- data/test/multiverse/suites/sequel/{sequel_test.rb → sequel_safety_test.rb} +2 -17
- data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +50 -5
- data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +15 -2
- data/test/multiverse/suites/typhoeus/typhoeus_test.rb +8 -0
- data/test/new_relic/agent/agent/connect_test.rb +3 -2
- data/test/new_relic/agent/agent_test.rb +89 -82
- data/test/new_relic/agent/browser_monitoring_test.rb +44 -1
- data/test/new_relic/agent/error_collector_test.rb +17 -20
- data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +13 -10
- data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +16 -1
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
- data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +1 -1
- data/test/new_relic/agent/new_relic_service_test.rb +78 -9
- data/test/new_relic/agent/pipe_channel_manager_test.rb +7 -9
- data/test/new_relic/agent/pipe_service_test.rb +4 -4
- data/test/new_relic/agent/request_sampler_test.rb +2 -2
- data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +15 -35
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +15 -7
- data/test/new_relic/agent/stats_engine_test.rb +4 -3
- data/test/new_relic/agent/threading/backtrace_service_test.rb +2 -0
- data/test/new_relic/agent/threading/thread_profile_test.rb +19 -0
- data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +4 -4
- data/test/new_relic/agent/transaction/force_persist_sample_buffer_test.rb +1 -1
- data/test/new_relic/agent/transaction_sampler_test.rb +60 -45
- data/test/new_relic/fake_collector.rb +37 -2
- data/test/new_relic/http_client_test_cases.rb +26 -1
- data/test/new_relic/language_support_test.rb +12 -31
- data/test/new_relic/local_environment_test.rb +6 -2
- data/test/new_relic/multiverse_helpers.rb +2 -5
- data/test/new_relic/transaction_sample_test.rb +57 -36
- data/test/performance/suites/config.rb +76 -0
- data/test/rum/no_html_and_no_header.result.html +3 -0
- data/test/rum/no_html_and_no_header.source.html +3 -0
- data/test/script/ci.sh +0 -2
- data/test/test_helper.rb +5 -0
- metadata +43 -26
- metadata.gz.sig +0 -0
@@ -8,6 +8,7 @@ module NewRelic
|
|
8
8
|
class TransactionSampleBuffer
|
9
9
|
attr_reader :samples
|
10
10
|
|
11
|
+
SINGLE_BUFFER_MAX = 20
|
11
12
|
NO_SAMPLES = [].freeze
|
12
13
|
|
13
14
|
def initialize
|
@@ -53,17 +54,35 @@ module NewRelic
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def full?
|
56
|
-
@samples.length >=
|
57
|
+
@samples.length >= max_capacity
|
57
58
|
end
|
58
59
|
|
59
|
-
#
|
60
|
-
#
|
60
|
+
# Capacity is the desired number of samples a buffer will hold. This
|
61
|
+
# can be user dictated via config if a feature wants.
|
62
|
+
#
|
63
|
+
# This value will be forcibly capped by the max_capacity
|
64
|
+
def capacity
|
65
|
+
raise NotImplementedError.new("TransactionSampleBuffer subclasses must provide a capacity override")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Apply hard upper limit to the capacity to prevent users from
|
69
|
+
# consuming too much memory buffering TT's.
|
70
|
+
#
|
71
|
+
# A typical buffer should NOT override this method (although we do for
|
72
|
+
# odd things like dev-mode)
|
73
|
+
def max_capacity
|
74
|
+
capacity > SINGLE_BUFFER_MAX ? SINGLE_BUFFER_MAX : capacity
|
75
|
+
end
|
76
|
+
|
77
|
+
# Our default truncation strategy is to keep max_capacity
|
78
|
+
# worth of the longest samples. Override this method for alternate
|
79
|
+
# behavior.
|
61
80
|
#
|
62
81
|
# This doesn't use the more convenient #last and #sort_by to avoid
|
63
82
|
# additional array allocations (and abundant alliteration)
|
64
83
|
def truncate_samples
|
65
84
|
@samples.sort!{|a,b| a.duration <=> b.duration}
|
66
|
-
@samples.slice!(0..-(
|
85
|
+
@samples.slice!(0..-(max_capacity + 1))
|
67
86
|
end
|
68
87
|
|
69
88
|
# When pushing a scope different sample buffers potentially want to
|
@@ -20,9 +20,9 @@ module NewRelic
|
|
20
20
|
@enabled = new_value
|
21
21
|
end
|
22
22
|
|
23
|
-
@
|
23
|
+
@capacity = NewRelic::Agent.config[:'xray_session.max_samples']
|
24
24
|
NewRelic::Agent.config.register_callback(:'xray_session.max_samples') do |new_value|
|
25
|
-
@
|
25
|
+
@capacity = new_value
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -30,8 +30,8 @@ module NewRelic
|
|
30
30
|
@xray_session_collection ||= NewRelic::Agent.instance.agent_command_router.xray_session_collection
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
@
|
33
|
+
def capacity
|
34
|
+
@capacity
|
35
35
|
end
|
36
36
|
|
37
37
|
def truncate_samples
|
@@ -235,31 +235,27 @@ module NewRelic
|
|
235
235
|
end
|
236
236
|
|
237
237
|
# Gather transaction traces that we'd like to transmit to the server.
|
238
|
-
|
239
|
-
|
240
|
-
def harvest(previous=[])
|
241
|
-
return [] if !enabled?
|
242
|
-
|
243
|
-
# If no unsent transactions from last time, we explicitly pass nil!
|
244
|
-
previous ||= []
|
238
|
+
def harvest
|
239
|
+
return [] unless enabled?
|
245
240
|
|
246
241
|
@samples_lock.synchronize do
|
247
242
|
@last_sample = nil
|
248
|
-
|
243
|
+
harvest_from_sample_buffers
|
249
244
|
end
|
250
245
|
end
|
251
246
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
247
|
+
def merge!(previous)
|
248
|
+
@samples_lock.synchronize do
|
249
|
+
@sample_buffers.each do |buffer|
|
250
|
+
buffer.store_previous(previous)
|
251
|
+
end
|
252
|
+
end
|
257
253
|
end
|
258
254
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
255
|
+
def count
|
256
|
+
@samples_lock.synchronize do
|
257
|
+
samples = @sample_buffers.inject([]) { |all, b| all.concat(b.samples) }
|
258
|
+
samples.uniq.size
|
263
259
|
end
|
264
260
|
end
|
265
261
|
|
@@ -268,7 +264,7 @@ module NewRelic
|
|
268
264
|
# want a single level flatten anyway, but, as you probably already
|
269
265
|
# know, Ruby 1.8.6 :/
|
270
266
|
result = []
|
271
|
-
@sample_buffers.each {|buffer| result.concat(buffer.harvest_samples)}
|
267
|
+
@sample_buffers.each { |buffer| result.concat(buffer.harvest_samples) }
|
272
268
|
result.uniq
|
273
269
|
end
|
274
270
|
|
data/lib/new_relic/control.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
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 'new_relic/language_support'
|
6
5
|
require 'new_relic/agent/null_logger'
|
7
6
|
require 'new_relic/agent/memory_logger'
|
8
7
|
require 'new_relic/agent/agent_logger'
|
data/lib/new_relic/helper.rb
CHANGED
@@ -52,8 +52,7 @@ module NewRelic
|
|
52
52
|
|
53
53
|
# Load the JSON library from the standard library.
|
54
54
|
def self::load_stdlib_json
|
55
|
-
|
56
|
-
return false if RUBY_VERSION == '1.9.1'
|
55
|
+
return false unless NewRelic::LanguageSupport.stdlib_json_usable?
|
57
56
|
|
58
57
|
require 'json'
|
59
58
|
define_method( :json_dump, &::JSON.method(:dump) )
|
@@ -64,19 +64,29 @@ module NewRelic::LanguageSupport
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
67
|
+
def object_space_usable?
|
68
68
|
if defined?(::JRuby) && JRuby.respond_to?(:runtime)
|
69
69
|
JRuby.runtime.is_object_space_enabled
|
70
|
+
elsif defined?(::ObjectSpace) && !rubinius?
|
71
|
+
true
|
70
72
|
else
|
71
|
-
|
73
|
+
false
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
77
|
+
def rubinius?
|
78
|
+
defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
79
|
+
end
|
80
|
+
|
75
81
|
def using_version?(version)
|
76
82
|
numbers = version.split('.')
|
77
83
|
numbers == ::RUBY_VERSION.split('.')[0, numbers.size]
|
78
84
|
end
|
79
85
|
|
86
|
+
def stdlib_json_usable?
|
87
|
+
RUBY_VERSION >= '1.9.2'
|
88
|
+
end
|
89
|
+
|
80
90
|
def test_forkability
|
81
91
|
child = Process.fork { exit! }
|
82
92
|
# calling wait here doesn't seem like it should necessary, but it seems to
|
@@ -35,7 +35,7 @@ module NewRelic
|
|
35
35
|
# Runs through all the objects in ObjectSpace to find the first one that
|
36
36
|
# match the provided class
|
37
37
|
def find_class_in_object_space(klass)
|
38
|
-
if NewRelic::LanguageSupport.
|
38
|
+
if NewRelic::LanguageSupport.object_space_usable?
|
39
39
|
ObjectSpace.each_object(klass) do |x|
|
40
40
|
return x
|
41
41
|
end
|
@@ -117,21 +117,21 @@ module NewRelic
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def check_for_unicorn
|
120
|
-
if (defined?(::Unicorn) && defined?(::Unicorn::HttpServer)) && NewRelic::LanguageSupport.
|
120
|
+
if (defined?(::Unicorn) && defined?(::Unicorn::HttpServer)) && NewRelic::LanguageSupport.object_space_usable?
|
121
121
|
v = find_class_in_object_space(::Unicorn::HttpServer)
|
122
122
|
@discovered_dispatcher = :unicorn if v
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
126
|
def check_for_rainbows
|
127
|
-
if (defined?(::Rainbows) && defined?(::Rainbows::HttpServer)) && NewRelic::LanguageSupport.
|
127
|
+
if (defined?(::Rainbows) && defined?(::Rainbows::HttpServer)) && NewRelic::LanguageSupport.object_space_usable?
|
128
128
|
v = find_class_in_object_space(::Rainbows::HttpServer)
|
129
129
|
@discovered_dispatcher = :rainbows if v
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
133
|
def check_for_delayed_job
|
134
|
-
if $0 =~ /delayed_job$/
|
134
|
+
if $0 =~ /delayed_job$/ || (File.basename($0) == 'rake' && ARGV.include?('jobs:work'))
|
135
135
|
@discovered_dispatcher = :delayed_job
|
136
136
|
end
|
137
137
|
end
|
@@ -156,16 +156,17 @@ module NewRelic
|
|
156
156
|
end
|
157
157
|
|
158
158
|
def check_for_thin
|
159
|
-
if defined?(::Thin) && defined?(::Thin::Server)
|
160
|
-
#
|
161
|
-
#
|
162
|
-
|
159
|
+
if defined?(::Thin) && defined?(::Thin::Server)
|
160
|
+
# If ObjectSpace is available, use it to search for a Thin::Server
|
161
|
+
# instance. Otherwise, just the presence of the constant is sufficient.
|
162
|
+
if NewRelic::LanguageSupport.object_space_usable?
|
163
|
+
ObjectSpace.each_object(Thin::Server) do |thin_dispatcher|
|
164
|
+
@discovered_dispatcher = :thin
|
165
|
+
end
|
166
|
+
else
|
163
167
|
@discovered_dispatcher = :thin
|
164
168
|
end
|
165
169
|
end
|
166
|
-
if defined?(::Thin) && defined?(::Thin::VERSION) && !@discovered_dispatcher
|
167
|
-
@discovered_dispatcher = :thin
|
168
|
-
end
|
169
170
|
end
|
170
171
|
|
171
172
|
def check_for_litespeed
|
data/lib/new_relic/rack.rb
CHANGED
@@ -2,7 +2,16 @@
|
|
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
|
+
# @api public
|
5
6
|
module NewRelic
|
7
|
+
# This module contains Rack middlewares used by the Ruby agent.
|
8
|
+
#
|
9
|
+
# Generally, these middlewares should be injected automatically when starting
|
10
|
+
# your application. If automatic injection into the middleware chain is not
|
11
|
+
# working for some reason, you may also include them manually.
|
12
|
+
#
|
13
|
+
#
|
14
|
+
# @api public
|
6
15
|
module Rack
|
7
16
|
end
|
8
17
|
end
|
@@ -5,6 +5,12 @@
|
|
5
5
|
require 'new_relic/agent/event_listener'
|
6
6
|
|
7
7
|
module NewRelic::Rack
|
8
|
+
# This middleware is used by the agent internally, and is usually injected
|
9
|
+
# automatically into the middleware chain. If automatic injection is not
|
10
|
+
# working, you may manually use it in your middleware chain instead.
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
#
|
8
14
|
class AgentHooks
|
9
15
|
def initialize(app, options = {})
|
10
16
|
@app = app
|
@@ -5,6 +5,13 @@
|
|
5
5
|
require 'rack'
|
6
6
|
|
7
7
|
module NewRelic::Rack
|
8
|
+
# This middleware is used by the agent for the Real user monitoring (RUM)
|
9
|
+
# feature, and will usually be automatically injected in the middleware chain.
|
10
|
+
# If automatic injection is not working, you may manually use it in your
|
11
|
+
# middleware chain instead.
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
#
|
8
15
|
class BrowserMonitoring
|
9
16
|
|
10
17
|
def initialize(app, options = {})
|
@@ -76,9 +83,9 @@ module NewRelic::Rack
|
|
76
83
|
# is really weird and we should punt.
|
77
84
|
if head_pos && (head_pos < body_close)
|
78
85
|
# rebuild the source
|
79
|
-
source = source[0
|
86
|
+
source = source[0...head_pos] <<
|
80
87
|
header <<
|
81
|
-
source[head_pos
|
88
|
+
source[head_pos...body_close] <<
|
82
89
|
footer <<
|
83
90
|
source[body_close..-1]
|
84
91
|
else
|
@@ -11,6 +11,20 @@ require 'new_relic/collection_helper'
|
|
11
11
|
|
12
12
|
module NewRelic
|
13
13
|
module Rack
|
14
|
+
# This middleware provides the 'developer mode' feature of newrelic_rpm,
|
15
|
+
# which allows you to see data about local web transactions in development
|
16
|
+
# mode immediately without needing to send this data to New Relic's servers.
|
17
|
+
#
|
18
|
+
# Enabling developer mode has serious performance and security impact, and
|
19
|
+
# thus you should never use this middleware in a production or non-local
|
20
|
+
# environment.
|
21
|
+
#
|
22
|
+
# This middleware should be automatically inserted in most contexts, but if
|
23
|
+
# automatic middleware insertion fails, you may manually insert it into your
|
24
|
+
# middleware chain.
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
#
|
14
28
|
class DeveloperMode
|
15
29
|
|
16
30
|
VIEW_PATH = File.expand_path('../../../../ui/views/', __FILE__)
|
@@ -141,7 +155,7 @@ module NewRelic
|
|
141
155
|
body = render_without_layout(view, binding)
|
142
156
|
end
|
143
157
|
if add_rack_array
|
144
|
-
::Rack::Response.new(body).finish
|
158
|
+
::Rack::Response.new(body, 200, {'Content-Type' => 'text/html'}).finish
|
145
159
|
else
|
146
160
|
body
|
147
161
|
end
|
@@ -3,6 +3,13 @@
|
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
4
|
|
5
5
|
module NewRelic::Rack
|
6
|
+
# This middleware is used by the agent in order to capture exceptions that
|
7
|
+
# occur within your web application. It will normally be injected into the
|
8
|
+
# middleware chain automatically, but if automatic injection fails in your
|
9
|
+
# environment, you may alternately include it manually.
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
#
|
6
13
|
class ErrorCollector
|
7
14
|
def initialize(app, options={})
|
8
15
|
@app = app
|
data/lib/new_relic/recipes.rb
CHANGED
@@ -18,6 +18,7 @@ module NewRelic
|
|
18
18
|
attr_accessor :params, :root_segment, :profile, :force_persist, :guid,
|
19
19
|
:threshold, :finished, :xray_session_id
|
20
20
|
attr_reader :root_segment, :params, :sample_id
|
21
|
+
attr_writer :prepared
|
21
22
|
|
22
23
|
@@start_time = Time.now
|
23
24
|
|
@@ -29,11 +30,16 @@ module NewRelic
|
|
29
30
|
@params = { :segment_count => -1, :request_params => {} }
|
30
31
|
@segment_count = -1
|
31
32
|
@root_segment = create_segment 0.0, "ROOT"
|
33
|
+
@prepared = false
|
32
34
|
|
33
35
|
@guid = generate_guid
|
34
36
|
NewRelic::Agent::TransactionState.get.request_guid = @guid
|
35
37
|
end
|
36
38
|
|
39
|
+
def prepared?
|
40
|
+
@prepared
|
41
|
+
end
|
42
|
+
|
37
43
|
def count_segments
|
38
44
|
@segment_count
|
39
45
|
end
|
@@ -182,21 +188,19 @@ module NewRelic
|
|
182
188
|
#
|
183
189
|
# :explain_sql : run EXPLAIN on all queries whose response times equal the value for this key
|
184
190
|
# (for example :explain_sql => 2.0 would explain everything over 2 seconds. 0.0 would explain everything.)
|
185
|
-
# :keep_backtraces : keep backtraces, significantly increasing size of trace (off by default)
|
186
191
|
# :record_sql => [ :raw | :obfuscated] : copy over the sql, obfuscating if necessary
|
187
|
-
def prepare_to_send(options={})
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
build_segment_for_transfer(sample, @root_segment, sample.root_segment, options)
|
192
|
+
def prepare_to_send!(options={})
|
193
|
+
return self if @prepared
|
194
|
+
|
195
|
+
if options[:record_sql]
|
196
|
+
collect_explain_plans!(options[:explain_sql]) if options[:explain_sql]
|
197
|
+
prepare_sql_for_transmission!(options[:record_sql])
|
198
|
+
else
|
199
|
+
strip_sql!
|
200
|
+
end
|
197
201
|
|
198
|
-
|
199
|
-
|
202
|
+
@prepared = true
|
203
|
+
self
|
200
204
|
end
|
201
205
|
|
202
206
|
def params=(params)
|
@@ -250,43 +254,30 @@ module NewRelic
|
|
250
254
|
return time_delta
|
251
255
|
end
|
252
256
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
target_segment.add_called_segment target_called_segment
|
264
|
-
source_called_segment.params.each do |k,v|
|
265
|
-
case k
|
266
|
-
when :backtrace
|
267
|
-
target_called_segment[k]=v if options[:keep_backtraces]
|
268
|
-
when :sql
|
269
|
-
# run an EXPLAIN on this sql if specified.
|
270
|
-
if options[:record_sql] && options[:record_sql] &&
|
271
|
-
options[:explain_sql] &&
|
272
|
-
source_called_segment.duration > options[:explain_sql].to_f
|
273
|
-
target_called_segment[:explain_plan] = source_called_segment.explain_sql
|
274
|
-
end
|
275
|
-
|
276
|
-
target_called_segment[:sql] = case options[:record_sql]
|
277
|
-
when :raw then v
|
278
|
-
when :obfuscated then NewRelic::Agent::Database.obfuscate_sql(v)
|
279
|
-
else raise "Invalid value for record_sql: #{options[:record_sql]}"
|
280
|
-
end.to_s if options[:record_sql]
|
281
|
-
when :connection_config
|
282
|
-
# don't copy it
|
283
|
-
else
|
284
|
-
target_called_segment[k]=v
|
285
|
-
end
|
257
|
+
def strip_sql!
|
258
|
+
each_segment do |segment|
|
259
|
+
segment.params.delete(:sql)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def collect_explain_plans!(threshold)
|
264
|
+
each_segment do |segment|
|
265
|
+
if segment[:sql] && segment.duration > threshold
|
266
|
+
segment[:explain_plan] = segment.explain_sql
|
286
267
|
end
|
268
|
+
end
|
269
|
+
end
|
287
270
|
|
288
|
-
|
289
|
-
|
271
|
+
def prepare_sql_for_transmission!(strategy)
|
272
|
+
each_segment do |segment|
|
273
|
+
if segment[:sql]
|
274
|
+
segment[:sql] = case strategy
|
275
|
+
when :raw
|
276
|
+
segment[:sql].to_s
|
277
|
+
when :obfuscated
|
278
|
+
NewRelic::Agent::Database.obfuscate_sql(segment[:sql]).to_s
|
279
|
+
end
|
280
|
+
end
|
290
281
|
end
|
291
282
|
end
|
292
283
|
end
|