newrelic_rpm 3.16.0.318 → 3.16.1.320

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -4
  3. data/CHANGELOG +41 -2
  4. data/lib/new_relic/agent/database.rb +15 -4
  5. data/lib/new_relic/agent/database/explain_plan_helpers.rb +2 -1
  6. data/lib/new_relic/agent/datastores.rb +13 -13
  7. data/lib/new_relic/agent/datastores/metric_helper.rb +33 -2
  8. data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +3 -9
  9. data/lib/new_relic/agent/error_collector.rb +2 -2
  10. data/lib/new_relic/agent/instrumentation/active_record.rb +9 -19
  11. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +2 -6
  12. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +49 -40
  13. data/lib/new_relic/agent/instrumentation/data_mapper.rb +29 -23
  14. data/lib/new_relic/agent/instrumentation/grape.rb +20 -11
  15. data/lib/new_relic/agent/instrumentation/memcache.rb +8 -10
  16. data/lib/new_relic/agent/instrumentation/mongo.rb +25 -16
  17. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +14 -19
  18. data/lib/new_relic/agent/method_tracer_helpers.rb +4 -8
  19. data/lib/new_relic/agent/sql_sampler.rb +14 -1
  20. data/lib/new_relic/agent/stats_engine/metric_stats.rb +18 -0
  21. data/lib/new_relic/agent/supported_versions.rb +2 -3
  22. data/lib/new_relic/agent/traced_method_stack.rb +7 -1
  23. data/lib/new_relic/agent/transaction.rb +6 -0
  24. data/lib/new_relic/agent/transaction/abstract_segment.rb +73 -0
  25. data/lib/new_relic/agent/transaction/datastore_segment.rb +49 -0
  26. data/lib/new_relic/agent/transaction/segment.rb +30 -0
  27. data/lib/new_relic/agent/transaction/tracing.rb +53 -0
  28. data/lib/new_relic/agent/transaction_sampler.rb +8 -1
  29. data/lib/new_relic/noticed_error.rb +3 -1
  30. data/lib/new_relic/version.rb +1 -1
  31. data/lib/sequel/extensions/newrelic_instrumentation.rb +22 -15
  32. data/lib/sequel/plugins/newrelic_instrumentation.rb +4 -3
  33. data/newrelic_rpm.gemspec +1 -9
  34. data/test/environments/lib/environments/runner.rb +6 -4
  35. data/test/environments/norails/Gemfile +9 -3
  36. data/test/environments/rails21/Gemfile +6 -3
  37. data/test/environments/rails22/Gemfile +5 -2
  38. data/test/environments/rails23/Gemfile +1 -1
  39. data/test/environments/rails30/Gemfile +1 -1
  40. data/test/environments/rails31/Gemfile +1 -1
  41. data/test/environments/rails32/Gemfile +1 -1
  42. data/test/environments/rails40/Gemfile +2 -2
  43. data/test/environments/rails41/Gemfile +2 -2
  44. data/test/environments/rails42/Gemfile +2 -2
  45. data/test/environments/rails50/Gemfile +2 -2
  46. data/test/helpers/mongo_metric_builder.rb +3 -4
  47. data/test/multiverse/lib/multiverse/shell_utils.rb +27 -0
  48. data/test/multiverse/lib/multiverse/suite.rb +47 -2
  49. data/test/multiverse/suites/active_record/Envfile +1 -1
  50. data/test/multiverse/suites/delayed_job/Envfile +2 -0
  51. data/test/multiverse/suites/grape/grape_versioning_test.rb +55 -1
  52. data/test/multiverse/suites/grape/grape_versioning_test_api.rb +61 -3
  53. data/test/multiverse/suites/mongo/mongo_instrumentation_test.rb +18 -0
  54. data/test/multiverse/suites/rails/Envfile +3 -3
  55. data/test/multiverse/suites/rails/error_tracing_test.rb +2 -2
  56. data/test/multiverse/suites/sequel/Envfile +7 -0
  57. data/test/multiverse/suites/sequel/sequel_extension_test.rb +1 -1
  58. data/test/new_relic/agent/database_test.rb +9 -0
  59. data/test/new_relic/agent/datastores/metric_helper_test.rb +76 -43
  60. data/test/new_relic/agent/datastores/mongo/metric_translator_test.rb +67 -117
  61. data/test/new_relic/agent/datastores_test.rb +17 -0
  62. data/test/new_relic/agent/error_collector_test.rb +21 -5
  63. data/test/new_relic/agent/instrumentation/active_record_helper_test.rb +40 -45
  64. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +2 -3
  65. data/test/new_relic/agent/instrumentation/mongodb_command_subscriber_test.rb +2 -0
  66. data/test/new_relic/agent/method_tracer_test.rb +54 -52
  67. data/test/new_relic/agent/mock_scope_listener.rb +4 -1
  68. data/test/new_relic/agent/sql_sampler_test.rb +15 -0
  69. data/test/new_relic/agent/transaction/abstract_segment_test.rb +94 -0
  70. data/test/new_relic/agent/transaction/datastore_segment_test.rb +99 -0
  71. data/test/new_relic/agent/transaction/segment_test.rb +53 -0
  72. data/test/new_relic/agent/transaction/tracing_test.rb +121 -0
  73. data/test/new_relic/agent/transaction_sampler_test.rb +13 -0
  74. data/test/new_relic/noticed_error_test.rb +7 -0
  75. data/test/performance/suites/datastores.rb +59 -0
  76. data/test/performance/suites/trace_execution_scoped.rb +8 -9
  77. metadata +13 -46
@@ -0,0 +1,94 @@
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 File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
6
+
7
+ require 'new_relic/agent/transaction'
8
+ require 'new_relic/agent/transaction/abstract_segment'
9
+
10
+ module NewRelic
11
+ module Agent
12
+ class Transaction
13
+ class AbstractSegmentTest < Minitest::Test
14
+ class BasicSegment < AbstractSegment
15
+ def record_metrics
16
+ metric_cache.record_scoped_and_unscoped name, duration, exclusive_duration
17
+ metric_cache.record_unscoped "Basic/all", duration, exclusive_duration
18
+ end
19
+ end
20
+
21
+ def setup
22
+ freeze_time
23
+ end
24
+
25
+ def teardown
26
+ NewRelic::Agent.drop_buffered_data
27
+ end
28
+
29
+ def test_segment_is_nameable
30
+ segment = BasicSegment.new "Custom/basic/segment"
31
+ assert_equal "Custom/basic/segment", segment.name
32
+ end
33
+
34
+ def test_segment_tracks_timing_information
35
+ segment = BasicSegment.new "Custom/basic/segment"
36
+ segment.start
37
+ assert_equal Time.now, segment.start_time
38
+
39
+ advance_time 1.0
40
+ segment.finish
41
+
42
+ assert_equal Time.now, segment.end_time
43
+ assert_equal 1.0, segment.duration
44
+ assert_equal 1.0, segment.exclusive_duration
45
+ end
46
+
47
+ def test_segment_records_metrics
48
+ segment = BasicSegment.new "Custom/basic/segment"
49
+ segment.start
50
+ advance_time 1.0
51
+ segment.finish
52
+
53
+ assert_metrics_recorded ["Custom/basic/segment", "Basic/all"]
54
+ end
55
+
56
+ def test_segment_records_metrics_in_local_cache_if_part_of_transaction
57
+ segment = BasicSegment.new "Custom/basic/segment"
58
+ txn = in_transaction "test_transaction" do
59
+ segment.transaction = txn
60
+ segment.start
61
+ advance_time 1.0
62
+ segment.finish
63
+
64
+ refute_metrics_recorded ["Custom/basic/segment", "Basic/all"]
65
+ end
66
+
67
+ #local metrics will be merged into global store at the end of the transction
68
+ assert_metrics_recorded ["Custom/basic/segment", "Basic/all"]
69
+ end
70
+
71
+ # this preserves a strange case that is currently present in the agent where for some
72
+ # segments we would like to create a TT node for the segment, but not record
73
+ # metrics
74
+ def test_segments_will_not_record_metrics_when_turned_off
75
+ segment = BasicSegment.new "Custom/basic/segment"
76
+ segment.record_metrics = false
77
+ segment.start
78
+ advance_time 1.0
79
+ segment.finish
80
+
81
+ refute_metrics_recorded ["Custom/basic/segment", "Basic/all"]
82
+ end
83
+
84
+ def test_segment_complete_callback_executes_when_segment_finished
85
+ segment = BasicSegment.new "Custom/basic/segment"
86
+ segment.expects(:segment_complete)
87
+ segment.start
88
+ advance_time 1.0
89
+ segment.finish
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,99 @@
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 File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
6
+
7
+ require 'new_relic/agent/transaction/datastore_segment'
8
+
9
+ module NewRelic
10
+ module Agent
11
+ class Transaction
12
+ class DatastoreSegmentTest < Minitest::Test
13
+ def setup
14
+ freeze_time
15
+ end
16
+
17
+ def teardown
18
+ NewRelic::Agent.drop_buffered_data
19
+ end
20
+
21
+ def test_datastore_segment_name_with_collection
22
+ segment = DatastoreSegment.new "SQLite", "insert", "Blog"
23
+ assert_equal "Datastore/statement/SQLite/Blog/insert", segment.name
24
+ end
25
+
26
+ def test_datastore_segment_name_with_operation
27
+ segment = DatastoreSegment.new "SQLite", "select"
28
+ assert_equal "Datastore/operation/SQLite/select", segment.name
29
+ end
30
+
31
+ def test_segment_records_expected_metrics
32
+ Transaction.stubs(:recording_web_transaction?).returns(true)
33
+
34
+ segment = DatastoreSegment.new "SQLite", "insert", "Blog"
35
+ segment.start
36
+ advance_time 1
37
+ segment.finish
38
+
39
+ assert_metrics_recorded [
40
+ "Datastore/statement/SQLite/Blog/insert",
41
+ "Datastore/operation/SQLite/insert",
42
+ "Datastore/SQLite/allWeb",
43
+ "Datastore/SQLite/all",
44
+ "Datastore/allWeb",
45
+ "Datastore/all"
46
+ ]
47
+ end
48
+
49
+ def test_segment_records_expected_metrics_without_collection
50
+ Transaction.stubs(:recording_web_transaction?).returns(true)
51
+
52
+ segment = DatastoreSegment.new "SQLite", "select"
53
+ segment.start
54
+ advance_time 1
55
+ segment.finish
56
+
57
+ assert_metrics_recorded [
58
+ "Datastore/operation/SQLite/select",
59
+ "Datastore/SQLite/allWeb",
60
+ "Datastore/SQLite/all",
61
+ "Datastore/allWeb",
62
+ "Datastore/all"
63
+ ]
64
+ end
65
+
66
+ def test_notice_sql
67
+ in_transaction do
68
+ segment = NewRelic::Agent::Transaction.start_datastore_segment "SQLite", "select"
69
+ segment.notice_sql "select * from blogs"
70
+ advance_time 2.0
71
+ Agent.instance.transaction_sampler.expects(:notice_sql_statement).with(segment.sql_statement, 2.0)
72
+ Agent.instance.sql_sampler.expects(:notice_sql_statement) do |statement, name, duration|
73
+ assert_equal segment.sql_statement.sql, statement.sql_statement
74
+ assert_equal segment.name, name
75
+ assert_equal duration, 2.0
76
+ end
77
+ segment.finish
78
+ end
79
+ end
80
+
81
+ def test_internal_notice_sql
82
+ explainer = stub(:explainer)
83
+ in_transaction do
84
+ segment = NewRelic::Agent::Transaction.start_datastore_segment "SQLite", "select"
85
+ segment._notice_sql "select * from blogs", {:adapter => :sqlite}, explainer
86
+ advance_time 2.0
87
+ Agent.instance.transaction_sampler.expects(:notice_sql_statement).with(segment.sql_statement, 2.0)
88
+ Agent.instance.sql_sampler.expects(:notice_sql_statement) do |statement, name, duration|
89
+ assert_equal segment.sql_statement.sql, statement.sql_statement
90
+ assert_equal segment.name, name
91
+ assert_equal duration, 2.0
92
+ end
93
+ segment.finish
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,53 @@
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 File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
6
+
7
+ require 'new_relic/agent/transaction/segment'
8
+
9
+ module NewRelic
10
+ module Agent
11
+ class Transaction
12
+ class SegmentTest < Minitest::Test
13
+ def setup
14
+ freeze_time
15
+ end
16
+
17
+ def teardown
18
+ NewRelic::Agent.drop_buffered_data
19
+ end
20
+
21
+ def test_assigns_unscoped_metrics
22
+ segment = Segment.new "Custom/simple/segment", "Segment/all"
23
+ assert_equal "Custom/simple/segment", segment.name
24
+ assert_equal "Segment/all", segment.unscoped_metrics
25
+ end
26
+
27
+ def test_assigns_unscoped_metrics_as_array
28
+ segment = Segment.new "Custom/simple/segment", ["Segment/all", "Other/all"]
29
+ assert_equal "Custom/simple/segment", segment.name
30
+ assert_equal ["Segment/all", "Other/all"], segment.unscoped_metrics
31
+ end
32
+
33
+ def test_segment_records_metrics
34
+ segment = Segment.new "Custom/simple/segment", "Segment/all"
35
+ segment.start
36
+ advance_time 1.0
37
+ segment.finish
38
+
39
+ assert_metrics_recorded ["Custom/simple/segment", "Segment/all"]
40
+ end
41
+
42
+ def test_segment_records_metrics_when_given_as_array
43
+ segment = Segment.new "Custom/simple/segment", ["Segment/all", "Other/all"]
44
+ segment.start
45
+ advance_time 1.0
46
+ segment.finish
47
+
48
+ assert_metrics_recorded ["Custom/simple/segment", "Segment/all", "Other/all"]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,121 @@
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 File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
6
+
7
+ require 'new_relic/agent/transaction'
8
+
9
+ module NewRelic
10
+ module Agent
11
+ class Transaction
12
+ class TracingTest < Minitest::Test
13
+ def setup
14
+ freeze_time
15
+ end
16
+
17
+ def teardown
18
+ NewRelic::Agent.drop_buffered_data
19
+ end
20
+
21
+ def test_segment_without_transaction_records_metrics
22
+ segment = Transaction.start_segment "Custom/simple/segment", "Segment/all"
23
+ segment.start
24
+ advance_time 1.0
25
+ segment.finish
26
+
27
+ assert_metrics_recorded ["Custom/simple/segment", "Segment/all"]
28
+ end
29
+
30
+ def test_segment_bound_to_transaction_records_metrics
31
+ in_transaction "test_txn" do
32
+ segment = Transaction.start_segment "Custom/simple/segment", "Segment/all"
33
+ segment.start
34
+ advance_time 1.0
35
+ segment.finish
36
+
37
+ refute_metrics_recorded ["Custom/simple/segment", "Segment/all"]
38
+ end
39
+
40
+ assert_metrics_recorded ["Custom/simple/segment", "Segment/all"]
41
+ end
42
+
43
+ def test_segment_bound_to_transaction_invokes_complete_callback_when_finished
44
+ in_transaction "test_txn" do |txn|
45
+ segment = Transaction.start_segment "Custom/simple/segment", "Segment/all"
46
+ txn.expects(:segment_complete).with(segment)
47
+ segment.start
48
+ advance_time 1.0
49
+ segment.finish
50
+ end
51
+ end
52
+
53
+ def test_segment_data_is_copied_to_trace
54
+ segment = nil
55
+ segment_name = "Custom/simple/segment"
56
+ in_transaction "test_txn" do
57
+ segment = Transaction.start_segment segment_name, "Segment/all"
58
+ segment.start
59
+ advance_time 1.0
60
+ segment.finish
61
+ end
62
+
63
+ trace = last_transaction_trace
64
+ node = find_node_with_name(trace, segment_name)
65
+
66
+ refute_nil node, "Expected trace to have node with name: #{segment_name}"
67
+ assert_equal segment.duration, node.duration
68
+ end
69
+
70
+ def test_start_segment
71
+ in_transaction "test_txn" do |txn|
72
+ segment = Transaction.start_segment "Custom/segment/method"
73
+ assert_equal Time.now, segment.start_time
74
+ assert_equal txn, segment.transaction
75
+
76
+ advance_time 1
77
+ segment.finish
78
+ assert_equal Time.now, segment.end_time
79
+ end
80
+ end
81
+
82
+ def test_start_datastore_segment
83
+ in_transaction "test_txn" do |txn|
84
+ segment = Transaction.start_datastore_segment "SQLite", "insert", "Blog"
85
+ assert_equal Time.now, segment.start_time
86
+ assert_equal txn, segment.transaction
87
+
88
+ advance_time 1
89
+ segment.finish
90
+ assert_equal Time.now, segment.end_time
91
+ end
92
+ end
93
+
94
+ def test_start_segment_with_tracing_disabled_in_transaction
95
+ segment = nil
96
+ in_transaction "test_txn" do |txn|
97
+ NewRelic::Agent.disable_all_tracing do
98
+ segment = Transaction.start_segment "Custom/segment/method", "Custom/all"
99
+ advance_time 1
100
+ segment.finish
101
+ end
102
+ end
103
+ assert_nil segment.transaction, "Did not expect segment to associated with a transaction"
104
+ refute_metrics_recorded ["Custom/segment/method", "Custom/all"]
105
+ end
106
+
107
+ def test_start_segment_with_tracing_disabled_outside_transaction
108
+ segment = nil
109
+ NewRelic::Agent.disable_all_tracing do
110
+ segment = Transaction.start_segment "Custom/segment/method", "Custom/all"
111
+ advance_time 1
112
+ segment.finish
113
+ end
114
+ assert_nil segment.transaction, "Did not expect segment to associated with a transaction"
115
+ refute_metrics_recorded ["Custom/segment/method", "Custom/all"]
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
@@ -202,6 +202,19 @@ class NewRelic::Agent::TransactionSamplerTest < Minitest::Test
202
202
  @sampler.notice_sql('some sql', {:config => 'a config'}, 1.0, @state)
203
203
  end
204
204
 
205
+ def test_notice_sql_statment_recording_sql
206
+ @state.record_sql = true
207
+ builder = @sampler.tl_builder
208
+ @sampler.expects(:notice_extra_data).with do |sample_builder, message, duration, key|
209
+ sample_builder == builder &&
210
+ message.sql == 'some sql' &&
211
+ duration == 1.0 &&
212
+ key == :sql
213
+ end
214
+ statement = NewRelic::Agent::Database::Statement.new 'some sql', {:config => 'a config'}
215
+ @sampler.notice_sql_statement(statement, 1.0)
216
+ end
217
+
205
218
  def test_notice_nosql
206
219
  builder = @sampler.tl_builder
207
220
  @sampler.expects(:notice_extra_data).with(builder, 'a key', 1.0, :key)
@@ -173,6 +173,13 @@ class NewRelic::Agent::NoticedErrorTest < Minitest::Test
173
173
  end
174
174
  end
175
175
 
176
+ def test_handles_exception_with_nil_cause
177
+ e = Exception.new('Buffy FOREVER')
178
+ e.stubs(:cause).returns(nil)
179
+ error = NewRelic::NoticedError.new(@path, e, @time)
180
+ assert_equal(error.message.to_s, 'Buffy FOREVER')
181
+ end
182
+
176
183
  def test_handles_exception_with_nil_original_exception
177
184
  e = Exception.new('Buffy FOREVER')
178
185
  e.stubs(:original_exception).returns(nil)
@@ -0,0 +1,59 @@
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
+ class DatastoresPerfTest < Performance::TestCase
6
+ class FauxDB
7
+ def self.query
8
+ "foo"
9
+ end
10
+ end
11
+
12
+ def test_instrumentation_via_trace
13
+ db_class = Class.new do
14
+ def query
15
+ "foo"
16
+ end
17
+ end
18
+
19
+ NewRelic::Agent::Datastores.trace(db_class, "query", "FakeDB")
20
+ db = db_class.new
21
+
22
+ measure do
23
+ in_transaction do
24
+ db.query
25
+ end
26
+ end
27
+ end
28
+
29
+ def test_wrap
30
+ product = "FauxDB".freeze
31
+ operation = "query".freeze
32
+ collection = "collection".freeze
33
+
34
+ measure do
35
+ in_transaction do
36
+ NewRelic::Agent::Datastores.wrap product, operation, collection do
37
+ FauxDB.query
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ SQL = "select * from users".freeze
44
+ METRIC_NAME = "Datastore/statement/MySQL/users/select".freeze
45
+
46
+ def test_notice_sql
47
+ measure do
48
+ NewRelic::Agent::Datastores.notice_sql(SQL, METRIC_NAME, 3.0)
49
+ end
50
+ end
51
+
52
+ def test_segment_notice_sql
53
+ segment = NewRelic::Agent::Transaction::DatastoreSegment.new "MySQL", "select", "users"
54
+ conf = {:adapter => :mysql}
55
+ measure do
56
+ segment._notice_sql SQL, conf
57
+ end
58
+ end
59
+ end