newrelic_rpm 3.13.0.299 → 3.13.1.300

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -0
  3. data/CHANGELOG +36 -1
  4. data/lib/new_relic/agent/agent.rb +0 -1
  5. data/lib/new_relic/agent/database.rb +1 -1
  6. data/lib/new_relic/agent/datastores/mongo.rb +8 -7
  7. data/lib/new_relic/agent/datastores/mongo/event_formatter.rb +49 -0
  8. data/lib/new_relic/agent/datastores/mongo/obfuscator.rb +2 -2
  9. data/lib/new_relic/agent/error_collector.rb +12 -51
  10. data/lib/new_relic/agent/error_trace_aggregator.rb +89 -0
  11. data/lib/new_relic/agent/instrumentation/active_record.rb +1 -1
  12. data/lib/new_relic/agent/instrumentation/active_record_4.rb +1 -1
  13. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +26 -1
  14. data/lib/new_relic/agent/instrumentation/mongo.rb +16 -1
  15. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +74 -0
  16. data/lib/new_relic/agent/supported_versions.rb +15 -1
  17. data/lib/new_relic/agent/system_info.rb +5 -0
  18. data/lib/new_relic/recipes/capistrano3.rb +1 -1
  19. data/lib/new_relic/recipes/capistrano_legacy.rb +1 -1
  20. data/lib/new_relic/version.rb +1 -1
  21. data/newrelic_rpm.gemspec +1 -1
  22. data/test/environments/lib/environments/runner.rb +1 -0
  23. data/test/fixtures/cross_agent_tests/proc_cpuinfo/README.md +4 -0
  24. data/test/fixtures/cross_agent_tests/proc_cpuinfo/malformed_file.txt +3 -0
  25. data/test/multiverse/lib/multiverse/suite.rb +4 -4
  26. data/test/multiverse/suites/active_record/active_record_test.rb +67 -26
  27. data/test/multiverse/suites/agent_only/start_up_test.rb +17 -3
  28. data/test/multiverse/suites/config_file_loading/Envfile +1 -1
  29. data/test/multiverse/suites/mongo/Envfile +3 -1
  30. data/test/multiverse/suites/mongo/mongo2_instrumentation_test.rb +344 -0
  31. data/test/multiverse/suites/mongo/mongo_connection_test.rb +2 -1
  32. data/test/multiverse/suites/mongo/mongo_instrumentation_test.rb +2 -1
  33. data/test/multiverse/suites/mongo/mongo_unsupported_version_test.rb +1 -1
  34. data/test/multiverse/suites/rails/rails3_app/app_rails3_plus.rb +7 -0
  35. data/test/multiverse/suites/sidekiq/Envfile +1 -1
  36. data/test/new_relic/agent/agent/start_test.rb +0 -5
  37. data/test/new_relic/agent/database_test.rb +8 -1
  38. data/test/new_relic/agent/datastores/mongo/event_formatter_test.rb +154 -0
  39. data/test/new_relic/agent/error_collector_test.rb +0 -13
  40. data/test/new_relic/agent/error_trace_aggregator_test.rb +30 -0
  41. data/test/new_relic/agent/instrumentation/mongodb_command_subscriber_test.rb +72 -0
  42. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +24 -22
  43. data/test/new_relic/agent/system_info_test.rb +9 -1
  44. data/test/new_relic/rack/error_collector_test.rb +1 -2
  45. metadata +10 -2
@@ -11,12 +11,27 @@ DependencyDetection.defer do
11
11
 
12
12
  depends_on do
13
13
  require 'new_relic/agent/datastores/mongo'
14
+ if NewRelic::Agent::Datastores::Mongo.is_unsupported_2x?
15
+ NewRelic::Agent.logger.log_once(:info, :mongo2, 'Detected unsupported Mongo 2, upgrade your Mongo Driver to 2.1 or newer for instrumentation')
16
+ end
14
17
  NewRelic::Agent::Datastores::Mongo.is_supported_version?
15
18
  end
16
19
 
17
20
  executes do
18
21
  NewRelic::Agent.logger.info 'Installing Mongo instrumentation'
19
- install_mongo_instrumentation
22
+ if NewRelic::Agent::Datastores::Mongo.is_monitoring_enabled?
23
+ install_mongo_command_subscriber
24
+ else
25
+ install_mongo_instrumentation
26
+ end
27
+ end
28
+
29
+ def install_mongo_command_subscriber
30
+ require 'new_relic/agent/instrumentation/mongodb_command_subscriber'
31
+ Mongo::Monitoring::Global.subscribe(
32
+ Mongo::Monitoring::COMMAND,
33
+ NewRelic::Agent::Instrumentation::MongodbCommandSubscriber.new
34
+ )
20
35
  end
21
36
 
22
37
  def install_mongo_instrumentation
@@ -0,0 +1,74 @@
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
+ require 'new_relic/agent/datastores/mongo/event_formatter'
5
+
6
+ module NewRelic
7
+ module Agent
8
+ module Instrumentation
9
+ class MongodbCommandSubscriber
10
+
11
+ MONGODB = 'MongoDB'.freeze
12
+
13
+ def started(event)
14
+ begin
15
+ return unless NewRelic::Agent.tl_is_execution_traced?
16
+ operations[event.operation_id] = event
17
+ rescue Exception => e
18
+ log_notification_error('started', e)
19
+ end
20
+ end
21
+
22
+ def completed(event)
23
+ begin
24
+ state = NewRelic::Agent::TransactionState.tl_get
25
+ return unless state.is_execution_traced?
26
+ started_event = operations.delete(event.operation_id)
27
+
28
+ base, *other_metrics = metrics(started_event)
29
+
30
+ NewRelic::Agent.instance.stats_engine.tl_record_scoped_and_unscoped_metrics(
31
+ base, other_metrics, event.duration
32
+ )
33
+
34
+ NewRelic::Agent.instance.transaction_sampler.notice_nosql_statement(
35
+ generate_statement(started_event), event.duration
36
+ )
37
+ rescue Exception => e
38
+ log_notification_error('completed', e)
39
+ end
40
+ end
41
+
42
+ alias :succeeded :completed
43
+ alias :failed :completed
44
+
45
+ private
46
+
47
+ def collection(event)
48
+ event.command.values.first
49
+ end
50
+
51
+ def metrics(event)
52
+ NewRelic::Agent::Datastores::MetricHelper.metrics_for(MONGODB, event.command_name, collection(event))
53
+ end
54
+
55
+ def log_notification_error(event_type, error)
56
+ NewRelic::Agent.logger.error("Error during MongoDB #{event_type} event:")
57
+ NewRelic::Agent.logger.log_exception(:error, error)
58
+ end
59
+
60
+ def operations
61
+ @operations ||= {}
62
+ end
63
+
64
+ def generate_statement(event)
65
+ NewRelic::Agent::Datastores::Mongo::EventFormatter.format(
66
+ event.command_name,
67
+ event.database_name,
68
+ event.command
69
+ )
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -148,12 +148,26 @@ module NewRelic
148
148
  :mongo =>
149
149
  {
150
150
  :type => :database,
151
- :supported => [">= 1.8.0", "< 2.0.0"],
151
+ :supported => ["~>1.8", "~>2.1"],
152
152
  :url => "https://rubygems.org/gems/mongo",
153
153
  :feed => "https://rubygems.org/gems/mongo/versions.atom"
154
154
  },
155
+ :redis =>
156
+ {
157
+ :type => :database,
158
+ :supported => ["~> 3.0"],
159
+ :url => "https://rubygems.org/gems/redis",
160
+ :feed => "https://rubygems.org/gems/redis/versions.atom"
161
+ },
155
162
 
156
163
  # Background Jobs
164
+ :rake =>
165
+ {
166
+ :type => :background,
167
+ :supported => ["~> 10.0"],
168
+ :url => "https://rubygems.org/gems/rake",
169
+ :feed => "https://rubygems.org/gems/rake/versions.atom"
170
+ },
157
171
  :resque =>
158
172
  {
159
173
  :type => :background,
@@ -113,6 +113,11 @@ module NewRelic
113
113
  if num_physical_cores == 0
114
114
  num_logical_processors = total_processors
115
115
 
116
+ if total_processors == 0
117
+ # Likely a malformed file.
118
+ num_logical_processors = nil
119
+ end
120
+
116
121
  if total_processors == 1
117
122
  # Some older, single-core processors might not list ids,
118
123
  # so we'll just mark them all 1.
@@ -58,7 +58,7 @@ namespace :newrelic do
58
58
  current_revision = fetch(:current_revision)
59
59
 
60
60
  if scm == :git
61
- log_command = "git log --no-color --pretty=format:' * %an: %s' " +
61
+ log_command = "git --no-pager log --no-color --pretty=format:' * %an: %s' " +
62
62
  "--abbrev-commit --no-merges #{previous_revision}..#{current_revision}"
63
63
  `#{log_command}`
64
64
  end
@@ -58,7 +58,7 @@ make_notify_task = Proc.new do
58
58
  from_revision = source.next_revision(current_revision)
59
59
 
60
60
  if scm == :git
61
- log_command = "git log --no-color --pretty=format:' * %an: %s' " +
61
+ log_command = "git --no-pager log --no-color --pretty=format:' * %an: %s' " +
62
62
  "--abbrev-commit --no-merges #{previous_revision}..#{real_revision}"
63
63
  else
64
64
  log_command = "#{source.log(from_revision)}"
@@ -12,7 +12,7 @@ module NewRelic
12
12
 
13
13
  MAJOR = 3
14
14
  MINOR = 13
15
- TINY = 0
15
+ TINY = 1
16
16
 
17
17
  begin
18
18
  require File.join(File.dirname(__FILE__), 'build')
@@ -61,7 +61,7 @@ EOS
61
61
 
62
62
  if RUBY_PLATFORM == 'java'
63
63
  s.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
64
- s.add_development_dependency 'jruby-openssl'
64
+ s.add_development_dependency 'jruby-openssl', '~> 0.9.10' unless JRUBY_VERSION > '1.7'
65
65
  else
66
66
  s.add_development_dependency 'sqlite3'
67
67
  end
@@ -18,6 +18,7 @@ module Environments
18
18
  "ree" => ["rails40", "rails41", "rails42"],
19
19
  "jruby-1.6" => ["rails40", "rails41", "rails42"],
20
20
  "jruby-1.7" => ["rails21", "rails22", "rails23"],
21
+ "jruby-9.0" => ["rails21", "rails22", "rails23", "rails30", "rails31", "rails32"],
21
22
  "rbx-2.0" => ["rails21", "rails22", "rails23", "rails30", "rails31", "rails32"],
22
23
  }
23
24
 
@@ -22,3 +22,7 @@ should produce the following expected values:
22
22
  If any of `A`, `B`, or `C` are the character `X` instead of an integer, then
23
23
  processing code should not return a value (return `null`, return `nil`,
24
24
  raise an exception... whatever makes most sense for your agent).
25
+
26
+ There is a malformed.txt file which is a random file that does not adhere to
27
+ any /proc/cpuinfo format. The expected result is `null` for packages, cores and
28
+ processors.
@@ -0,0 +1,3 @@
1
+ This is a random text file that does NOT adhere to the /proc/cpuinfo format.
2
+ xxxYYYZZz
3
+
@@ -172,7 +172,7 @@ module Multiverse
172
172
  f.puts ' source "https://rubygems.org"' unless local
173
173
  f.print gemfile_text
174
174
  f.puts newrelic_gemfile_line unless gemfile_text =~ /^\s*gem .newrelic_rpm./
175
- f.puts jruby_openssl_line unless gemfile_text =~ /^\s*gem .jruby-openssl./
175
+ f.puts jruby_openssl_line unless gemfile_text =~ /^\s*gem .jruby-openssl./ || (defined?(JRUBY_VERSION) && JRUBY_VERSION > '1.7')
176
176
  f.puts minitest_line unless gemfile_text =~ /^\s*gem .minitest[^_]./
177
177
 
178
178
  rbx_gemfile_lines(f, gemfile_text)
@@ -184,8 +184,8 @@ module Multiverse
184
184
 
185
185
  # Pry 0.10.0 breaks compatibility with Ruby 1.8.7 :(
186
186
  f.puts " gem 'pry', '~> #{pry_version}'"
187
- f.puts " gem 'pry-byebug'" if RUBY_VERSION >= "2.0.0"
188
- f.puts " gem 'pry-stack_explorer'"
187
+ f.puts " gem 'pry-byebug'" if RUBY_VERSION >= "2.0.0" && RUBY_ENGINE == "ruby"
188
+ f.puts " gem 'pry-stack_explorer'" if RUBY_ENGINE == "ruby"
189
189
  end
190
190
  end
191
191
  puts yellow("Gemfile.#{env_index} set to:") if verbose?
@@ -212,7 +212,7 @@ module Multiverse
212
212
  end
213
213
 
214
214
  def jruby_openssl_line
215
- "gem 'jruby-openssl', :require => false, :platforms => [:jruby]"
215
+ "gem 'jruby-openssl', '~> 0.9.10', :require => false, :platforms => [:jruby]"
216
216
  end
217
217
 
218
218
  def minitest_line
@@ -9,11 +9,76 @@ class ActiveRecordInstrumentationTest < Minitest::Test
9
9
  include MultiverseHelpers
10
10
  setup_and_teardown_agent
11
11
 
12
+ module VersionHelpers
13
+ def active_record_major_version
14
+ if defined?(::ActiveRecord::VERSION::MAJOR)
15
+ ::ActiveRecord::VERSION::MAJOR.to_i
16
+ else
17
+ 2
18
+ end
19
+ end
20
+
21
+ def active_record_minor_version
22
+ if defined?(::ActiveRecord::VERSION::MINOR)
23
+ ::ActiveRecord::VERSION::MINOR.to_i
24
+ else
25
+ 1
26
+ end
27
+ end
28
+
29
+ def active_record_version
30
+ if defined?(::ActiveRecord::VERSION::MINOR)
31
+ NewRelic::VersionNumber.new(::ActiveRecord::VERSION::STRING)
32
+ else
33
+ NewRelic::VersionNumber.new("2.1.0") # Can't tell between 2.1 and 2.2. Meh.
34
+ end
35
+ end
36
+ end
37
+
38
+ include VersionHelpers
39
+ extend VersionHelpers
40
+
12
41
  def after_setup
13
42
  super
14
43
  NewRelic::Agent.drop_buffered_data
15
44
  end
16
45
 
46
+ def test_metrics_for_calculation_methods
47
+ in_web_transaction do
48
+ Order.count
49
+ Order.average(:id)
50
+ Order.minimum(:id)
51
+ Order.maximum(:id)
52
+ Order.sum(:id)
53
+ end
54
+
55
+ if active_record_major_version >= 3
56
+ assert_activerecord_metrics(Order, 'select', :call_count => 5)
57
+ else
58
+ assert_generic_rollup_metrics('select')
59
+ end
60
+ end
61
+
62
+ if active_record_version >= NewRelic::VersionNumber.new('3.2.0')
63
+ def test_metrics_for_pluck
64
+ in_web_transaction do
65
+ Order.pluck(:id)
66
+ end
67
+
68
+ assert_activerecord_metrics(Order, 'select')
69
+ end
70
+ end
71
+
72
+ if active_record_version >= NewRelic::VersionNumber.new('4.0.0')
73
+ def test_metrics_for_ids
74
+ in_web_transaction do
75
+ Order.ids
76
+ end
77
+
78
+ assert_activerecord_metrics(Order, 'select')
79
+ end
80
+ end
81
+
17
82
  def test_metrics_for_create
18
83
  in_web_transaction do
19
84
  Order.create(:name => 'bob')
@@ -157,7 +222,7 @@ class ActiveRecordInstrumentationTest < Minitest::Test
157
222
  end
158
223
 
159
224
  # delete and touch did not exist in AR 2.2
160
- if defined?(::ActiveRecord::VERSION) && ::ActiveRecord::VERSION::MAJOR >= 3
225
+ if active_record_version >= NewRelic::VersionNumber.new('3.0.0')
161
226
  def test_metrics_for_delete
162
227
  in_web_transaction do
163
228
  order = Order.create("name" => "burt")
@@ -256,7 +321,7 @@ class ActiveRecordInstrumentationTest < Minitest::Test
256
321
  end
257
322
 
258
323
  # update & update! didn't become public until 4.0
259
- if defined?(::ActiveRecord::VERSION) && ::ActiveRecord::VERSION::MAJOR >= 4
324
+ if active_record_version >= NewRelic::VersionNumber.new('4.0.0')
260
325
  def test_metrics_for_update
261
326
  in_web_transaction do
262
327
  order = Order.create(:name => "wendy")
@@ -525,30 +590,6 @@ class ActiveRecordInstrumentationTest < Minitest::Test
525
590
  NewRelic::Agent::Instrumentation::ActiveRecordHelper::PRODUCT_NAMES[adapter.to_s]
526
591
  end
527
592
 
528
- def active_record_major_version
529
- if defined?(::ActiveRecord::VERSION::MAJOR)
530
- ::ActiveRecord::VERSION::MAJOR.to_i
531
- else
532
- 2
533
- end
534
- end
535
-
536
- def active_record_minor_version
537
- if defined?(::ActiveRecord::VERSION::MINOR)
538
- ::ActiveRecord::VERSION::MINOR.to_i
539
- else
540
- 1
541
- end
542
- end
543
-
544
- def active_record_version
545
- if defined?(::ActiveRecord::VERSION::MINOR)
546
- NewRelic::VersionNumber.new(::ActiveRecord::VERSION::STRING)
547
- else
548
- NewRelic::VersionNumber.new("2.1.0") # Can't tell between 2.1 and 2.2. Meh.
549
- end
550
- end
551
-
552
593
  def assert_activerecord_metrics(model, operation, stats={})
553
594
  assert_metrics_recorded({
554
595
  "Datastore/statement/#{current_product}/#{model}/#{operation}" => stats,
@@ -7,6 +7,10 @@ require 'open3'
7
7
 
8
8
  class StartUpTest < Minitest::Test
9
9
  GIT_NOISE = "fatal: Not a git repository (or any of the parent directories): .git\n"
10
+ JRUBY_9000_NOISE = [
11
+ /uri\:classloader\:\/jruby\/kernel\/kernel\.rb\:\d*\: warning: unsupported exec option: close_others/, # https://github.com/jruby/jruby/issues/1913
12
+ /.*\/lib\/ruby\/stdlib\/jar_dependencies.rb:\d*: warning: shadowing outer local variable - (group_id|artifact_id)/, #https://github.com/mkristian/jar-dependencies/commit/65c71261b1522f7b10fcb95de42ea4799de3a83a
13
+ ]
10
14
 
11
15
  include MultiverseHelpers
12
16
 
@@ -25,7 +29,9 @@ class StartUpTest < Minitest::Test
25
29
  GIT_NOISE,
26
30
  /Exception\: java\.lang.*\n/]
27
31
 
28
- expected_noise.each {|noise| output.gsub!(noise, "")}
32
+ expected_noise << JRUBY_9000_NOISE if jruby_9000
33
+
34
+ expected_noise.flatten.each {|noise| output.gsub!(noise, "")}
29
35
 
30
36
  assert_equal '', output.chomp
31
37
  end
@@ -64,8 +70,12 @@ class StartUpTest < Minitest::Test
64
70
  'NEW_RELIC_PORT' => $collector.port.to_s) do
65
71
 
66
72
  output = `bundle exec ruby -w script/warnings.rb 2>&1`
67
- output.gsub!(GIT_NOISE, "")
68
- output.chomp!
73
+ expected_noise = [GIT_NOISE]
74
+
75
+ expected_noise << JRUBY_9000_NOISE if jruby_9000
76
+
77
+ expected_noise.flatten.each {|noise| output.gsub!(noise, "")}
78
+ output.strip!
69
79
 
70
80
  assert_equal NewRelic::VERSION::STRING, output
71
81
  end
@@ -79,4 +89,8 @@ class StartUpTest < Minitest::Test
79
89
  problems = output.scan(/ERROR : .*/)
80
90
  assert_empty problems
81
91
  end
92
+
93
+ def jruby_9000
94
+ defined?(JRUBY_VERSION) && NewRelic::VersionNumber.new(JRUBY_VERSION) >= "9.0.0"
95
+ end
82
96
  end
@@ -6,7 +6,7 @@ gemfile <<-RB
6
6
  gem 'fakefs', :require => 'fakefs/safe'
7
7
 
8
8
  # Because we delay the agent, order of jruby-openssl matters
9
- gem 'jruby-openssl', :platforms => [:jruby]
9
+ gem 'jruby-openssl', '~> 0.9.10', :platforms => [:jruby]
10
10
 
11
11
  # don't start the agent
12
12
  gem 'newrelic_rpm', :require => false, :path => File.expand_path('../../../../')
@@ -1,7 +1,9 @@
1
1
  if RUBY_VERSION >= '1.9.3'
2
+ gemfile <<-RB
3
+ gem 'mongo', '~>2.1.0'
4
+ RB
2
5
  gemfile <<-RB
3
6
  gem 'mongo', '~>2.0.1'
4
- gem 'bson_ext', :platforms => :ruby
5
7
  RB
6
8
  end
7
9
 
@@ -0,0 +1,344 @@
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 'mongo'
6
+ require 'newrelic_rpm'
7
+ require 'new_relic/agent/datastores/mongo'
8
+ require 'helpers/mongo_metric_builder'
9
+
10
+ if NewRelic::Agent::Datastores::Mongo.is_supported_version? &&
11
+ NewRelic::Agent::Datastores::Mongo.is_monitoring_enabled?
12
+ module NewRelic
13
+ module Agent
14
+ module Instrumentation
15
+ class Mongo2InstrumentationTest < Minitest::Test
16
+ include Mongo
17
+ include TestHelpers::MongoMetricBuilder
18
+
19
+ def setup
20
+ @database_name = "multiverse"
21
+ @client = Mongo::Client.new(["#{$mongo.host}:#{$mongo.port}"], :database => @database_name)
22
+ @database = @client.database
23
+
24
+ @collection_name = "tribbles-#{SecureRandom.hex(16)}"
25
+ @collection = @database.collection(@collection_name)
26
+
27
+ @tribbles = [{'name' => 'soterios johnson'}, {'name' => 'wes mantooth'}]
28
+
29
+ NewRelic::Agent::Transaction.stubs(:recording_web_transaction?).returns(true)
30
+ NewRelic::Agent.drop_buffered_data
31
+ end
32
+
33
+ def teardown
34
+ NewRelic::Agent.drop_buffered_data
35
+ @collection.drop
36
+ end
37
+
38
+ def test_records_metrics_for_insert_one
39
+ @collection.insert_one(@tribbles.first)
40
+
41
+ metrics = build_test_metrics(:insert)
42
+ expected = metrics_with_attributes(metrics)
43
+
44
+ assert_metrics_recorded(expected)
45
+ end
46
+
47
+ def test_records_metrics_for_insert_many
48
+ @collection.insert_many(@tribbles)
49
+
50
+ metrics = build_test_metrics(:insert)
51
+ expected = metrics_with_attributes(metrics)
52
+
53
+ assert_metrics_recorded(expected)
54
+ end
55
+
56
+ def test_records_metrics_for_delete_one
57
+ @collection.insert_one(@tribbles.first)
58
+ NewRelic::Agent.drop_buffered_data
59
+
60
+ @collection.delete_one(@tribbles.first)
61
+
62
+ metrics = build_test_metrics(:delete)
63
+ expected = metrics_with_attributes(metrics)
64
+
65
+ assert_metrics_recorded(expected)
66
+ end
67
+
68
+ def test_records_metrics_for_delete_many
69
+ @collection.insert_one(@tribbles.first)
70
+ NewRelic::Agent.drop_buffered_data
71
+
72
+ @collection.delete_many(@tribbles.first)
73
+
74
+ metrics = build_test_metrics(:delete)
75
+ expected = metrics_with_attributes(metrics)
76
+
77
+ assert_metrics_recorded(expected)
78
+ end
79
+
80
+ def test_records_metrics_for_replace_one
81
+ @collection.insert_one(@tribbles.first)
82
+ NewRelic::Agent.drop_buffered_data
83
+
84
+ @collection.replace_one(@tribbles[0], @tribbles[1])
85
+
86
+ metrics = build_test_metrics(:update)
87
+ expected = metrics_with_attributes(metrics)
88
+
89
+ assert_metrics_recorded(expected)
90
+ end
91
+
92
+ def test_records_metrics_for_update_one
93
+ @collection.insert_one(@tribbles.first)
94
+ NewRelic::Agent.drop_buffered_data
95
+
96
+ @collection.update_one(@tribbles[0], "$set" => @tribbles[1])
97
+
98
+ metrics = build_test_metrics(:update)
99
+ expected = metrics_with_attributes(metrics)
100
+
101
+ assert_metrics_recorded(expected)
102
+ end
103
+
104
+ def test_records_metrics_for_update_many
105
+ @collection.insert_one(@tribbles.first)
106
+ NewRelic::Agent.drop_buffered_data
107
+
108
+ @collection.update_many(@tribbles[0], "$set" => @tribbles[1])
109
+
110
+ metrics = build_test_metrics(:update)
111
+ expected = metrics_with_attributes(metrics)
112
+
113
+ assert_metrics_recorded(expected)
114
+ end
115
+
116
+ def test_records_metrics_for_find
117
+ @collection.insert_one(@tribbles.first)
118
+ NewRelic::Agent.drop_buffered_data
119
+
120
+ @collection.find(@tribbles.first).to_a
121
+
122
+ metrics = build_test_metrics(:find)
123
+ expected = metrics_with_attributes(metrics)
124
+
125
+ assert_metrics_recorded(expected)
126
+ end
127
+
128
+ def test_records_metrics_for_find_one_and_delete
129
+ @collection.insert_one(@tribbles.first)
130
+ NewRelic::Agent.drop_buffered_data
131
+
132
+ @collection.find_one_and_delete(@tribbles.first)
133
+
134
+ metrics = build_test_metrics(:findandmodify)
135
+ expected = metrics_with_attributes(metrics)
136
+
137
+ assert_metrics_recorded(expected)
138
+ end
139
+
140
+ def test_records_metrics_for_find_one_and_replace
141
+ @collection.insert_one(@tribbles.first)
142
+ NewRelic::Agent.drop_buffered_data
143
+
144
+ @collection.find_one_and_replace(@tribbles[0], @tribbles[1])
145
+
146
+ metrics = build_test_metrics(:findandmodify)
147
+ expected = metrics_with_attributes(metrics)
148
+
149
+ assert_metrics_recorded(expected)
150
+ end
151
+
152
+ def test_records_metrics_for_find_one_and_update
153
+ @collection.insert_one(@tribbles.first)
154
+ NewRelic::Agent.drop_buffered_data
155
+
156
+ @collection.find_one_and_update(@tribbles[0], "$set" => @tribbles[1])
157
+
158
+ metrics = build_test_metrics(:findandmodify)
159
+ expected = metrics_with_attributes(metrics)
160
+
161
+ assert_metrics_recorded(expected)
162
+ end
163
+
164
+ def test_records_metrics_for_distinct
165
+ @collection.distinct('name')
166
+
167
+ metrics = build_test_metrics(:distinct)
168
+ expected = metrics_with_attributes(metrics)
169
+
170
+ assert_metrics_recorded(expected)
171
+ end
172
+
173
+ def test_records_metrics_for_count
174
+ @collection.count
175
+
176
+ metrics = build_test_metrics(:count)
177
+ expected = metrics_with_attributes(metrics)
178
+
179
+ assert_metrics_recorded(expected)
180
+ end
181
+
182
+ def test_drop_collection
183
+ @collection.drop
184
+
185
+ metrics = build_test_metrics(:drop)
186
+ expected = metrics_with_attributes(metrics)
187
+
188
+ assert_metrics_recorded(expected)
189
+ end
190
+
191
+ def test_web_scoped_metrics
192
+ in_web_transaction("webby") do
193
+ @collection.insert_one(@tribbles.first)
194
+ end
195
+
196
+ metric = statement_metric(:insert)
197
+ assert_metrics_recorded([[metric, "webby"]])
198
+ end
199
+
200
+ def statement_metric(action)
201
+ metrics = build_test_metrics(action)
202
+ metrics.select { |m| m.start_with?("Datastore/statement") }.first
203
+ end
204
+
205
+ def test_background_scoped_metrics
206
+ in_background_transaction("backed-up") do
207
+ @collection.insert_one(@tribbles.first)
208
+ end
209
+
210
+ metric = statement_metric(:insert)
211
+ assert_metrics_recorded([[metric, "backed-up"]])
212
+ end
213
+
214
+ def test_notices_nosql
215
+ node = nil
216
+
217
+ in_transaction do
218
+ @collection.insert_one(@tribbles.first)
219
+
220
+ node = find_last_transaction_node
221
+ end
222
+
223
+ expected = {
224
+ :database => @database_name,
225
+ :collection => @collection_name,
226
+ 'insert' => @collection_name,
227
+ :operation => :insert,
228
+ 'writeConcern' => { :w => 1 },
229
+ 'ordered' => true
230
+ }
231
+
232
+ result = node.params[:statement]
233
+
234
+ assert_equal expected, result
235
+ end
236
+
237
+ def test_noticed_nosql_includes_operation
238
+ node = nil
239
+
240
+ in_transaction do
241
+ @collection.insert_one(@tribbles.first)
242
+ node = find_last_transaction_node
243
+ end
244
+
245
+ query = node.params[:statement]
246
+
247
+ assert_equal :insert, query[:operation]
248
+ end
249
+
250
+ def test_noticed_nosql_includes_update_one_operation
251
+ node = nil
252
+
253
+ in_transaction do
254
+ @collection.update_one(@tribbles[0], @tribbles[1])
255
+
256
+ node = find_last_transaction_node
257
+ end
258
+
259
+ query = node.params[:statement]
260
+
261
+ assert_equal :update, query[:operation]
262
+ end
263
+
264
+ def test_noticed_nosql_includes_find_operation
265
+ node = nil
266
+
267
+ in_transaction do
268
+ @collection.insert_one(@tribbles.first)
269
+ @collection.find(@tribbles.first).to_a
270
+ node = find_last_transaction_node
271
+ end
272
+
273
+ query = node.params[:statement]
274
+
275
+ assert_equal 'find', query[:operation]
276
+ end
277
+
278
+ def test_noticed_nosql_does_not_contain_documents
279
+ node = nil
280
+
281
+ in_transaction do
282
+ @collection.insert_one(@tribbles.first)
283
+ node = find_last_transaction_node
284
+ end
285
+
286
+ statement = node.params[:statement]
287
+
288
+ refute statement.keys.include?(:documents), "Noticed NoSQL should not include documents: #{statement}"
289
+ end
290
+
291
+ def test_noticed_nosql_does_not_contain_selector_values
292
+ @collection.insert_one({'password' => '$ecret'})
293
+ node = nil
294
+
295
+ in_transaction do
296
+ @collection.find({'password' => '$ecret'}).to_a
297
+ node = find_last_transaction_node
298
+ end
299
+
300
+ statement = node.params[:statement]
301
+
302
+ refute statement.inspect.include?('$secret')
303
+
304
+ assert_equal '?', statement['filter']['password']
305
+ end
306
+
307
+ def test_web_requests_record_all_web_metric
308
+ NewRelic::Agent::Transaction.stubs(:recording_web_transaction?).returns(true)
309
+ @collection.insert_one(@tribbles.first)
310
+
311
+ metrics = build_test_metrics(:insert)
312
+ expected = metrics_with_attributes(metrics)
313
+
314
+ assert_metrics_recorded(expected)
315
+ end
316
+
317
+ def test_web_requests_do_not_record_all_other_metric
318
+ NewRelic::Agent::Transaction.stubs(:recording_web_transaction?).returns(true)
319
+ @collection.insert_one(@tribbles.first)
320
+
321
+ assert_metrics_not_recorded(['Datastore/allOther'])
322
+ end
323
+
324
+ def test_other_requests_record_all_other_metric
325
+ NewRelic::Agent::Transaction.stubs(:recording_web_transaction?).returns(false)
326
+ @collection.insert_one(@tribbles.first)
327
+
328
+ metrics = build_test_metrics(:insert)
329
+ expected = metrics_with_attributes(metrics)
330
+
331
+ assert_metrics_recorded(expected)
332
+ end
333
+
334
+ def test_other_requests_do_not_record_all_web_metric
335
+ NewRelic::Agent::Transaction.stubs(:recording_web_transaction?).returns(false)
336
+ @collection.insert_one(@tribbles.first)
337
+
338
+ assert_metrics_not_recorded(['Datastore/allWeb'])
339
+ end
340
+ end
341
+ end
342
+ end
343
+ end
344
+ end