newrelic_rpm 3.14.0.305 → 3.14.1.311
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +55 -3
- data/lib/new_relic/agent/agent.rb +1 -0
- data/lib/new_relic/agent/configuration/default_source.rb +25 -2
- data/lib/new_relic/agent/error_collector.rb +2 -1
- data/lib/new_relic/agent/error_event_aggregator.rb +10 -7
- data/lib/new_relic/agent/hostname.rb +1 -1
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +82 -4
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +5 -4
- data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +24 -4
- data/lib/new_relic/agent/instrumentation/rack.rb +80 -29
- data/lib/new_relic/agent/pipe_service.rb +4 -0
- data/lib/new_relic/agent/transaction.rb +5 -0
- data/lib/new_relic/version.rb +1 -1
- data/test/multiverse/suites/agent_only/agent_attributes_test.rb +15 -0
- data/test/multiverse/suites/agent_only/error_events_test.rb +15 -1
- data/test/multiverse/suites/delayed_job/Envfile +10 -0
- data/test/multiverse/suites/delayed_job/before_suite.rb +10 -0
- data/test/multiverse/suites/delayed_job/delayed_job_instrumentation_test.rb +106 -0
- data/test/multiverse/suites/mongo/mongo2_instrumentation_test.rb +45 -0
- data/test/multiverse/suites/rack/Envfile +10 -0
- data/test/multiverse/suites/rack/before_suite.rb +12 -0
- data/test/multiverse/suites/rack/http_response_code_test.rb +2 -2
- data/test/multiverse/suites/rack/puma_rack_builder_test.rb +81 -0
- data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +12 -3
- data/test/multiverse/suites/rack/rack_cascade_test.rb +31 -31
- data/test/multiverse/suites/rack/rack_env_mutation_test.rb +2 -2
- data/test/multiverse/suites/rack/rack_unsupported_version_test.rb +1 -1
- data/test/multiverse/suites/rack/response_content_type_test.rb +2 -2
- data/test/multiverse/suites/rack/url_map_test.rb +45 -11
- data/test/new_relic/agent/agent/connect_test.rb +1 -1
- data/test/new_relic/agent/agent_logger_test.rb +2 -0
- data/test/new_relic/agent/agent_test.rb +1 -0
- data/test/new_relic/agent/audit_logger_test.rb +4 -0
- data/test/new_relic/agent/error_collector_test.rb +34 -10
- data/test/new_relic/agent/error_event_aggregator_test.rb +12 -1
- data/test/new_relic/agent/hostname_test.rb +5 -0
- data/test/new_relic/agent/instrumentation/delayed_job_instrumentation_test.rb +23 -0
- data/test/new_relic/agent/pipe_service_test.rb +7 -0
- data/test/new_relic/marshalling_test_cases.rb +42 -0
- metadata +6 -2
@@ -546,6 +546,11 @@ module NewRelic
|
|
546
546
|
if @request_attributes
|
547
547
|
@request_attributes.assign_agent_attributes self
|
548
548
|
end
|
549
|
+
|
550
|
+
display_host = Agent.config[:'process_host.display_name']
|
551
|
+
unless display_host == NewRelic::Agent::Hostname.get
|
552
|
+
add_agent_attribute(:'host.displayName', display_host, default_destinations)
|
553
|
+
end
|
549
554
|
end
|
550
555
|
|
551
556
|
def assign_intrinsics(state)
|
data/lib/new_relic/version.rb
CHANGED
@@ -208,6 +208,21 @@ class AgentAttributesTest < Minitest::Test
|
|
208
208
|
refute_event_has_attribute('httpResponseCode')
|
209
209
|
end
|
210
210
|
|
211
|
+
def test_host_display_name_included_when_enabled_and_set
|
212
|
+
config = {:'process_host.display_name' => 'Fancy Host Name',
|
213
|
+
:'transaction_events.attributes.include' => 'host.displayName',}
|
214
|
+
run_transaction(config)
|
215
|
+
|
216
|
+
assert_event_has_agent_attribute('host.displayName', 'Fancy Host Name')
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_host_display_name_excluded_when_enabled_but_not_set
|
220
|
+
config = {:'transaction_events.attributes.include' => 'host.displayName',}
|
221
|
+
run_transaction(config)
|
222
|
+
|
223
|
+
refute_event_has_attribute('host.displayName')
|
224
|
+
end
|
225
|
+
|
211
226
|
def run_transaction(config = {}, txn_options = {})
|
212
227
|
default_config = {
|
213
228
|
:'transaction_tracer.transaction_threshold' => -10,
|
@@ -5,7 +5,9 @@
|
|
5
5
|
class ErrorEventsTest < Minitest::Test
|
6
6
|
include MultiverseHelpers
|
7
7
|
|
8
|
-
setup_and_teardown_agent
|
8
|
+
setup_and_teardown_agent do
|
9
|
+
freeze_time
|
10
|
+
end
|
9
11
|
|
10
12
|
def test_error_events_are_submitted
|
11
13
|
txn = generate_errors
|
@@ -64,6 +66,18 @@ class ErrorEventsTest < Minitest::Test
|
|
64
66
|
assert_equal(0, $collector.calls_for(:error_event_data).size)
|
65
67
|
end
|
66
68
|
|
69
|
+
def test_error_events_created_outside_of_transaction
|
70
|
+
NewRelic::Agent.notice_error RuntimeError.new "No Txn"
|
71
|
+
NewRelic::Agent.agent.send(:harvest_and_send_error_event_data)
|
72
|
+
|
73
|
+
intrinsics, _, _ = last_error_event
|
74
|
+
|
75
|
+
assert_equal "TransactionError", intrinsics["type"]
|
76
|
+
assert_in_delta Time.now.to_f, intrinsics["timestamp"], 0.001
|
77
|
+
assert_equal "RuntimeError", intrinsics["error.class"]
|
78
|
+
assert_equal "No Txn", intrinsics["error.message"]
|
79
|
+
end
|
80
|
+
|
67
81
|
def generate_errors num_errors = 1
|
68
82
|
in_transaction :transaction_name => "Controller/blogs/index" do |t|
|
69
83
|
num_errors.times { t.notice_error RuntimeError.new "Big Controller" }
|
@@ -22,6 +22,16 @@ if RUBY_VERSION >= '1.9.3'
|
|
22
22
|
RB
|
23
23
|
end
|
24
24
|
|
25
|
+
if RUBY_VERSION >= '1.9.3'
|
26
|
+
gemfile <<-RB
|
27
|
+
gem 'delayed_job', '~> 4.1.0'
|
28
|
+
gem 'delayed_job_active_record', '~> 4.1.0'
|
29
|
+
gem 'activerecord', '~> 3.2.19'
|
30
|
+
gem 'i18n', '~> 0.6.11'
|
31
|
+
#{boilerplate_gems}
|
32
|
+
RB
|
33
|
+
end
|
34
|
+
|
25
35
|
# delayed_job_active_record (and older baked into delayed_job) support
|
26
36
|
if RUBY_VERSION >= '1.9.3'
|
27
37
|
dj4_with_active_record = <<-DJ
|
@@ -29,5 +29,15 @@ if Delayed::Worker.backend.to_s == "Delayed::Backend::ActiveRecord::Job"
|
|
29
29
|
@connection = $db_connection
|
30
30
|
end
|
31
31
|
|
32
|
+
class CreatePelicans < ActiveRecord::Migration
|
33
|
+
@connection = $db_connection
|
34
|
+
def self.up
|
35
|
+
create_table :pelicans do |t|
|
36
|
+
t.string :name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
32
41
|
CreateDelayedJobs.up
|
42
|
+
CreatePelicans.up
|
33
43
|
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
|
+
if defined?(Delayed::Backend::ActiveRecord) && Delayed::Worker.respond_to?(:delay_jobs)
|
6
|
+
class DelayedJobInstrumentationTest < Minitest::Test
|
7
|
+
include MultiverseHelpers
|
8
|
+
|
9
|
+
class QuackJob
|
10
|
+
def initialize(index)
|
11
|
+
@index = index
|
12
|
+
end
|
13
|
+
|
14
|
+
def display_name
|
15
|
+
"Quack Job: #{@index}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def perform
|
19
|
+
"Performing Quack Job #{@index} .."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Pelican < ActiveRecord::Base
|
24
|
+
self.table_name = :pelicans
|
25
|
+
|
26
|
+
def quack
|
27
|
+
"quack..."
|
28
|
+
end
|
29
|
+
|
30
|
+
def quack_later
|
31
|
+
"...quack"
|
32
|
+
end
|
33
|
+
|
34
|
+
handle_asynchronously :quack_later
|
35
|
+
end
|
36
|
+
|
37
|
+
setup_and_teardown_agent
|
38
|
+
|
39
|
+
def after_setup
|
40
|
+
Delayed::Worker.delay_jobs = false
|
41
|
+
# We set Delayed::Worker.delay_jobs = false to run jobs inline for testing purposes, but
|
42
|
+
# we unfortunately hook the initialize method on Delayed::Worker
|
43
|
+
# to install our instrumentation. Delayed::Workers are not initialized when running
|
44
|
+
# tests inline so we have to manually instantiate one to install our instrumentation.
|
45
|
+
# We also need to take care to only install the instrumentation once.
|
46
|
+
unless Delayed::Job.instance_methods.any? { |m| m == :invoke_job_without_new_relic || m == "invoke_job_without_new_relic" }
|
47
|
+
Delayed::Worker.new
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def after_teardown
|
52
|
+
Delayed::Worker.delay_jobs = true
|
53
|
+
end
|
54
|
+
|
55
|
+
# Delayed Job doesn't expose a version number, so we have to resort to checking Gem.loaded_specs.
|
56
|
+
# Additionally, earlier versions of Delayed Job do not call invoke_job when running jobs inline.
|
57
|
+
# We can only test methods using delay and handle_asynchronously on versions that run jobs via
|
58
|
+
# the invoke_job method.
|
59
|
+
def self.dj_invokes_job_inline?
|
60
|
+
Gem.loaded_specs["delayed_job"].version >= Gem::Version.new("3.0.0")
|
61
|
+
end
|
62
|
+
|
63
|
+
if dj_invokes_job_inline?
|
64
|
+
def test_delay_method
|
65
|
+
p = Pelican.create(:name => "Charlie")
|
66
|
+
p.delay.quack
|
67
|
+
|
68
|
+
assert_metrics_recorded [
|
69
|
+
'OtherTransaction/all',
|
70
|
+
'OtherTransaction/DelayedJob/all',
|
71
|
+
'OtherTransaction/DelayedJob/DelayedJobInstrumentationTest::Pelican#quack'
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_handle_asynchronously
|
76
|
+
p = Pelican.create(:name => "Charlieee")
|
77
|
+
p.quack_later
|
78
|
+
|
79
|
+
assert_metrics_recorded [
|
80
|
+
'OtherTransaction/all',
|
81
|
+
'OtherTransaction/DelayedJob/all',
|
82
|
+
'OtherTransaction/DelayedJob/DelayedJobInstrumentationTest::Pelican#quack_later_without_delay'
|
83
|
+
]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_enqueue_standalone_job
|
88
|
+
job = QuackJob.new rand(100)
|
89
|
+
invoke_job(job)
|
90
|
+
|
91
|
+
assert_metrics_recorded [
|
92
|
+
'OtherTransaction/all',
|
93
|
+
'OtherTransaction/DelayedJob/all',
|
94
|
+
'OtherTransaction/DelayedJob/DelayedJobInstrumentationTest::QuackJob'
|
95
|
+
]
|
96
|
+
end
|
97
|
+
|
98
|
+
# Note we use this method instead of Delayed::Job.enqueue because Delayed Job 2.1.4 does
|
99
|
+
# not call invoke_job when running jobs inline it instead calls perform directly. This
|
100
|
+
# allows us to test the stand alone job case on all supported versions of Delayed Job.
|
101
|
+
def invoke_job(job)
|
102
|
+
job = Delayed::Job.new(:payload_object => job)
|
103
|
+
job.invoke_job
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -179,6 +179,51 @@ if NewRelic::Agent::Datastores::Mongo.is_supported_version? &&
|
|
179
179
|
assert_metrics_recorded(expected)
|
180
180
|
end
|
181
181
|
|
182
|
+
def test_batched_queries
|
183
|
+
25.times do |i|
|
184
|
+
@collection.insert_one :name => "test-#{i}", :active => true
|
185
|
+
end
|
186
|
+
NewRelic::Agent.drop_buffered_data
|
187
|
+
|
188
|
+
@collection.find(:active => true).batch_size(10).to_a
|
189
|
+
|
190
|
+
expected = {
|
191
|
+
"Datastore/statement/MongoDB/#{@collection_name}/find" => {:call_count=>1},
|
192
|
+
"Datastore/statement/MongoDB/#{@collection_name}/getMore" => {:call_count=>2},
|
193
|
+
"Datastore/operation/MongoDB/find" => {:call_count=>1},
|
194
|
+
"Datastore/operation/MongoDB/getMore" => {:call_count=>2},
|
195
|
+
"Datastore/MongoDB/allWeb" => {:call_count=>3},
|
196
|
+
"Datastore/MongoDB/all" => {:call_count=>3},
|
197
|
+
"Datastore/allWeb" => { :call_count=>3},
|
198
|
+
"Datastore/all" => {:call_count=>3}
|
199
|
+
}
|
200
|
+
assert_metrics_recorded_exclusive expected
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_batched_queries_have_node_per_query
|
204
|
+
25.times do |i|
|
205
|
+
@collection.insert_one :name => "test-#{i}", :active => true
|
206
|
+
end
|
207
|
+
NewRelic::Agent.drop_buffered_data
|
208
|
+
in_transaction "webby" do
|
209
|
+
@collection.find(:active => true).batch_size(10).to_a
|
210
|
+
end
|
211
|
+
|
212
|
+
expected = [
|
213
|
+
"Datastore/statement/MongoDB/#{@collection_name}/find",
|
214
|
+
"Datastore/statement/MongoDB/#{@collection_name}/getMore",
|
215
|
+
"Datastore/statement/MongoDB/#{@collection_name}/getMore"
|
216
|
+
]
|
217
|
+
|
218
|
+
trace = last_transaction_trace
|
219
|
+
actual = []
|
220
|
+
trace.each_node do |n|
|
221
|
+
actual << n.metric_name if n.metric_name.start_with? "Datastore/statement/MongoDB"
|
222
|
+
end
|
223
|
+
|
224
|
+
assert_equal expected, actual
|
225
|
+
end
|
226
|
+
|
182
227
|
def test_drop_collection
|
183
228
|
@collection.drop
|
184
229
|
|
@@ -0,0 +1,12 @@
|
|
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 is a bit ugly, but Puma::Rack::Bundler isn't required by puma unless it's
|
6
|
+
# running as a webserver. This terrible hack is to install our instrumentation
|
7
|
+
# for these tests since our requests aren't served by an actual Puma webserver.
|
8
|
+
if NewRelic::Agent::Instrumentation::RackHelpers.puma_rack_version_supported?
|
9
|
+
require 'puma/rack/builder' unless defined? Puma::Rack::Builder
|
10
|
+
require 'puma/rack/urlmap' unless defined? Puma::Rack::URLMap
|
11
|
+
DependencyDetection.detect!
|
12
|
+
end
|
@@ -2,13 +2,13 @@
|
|
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
|
+
if NewRelic::Agent::Instrumentation::RackHelpers.rack_version_supported?
|
6
|
+
|
5
7
|
require File.join(File.dirname(__FILE__), 'example_app')
|
6
8
|
require 'new_relic/rack/browser_monitoring'
|
7
9
|
require 'new_relic/rack/agent_hooks'
|
8
10
|
require 'new_relic/rack/error_collector'
|
9
11
|
|
10
|
-
if NewRelic::Agent::Instrumentation::RackHelpers.rack_version_supported?
|
11
|
-
|
12
12
|
class HttpResponseCodeTest < Minitest::Test
|
13
13
|
include MultiverseHelpers
|
14
14
|
|
@@ -0,0 +1,81 @@
|
|
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
|
+
if NewRelic::Agent::Instrumentation::RackHelpers.puma_rack_version_supported?
|
6
|
+
|
7
|
+
class PumaRackBuilderTest < Minitest::Test
|
8
|
+
include MultiverseHelpers
|
9
|
+
|
10
|
+
class ExampleApp
|
11
|
+
def call env
|
12
|
+
[200, {'Content-Type' => 'text/html'}, ['Hello!']]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class MiddlewareOne
|
17
|
+
def initialize app
|
18
|
+
@app = app
|
19
|
+
end
|
20
|
+
|
21
|
+
def call env
|
22
|
+
env['MiddlewareOne'] = true
|
23
|
+
@app.call env
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class MiddlewareTwo
|
28
|
+
def initialize app
|
29
|
+
@app = app
|
30
|
+
end
|
31
|
+
|
32
|
+
def call env
|
33
|
+
env['MiddlewareTwo'] = true
|
34
|
+
@app.call env
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def setup
|
39
|
+
@app = build_app
|
40
|
+
@env = {}
|
41
|
+
end
|
42
|
+
|
43
|
+
def teardown
|
44
|
+
NewRelic::Agent.drop_buffered_data
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_app
|
48
|
+
Puma::Rack::Builder.app do
|
49
|
+
use MiddlewareOne
|
50
|
+
use MiddlewareTwo
|
51
|
+
run ExampleApp.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def test_middlewares_are_visited_with_puma_rack
|
57
|
+
@app.call @env
|
58
|
+
assert @env['MiddlewareOne'], 'Expected MiddlewareOne to be present and true in env'
|
59
|
+
assert @env['MiddlewareTwo'], 'Expected MiddlewareTwo to be present and true in env'
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_puma_rack_builder_is_auto_instrumented
|
63
|
+
@app.call @env
|
64
|
+
|
65
|
+
assert_metrics_recorded_exclusive [
|
66
|
+
"Apdex",
|
67
|
+
"ApdexAll",
|
68
|
+
"HttpDispatcher",
|
69
|
+
"Middleware/all",
|
70
|
+
"Apdex/Rack/PumaRackBuilderTest::ExampleApp/call",
|
71
|
+
"Controller/Rack/PumaRackBuilderTest::ExampleApp/call",
|
72
|
+
"Middleware/Rack/PumaRackBuilderTest::MiddlewareOne/call",
|
73
|
+
"Middleware/Rack/PumaRackBuilderTest::MiddlewareTwo/call",
|
74
|
+
"Nested/Controller/Rack/PumaRackBuilderTest::ExampleApp/call",
|
75
|
+
["Middleware/Rack/PumaRackBuilderTest::MiddlewareOne/call", "Controller/Rack/PumaRackBuilderTest::ExampleApp/call"],
|
76
|
+
["Middleware/Rack/PumaRackBuilderTest::MiddlewareTwo/call", "Controller/Rack/PumaRackBuilderTest::ExampleApp/call"],
|
77
|
+
["Nested/Controller/Rack/PumaRackBuilderTest::ExampleApp/call", "Controller/Rack/PumaRackBuilderTest::ExampleApp/call"]
|
78
|
+
]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -2,13 +2,13 @@
|
|
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
|
+
if NewRelic::Agent::Instrumentation::RackHelpers.version_supported? && defined? Rack
|
6
|
+
|
5
7
|
require File.join(File.dirname(__FILE__), 'example_app')
|
6
8
|
require 'new_relic/rack/browser_monitoring'
|
7
9
|
require 'new_relic/rack/agent_hooks'
|
8
10
|
require 'new_relic/rack/error_collector'
|
9
11
|
|
10
|
-
if NewRelic::Agent::Instrumentation::RackHelpers.rack_version_supported?
|
11
|
-
|
12
12
|
class RackAutoInstrumentationTest < Minitest::Test
|
13
13
|
include MultiverseHelpers
|
14
14
|
|
@@ -16,8 +16,16 @@ class RackAutoInstrumentationTest < Minitest::Test
|
|
16
16
|
|
17
17
|
include Rack::Test::Methods
|
18
18
|
|
19
|
+
def builder_class
|
20
|
+
if defined? Puma::Rack::Builder
|
21
|
+
Puma::Rack::Builder
|
22
|
+
else
|
23
|
+
Rack::Builder
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
19
27
|
def app
|
20
|
-
|
28
|
+
builder_class.app do
|
21
29
|
use MiddlewareOne
|
22
30
|
use MiddlewareTwo, 'the correct tag' do |headers|
|
23
31
|
headers['MiddlewareTwoBlockTag'] = 'the block tag'
|
@@ -113,6 +121,7 @@ class RackAutoInstrumentationTest < Minitest::Test
|
|
113
121
|
|
114
122
|
def test_middleware_that_returns_early_records_middleware_rollup_metric
|
115
123
|
get '/?return-early=true'
|
124
|
+
|
116
125
|
assert_metrics_recorded_exclusive([
|
117
126
|
"Apdex",
|
118
127
|
"ApdexAll",
|