newrelic_rpm 3.8.0.218 → 3.8.1.221

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +32 -0
  3. data/README.md +4 -7
  4. data/Rakefile +3 -0
  5. data/lib/new_relic/agent.rb +3 -7
  6. data/lib/new_relic/agent/agent.rb +4 -14
  7. data/lib/new_relic/agent/agent_logger.rb +19 -11
  8. data/lib/new_relic/agent/autostart.rb +1 -1
  9. data/lib/new_relic/agent/configuration/default_source.rb +25 -12
  10. data/lib/new_relic/agent/configuration/manager.rb +14 -7
  11. data/lib/new_relic/agent/configuration/yaml_source.rb +39 -8
  12. data/lib/new_relic/agent/cross_app_monitor.rb +9 -7
  13. data/lib/new_relic/agent/cross_app_tracing.rb +6 -6
  14. data/lib/new_relic/agent/datastores/mongo.rb +6 -7
  15. data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +32 -13
  16. data/lib/new_relic/agent/datastores/mongo/statement_formatter.rb +4 -3
  17. data/lib/new_relic/agent/error_collector.rb +2 -2
  18. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +10 -69
  19. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +5 -7
  20. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +2 -2
  21. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +77 -93
  22. data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +1 -1
  23. data/lib/new_relic/agent/instrumentation/mongo.rb +26 -42
  24. data/lib/new_relic/agent/instrumentation/rubyprof.rb +1 -1
  25. data/lib/new_relic/agent/instrumentation/sinatra.rb +4 -1
  26. data/lib/new_relic/agent/javascript_instrumentor.rb +15 -6
  27. data/lib/new_relic/agent/method_tracer.rb +41 -92
  28. data/lib/new_relic/agent/request_sampler.rb +0 -1
  29. data/lib/new_relic/agent/rules_engine.rb +36 -12
  30. data/lib/new_relic/agent/shim_agent.rb +0 -1
  31. data/lib/new_relic/agent/sql_sampler.rb +8 -15
  32. data/lib/new_relic/agent/stats_engine.rb +2 -6
  33. data/lib/new_relic/agent/stats_engine/metric_stats.rb +8 -2
  34. data/lib/new_relic/agent/stats_engine/stats_hash.rb +1 -1
  35. data/lib/new_relic/agent/supported_versions.rb +1 -1
  36. data/lib/new_relic/agent/traced_method_stack.rb +87 -0
  37. data/lib/new_relic/agent/transaction.rb +277 -107
  38. data/lib/new_relic/agent/transaction_sample_builder.rb +2 -2
  39. data/lib/new_relic/agent/transaction_sampler.rb +18 -27
  40. data/lib/new_relic/agent/transaction_state.rb +15 -40
  41. data/lib/new_relic/control/instance_methods.rb +8 -4
  42. data/lib/new_relic/recipes.rb +3 -3
  43. data/lib/new_relic/transaction_sample.rb +3 -7
  44. data/lib/new_relic/version.rb +1 -1
  45. data/lib/sequel/extensions/newrelic_instrumentation.rb +3 -3
  46. data/newrelic_rpm.gemspec +15 -9
  47. data/test/agent_helper.rb +71 -36
  48. data/test/environments/norails/Gemfile +2 -0
  49. data/test/environments/rails21/Gemfile +2 -0
  50. data/test/environments/rails22/Gemfile +2 -0
  51. data/test/environments/rails23/Gemfile +2 -0
  52. data/test/environments/rails30/Gemfile +2 -0
  53. data/test/environments/rails31/Gemfile +2 -0
  54. data/test/environments/rails32/Gemfile +2 -0
  55. data/test/environments/rails40/Gemfile +2 -0
  56. data/test/environments/rails41/Gemfile +1 -0
  57. data/test/helpers/mongo_metric_builder.rb +1 -1
  58. data/test/multiverse/suites/agent_only/audit_log_test.rb +2 -2
  59. data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +9 -1
  60. data/test/multiverse/suites/agent_only/encoding_handling_test.rb +1 -1
  61. data/test/multiverse/suites/agent_only/logging_test.rb +2 -2
  62. data/test/multiverse/suites/agent_only/marshaling_test.rb +8 -9
  63. data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +14 -1
  64. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +30 -13
  65. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +9 -8
  66. data/test/multiverse/suites/agent_only/transaction_ignoring_test.rb +43 -0
  67. data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +77 -5
  68. data/test/multiverse/suites/excon/excon_test.rb +1 -1
  69. data/test/multiverse/suites/mongo/Envfile +4 -7
  70. data/test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb +55 -16
  71. data/test/multiverse/suites/mongo/helpers/mongo_server.rb +6 -4
  72. data/test/multiverse/suites/rails/bad_instrumentation_test.rb +2 -2
  73. data/test/multiverse/suites/rails/error_tracing_test.rb +3 -1
  74. data/test/multiverse/suites/rails/request_statistics_test.rb +14 -14
  75. data/test/multiverse/suites/rails/transaction_ignoring_test.rb +45 -0
  76. data/test/multiverse/suites/sequel/sequel_instrumentation_test.rb +1 -1
  77. data/test/new_relic/agent/agent/connect_test.rb +4 -4
  78. data/test/new_relic/agent/agent_logger_test.rb +32 -0
  79. data/test/new_relic/agent/configuration/manager_test.rb +12 -4
  80. data/test/new_relic/agent/configuration/yaml_source_test.rb +2 -2
  81. data/test/new_relic/agent/cross_app_monitor_test.rb +6 -2
  82. data/test/new_relic/agent/cross_app_tracing_test.rb +5 -5
  83. data/test/new_relic/agent/datastores/mongo/statement_formatter_test.rb +7 -6
  84. data/test/new_relic/agent/error_collector_test.rb +1 -2
  85. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +24 -11
  86. data/test/new_relic/agent/instrumentation/action_view_subscriber_test.rb +2 -2
  87. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +12 -17
  88. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +43 -32
  89. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +3 -4
  90. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +36 -20
  91. data/test/new_relic/agent/javascript_instrumentor_test.rb +1 -2
  92. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +15 -26
  93. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +66 -103
  94. data/test/new_relic/agent/method_tracer_test.rb +2 -2
  95. data/test/new_relic/agent/mock_scope_listener.rb +3 -6
  96. data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -4
  97. data/test/new_relic/agent/rules_engine_test.rb +13 -0
  98. data/test/new_relic/agent/sql_sampler_test.rb +8 -10
  99. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +18 -0
  100. data/test/new_relic/agent/stats_engine_test.rb +0 -173
  101. data/test/new_relic/agent/threading/agent_thread_test.rb +27 -26
  102. data/test/new_relic/agent/traced_method_stack_test.rb +139 -0
  103. data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -12
  104. data/test/new_relic/agent/transaction_sampler_test.rb +98 -107
  105. data/test/new_relic/agent/transaction_state_test.rb +52 -61
  106. data/test/new_relic/agent/transaction_test.rb +209 -140
  107. data/test/new_relic/agent_test.rb +3 -2
  108. data/test/new_relic/control_test.rb +10 -9
  109. data/test/new_relic/fake_collector.rb +34 -2
  110. data/test/new_relic/http_client_test_cases.rb +0 -5
  111. data/test/new_relic/license_test.rb +4 -2
  112. data/test/new_relic/local_environment_test.rb +14 -28
  113. data/test/new_relic/multiverse_helpers.rb +2 -2
  114. data/test/new_relic/rack/developer_mode_test.rb +4 -5
  115. data/test/new_relic/transaction_ignoring_test_cases.rb +104 -0
  116. data/test/new_relic/transaction_sample_test.rb +14 -7
  117. data/test/performance/lib/performance/instrumentation/gc_stats.rb +6 -3
  118. data/test/performance/suites/transaction_tracing.rb +4 -1
  119. data/test/test_helper.rb +31 -60
  120. data/ui/views/newrelic/show_sample.rhtml +1 -1
  121. metadata +46 -101
  122. metadata.gz.sig +0 -0
  123. data/lib/new_relic/agent/stats_engine/transactions.rb +0 -114
  124. data/lib/new_relic/agent/transaction/pop.rb +0 -52
  125. data/test/new_relic/agent/transaction/pop_test.rb +0 -79
@@ -120,8 +120,8 @@ module NewRelic
120
120
 
121
121
  def transaction_trace_threshold
122
122
  source_class = Agent.config.source(TT_THRESHOLD_KEY).class
123
- if source_class == Configuration::DefaultSource && TransactionState.get.transaction
124
- TransactionState.get.transaction.apdex_t * 4
123
+ if source_class == Configuration::DefaultSource && TransactionState.get.current_transaction
124
+ TransactionState.get.current_transaction.apdex_t * 4
125
125
  else
126
126
  Agent.config[TT_THRESHOLD_KEY]
127
127
  end
@@ -19,11 +19,10 @@ module NewRelic
19
19
 
20
20
  # Module defining methods stubbed out when the agent is disabled
21
21
  module Shim #:nodoc:
22
- def notice_transaction(*args); end
23
- def notice_first_scope_push(*args); end
24
- def notice_push_scope(*args); end
25
- def notice_pop_scope(*args); end
26
- def notice_scope_empty(*args); end
22
+ def on_start_transaction(*args); end
23
+ def notice_push_frame(*args); end
24
+ def notice_pop_frame(*args); end
25
+ def on_finishing_transaction(*args); end
27
26
  end
28
27
 
29
28
  attr_reader :last_sample, :dev_mode_sample_buffer, :xray_sample_buffer
@@ -63,20 +62,19 @@ module NewRelic
63
62
  Agent.config[:'transaction_tracer.enabled'] || Agent.config[:developer_mode]
64
63
  end
65
64
 
66
- # Creates a new transaction sample builder, unless the
67
- # transaction sampler is disabled. Takes a time parameter for
68
- # the start of the transaction sample
69
- def notice_first_scope_push(time)
70
- start_builder(time.to_f) if enabled?
65
+ def on_start_transaction(start_time, uri=nil, params={})
66
+ if enabled?
67
+ start_builder(start_time.to_f)
68
+ builder.set_transaction_info(uri, params) if builder
69
+ end
71
70
  end
72
71
 
73
- # This delegates to the builder to create a new open transaction
74
- # segment for the specified scope, beginning at the optionally
75
- # specified time.
72
+ # This delegates to the builder to create a new open transaction segment
73
+ # for the frame, beginning at the optionally specified time.
76
74
  #
77
75
  # Note that in developer mode, this captures a stacktrace for
78
76
  # the beginning of each segment, which can be fairly slow
79
- def notice_push_scope(time=Time.now)
77
+ def notice_push_frame(time=Time.now)
80
78
  return unless builder
81
79
 
82
80
  segment = builder.trace_entry(time.to_f)
@@ -84,12 +82,11 @@ module NewRelic
84
82
  return segment
85
83
  end
86
84
 
87
- # Informs the transaction sample builder about the end of a
88
- # traced scope
89
- def notice_pop_scope(scope, time = Time.now)
85
+ # Informs the transaction sample builder about the end of a traced frame
86
+ def notice_pop_frame(frame, time = Time.now)
90
87
  return unless builder
91
88
  raise "finished already???" if builder.sample.finished
92
- builder.trace_exit(scope, time.to_f)
89
+ builder.trace_exit(frame, time.to_f)
93
90
  end
94
91
 
95
92
  def custom_parameters_from_transaction(txn)
@@ -103,13 +100,13 @@ module NewRelic
103
100
  # This is called when we are done with the transaction. We've
104
101
  # unwound the stack to the top level. It also clears the
105
102
  # transaction sample builder so that it won't continue to have
106
- # scopes appended to it.
103
+ # frames appended to it.
107
104
  #
108
105
  # It sets various instance variables to the finished sample,
109
106
  # depending on which settings are active. See `store_sample`
110
- def notice_scope_empty(txn, time=Time.now, gc_time=nil)
107
+ def on_finishing_transaction(txn, time=Time.now, gc_time=nil)
111
108
  last_builder = builder
112
- last_builder.set_transaction_name(txn.name) if enabled? && last_builder
109
+ last_builder.set_transaction_name(txn.best_name) if enabled? && last_builder
113
110
 
114
111
  return unless last_builder
115
112
 
@@ -132,12 +129,6 @@ module NewRelic
132
129
  end
133
130
  end
134
131
 
135
- # Delegates to the builder to store the uri, and
136
- # parameters if the sampler is active
137
- def notice_transaction(uri=nil, params={})
138
- builder.set_transaction_info(uri, params) if enabled? && builder
139
- end
140
-
141
132
  # Tells the builder to ignore a transaction, if we are currently
142
133
  # creating one. Only causes the sample to be ignored upon end of
143
134
  # the transaction, and does not change the metrics gathered
@@ -3,6 +3,7 @@
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
 
5
5
  require 'new_relic/agent/browser_token'
6
+ require 'new_relic/agent/traced_method_stack'
6
7
 
7
8
  module NewRelic
8
9
  module Agent
@@ -38,11 +39,11 @@ module NewRelic
38
39
  end
39
40
 
40
41
  def initialize
41
- @stats_scope_stack = []
42
+ @traced_method_stack = TracedMethodStack.new
43
+ @current_transaction = nil
42
44
  end
43
45
 
44
46
  def request=(request)
45
- reset unless reset?
46
47
  @request = request
47
48
  @request_token = BrowserToken.get_token(request)
48
49
  end
@@ -52,7 +53,7 @@ module NewRelic
52
53
  # not available, we track the last reset. No accessor, as only the
53
54
  # TransactionState class should use it.
54
55
  @last_reset_time = Time.now
55
- @transaction = nil
56
+ @most_recent_transaction = nil
56
57
  @timings = nil
57
58
  @request = nil
58
59
  @request_token = nil
@@ -61,10 +62,6 @@ module NewRelic
61
62
  @referring_transaction_info = nil
62
63
  end
63
64
 
64
- def reset?
65
- @transaction.nil?
66
- end
67
-
68
65
  def timings
69
66
  @timings ||= TransactionTimings.new(transaction_queue_time, transaction_start_time, transaction_name)
70
67
  end
@@ -91,8 +88,8 @@ module NewRelic
91
88
  attr_accessor :request_token, :request_ignore_enduser
92
89
 
93
90
  def request_guid
94
- return nil unless transaction
95
- transaction.guid
91
+ return nil unless most_recent_transaction
92
+ most_recent_transaction.guid
96
93
  end
97
94
 
98
95
  def request_guid_to_include
@@ -101,40 +98,31 @@ module NewRelic
101
98
  end
102
99
 
103
100
  def include_guid?
104
- request_token && timings.app_time_in_seconds > transaction.apdex_t
101
+ request_token && timings.app_time_in_seconds > most_recent_transaction.apdex_t
105
102
  end
106
103
 
107
104
  # Current transaction stack and sample building
108
- attr_accessor :transaction, :transaction_sample_builder
109
- attr_writer :current_transaction_stack
110
-
111
- # Returns and initializes the transaction stack if necessary
112
- #
113
- # We don't default in the initializer so non-transaction threads retain
114
- # a nil stack, and methods in this class use has_current_transction?
115
- # instead of this accessor to see if we're a transaction thread or not
116
- def current_transaction_stack
117
- @current_transaction_stack ||= []
118
- end
105
+ attr_accessor :most_recent_transaction, :transaction_sample_builder,
106
+ :current_transaction
119
107
 
120
108
  def transaction_start_time
121
- if transaction.nil?
109
+ if most_recent_transaction.nil?
122
110
  @last_reset_time
123
111
  else
124
- transaction.start_time
112
+ most_recent_transaction.start_time
125
113
  end
126
114
  end
127
115
 
128
116
  def transaction_queue_time
129
- transaction.nil? ? 0.0 : transaction.queue_time
117
+ most_recent_transaction.nil? ? 0.0 : most_recent_transaction.queue_time
130
118
  end
131
119
 
132
120
  def transaction_name
133
- transaction.nil? ? nil : transaction.name
121
+ most_recent_transaction.nil? ? nil : most_recent_transaction.best_name
134
122
  end
135
123
 
136
124
  def transaction_noticed_error_ids
137
- transaction.nil? ? [] : transaction.noticed_error_ids
125
+ most_recent_transaction.nil? ? [] : most_recent_transaction.noticed_error_ids
138
126
  end
139
127
 
140
128
  def self.in_background_transaction?(thread)
@@ -153,14 +141,6 @@ module NewRelic
153
141
  !current_transaction.nil? && !current_transaction.request.nil?
154
142
  end
155
143
 
156
- def current_transaction
157
- current_transaction_stack.last if has_current_transaction?
158
- end
159
-
160
- def has_current_transaction?
161
- !@current_transaction_stack.nil?
162
- end
163
-
164
144
  # Execution tracing on current thread
165
145
  attr_accessor :untraced
166
146
 
@@ -196,12 +176,7 @@ module NewRelic
196
176
 
197
177
  # Scope stack tracking from NewRelic::StatsEngine::Transactions
198
178
  # Should not be nil--this class manages its initialization and resetting
199
- attr_accessor :stats_scope_stack
200
-
201
- def clear_stats_scope_stack
202
- @stats_scope_stack = []
203
- end
204
-
179
+ attr_reader :traced_method_stack
205
180
  end
206
181
  end
207
182
  end
@@ -50,7 +50,7 @@ module NewRelic
50
50
  def init_plugin(options={})
51
51
  env = options[:env] || self.env
52
52
  Agent.logger.info("Starting the New Relic agent in #{env.inspect} environment.")
53
- Agent.logger.info("To prevent agent startup add a NEWRELIC_ENABLE=false environment variable or modify the #{env.inspect} section of your newrelic.yml.")
53
+ Agent.logger.info("To prevent agent startup add a NEWRELIC_AGENT_ENABLED=false environment variable or modify the #{env.inspect} section of your newrelic.yml.")
54
54
 
55
55
  configure_agent(env, options)
56
56
 
@@ -79,9 +79,13 @@ module NewRelic
79
79
  end
80
80
 
81
81
  def configure_agent(env, options)
82
- yaml = Agent::Configuration::YamlSource.new(@config_file_path, env)
83
- Agent.config.replace_or_add_config(yaml, 1)
82
+ manual = Agent::Configuration::ManualSource.new(options)
83
+ Agent.config.replace_or_add_config(manual, 1)
84
84
 
85
+ config_file_path = @config_file_override || Agent.config[:config_path]
86
+ Agent.config.replace_or_add_config(Agent::Configuration::YamlSource.new(config_file_path, env), 1)
87
+
88
+ Agent.config.remove_config(manual)
85
89
  Agent.config.replace_or_add_config(Agent::Configuration::ManualSource.new(options), 1)
86
90
  end
87
91
 
@@ -122,7 +126,7 @@ module NewRelic
122
126
  def initialize(local_env, config_file_override=nil)
123
127
  @local_env = local_env
124
128
  @instrumentation_files = []
125
- @config_file_path = config_file_override || Agent.config[:config_path]
129
+ @config_file_override = config_file_override
126
130
  end
127
131
 
128
132
  def root
@@ -34,7 +34,7 @@ make_notify_task = Proc.new do
34
34
  user = fetch(:newrelic_user) if exists?(:newrelic_user)
35
35
  license_key = fetch(:newrelic_license_key) if exists?(:newrelic_license_key)
36
36
 
37
- unless scm == :none
37
+ unless scm.to_sym == :none
38
38
  changelog = lookup_changelog(changelog)
39
39
  rev = lookup_rev(rev)
40
40
  end
@@ -76,7 +76,7 @@ make_notify_task = Proc.new do
76
76
  logger.debug "Getting log of changes for New Relic Deployment details"
77
77
  from_revision = source.next_revision(current_revision)
78
78
 
79
- if scm == :git
79
+ if scm.to_sym == :git
80
80
  log_command = "git log --no-color --pretty=format:' * %an: %s' " +
81
81
  "--abbrev-commit --no-merges #{previous_revision}..#{real_revision}"
82
82
  else
@@ -95,7 +95,7 @@ make_notify_task = Proc.new do
95
95
  `#{cmd}`
96
96
  end
97
97
 
98
- rev = rev[0..6] if scm == :git
98
+ rev = rev[0..6] if scm.to_sym == :git
99
99
  end
100
100
  rev
101
101
  end
@@ -16,7 +16,7 @@ module NewRelic
16
16
  class TransactionSample
17
17
 
18
18
  attr_accessor :params, :root_segment, :profile, :force_persist, :guid,
19
- :threshold, :finished, :xray_session_id
19
+ :threshold, :finished, :xray_session_id, :start_time
20
20
  attr_reader :root_segment, :params, :sample_id
21
21
  attr_writer :prepared
22
22
 
@@ -84,10 +84,6 @@ module NewRelic
84
84
  ]
85
85
  end
86
86
 
87
- def start_time
88
- Time.at(@start_time)
89
- end
90
-
91
87
  def path_string
92
88
  @root_segment.path_string
93
89
  end
@@ -139,7 +135,7 @@ module NewRelic
139
135
  end
140
136
 
141
137
  def to_s
142
- s = "Transaction Sample collected at #{start_time}\n"
138
+ s = "Transaction Sample collected at #{Time.at(start_time)}\n"
143
139
  s << " {\n"
144
140
  s << " Path: #{params[:path]} \n"
145
141
 
@@ -201,7 +197,7 @@ module NewRelic
201
197
 
202
198
  def force_persist_sample?
203
199
  NewRelic::Agent::TransactionState.get.request_token &&
204
- self.duration > NewRelic::Agent::TransactionState.get.transaction.apdex_t
200
+ self.duration > NewRelic::Agent::TransactionState.get.current_transaction.apdex_t
205
201
  end
206
202
 
207
203
  private
@@ -12,7 +12,7 @@ module NewRelic
12
12
 
13
13
  MAJOR = 3
14
14
  MINOR = 8
15
- TINY = 0
15
+ TINY = 1
16
16
 
17
17
  begin
18
18
  require File.join(File.dirname(__FILE__), 'build')
@@ -71,7 +71,7 @@ module Sequel
71
71
  (defined?(::Sequel::ThreadedConnectionPool) && ::Sequel::ThreadedConnectionPool),
72
72
  ].compact.freeze
73
73
 
74
- # Record the given +sql+ within a new scope, using the given +start+ and
74
+ # Record the given +sql+ within a new frame, using the given +start+ and
75
75
  # +finish+ times.
76
76
  def notice_sql( sql, args, start, finish )
77
77
  metric = primary_metric_for( sql, args )
@@ -79,7 +79,7 @@ module Sequel
79
79
  duration = finish - start
80
80
 
81
81
  begin
82
- scope = agent.stats_engine.push_scope( :sequel, start )
82
+ frame = NewRelic::Agent::TracedMethodStack.push_frame( :sequel, start )
83
83
  explainer = Proc.new do |*|
84
84
  if THREAD_SAFE_CONNECTION_POOL_CLASSES.include?(self.pool.class)
85
85
  self[ sql ].explain
@@ -91,7 +91,7 @@ module Sequel
91
91
  agent.transaction_sampler.notice_sql( sql, self.opts, duration, &explainer )
92
92
  agent.sql_sampler.notice_sql( sql, metric, self.opts, duration, &explainer )
93
93
  ensure
94
- agent.stats_engine.pop_scope( scope, metric, finish )
94
+ NewRelic::Agent::TracedMethodStack.pop_frame( frame, metric, finish )
95
95
  end
96
96
  end
97
97
 
@@ -36,27 +36,33 @@ EOS
36
36
  s.files = file_list
37
37
 
38
38
  s.homepage = "http://www.github.com/newrelic/rpm"
39
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "New Relic Ruby Agent"]
40
39
  s.require_paths = ["lib"]
41
40
  s.rubygems_version = Gem::VERSION
42
41
  s.summary = "New Relic Ruby Agent"
43
42
  s.post_install_message = NewRelic::LatestChanges.read
44
- s.add_development_dependency 'rubysl' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
45
- s.add_development_dependency 'racc' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
43
+
46
44
  s.add_development_dependency 'rake', '10.1.0'
47
45
  s.add_development_dependency 'minitest', '~> 4.7.5'
48
46
  s.add_development_dependency 'mocha', '~> 0.13.0'
49
- s.add_development_dependency 'sdoc-helpers'
50
- s.add_development_dependency 'rdoc', '>= 2.4.2'
47
+ s.add_development_dependency 'yard'
51
48
  s.add_development_dependency 'rails', '~> 3.2.13'
52
- s.add_development_dependency 'sqlite3', '1.3.8' unless RUBY_PLATFORM == 'java'
53
- s.add_development_dependency 'activerecord-jdbcsqlite3-adapter' if RUBY_PLATFORM == 'java'
54
- s.add_development_dependency 'jruby-openssl' if RUBY_PLATFORM == 'java'
55
- s.add_development_dependency 'sequel', '~> 3.46.0'
56
49
  s.add_development_dependency 'pry'
50
+ # s.add_development_dependency 'pry-nav'
57
51
  s.add_development_dependency 'guard', '~> 1.8.3' # Guard 2.0 is Ruby 1.9 only
58
52
  s.add_development_dependency 'guard-minitest'
59
53
  s.add_development_dependency 'rb-fsevent', '~> 0.9.1'
54
+ s.add_development_dependency 'jruby-openssl' if RUBY_PLATFORM == 'java'
55
+
56
+ if RUBY_PLATFORM == 'java'
57
+ s.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
58
+ else
59
+ s.add_development_dependency 'sqlite3', '1.3.8'
60
+ end
61
+
62
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
63
+ s.add_development_dependency 'rubysl'
64
+ s.add_development_dependency 'racc'
65
+ end
60
66
 
61
67
  # Only sign with our private key if you can find it
62
68
  signing_key_path = File.expand_path('~/.ssh/newrelic_rpm-private_key.pem')
@@ -5,6 +5,19 @@
5
5
  # These helpers should not have any gem dependencies except on newrelic_rpm
6
6
  # itself, and should be usable from within any multiverse suite.
7
7
 
8
+ class ArrayLogDevice
9
+ def initialize( array=[] )
10
+ @array = array
11
+ end
12
+ attr_reader :array
13
+
14
+ def write( message )
15
+ @array << message
16
+ end
17
+
18
+ def close; end
19
+ end
20
+
8
21
  def assert_between(floor, ceiling, value, message="expected #{floor} <= #{value} <= #{ceiling}")
9
22
  assert((floor <= value && value <= ceiling), message)
10
23
  end
@@ -19,14 +32,6 @@ def assert_has_error(error_class)
19
32
  "Didn't find error of class #{error_class}"
20
33
  end
21
34
 
22
-
23
- unless defined?( build_message )
24
- def build_message(head, template=nil, *arguments)
25
- template &&= template.chomp
26
- template.gsub(/\?/) { mu_pp(arguments.shift) }
27
- end
28
- end
29
-
30
35
  unless defined?( assert_block )
31
36
  def assert_block(*msgs)
32
37
  assert yield, *msgs
@@ -35,14 +40,14 @@ end
35
40
 
36
41
  unless defined?( assert_includes )
37
42
  def assert_includes( collection, member, msg=nil )
38
- msg = build_message( msg, "Expected ? to include ?", collection, member )
43
+ msg = "Expected #{collection.inspect} to include #{member.inspect}"
39
44
  assert_block( msg ) { collection.include?(member) }
40
45
  end
41
46
  end
42
47
 
43
48
  unless defined?( assert_not_includes )
44
49
  def assert_not_includes( collection, member, msg=nil )
45
- msg = build_message( msg, "Expected ? not to include ?", collection, member )
50
+ msg = "Expected #{collection.inspect} not to include #{member.inspect}"
46
51
  assert !collection.include?(member), msg
47
52
  end
48
53
  end
@@ -91,14 +96,14 @@ def assert_metrics_recorded(expected)
91
96
  expected_spec = metric_spec_from_specish(specish)
92
97
  actual_stats = NewRelic::Agent.instance.stats_engine.lookup_stats(*Array(specish))
93
98
  if !actual_stats
94
- all_specs = NewRelic::Agent.instance.stats_engine.metric_specs
99
+ all_specs = NewRelic::Agent.instance.stats_engine.metric_specs.sort
95
100
  matches = all_specs.select { |spec| spec.name == expected_spec.name }
96
101
  matches.map! { |m| " #{m.inspect}" }
97
102
  msg = "Did not find stats for spec #{expected_spec.inspect}."
98
103
  msg += "\nDid find specs: [\n#{matches.join(",\n")}\n]" unless matches.empty?
99
104
 
100
105
  msg += "\nAll specs in there were: [\n#{all_specs.map do |s|
101
- "#{s.name} (#{s.scope.empty? ? '<unscoped>' : s.scope})"
106
+ " #{s.name} (#{s.scope.empty? ? '<unscoped>' : s.scope})"
102
107
  end.join(",\n")}\n]"
103
108
 
104
109
  assert(actual_stats, msg)
@@ -142,12 +147,12 @@ def assert_metrics_not_recorded(not_expected)
142
147
  end
143
148
 
144
149
  def assert_truthy(expected, msg = nil)
145
- msg = build_message( msg, "Expected ? to be truthy", expected )
150
+ msg = "Expected #{expected.inspect} to be truthy"
146
151
  assert !!expected, msg
147
152
  end
148
153
 
149
154
  def assert_falsy(expected, msg = nil)
150
- msg = build_message( msg, "Expected ? to be falsy", expected )
155
+ msg = "Expected #{expected.inspect} to be falsy"
151
156
  assert !expected, msg
152
157
  end
153
158
 
@@ -157,7 +162,7 @@ unless defined?( assert_false )
157
162
  end
158
163
  end
159
164
 
160
- unless defined? ( refute )
165
+ unless defined?(refute)
161
166
  alias refute assert_false
162
167
  end
163
168
 
@@ -181,16 +186,19 @@ end
181
186
  #
182
187
  def in_transaction(*args)
183
188
  opts = (args.last && args.last.is_a?(Hash)) ? args.pop : {}
184
- name = args.first || 'dummy'
189
+ opts[:transaction_name] = args.first || 'dummy'
185
190
  transaction_type = (opts && opts.delete(:type)) || :other
186
191
 
187
- NewRelic::Agent.instance.instance_variable_set(:@transaction_sampler,
188
- NewRelic::Agent::TransactionSampler.new)
189
- NewRelic::Agent.instance.stats_engine.transaction_sampler = \
190
- NewRelic::Agent.instance.transaction_sampler
191
- NewRelic::Agent::Transaction.start(transaction_type, opts || {})
192
- val = yield NewRelic::Agent::Transaction.current
193
- NewRelic::Agent::Transaction.stop(name)
192
+ NewRelic::Agent::Transaction.start(transaction_type, opts)
193
+
194
+ val = nil
195
+
196
+ begin
197
+ val = yield NewRelic::Agent::Transaction.current
198
+ ensure
199
+ NewRelic::Agent::Transaction.stop()
200
+ end
201
+
194
202
  val
195
203
  end
196
204
 
@@ -251,27 +259,34 @@ def advance_time(seconds)
251
259
  freeze_time(Time.now + seconds)
252
260
  end
253
261
 
254
- def define_constant(constant_symbol, implementation)
255
- if Object.const_defined?(constant_symbol)
256
- existing_implementation = Object.send(:remove_const, constant_symbol)
257
- end
258
-
259
- Object.const_set(constant_symbol, implementation)
262
+ def with_constant_defined(constant_symbol, implementation)
263
+ const_path = constant_path(constant_symbol.to_s)
260
264
 
261
- yield
262
- ensure
263
- Object.send(:remove_const, constant_symbol)
265
+ if const_path
266
+ # Constant is already defined, nothing to do
267
+ return yield
268
+ else
269
+ const_path = constant_path(constant_symbol.to_s, :allow_partial => true)
270
+ parent = const_path[-1]
271
+ constant_symbol = constant_symbol.to_s.split('::').last.to_sym
272
+ end
264
273
 
265
- if existing_implementation
266
- Object.const_set(constant_symbol, existing_implementation)
274
+ begin
275
+ parent.const_set(constant_symbol, implementation)
276
+ yield
277
+ ensure
278
+ parent.send(:remove_const, constant_symbol)
267
279
  end
268
280
  end
269
281
 
270
- def constant_path(name)
282
+ def constant_path(name, opts={})
283
+ allow_partial = opts[:allow_partial]
271
284
  path = [Object]
272
285
  parts = name.gsub(/^::/, '').split('::')
273
286
  parts.each do |part|
274
- return nil unless path.last.const_defined?(part)
287
+ if !path.last.const_defined?(part)
288
+ return allow_partial ? path : nil
289
+ end
275
290
  path << path.last.const_get(part)
276
291
  end
277
292
  path
@@ -320,3 +335,23 @@ def wait_for_backtrace_service_poll(opts={})
320
335
  end
321
336
  end
322
337
  end
338
+
339
+ def with_array_logger(level=:info)
340
+ orig_logger = NewRelic::Agent.logger
341
+ config = {
342
+ :log_file_path => nil,
343
+ :log_file_name => nil,
344
+ :log_level => level,
345
+ }
346
+ logdev = ArrayLogDevice.new
347
+ override_logger = Logger.new(logdev)
348
+
349
+ with_config(config) do
350
+ NewRelic::Agent.logger = NewRelic::Agent::AgentLogger.new("", override_logger)
351
+ yield
352
+ end
353
+
354
+ return logdev
355
+ ensure
356
+ NewRelic::Agent.logger = orig_logger
357
+ end