newrelic_rpm 3.12.0.288 → 3.12.1.298

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +42 -0
  3. data/Rakefile +5 -5
  4. data/lib/new_relic/agent.rb +23 -11
  5. data/lib/new_relic/agent/agent.rb +17 -67
  6. data/lib/new_relic/agent/agent_logger.rb +9 -33
  7. data/lib/new_relic/agent/attribute_processing.rb +2 -2
  8. data/lib/new_relic/agent/autostart.rb +1 -18
  9. data/lib/new_relic/agent/aws_info.rb +90 -0
  10. data/lib/new_relic/agent/configuration/default_source.rb +45 -16
  11. data/lib/new_relic/agent/configuration/dotted_hash.rb +0 -2
  12. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -1
  13. data/lib/new_relic/agent/configuration/manager.rb +1 -31
  14. data/lib/new_relic/agent/configuration/server_source.rb +0 -1
  15. data/lib/new_relic/agent/configuration/yaml_source.rb +26 -7
  16. data/lib/new_relic/agent/database.rb +5 -5
  17. data/lib/new_relic/agent/database/postgres_explain_obfuscator.rb +0 -1
  18. data/lib/new_relic/agent/datastores/metric_helper.rb +15 -3
  19. data/lib/new_relic/agent/error_collector.rb +28 -18
  20. data/lib/new_relic/agent/instrumentation/active_record.rb +8 -2
  21. data/lib/new_relic/agent/instrumentation/active_record_4.rb +1 -0
  22. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +49 -1
  23. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +2 -2
  24. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +9 -0
  25. data/lib/new_relic/agent/instrumentation/grape.rb +1 -1
  26. data/lib/new_relic/agent/instrumentation/resque.rb +8 -20
  27. data/lib/new_relic/agent/instrumentation/sequel.rb +0 -2
  28. data/lib/new_relic/agent/instrumentation/sidekiq.rb +6 -0
  29. data/lib/new_relic/agent/log_once.rb +39 -0
  30. data/lib/new_relic/agent/memory_logger.rb +8 -1
  31. data/lib/new_relic/agent/method_tracer.rb +5 -1
  32. data/lib/new_relic/agent/new_relic_service.rb +13 -14
  33. data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -0
  34. data/lib/new_relic/agent/samplers/memory_sampler.rb +6 -3
  35. data/lib/new_relic/agent/sql_sampler.rb +4 -15
  36. data/lib/new_relic/agent/stats_engine/metric_stats.rb +1 -1
  37. data/lib/new_relic/agent/stats_engine/samplers.rb +0 -6
  38. data/lib/new_relic/agent/stats_engine/stats_hash.rb +92 -35
  39. data/lib/new_relic/agent/system_info.rb +53 -6
  40. data/lib/new_relic/agent/transaction.rb +4 -13
  41. data/lib/new_relic/agent/transaction/attributes.rb +2 -0
  42. data/lib/new_relic/agent/transaction/trace_node.rb +1 -1
  43. data/lib/new_relic/agent/transaction_event_aggregator.rb +1 -9
  44. data/lib/new_relic/agent/transaction_sample_builder.rb +0 -6
  45. data/lib/new_relic/agent/transaction_sampler.rb +1 -13
  46. data/lib/new_relic/agent/utilization_data.rb +29 -42
  47. data/lib/new_relic/agent/worker_loop.rb +2 -3
  48. data/lib/new_relic/cli/commands/deployments.rb +5 -0
  49. data/lib/new_relic/coerce.rb +1 -1
  50. data/lib/new_relic/collection_helper.rb +0 -2
  51. data/lib/new_relic/control/instance_methods.rb +4 -1
  52. data/lib/new_relic/control/instrumentation.rb +1 -9
  53. data/lib/new_relic/control/server_methods.rb +3 -56
  54. data/lib/new_relic/helper.rb +1 -0
  55. data/lib/new_relic/language_support.rb +21 -0
  56. data/lib/new_relic/local_environment.rb +1 -0
  57. data/lib/new_relic/metric_data.rb +1 -1
  58. data/lib/new_relic/noticed_error.rb +1 -1
  59. data/lib/new_relic/rack/agent_middleware.rb +9 -0
  60. data/lib/new_relic/version.rb +1 -1
  61. data/lib/sequel/extensions/newrelic_instrumentation.rb +2 -2
  62. data/lib/tasks/multiverse.rake +2 -0
  63. data/lib/tasks/multiverse.rb +50 -0
  64. data/test/agent_helper.rb +24 -5
  65. data/test/fixtures/cross_agent_tests/aws.json +218 -0
  66. data/test/fixtures/cross_agent_tests/docker_container_id/cases.json +40 -11
  67. data/test/fixtures/cross_agent_tests/docker_container_id/invalid-characters.txt +9 -0
  68. data/test/fixtures/cross_agent_tests/docker_container_id/invalid-length.txt +9 -0
  69. data/test/multiverse/lib/multiverse/suite.rb +3 -0
  70. data/test/multiverse/suites/active_record/Envfile +18 -12
  71. data/test/multiverse/suites/active_record/active_record_test.rb +203 -9
  72. data/test/multiverse/suites/active_record/app/models/models.rb +16 -9
  73. data/test/multiverse/suites/active_record/config/database.rb +3 -2
  74. data/test/multiverse/suites/active_record/db/migrate/20150413011200_add_timestamps_to_orders.rb +16 -0
  75. data/test/multiverse/suites/active_record/db/migrate/20150414084400_create_groups.rb +21 -0
  76. data/test/multiverse/suites/agent_only/agent_attributes_test.rb +26 -3
  77. data/test/multiverse/suites/agent_only/config/newrelic.yml +1 -1
  78. data/test/multiverse/suites/agent_only/script/public_api_when_disabled.rb +68 -0
  79. data/test/multiverse/suites/agent_only/service_timeout_test.rb +1 -1
  80. data/test/multiverse/suites/agent_only/ssl_test.rb +2 -1
  81. data/test/multiverse/suites/agent_only/start_up_test.rb +20 -1
  82. data/test/multiverse/suites/agent_only/utilization_data_collection_test.rb +43 -104
  83. data/test/multiverse/suites/bare/standalone_instrumentation_test.rb +2 -2
  84. data/test/multiverse/suites/high_security/high_security_test.rb +2 -2
  85. data/test/multiverse/suites/rack/http_response_code_test.rb +4 -4
  86. data/test/multiverse/suites/rails/error_tracing_test.rb +1 -1
  87. data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +38 -0
  88. data/test/multiverse/suites/sidekiq/test_worker.rb +13 -1
  89. data/test/new_relic/agent/agent_test.rb +0 -70
  90. data/test/new_relic/agent/attribute_processing_test.rb +10 -5
  91. data/test/new_relic/agent/autostart_test.rb +0 -31
  92. data/test/new_relic/agent/aws_info_test.rb +61 -0
  93. data/test/new_relic/agent/configuration/manager_test.rb +1 -1
  94. data/test/new_relic/agent/configuration/yaml_source_test.rb +25 -1
  95. data/test/new_relic/agent/database_test.rb +16 -15
  96. data/test/new_relic/agent/datastores/metric_helper_test.rb +35 -0
  97. data/test/new_relic/agent/error_collector_test.rb +28 -5
  98. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +23 -20
  99. data/test/new_relic/agent/memory_logger_test.rb +18 -0
  100. data/test/new_relic/agent/new_relic_service_test.rb +2 -9
  101. data/test/new_relic/agent/rpm_agent_test.rb +0 -10
  102. data/test/new_relic/agent/sql_sampler_test.rb +4 -4
  103. data/test/new_relic/agent/stats_engine/stats_hash_test.rb +18 -22
  104. data/test/new_relic/agent/system_info_test.rb +81 -23
  105. data/test/new_relic/agent/transaction_event_aggregator_test.rb +0 -7
  106. data/test/new_relic/agent/transaction_test.rb +1 -1
  107. data/test/new_relic/agent/utilization_data_test.rb +135 -6
  108. data/test/new_relic/cli/commands/deployments_test.rb +12 -2
  109. data/test/new_relic/control/instrumentation_test.rb +0 -15
  110. data/test/new_relic/control_test.rb +0 -63
  111. data/test/new_relic/fake_collector.rb +4 -17
  112. data/test/new_relic/language_support_test.rb +30 -0
  113. data/test/new_relic/license_test.rb +2 -0
  114. data/test/new_relic/multiverse_helpers.rb +12 -0
  115. data/test/performance/suites/stats_hash.rb +6 -5
  116. data/test/test_helper.rb +1 -2
  117. metadata +13 -4
  118. data/lib/new_relic/agent/shim_agent.rb +0 -33
  119. data/test/new_relic/agent/shim_agent_test.rb +0 -20
@@ -13,6 +13,7 @@ module NewRelic
13
13
  named :cpu
14
14
 
15
15
  def initialize
16
+ @last_time = nil
16
17
  @processor_count = NewRelic::Agent::SystemInfo.num_logical_processors
17
18
  if @processor_count.nil?
18
19
  NewRelic::Agent.logger.warn("Failed to determine processor count, assuming 1")
@@ -62,6 +62,10 @@ module NewRelic
62
62
  end
63
63
 
64
64
  class Base
65
+ def initialize
66
+ @broken = false
67
+ end
68
+
65
69
  def can_run?
66
70
  return false if @broken
67
71
  m = get_memory rescue nil
@@ -86,11 +90,11 @@ module NewRelic
86
90
  end
87
91
 
88
92
  class JavaHeapSampler < Base
89
-
90
93
  def get_memory
91
94
  raise "Can't sample Java heap unless running in JRuby" unless defined? JRuby
92
95
  java.lang.Runtime.getRuntime.totalMemory / (1024 * 1024).to_f rescue nil
93
96
  end
97
+
94
98
  def to_s
95
99
  "JRuby Java heap sampler"
96
100
  end
@@ -101,6 +105,7 @@ module NewRelic
101
105
  super()
102
106
  @command = command
103
107
  end
108
+
104
109
  # Returns the amount of resident memory this process is using in MB
105
110
  #
106
111
  def get_memory
@@ -121,9 +126,7 @@ module NewRelic
121
126
  # A class that samples memory by reading the file /proc/$$/status, which is specific to linux
122
127
  #
123
128
  class ProcStatus < Base
124
-
125
129
  # Returns the amount of resident memory this process is using in MB
126
- #
127
130
  def get_memory
128
131
  proc_status = File.open(proc_status_file, "r") {|f| f.read_nonblock(4096).strip }
129
132
  if proc_status =~ /RSS:\s*(\d+) kB/i
@@ -6,9 +6,6 @@ require 'zlib'
6
6
  require 'base64'
7
7
  require 'digest/md5'
8
8
 
9
- require 'new_relic/agent'
10
- require 'new_relic/control'
11
-
12
9
  module NewRelic
13
10
  module Agent
14
11
  # This class contains the logic of recording slow SQL traces, which may
@@ -27,13 +24,6 @@ module NewRelic
27
24
  #
28
25
  # @api public
29
26
  class SqlSampler
30
-
31
- # Module defining methods stubbed out when the agent is disabled
32
- module Shim
33
- def on_start_transaction(*args); end
34
- def on_finishing_transaction(*args); end
35
- end
36
-
37
27
  attr_reader :disabled
38
28
 
39
29
  # this is for unit tests only
@@ -150,7 +140,7 @@ module NewRelic
150
140
  # @api public
151
141
  # @deprecated Use {Datastores.notice_sql} instead.
152
142
  #
153
- def notice_sql(sql, metric_name, config, duration, state=nil, &explainer) #THREAD_LOCAL_ACCESS sometimes
143
+ def notice_sql(sql, metric_name, config, duration, state=nil, explainer=nil) #THREAD_LOCAL_ACCESS sometimes
154
144
  state ||= TransactionState.tl_get
155
145
  data = state.sql_sampler_transaction_data
156
146
  return unless data
@@ -160,7 +150,7 @@ module NewRelic
160
150
  backtrace = caller.join("\n")
161
151
  data.sql_data << SlowSql.new(Database.capture_query(sql),
162
152
  metric_name, config,
163
- duration, backtrace, &explainer)
153
+ duration, backtrace, explainer)
164
154
  end
165
155
  end
166
156
  end
@@ -223,8 +213,7 @@ module NewRelic
223
213
  attr_reader :duration
224
214
  attr_reader :backtrace
225
215
 
226
- def initialize(sql, metric_name, config, duration, backtrace=nil,
227
- &explainer)
216
+ def initialize(sql, metric_name, config, duration, backtrace=nil, explainer=nil)
228
217
  @sql = sql
229
218
  @metric_name = metric_name
230
219
  @config = config
@@ -244,7 +233,7 @@ module NewRelic
244
233
 
245
234
  def explain
246
235
  if @config && @explainer
247
- NewRelic::Agent::Database.explain_sql(@sql, @config, &@explainer)
236
+ NewRelic::Agent::Database.explain_sql(@sql, @config, @explainer)
248
237
  end
249
238
  end
250
239
 
@@ -229,7 +229,7 @@ module NewRelic
229
229
 
230
230
  # For use by test code only.
231
231
  def to_h
232
- with_stats_lock { Hash[@stats_hash] }
232
+ with_stats_lock { @stats_hash.to_h }
233
233
  end
234
234
  end
235
235
  end
@@ -8,12 +8,6 @@ module Agent
8
8
  # Sampler functionality is now controlled by the SamplerManager class.
9
9
  # @deprecated
10
10
  class StatsEngine
11
- module Shim # :nodoc:
12
- def add_sampler(*args); end
13
- def add_harvest_sampler(*args); end
14
- def start_sampler_thread(*args); end
15
- end
16
-
17
11
  module Samplers
18
12
  def add_sampler(*args)
19
13
  NewRelic::Agent.logger.warn("Ignoring request to add periodic sampler - add_sampler is deprecated")
@@ -2,10 +2,17 @@
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
- # A Hash-descended class for storing metric data in the NewRelic Agent.
5
+ # A Hash-like class for storing metric data.
6
6
  #
7
- # Keys are NewRelic::MetricSpec objects.
8
- # Values are NewRelic::Agent::Stats objects.
7
+ # Internally, metrics are split into unscoped and scoped collections.
8
+ #
9
+ # Unscoped metrics are stored in a Hash, keyed by Strings representing the name
10
+ # of the metrics.
11
+ #
12
+ # Scoped metrics are stored in a Hash where the keys are NewRelic::MetricSpec
13
+ # objects (effectively <name, scope> tuples).
14
+ #
15
+ # Values in both hashes are NewRelic::Agent::Stats objects.
9
16
  #
10
17
  # Missing keys will be automatically created as empty NewRelic::Agent::Stats
11
18
  # instances, so use has_key? explicitly to check for key existence.
@@ -22,30 +29,68 @@ require 'new_relic/agent/internal_agent_error'
22
29
 
23
30
  module NewRelic
24
31
  module Agent
25
- class StatsHash < ::Hash
32
+ class StatsHash
26
33
 
27
34
  attr_accessor :started_at, :harvested_at
28
35
 
29
36
  def initialize(started_at=Time.now)
30
37
  @started_at = started_at.to_f
31
- super() { |hash, key| hash[key] = NewRelic::Agent::Stats.new }
38
+ @scoped = Hash.new { |h, k| h[k] = NewRelic::Agent::Stats.new }
39
+ @unscoped = Hash.new { |h, k| h[k] = NewRelic::Agent::Stats.new }
32
40
  end
33
41
 
34
42
  def marshal_dump
35
- [@started_at, Hash[self]]
43
+ [@started_at, Hash[@scoped], Hash[@unscoped]]
36
44
  end
37
45
 
38
46
  def marshal_load(data)
39
47
  @started_at = data.shift
40
- self.merge!(data.shift)
48
+ @scoped = Hash.new { |h, k| h[k] = NewRelic::Agent::Stats.new }
49
+ @unscoped = Hash.new { |h, k| h[k] = NewRelic::Agent::Stats.new }
50
+ @scoped.merge!(data.shift)
51
+ @unscoped.merge!(data.shift)
41
52
  end
42
53
 
43
54
  def ==(other)
44
- Hash[self] == Hash[other]
55
+ self.to_h == other.to_h
45
56
  end
46
57
 
47
58
  def to_h
48
- Hash[self]
59
+ hash = {}
60
+ @scoped.each { |k, v| hash[k] = v }
61
+ @unscoped.each { |k, v| hash[NewRelic::MetricSpec.new(k)] = v }
62
+ hash
63
+ end
64
+
65
+ def [](key)
66
+ case key
67
+ when String
68
+ @unscoped[key]
69
+ when NewRelic::MetricSpec
70
+ if key.scope.empty?
71
+ @unscoped[key.name]
72
+ else
73
+ @scoped[key]
74
+ end
75
+ end
76
+ end
77
+
78
+ def each
79
+ @scoped.each do |k, v|
80
+ yield k, v
81
+ end
82
+ @unscoped.each do |k, v|
83
+ spec = NewRelic::MetricSpec.new(k)
84
+ yield spec, v
85
+ end
86
+ end
87
+
88
+ def empty?
89
+ @unscoped.empty? && @scoped.empty?
90
+ end
91
+
92
+ def size
93
+ @unscoped.size + @scoped.size
49
94
  end
50
95
 
51
96
  class StatsHashLookupError < NewRelic::Agent::InternalAgentError
@@ -56,54 +101,66 @@ module NewRelic
56
101
 
57
102
  def record(metric_specs, value=nil, aux=nil, &blk)
58
103
  Array(metric_specs).each do |metric_spec|
59
- stats = nil
104
+ if metric_spec.scope.empty?
105
+ key = metric_spec.name
106
+ hash = @unscoped
107
+ else
108
+ key = metric_spec
109
+ hash = @scoped
110
+ end
111
+
60
112
  begin
61
- stats = self[metric_spec]
113
+ stats = hash[key]
62
114
  rescue NoMethodError => e
63
- # This only happen in the case of a corrupted default_proc
64
- # Side-step it manually, notice the issue, and carry on....
65
- NewRelic::Agent.instance.error_collector. \
66
- notice_agent_error(StatsHashLookupError.new(e, self, metric_spec))
67
-
68
- stats = NewRelic::Agent::Stats.new
69
- self[metric_spec] = stats
70
-
71
- # Try to restore the default_proc so we won't continually trip the error
72
- if respond_to?(:default_proc=)
73
- self.default_proc = Proc.new { |hash, key| hash[key] = NewRelic::Agent::Stats.new }
74
- end
115
+ stats = handle_stats_lookup_error(key, hash, e)
75
116
  end
76
117
 
77
118
  stats.record(value, aux, &blk)
78
119
  end
79
120
  end
80
121
 
81
- def merge!(other)
82
- if other.is_a?(StatsHash) && other.started_at < @started_at
83
- @started_at = other.started_at
122
+ def handle_stats_lookup_error(key, hash, error)
123
+ # This only happen in the case of a corrupted default_proc
124
+ # Side-step it manually, notice the issue, and carry on....
125
+ NewRelic::Agent.instance.error_collector. \
126
+ notice_agent_error(StatsHashLookupError.new(error, hash, key))
127
+ stats = NewRelic::Agent::Stats.new
128
+ hash[key] = stats
129
+ # Try to restore the default_proc so we won't continually trip the error
130
+ if hash.respond_to?(:default_proc=)
131
+ hash.default_proc = Proc.new { |h, k| h[k] = NewRelic::Agent::Stats.new }
84
132
  end
85
- other.each do |key, val|
86
- merge_or_insert(key, val)
133
+ stats
134
+ end
135
+
136
+ def merge!(other)
137
+ @started_at = other.started_at if other.started_at < @started_at
138
+
139
+ other.each do |spec, val|
140
+ if spec.scope.empty?
141
+ merge_or_insert(@unscoped, spec.name, val)
142
+ else
143
+ merge_or_insert(@scoped, spec, val)
144
+ end
87
145
  end
88
146
  self
89
147
  end
90
148
 
91
149
  def merge_transaction_metrics!(txn_metrics, scope)
92
150
  txn_metrics.each_unscoped do |name, stats|
93
- spec = NewRelic::MetricSpec.new(name)
94
- merge_or_insert(spec, stats)
151
+ merge_or_insert(@unscoped, name, stats)
95
152
  end
96
153
  txn_metrics.each_scoped do |name, stats|
97
154
  spec = NewRelic::MetricSpec.new(name, scope)
98
- merge_or_insert(spec, stats)
155
+ merge_or_insert(@scoped, spec, stats)
99
156
  end
100
157
  end
101
158
 
102
- def merge_or_insert(metric_spec, stats)
103
- if self.has_key?(metric_spec)
104
- self[metric_spec].merge!(stats)
159
+ def merge_or_insert(target, name, stats)
160
+ if target.has_key?(name)
161
+ target[name].merge!(stats)
105
162
  else
106
- self[metric_spec] = stats
163
+ target[name] = stats
107
164
  end
108
165
  end
109
166
  end
@@ -16,15 +16,27 @@ module NewRelic
16
16
  RbConfig::CONFIG['target_os']
17
17
  end
18
18
 
19
+ def self.darwin?
20
+ !!(ruby_os_identifier =~ /darwin/i)
21
+ end
22
+
23
+ def self.linux?
24
+ !!(ruby_os_identifier =~ /linux/i)
25
+ end
26
+
27
+ def self.bsd?
28
+ !!(ruby_os_identifier =~ /bsd/i)
29
+ end
30
+
31
+ @processor_info = nil
32
+
19
33
  def self.clear_processor_info
20
34
  @processor_info = nil
21
35
  end
22
36
 
23
37
  def self.get_processor_info
24
38
  if @processor_info.nil?
25
- case ruby_os_identifier
26
-
27
- when /darwin/
39
+ if darwin?
28
40
  @processor_info = {
29
41
  :num_physical_packages => sysctl_value('hw.packages').to_i,
30
42
  :num_physical_cores => sysctl_value('hw.physicalcpu_max').to_i,
@@ -41,11 +53,11 @@ module NewRelic
41
53
  @processor_info[:num_logical_processors] = sysctl_value('hw.ncpu').to_i
42
54
  end
43
55
 
44
- when /linux/
56
+ elsif linux?
45
57
  cpuinfo = proc_try_read('/proc/cpuinfo')
46
58
  @processor_info = cpuinfo ? parse_cpuinfo(cpuinfo) : {}
47
59
 
48
- when /freebsd/
60
+ elsif bsd?
49
61
  @processor_info = {
50
62
  :num_physical_packages => nil,
51
63
  :num_physical_cores => nil,
@@ -146,7 +158,7 @@ module NewRelic
146
158
  cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu']
147
159
  return unless cpu_cgroup
148
160
 
149
- case cpu_cgroup
161
+ container_id = case cpu_cgroup
150
162
  # docker native driver w/out systemd (fs)
151
163
  when %r{^/docker/([0-9a-f]+)$} then $1
152
164
  # docker native driver with systemd
@@ -156,9 +168,21 @@ module NewRelic
156
168
  # not in any cgroup
157
169
  when '/' then nil
158
170
  # in a cgroup, but we don't recognize its format
171
+ when %r{docker} then
172
+ ::NewRelic::Agent.logger.debug("Cgroup indicates docker but container_id unrecognized: '#{cpu_cgroup}'")
173
+ ::NewRelic::Agent.increment_metric "Supportability/utilization/docker/error"
174
+ return
159
175
  else
160
176
  ::NewRelic::Agent.logger.debug("Ignoring unrecognized cgroup ID format: '#{cpu_cgroup}'")
177
+ return
178
+ end
179
+
180
+ if container_id && container_id.size != 64
181
+ ::NewRelic::Agent.logger.debug("Found docker container_id with invalid length: #{container_id}")
182
+ ::NewRelic::Agent.increment_metric "Supportability/utilization/docker/error"
161
183
  nil
184
+ else
185
+ container_id
162
186
  end
163
187
  end
164
188
 
@@ -199,6 +223,29 @@ module NewRelic
199
223
  end
200
224
  content
201
225
  end
226
+
227
+ def self.ram_in_mib
228
+ if darwin?
229
+ sysctl_value('hw.memsize').to_i / (1024 ** 2)
230
+ elsif linux?
231
+ meminfo = proc_try_read('/proc/meminfo')
232
+ parse_linux_meminfo_in_mib(meminfo)
233
+ elsif bsd?
234
+ sysctl_value('hw.realmem').to_i / (1024 ** 2)
235
+ else
236
+ ::NewRelic::Agent.logger.debug("Unable to determine ram_in_mib for host os: #{ruby_os_identifier}")
237
+ nil
238
+ end
239
+ end
240
+
241
+ def self.parse_linux_meminfo_in_mib(meminfo)
242
+ if mem_total = meminfo[/MemTotal:\s*(\d*)\skB/,1]
243
+ mem_total.to_i / 1024
244
+ else
245
+ ::NewRelic::Agent.logger.debug("Failed to parse MemTotal from /proc/meminfo: #{meminfo}")
246
+ nil
247
+ end
248
+ end
202
249
  end
203
250
  end
204
251
  end
@@ -191,7 +191,7 @@ module NewRelic
191
191
  txn = state.current_transaction
192
192
  if txn
193
193
  txn.notice_error(e, options)
194
- else
194
+ elsif NewRelic::Agent.instance
195
195
  NewRelic::Agent.instance.error_collector.notice_error(e, options)
196
196
  end
197
197
  end
@@ -308,10 +308,6 @@ module NewRelic
308
308
  @instrumentation_state ||= {}
309
309
  end
310
310
 
311
- def noticed_error_ids
312
- @noticed_error_ids ||= []
313
- end
314
-
315
311
  def overridden_name=(name)
316
312
  @overridden_name = Helper.correctly_encoded(name)
317
313
  end
@@ -522,7 +518,7 @@ module NewRelic
522
518
  end
523
519
 
524
520
  if http_response_code
525
- add_agent_attribute(:httpResponseCode, http_response_code,
521
+ add_agent_attribute(:httpResponseCode, http_response_code.to_s,
526
522
  NewRelic::Agent::AttributeFilter::DST_TRANSACTION_TRACER|
527
523
  NewRelic::Agent::AttributeFilter::DST_TRANSACTION_EVENTS|
528
524
  NewRelic::Agent::AttributeFilter::DST_ERROR_COLLECTOR)
@@ -579,15 +575,10 @@ module NewRelic
579
575
  append_apdex_perf_zone(duration, payload)
580
576
  append_synthetics_to(state, payload)
581
577
  append_referring_transaction_guid_to(state, payload)
582
- append_http_response_code(payload)
583
578
 
584
579
  agent.events.notify(:transaction_finished, payload)
585
580
  end
586
581
 
587
- def append_http_response_code(payload)
588
- payload[:http_response_code] = http_response_code if http_response_code
589
- end
590
-
591
582
  def include_guid?(state, duration)
592
583
  state.is_cross_app? || is_synthetics_request?
593
584
  end
@@ -800,7 +791,7 @@ module NewRelic
800
791
  Agent.config[key] && Agent.config[key][best_name]
801
792
  end
802
793
 
803
- def with_database_metric_name(model, method)
794
+ def with_database_metric_name(model, method, product=nil)
804
795
  previous = self.instrumentation_state[:datastore_override]
805
796
  model_name = case model
806
797
  when Class
@@ -810,7 +801,7 @@ module NewRelic
810
801
  else
811
802
  model.to_s
812
803
  end
813
- self.instrumentation_state[:datastore_override] = [method, model_name]
804
+ self.instrumentation_state[:datastore_override] = [method, model_name, product]
814
805
  yield
815
806
  ensure
816
807
  self.instrumentation_state[:datastore_override] = previous