newrelic_rpm 3.1.0 → 3.1.1.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of newrelic_rpm might be problematic. Click here for more details.

Files changed (94) hide show
  1. data/CHANGELOG +3 -0
  2. data/lib/new_relic/agent.rb +29 -12
  3. data/lib/new_relic/agent/agent.rb +355 -78
  4. data/lib/new_relic/agent/beacon_configuration.rb +49 -7
  5. data/lib/new_relic/agent/browser_monitoring.rb +20 -1
  6. data/lib/new_relic/agent/busy_calculator.rb +11 -3
  7. data/lib/new_relic/agent/chained_call.rb +2 -2
  8. data/lib/new_relic/agent/error_collector.rb +229 -183
  9. data/lib/new_relic/agent/instrumentation.rb +2 -2
  10. data/lib/new_relic/agent/instrumentation/active_merchant.rb +5 -1
  11. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +5 -1
  12. data/lib/new_relic/agent/instrumentation/authlogic.rb +4 -0
  13. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +16 -5
  14. data/lib/new_relic/agent/instrumentation/data_mapper.rb +5 -1
  15. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +5 -1
  16. data/lib/new_relic/agent/instrumentation/memcache.rb +5 -1
  17. data/lib/new_relic/agent/instrumentation/merb/controller.rb +5 -1
  18. data/lib/new_relic/agent/instrumentation/merb/errors.rb +5 -1
  19. data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +0 -5
  20. data/lib/new_relic/agent/instrumentation/net.rb +5 -1
  21. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +7 -3
  22. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +5 -1
  23. data/lib/new_relic/agent/instrumentation/rails/active_record_instrumentation.rb +5 -1
  24. data/lib/new_relic/agent/instrumentation/rails/errors.rb +4 -0
  25. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +4 -0
  26. data/lib/new_relic/agent/instrumentation/rails3/active_record_instrumentation.rb +13 -6
  27. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +4 -0
  28. data/lib/new_relic/agent/instrumentation/sinatra.rb +4 -0
  29. data/lib/new_relic/agent/instrumentation/sunspot.rb +4 -0
  30. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +5 -1
  31. data/lib/new_relic/agent/method_tracer.rb +205 -99
  32. data/lib/new_relic/agent/shim_agent.rb +0 -1
  33. data/lib/new_relic/agent/stats_engine.rb +1 -0
  34. data/lib/new_relic/agent/stats_engine/metric_stats.rb +23 -7
  35. data/lib/new_relic/agent/stats_engine/samplers.rb +8 -2
  36. data/lib/new_relic/agent/stats_engine/transactions.rb +26 -12
  37. data/lib/new_relic/agent/transaction_sampler.rb +3 -1
  38. data/lib/new_relic/agent/worker_loop.rb +13 -5
  39. data/lib/new_relic/collection_helper.rb +6 -3
  40. data/lib/new_relic/control.rb +1 -3
  41. data/lib/new_relic/control/class_methods.rb +8 -3
  42. data/lib/new_relic/control/configuration.rb +24 -5
  43. data/lib/new_relic/control/frameworks.rb +10 -0
  44. data/lib/new_relic/control/frameworks/external.rb +4 -4
  45. data/lib/new_relic/control/frameworks/merb.rb +1 -0
  46. data/lib/new_relic/control/frameworks/rails.rb +5 -5
  47. data/lib/new_relic/control/frameworks/rails3.rb +5 -3
  48. data/lib/new_relic/control/frameworks/ruby.rb +5 -5
  49. data/lib/new_relic/control/frameworks/sinatra.rb +1 -4
  50. data/lib/new_relic/control/instance_methods.rb +23 -7
  51. data/lib/new_relic/control/instrumentation.rb +22 -3
  52. data/lib/new_relic/control/logging_methods.rb +25 -7
  53. data/lib/new_relic/control/server_methods.rb +16 -6
  54. data/lib/new_relic/data_serialization.rb +83 -14
  55. data/lib/new_relic/delayed_job_injection.rb +7 -1
  56. data/lib/new_relic/local_environment.rb +55 -25
  57. data/lib/new_relic/metric_data.rb +7 -2
  58. data/lib/new_relic/metric_spec.rb +5 -3
  59. data/lib/new_relic/stats.rb +16 -7
  60. data/lib/new_relic/transaction_analysis.rb +2 -1
  61. data/lib/new_relic/transaction_analysis/segment_summary.rb +4 -2
  62. data/lib/new_relic/transaction_sample.rb +33 -7
  63. data/lib/new_relic/transaction_sample/segment.rb +21 -3
  64. data/lib/new_relic/version.rb +2 -2
  65. data/newrelic_rpm.gemspec +7 -11
  66. data/test/config/newrelic.yml +1 -1
  67. data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -4
  68. data/test/new_relic/agent/agent_test.rb +16 -0
  69. data/test/new_relic/agent/agent_test_controller.rb +1 -1
  70. data/test/new_relic/agent/agent_test_controller_test.rb +14 -19
  71. data/test/new_relic/agent/beacon_configuration_test.rb +2 -2
  72. data/test/new_relic/agent/browser_monitoring_test.rb +7 -3
  73. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +13 -4
  74. data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +0 -10
  75. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +1 -1
  76. data/test/new_relic/agent_test.rb +168 -0
  77. data/test/new_relic/collection_helper_test.rb +21 -3
  78. data/test/new_relic/control/configuration_test.rb +25 -0
  79. data/test/new_relic/data_serialization_test.rb +58 -3
  80. data/test/new_relic/delayed_job_injection_test.rb +17 -0
  81. data/test/new_relic/transaction_analysis/segment_summary_test.rb +14 -0
  82. data/test/new_relic/transaction_analysis_test.rb +3 -3
  83. data/test/new_relic/transaction_sample/segment_test.rb +11 -0
  84. data/test/test_helper.rb +1 -1
  85. data/vendor/gems/dependency_detection-0.0.1.build/LICENSE +4 -18
  86. metadata +13 -13
  87. data/lib/new_relic/histogram.rb +0 -91
  88. data/lib/new_relic/rack/metric_app.rb +0 -65
  89. data/lib/new_relic/rack/mongrel_rpm.ru +0 -28
  90. data/lib/new_relic/rack/newrelic.yml +0 -27
  91. data/lib/new_relic/rack_app.rb +0 -6
  92. data/vendor/gems/dependency_detection-0.0.1.build/README +0 -0
  93. data/vendor/gems/metric_parser-0.1.0.pre1/LICENSE +0 -0
  94. data/vendor/gems/metric_parser-0.1.0.pre1/README +0 -0
@@ -9,7 +9,6 @@ module NewRelic
9
9
  end
10
10
  def initialize
11
11
  super
12
- @histogram.extend NewRelic::Histogram::Shim
13
12
  @stats_engine.extend NewRelic::Agent::StatsEngine::Shim
14
13
  @stats_engine.extend NewRelic::Agent::StatsEngine::Transactions::Shim
15
14
  @transaction_sampler.extend NewRelic::Agent::TransactionSampler::Shim
@@ -4,6 +4,7 @@ require 'new_relic/agent/stats_engine/transactions'
4
4
 
5
5
  module NewRelic
6
6
  module Agent
7
+ # This class handles all the statistics gathering for the agent
7
8
  class StatsEngine
8
9
  include MetricStats
9
10
  include Samplers
@@ -1,7 +1,10 @@
1
1
  module NewRelic
2
2
  module Agent
3
3
  class StatsEngine
4
+ # Handles methods related to actual Metric collection
4
5
  module MetricStats
6
+ # A simple mutex-synchronized hash to make sure our statistics
7
+ # are internally consistent even in truly-threaded rubies like JRuby
5
8
  class SynchronizedHash < Hash
6
9
  def initialize(*args)
7
10
  @mutex = Mutex.new
@@ -38,17 +41,20 @@ module NewRelic
38
41
  }
39
42
  end
40
43
  end
41
-
44
+
45
+ # Returns all of the metric names of all the stats in the engine
42
46
  def metrics
43
47
  stats_hash.keys.map(&:to_s)
44
48
  end
45
-
49
+
50
+ # a simple accessor for looking up a stat with no scope -
51
+ # returns a new stats object if no stats object for that
52
+ # metric exists yet
46
53
  def get_stats_no_scope(metric_name)
47
54
  stats_hash[NewRelic::MetricSpec.new(metric_name, '')] ||= NewRelic::MethodTraceStats.new
48
55
  end
49
56
 
50
57
  # This version allows a caller to pass a stat class to use
51
- #
52
58
  def get_custom_stats(metric_name, stat_class)
53
59
  stats_hash[NewRelic::MetricSpec.new(metric_name)] ||= stat_class.new
54
60
  end
@@ -69,13 +75,21 @@ module NewRelic
69
75
  end
70
76
  stats
71
77
  end
72
-
78
+
79
+ # Returns a stat if one exists, otherwise returns nil. If you
80
+ # want auto-initialization, use one of get_stats or get_stats_no_scope
73
81
  def lookup_stats(metric_name, scope_name = '')
74
82
  stats_hash[NewRelic::MetricSpec.new(metric_name, scope_name)]
75
83
  end
76
-
84
+
85
+ # This module was extracted from the harvest method and should
86
+ # be refactored
77
87
  module Harvest
78
-
88
+
89
+ # merge data from previous harvests into this stats engine -
90
+ # takes into account the case where there are new stats for
91
+ # that metric, and the case where there is no current data
92
+ # for that metric
79
93
  def merge_data(metric_data_hash)
80
94
  metric_data_hash.each do |metric_spec, metric_data|
81
95
  new_data = lookup_stats(metric_spec.name, metric_spec.scope)
@@ -172,7 +186,9 @@ module NewRelic
172
186
  def reset_stats
173
187
  stats_hash.values.each { |s| s.reset }
174
188
  end
175
-
189
+
190
+ # returns a memoized SynchronizedHash that holds the actual
191
+ # instances of Stats keyed off their MetricName
176
192
  def stats_hash
177
193
  @stats_hash ||= SynchronizedHash.new
178
194
  end
@@ -6,14 +6,20 @@ module Agent
6
6
  def add_harvest_sampler(*args); end
7
7
  def start_sampler_thread(*args); end
8
8
  end
9
-
9
+
10
+ # Contains statistics engine extensions to support the concept of samplers
10
11
  module Samplers
11
12
 
12
13
  # By default a sampler polls on harvest time, once a minute. However you can
13
14
  # override #use_harvest_sampler? to return false and it will sample
14
15
  # every POLL_PERIOD seconds on a background thread.
15
16
  POLL_PERIOD = 20
16
-
17
+
18
+ # starts the sampler thread which runs periodically, rather than
19
+ # at harvest time. This is deprecated, and should not actually
20
+ # be used - mo threads mo problems
21
+ #
22
+ # returns unless there are actually periodic samplers to run
17
23
  def start_sampler_thread
18
24
 
19
25
  return if @sampler_thread && @sampler_thread.alive?
@@ -1,10 +1,9 @@
1
+ # -*- coding: utf-8 -*-
1
2
  module NewRelic
2
3
  module Agent
3
4
  class StatsEngine
4
-
5
- # Defines methods that stub out the stats engine methods
6
- # when the agent is disabled
7
-
5
+ # A simple stack element that tracks the current name and length
6
+ # of the executing stack
8
7
  class ScopeStackElement
9
8
  attr_reader :name, :deduct_call_time_from_parent
10
9
  attr_accessor :children_time
@@ -14,8 +13,13 @@ module Agent
14
13
  @children_time = 0
15
14
  end
16
15
  end
17
-
16
+
17
+ # Handles pushing and popping elements onto an internal stack that
18
+ # tracks where time should be allocated in Transaction Traces
18
19
  module Transactions
20
+
21
+ # Defines methods that stub out the stats engine methods
22
+ # when the agent is disabled
19
23
  module Shim # :nodoc:
20
24
  def start_transaction(*args); end
21
25
  def end_transaction; end
@@ -25,16 +29,21 @@ module Agent
25
29
  def scope_name; end
26
30
  def pop_scope(*args); end
27
31
  end
28
-
32
+
33
+ # add a new transaction sampler, unless we're currently in a
34
+ # transaction (then we fail)
29
35
  def transaction_sampler= sampler
30
36
  fail "Can't add a scope listener midflight in a transaction" if scope_stack.any?
31
37
  @transaction_sampler = sampler
32
38
  end
33
-
39
+
40
+ # removes a transaction sampler
34
41
  def remove_transaction_sampler(l)
35
42
  @transaction_sampler = nil
36
43
  end
37
-
44
+
45
+ # Pushes a scope onto the transaction stack - this generates a
46
+ # TransactionSample::Segment at the end of transaction execution
38
47
  def push_scope(metric, time = Time.now.to_f, deduct_call_time_from_parent = true)
39
48
 
40
49
  stack = scope_stack
@@ -52,7 +61,9 @@ module Agent
52
61
  stack.push scope
53
62
  scope
54
63
  end
55
-
64
+
65
+ # Pops a scope off the transaction stack - this updates the
66
+ # transaction sampler that we've finished execution of a traced method
56
67
  def pop_scope(expected_scope, duration, time=Time.now.to_f)
57
68
  capture_gc_time if collecting_gc?
58
69
  stack = scope_stack
@@ -69,7 +80,8 @@ module Agent
69
80
  @transaction_sampler.notice_pop_scope(scope.name, time) if @transaction_sampler
70
81
  scope
71
82
  end
72
-
83
+
84
+ # Returns the latest ScopeStackElement
73
85
  def peek_scope
74
86
  scope_stack.last
75
87
  end
@@ -86,7 +98,8 @@ module Agent
86
98
  Thread::current[:newrelic_scope_name] = transaction
87
99
  Thread::current[:newrelic_most_recent_transaction] = transaction
88
100
  end
89
-
101
+
102
+ # Returns the current scope name from the thread local
90
103
  def scope_name
91
104
  Thread::current[:newrelic_scope_name]
92
105
  end
@@ -173,7 +186,8 @@ module Agent
173
186
  pop_scope(gc_scope, elapsed, time)
174
187
  end
175
188
  end
176
-
189
+
190
+ # Returns the current scope stack, memoized to a thread local variable
177
191
  def scope_stack
178
192
  Thread::current[:newrelic_scope_stack] ||= []
179
193
  end
@@ -3,7 +3,9 @@ require 'new_relic/control'
3
3
  require 'new_relic/agent/transaction_sample_builder'
4
4
  module NewRelic
5
5
  module Agent
6
-
6
+
7
+ # This class contains the logic of sampling a transaction -
8
+ # creation and modification of transaction samples
7
9
  class TransactionSampler
8
10
 
9
11
  # Module defining methods stubbed out when the agent is disabled
@@ -12,14 +12,17 @@ module NewRelic
12
12
  @next_invocation_time = Time.now
13
13
  @period = 60.0
14
14
  end
15
-
15
+
16
+ # returns a class-level memoized mutex to make sure we don't run overlapping
16
17
  def lock
17
18
  @@lock ||= Mutex.new
18
19
  end
19
-
20
+
21
+ # a helper to access the NewRelic::Control.instance.log
20
22
  def log
21
23
  NewRelic::Control.instance.log
22
24
  end
25
+
23
26
  # Run infinitely, calling the registered tasks at their specified
24
27
  # call periods. The caller is responsible for creating the thread
25
28
  # that runs this worker loop. This will run the task immediately.
@@ -38,15 +41,20 @@ module NewRelic
38
41
  run_task if keep_running
39
42
  end
40
43
  end
41
-
44
+
45
+ # a simple accessor for @should_run
42
46
  def keep_running
43
47
  @should_run
44
48
  end
45
-
49
+
50
+ # Sets @should_run to false. Returns false
46
51
  def stop
47
52
  @should_run = false
48
53
  end
49
-
54
+
55
+ # Executes the block given to the worker loop, and handles many
56
+ # possible errors. Also updates the execution time so that the
57
+ # next run occurs on schedule, even if we execute at some odd time
50
58
  def run_task
51
59
  begin
52
60
  lock.synchronize do
@@ -1,3 +1,5 @@
1
+ require 'new_relic/control'
2
+
1
3
  module NewRelic
2
4
  module CollectionHelper
3
5
  DEFAULT_TRUNCATION_SIZE=256
@@ -29,12 +31,13 @@ module NewRelic
29
31
  # Return nil if there is no backtrace
30
32
 
31
33
  def strip_nr_from_backtrace(backtrace)
32
- if backtrace
34
+ if backtrace && !NewRelic::Control.instance.disable_backtrace_cleanup?
33
35
  # this is for 1.9.1, where strings no longer have Enumerable
34
36
  backtrace = backtrace.split("\n") if String === backtrace
35
- backtrace = backtrace.reject {|line| line =~ /new_?relic/ }
37
+ backtrace = backtrace.map &:to_s
38
+ backtrace = backtrace.reject {|line| line.include?(NewRelic::Control.newrelic_root) }
36
39
  # rename methods back to their original state
37
- backtrace = backtrace.collect {|line| line.to_s.gsub(/_without_(newrelic|trace)/, "")}
40
+ backtrace = backtrace.collect {|line| line.gsub(/_without_(newrelic|trace)/, "")}
38
41
  end
39
42
  backtrace
40
43
  end
@@ -8,6 +8,7 @@ require 'erb'
8
8
  require 'socket'
9
9
  require 'net/https'
10
10
  require 'logger'
11
+ require 'new_relic/control/frameworks'
11
12
  require 'new_relic/control/profiling'
12
13
  require 'new_relic/control/logging_methods'
13
14
  require 'new_relic/control/configuration'
@@ -30,9 +31,6 @@ module NewRelic
30
31
  # The Control also implements some of the public API for the agent.
31
32
  #
32
33
  class Control
33
- # used for framework-specific subclasses
34
- module Frameworks; end
35
-
36
34
  # done in a subfile for load order purposes
37
35
  # extend ClassMethods
38
36
  # include InstanceMethods
@@ -1,16 +1,19 @@
1
1
  module NewRelic
2
2
  class Control
3
+ # class-level methods for lazy creation of NewRelic::Control and
4
+ # NewRelic::LocalEnvironment instances.
3
5
  module ClassMethods
4
6
  # Access the Control singleton, lazy initialized
5
7
  def instance
6
8
  @instance ||= new_instance
7
9
  end
8
-
10
+
11
+ # Access the LocalEnvironment singleton, lazy initialized
9
12
  def local_env
10
13
  @local_env ||= NewRelic::LocalEnvironment.new
11
14
  end
12
15
 
13
- # Create the concrete class for environment specific behavior:
16
+ # Create the concrete class for environment specific behavior
14
17
  def new_instance
15
18
  if local_env.framework == :test
16
19
  load_test_framework
@@ -25,7 +28,9 @@ module NewRelic
25
28
  require "config/test_control"
26
29
  NewRelic::Control::Frameworks::Test.new(local_env, config)
27
30
  end
28
-
31
+
32
+ # Loads the specified framework class from the
33
+ # NewRelic::Control::Frameworks module
29
34
  def load_framework_class(framework)
30
35
  begin
31
36
  require "new_relic/control/frameworks/#{framework}"
@@ -1,5 +1,7 @@
1
1
  module NewRelic
2
2
  class Control
3
+ # used to contain methods to look up settings from the
4
+ # configuration located in newrelic.yml
3
5
  module Configuration
4
6
  def settings
5
7
  unless @settings
@@ -65,11 +67,13 @@ module NewRelic
65
67
  end
66
68
 
67
69
  def license_key
68
- fetch('license_key')
70
+ fetch('license_key', ENV['NEWRELIC_LICENSE_KEY'])
69
71
  end
72
+
70
73
  def capture_params
71
74
  fetch('capture_params')
72
75
  end
76
+
73
77
  # True if we are sending data to the server, monitoring production
74
78
  def monitor_mode?
75
79
  fetch('monitor_mode', fetch('enabled'))
@@ -79,12 +83,14 @@ module NewRelic
79
83
  def developer_mode?
80
84
  fetch('developer_mode', fetch('developer'))
81
85
  end
82
-
86
+
87
+ # whether we should install the
88
+ # NewRelic::Rack::BrowserMonitoring middleware automatically on
89
+ # Rails applications
83
90
  def browser_monitoring_auto_instrument?
84
91
  fetch('browser_monitoring', {}).fetch('auto_instrument', true)
85
92
  end
86
93
 
87
- # True if the app runs in multi-threaded mode
88
94
  def multi_threaded?
89
95
  fetch('multi_threaded')
90
96
  end
@@ -97,6 +103,8 @@ module NewRelic
97
103
  def use_textmate?
98
104
  fetch('textmate')
99
105
  end
106
+
107
+ # defaults to 2MiB
100
108
  def post_size_limit
101
109
  fetch('post_size_limit', 2 * 1024 * 1024)
102
110
  end
@@ -135,12 +143,19 @@ module NewRelic
135
143
  def validate_token
136
144
  self['validate_token'] || ENV['NR_VALIDATE_TOKEN']
137
145
  end
138
-
146
+
139
147
  def use_ssl?
140
148
  @use_ssl = fetch('ssl', false) unless @use_ssl
141
149
  @use_ssl
142
150
  end
143
-
151
+
152
+ def log_file_path
153
+ fetch('log_file_path', 'log/')
154
+ end
155
+
156
+ # only verify certificates if you're very sure you want this
157
+ # level of security, it includes possibly app-crashing dns
158
+ # lookups every connection to the server
144
159
  def verify_certificate?
145
160
  unless @verify_certificate
146
161
  unless use_ssl?
@@ -151,6 +166,10 @@ module NewRelic
151
166
  end
152
167
  @verify_certificate
153
168
  end
169
+
170
+ def disable_backtrace_cleanup?
171
+ fetch('disable_backtrace_cleanup')
172
+ end
154
173
  end
155
174
  include Configuration
156
175
  end
@@ -0,0 +1,10 @@
1
+ module NewRelic
2
+ class Control
3
+ # Contains subclasses of NewRelic::Control that are used when
4
+ # starting the agent within an application. Framework-specific
5
+ # logic should be included here, as documented within the Control
6
+ # abstract parent class
7
+ module Frameworks
8
+ end
9
+ end
10
+ end
@@ -1,11 +1,11 @@
1
- # This is the control used when starting up in the context of
2
- # The New Relic Infrastructure Agent. We want to call this
3
- # out specifically because in this context we are not monitoring
4
- # the running process, but actually external things.
5
1
  require 'new_relic/control/frameworks/ruby'
6
2
  module NewRelic
7
3
  class Control
8
4
  module Frameworks
5
+ # This is the control used when starting up in the context of
6
+ # The New Relic Infrastructure Agent. We want to call this
7
+ # out specifically because in this context we are not monitoring
8
+ # the running process, but actually external things.
9
9
  class External < NewRelic::Control::Frameworks::Ruby
10
10
  def init_config(options={})
11
11
  super
@@ -1,6 +1,7 @@
1
1
  module NewRelic
2
2
  class Control
3
3
  module Frameworks
4
+ # Includes limited support for Merb
4
5
  class Merb < NewRelic::Control
5
6
 
6
7
  def env