newrelic_rpm 3.3.1.beta1 → 3.3.1.beta2

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.

data/CHANGELOG CHANGED
@@ -1,6 +1,8 @@
1
1
  v3.3.1
2
2
  * improved Ruby 1.8.6 support
3
3
  * fix for issues with RAILS_ROOT deprecation warnings
4
+ * fixed incorrect 1.9 GC time reporting
5
+ * obfusction for Slow SQL queries respects transaction trace config
4
6
 
5
7
  v3.3.0
6
8
  * fix for GC instrumentation when using Ruby 1.9
@@ -231,7 +231,8 @@ module NewRelic
231
231
  # If a single argument is passed in, it is treated as a metric
232
232
  # path. This form is deprecated.
233
233
  def perform_action_with_newrelic_trace(*args, &block)
234
- NewRelic::Agent::TransactionInfo.clear
234
+ NewRelic::Agent::TransactionInfo.reset unless NewRelic::Control.
235
+ instance.browser_monitoring_auto_instrument?
235
236
 
236
237
  # Skip instrumentation based on the value of 'do_not_trace' and if
237
238
  # we aren't calling directly with a block.
@@ -43,14 +43,22 @@ module NewRelic
43
43
  disable
44
44
  end
45
45
  end
46
-
46
+
47
47
  def config
48
- control = NewRelic::Control.instance
49
- # Default slow_sql config values to transaction tracer config
50
- control.fetch('transaction_tracer', {}).
51
- merge( control.fetch('slow_sql', {}) )
48
+ self.class.config
52
49
  end
53
50
 
51
+ def self.config
52
+ control = NewRelic::Control.instance
53
+ txn_config = control.fetch('transaction_tracer', {})
54
+
55
+ if txn_config.fetch('enabled', true) && control.has_slow_sql_config?
56
+ txn_config['enabled'] = control['slow_sql']['enabled']
57
+ end
58
+
59
+ txn_config
60
+ end
61
+
54
62
  # Enable the sql sampler - this also registers it with
55
63
  # the statistics engine.
56
64
  def enable
@@ -246,9 +254,7 @@ module NewRelic
246
254
  end
247
255
 
248
256
  def agent_config
249
- control = NewRelic::Control.instance
250
- control.fetch('slow_sql',
251
- control.fetch('transaction_tracer', {}))
257
+ NewRelic::Agent::SqlSampler.config
252
258
  end
253
259
 
254
260
  def need_to_obfuscate?
@@ -40,7 +40,7 @@ module NewRelic
40
40
 
41
41
  def record_gc_metric(num_calls, elapsed)
42
42
  if num_calls > 0
43
- # µs to seconds
43
+ # microseconds to seconds
44
44
  elapsed = elapsed / 1_000_000.0
45
45
  # Allocate the GC time to a scope as if the GC just ended
46
46
  # right now.
@@ -64,8 +64,9 @@ module NewRelic
64
64
  ::GC.respond_to?(:time) && ::GC.respond_to?(:collections)
65
65
  end
66
66
 
67
+ # microseconds spent in GC
67
68
  def call_time
68
- ::GC.time
69
+ ::GC.time # this should already be microseconds
69
70
  end
70
71
 
71
72
  def call_count
@@ -78,8 +79,10 @@ module NewRelic
78
79
  defined?(::GC::Profiler) && ::GC::Profiler.enabled?
79
80
  end
80
81
 
82
+ # microseconds spent in GC
83
+ # 1.9 total_time returns seconds. Don't trust the docs. It's seconds.
81
84
  def call_time
82
- ::GC::Profiler.total_time * 1000.0
85
+ ::GC::Profiler.total_time * 1_000_000.0 # convert seconds to microseconds
83
86
  end
84
87
 
85
88
  def call_count
@@ -1,48 +1,55 @@
1
1
  module NewRelic
2
2
  module Agent
3
3
  class TransactionInfo
4
-
4
+
5
5
  attr_accessor :token, :capture_deep_tt, :transaction_name
6
6
  attr_reader :start_time
7
-
7
+
8
8
  def initialize
9
9
  @guid = ""
10
10
  @transaction_name = "(unknown)"
11
11
  @start_time = Time.now
12
12
  end
13
-
13
+
14
14
  def force_persist_sample?(sample)
15
15
  token && sample.duration > NewRelic::Control.instance.apdex_t
16
16
  end
17
-
17
+
18
18
  def include_guid?
19
19
  token && duration > NewRelic::Control.instance.apdex_t
20
20
  end
21
-
21
+
22
22
  def guid
23
23
  @guid
24
24
  end
25
-
25
+
26
26
  def guid=(value)
27
27
  @guid = value
28
28
  end
29
-
29
+
30
30
  def duration
31
31
  Time.now - start_time
32
32
  end
33
-
33
+
34
34
  def self.get()
35
35
  Thread.current[:newrelic_transaction_info] ||= TransactionInfo.new
36
36
  end
37
-
37
+
38
38
  def self.set(instance)
39
39
  Thread.current[:newrelic_transaction_info] = instance
40
40
  end
41
-
41
+
42
42
  def self.clear
43
43
  Thread.current[:newrelic_transaction_info] = nil
44
44
  end
45
-
45
+
46
+ # clears any existing transaction info object and initializes a new one.
47
+ # This starts the timer for the transaction.
48
+ def self.reset
49
+ clear
50
+ get
51
+ end
52
+
46
53
  end
47
54
  end
48
55
  end
@@ -38,7 +38,7 @@ module NewRelic
38
38
  @leftover = @options.parse(command_line_args)
39
39
  end
40
40
  rescue OptionParser::ParseError => e
41
- raise CommandFailure.new e.message, @options
41
+ raise CommandFailure.new(e.message, @options)
42
42
  end
43
43
 
44
44
  @commands = []
@@ -196,6 +196,10 @@ module NewRelic
196
196
  def disable_backtrace_cleanup?
197
197
  fetch('disable_backtrace_cleanup')
198
198
  end
199
+
200
+ def has_slow_sql_config?
201
+ self['slow_sql'] && self['slow_sql'].has_key?('enabled')
202
+ end
199
203
  end
200
204
  include Configuration
201
205
  end
@@ -52,7 +52,7 @@ module NewRelic
52
52
  def install_browser_monitoring(config)
53
53
  return if @browser_monitoring_installed
54
54
  @browser_monitoring_installed = true
55
- return if config.nil? || !config.respond_to?(:middleware) || !browser_monitoring_auto_instrument?
55
+ return if config.nil? || !config.respond_to?(:middleware) || ! browser_monitoring_auto_instrument?
56
56
  begin
57
57
  require 'new_relic/rack/browser_monitoring'
58
58
  config.middleware.use NewRelic::Rack::BrowserMonitoring
@@ -18,7 +18,12 @@ class NewRelic::NoticedError
18
18
  # clamp long messages to 4k so that we don't send a lot of
19
19
  # overhead across the wire
20
20
  self.message = self.message[0..4095] if self.message.length > 4096
21
-
21
+
22
+ # obfuscate error message if necessary
23
+ if NewRelic::Control.instance.fetch('high_security', false)
24
+ self.message = NewRelic::Agent::Database.obfuscate_sql(self.message)
25
+ end
26
+
22
27
  self.timestamp = timestamp
23
28
  end
24
29
  end
@@ -13,7 +13,7 @@ module NewRelic::Rack
13
13
  req = Rack::Request.new(env)
14
14
 
15
15
  # clear any previous transaction info
16
- NewRelic::Agent::TransactionInfo.clear
16
+ NewRelic::Agent::TransactionInfo.reset
17
17
 
18
18
  agent_flag = req.cookies['NRAGENT']
19
19
 
@@ -22,8 +22,8 @@ module NewRelic
22
22
  @root_segment = create_segment 0.0, "ROOT"
23
23
  @params = {}
24
24
  @params[:request_params] = {}
25
-
26
- @guid = (0..15).to_a.map{|a| rand(16).to_s(16)}.join # a 64 bit random GUID
25
+
26
+ @guid = generate_guid
27
27
  NewRelic::Agent::TransactionInfo.get.guid = @guid
28
28
  end
29
29
 
@@ -173,6 +173,10 @@ module NewRelic
173
173
 
174
174
  private
175
175
 
176
+ def generate_guid
177
+ (0..15).to_a.map{|a| rand(16).to_s(16)}.join # a 64 bit random GUID
178
+ end
179
+
176
180
  # This is badly in need of refactoring
177
181
  def build_segment_with_omissions(new_sample, time_delta, source_segment, target_segment, regex)
178
182
  source_segment.called_segments.each do |source_called_segment|
@@ -4,7 +4,7 @@ module NewRelic
4
4
  MAJOR = 3
5
5
  MINOR = 3
6
6
  TINY = 1
7
- BUILD = 'beta1' # Set to nil for a release, 'beta1', 'alpha', etc for prerelease builds
7
+ BUILD = 'beta2' # Set to nil for a release, 'beta1', 'alpha', etc for prerelease builds
8
8
  STRING = [MAJOR, MINOR, TINY, BUILD].compact.join('.')
9
9
  end
10
10
 
data/newrelic_rpm.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "newrelic_rpm"
8
- s.version = "3.3.1.beta1"
8
+ s.version = "3.3.1.beta2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bill Kayser", "Jon Guymon", "Justin George", "Darin Swanson"]
12
- s.date = "2011-11-11"
12
+ s.date = "2011-11-29"
13
13
  s.description = "New Relic is a performance management system, developed by New Relic,\nInc (http://www.newrelic.com). New Relic provides you with deep\ninformation about the performance of your web application as it runs\nin production. The New Relic Ruby Agent is dual-purposed as a either a\nGem or plugin, hosted on\nhttp://github.com/newrelic/rpm/\n"
14
14
  s.email = "support@newrelic.com"
15
15
  s.executables = ["mongrel_rpm", "newrelic", "newrelic_cmd"]
@@ -21,7 +21,7 @@ class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
21
21
  mocha_teardown
22
22
  end
23
23
 
24
- def test_browser_monitoring_start_time_is_reset_each_request
24
+ def test_browser_monitoring_start_time_is_reset_each_request_when_auto_instrument_is_disabled
25
25
  controller = Object.new
26
26
  def controller.perform_action_without_newrelic_trace(method, options={});
27
27
  # noop; instrument me
@@ -29,6 +29,7 @@ class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
29
29
  def controller.newrelic_metric_path; "foo"; end
30
30
  controller.extend ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
31
31
  controller.extend ::NewRelic::Agent::BrowserMonitoring
32
+ NewRelic::Control.instance['browser_monitoring'] = { 'auto_instrument' => false }
32
33
 
33
34
  controller.perform_action_with_newrelic_trace(:index)
34
35
  first_request_start_time = controller.send(:browser_monitoring_start_time)
@@ -3,12 +3,12 @@ ENV['SKIP_RAILS'] = 'true'
3
3
  require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
4
4
 
5
5
  class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
6
-
7
6
  def setup
8
7
  super
9
8
  @error_collector = NewRelic::Agent::ErrorCollector.new
10
9
  @error_collector.stubs(:enabled).returns(true)
11
10
  end
11
+
12
12
  def test_empty
13
13
  @error_collector.harvest_errors([])
14
14
  @error_collector.notice_error(nil, :metric=> 'path', :request_params => {:x => 'y'})
@@ -26,8 +26,8 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
26
26
  assert_equal '', err.params[:request_referer]
27
27
  assert_equal 'path', err.path
28
28
  assert_equal 'Error', err.exception_class
29
-
30
29
  end
30
+
31
31
  def test_simple
32
32
  @error_collector.notice_error(Exception.new("message"), :uri => '/myurl/', :metric => 'path', :referer => 'test_referer', :request_params => {:x => 'y'})
33
33
 
@@ -155,6 +155,23 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
155
155
  assert_equal 1, errors.length
156
156
  end
157
157
 
158
+ def test_obfuscates_error_messages_when_high_security_is_set
159
+ NewRelic::Control.instance['high_security'] = true
160
+
161
+ @error_collector.notice_error(Exception.new("YO SQL BAD: serect * flom test where foo = 'bar'"))
162
+ @error_collector.notice_error(Exception.new("YO SQL BAD: serect * flom test where foo in (1,2,3,4,5)"))
163
+
164
+ old_errors = []
165
+ errors = @error_collector.harvest_errors([])
166
+
167
+ assert_equal('YO SQL BAD: serect * flom test where foo = ?',
168
+ errors[0].message)
169
+ assert_equal('YO SQL BAD: serect * flom test where foo in (?,?,?,?,?)',
170
+ errors[1].message)
171
+
172
+ NewRelic::Control.instance['high_security'] = nil
173
+ end
174
+
158
175
  private
159
176
 
160
177
  def wrapped_filter_proc
@@ -147,7 +147,7 @@ class NewRelic::Agent::SqlSamplerTest < Test::Unit::TestCase
147
147
  end
148
148
 
149
149
  def test_should_not_collect_explain_plans_when_disabled
150
- NewRelic::Control.instance['slow_sql'] = { 'explain_enabled' => false }
150
+ NewRelic::Control.instance['transaction_tracer'] = { 'explain_enabled' => false }
151
151
  data = NewRelic::Agent::TransactionSqlData.new
152
152
  data.set_transaction_info("WebTransaction/Controller/c/a", "/c/a", {},
153
153
  'guid')
@@ -160,7 +160,7 @@ class NewRelic::Agent::SqlSamplerTest < Test::Unit::TestCase
160
160
  @sampler.harvest_slow_sql data
161
161
  sql_traces = @sampler.harvest
162
162
  assert_equal(nil, sql_traces[0].params[:explain_plan])
163
- NewRelic::Control.instance['slow_sql'] = { 'explain_enabled' => true }
163
+ NewRelic::Control.instance['transaction_tracer'] = { 'explain_enabled' => true }
164
164
  end
165
165
 
166
166
  def test_sql_id_fits_in_a_mysql_int_11
@@ -173,15 +173,20 @@ class NewRelic::Agent::SqlSamplerTest < Test::Unit::TestCase
173
173
  assert 2147483647 >= sql_trace.sql_id, "sql_id too large"
174
174
  end
175
175
 
176
- def test_config_values_default_to_transaction_tracer_config
177
-
178
- NewRelic::Control.instance['slow_sql'] = { "explain_enabled"=> false }
179
-
180
- assert_equal NewRelic::Agent.instance.sql_sampler.config['stack_trace_threshold'], 0.1 # transaction_tracer default
181
- assert_equal NewRelic::Agent.instance.sql_sampler.config['explain_enabled'], false
182
-
183
- # put things back how we found them
184
- NewRelic::Control.instance['slow_sql'] = { "explain_enabled"=> true }
176
+ def test_sends_obfuscated_queries_when_configured
177
+ NewRelic::Control.instance['transaction_tracer'] = { 'record_sql' => 'obfuscated' }
178
+
179
+ data = NewRelic::Agent::TransactionSqlData.new
180
+ data.set_transaction_info("WebTransaction/Controller/c/a", "/c/a", {},
181
+ 'guid')
182
+ data.sql_data.concat([NewRelic::Agent::SlowSql.new("select * from test where foo = 'bar'",
183
+ "Database/test/select", {}, 1.5),
184
+ NewRelic::Agent::SlowSql.new("select * from test where foo in (1,2,3,4,5)",
185
+ "Database/test/select", {}, 1.2)])
186
+ @sampler.harvest_slow_sql(data)
187
+ sql_traces = @sampler.harvest
185
188
 
189
+ assert_equal('select * from test where foo = ?', sql_traces[0].sql)
190
+ assert_equal('select * from test where foo in (?,?,?,?,?)', sql_traces[1].sql)
186
191
  end
187
192
  end
@@ -193,7 +193,7 @@ class NewRelic::Agent::StatsEngineTest < Test::Unit::TestCase
193
193
  ::Rubinius::Agent.stubs(:loopback).returns(agent)
194
194
  elsif NewRelic::LanguageSupport.using_version?('1.9')
195
195
  ::GC::Profiler.stubs(:enabled?).returns(true)
196
- ::GC::Profiler.stubs(:total_time).returns(1000, 4000)
196
+ ::GC::Profiler.stubs(:total_time).returns(1.0, 4.0)
197
197
  ::GC.stubs(:count).returns(1, 3)
198
198
  elsif NewRelic::LanguageSupport.using_version?('1.8')
199
199
  ::GC.stubs(:time).returns(1000000, 4000000)
@@ -5,11 +5,26 @@ require 'new_relic/rack/browser_monitoring'
5
5
 
6
6
  ENV['RACK_ENV'] = 'test'
7
7
 
8
+ # we should expand the environments we support, any rack app could
9
+ # benefit from auto-rum, but the truth of the matter is that atm
10
+ # we only support Rails >= 2.3
11
+ def middleware_supported?
12
+ ::Rails::VERSION::MAJOR >= 2 && ::Rails::VERSION::MINOR >= 3
13
+ end
14
+
15
+ if middleware_supported?
8
16
  class BrowserMonitoringTest < Test::Unit::TestCase
9
17
  include Rack::Test::Methods
18
+
19
+ class TestApp
20
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
21
+
22
+ def self.doc=(other)
23
+ @@doc = other
24
+ end
10
25
 
11
- def app
12
- @doc ||= <<-EOL
26
+ def call(env)
27
+ @@doc ||= <<-EOL
13
28
  <html>
14
29
  <head>
15
30
  <title>im a title</title>
@@ -21,21 +36,40 @@ class BrowserMonitoringTest < Test::Unit::TestCase
21
36
  <body>im some body text</body>
22
37
  </html>
23
38
  EOL
24
- mock_app = lambda do |env|
25
- [200, {'Content-Type' => 'text/html'}, Rack::Response.new(@doc)]
39
+ [200, {'Content-Type' => 'text/html'}, Rack::Response.new(@@doc)]
26
40
  end
27
- NewRelic::Rack::BrowserMonitoring.new(mock_app)
41
+ add_transaction_tracer :call, :category => :rack
28
42
  end
29
-
43
+
44
+ def app
45
+ NewRelic::Rack::BrowserMonitoring.new(TestApp.new)
46
+ end
47
+
30
48
  def setup
31
- NewRelic::Agent.stubs(:browser_timing_header) \
32
- .returns("<script>header</script>")
33
- NewRelic::Agent.stubs(:browser_timing_footer) \
34
- .returns("<script>footer</script>")
49
+ super
50
+ clear_cookies
51
+ NewRelic::Agent.manual_start
52
+ config = NewRelic::Agent::BeaconConfiguration.new("browser_key" => "browserKey",
53
+ "application_id" => "apId",
54
+ "beacon"=>"beacon",
55
+ "episodes_url"=>"this_is_my_file")
56
+ NewRelic::Agent.instance.stubs(:beacon_configuration).returns(config)
57
+ NewRelic::Agent.stubs(:is_transaction_traced?).returns(true)
35
58
  end
36
59
 
37
60
  def teardown
61
+ super
62
+ clear_cookies
38
63
  mocha_teardown
64
+ TestApp.doc = nil
65
+ end
66
+
67
+ def test_make_sure_header_is_set
68
+ assert NewRelic::Agent.browser_timing_header.size > 0
69
+ end
70
+
71
+ def test_make_sure_footer_is_set
72
+ assert NewRelic::Agent.browser_timing_footer.size > 0
39
73
  end
40
74
 
41
75
  def test_should_only_instrument_successfull_html_requests
@@ -47,12 +81,13 @@ EOL
47
81
  def test_insert_timing_header_right_after_open_head_if_no_meta_tags
48
82
  get '/'
49
83
 
50
- assert(last_response.body.include?("head>#{NewRelic::Agent.browser_timing_header}"), last_response.body)
51
- @doc = nil
84
+ assert(last_response.body.include?("head>#{NewRelic::Agent.browser_timing_header}"),
85
+ last_response.body)
86
+ TestApp.doc = nil
52
87
  end
53
88
 
54
89
  def test_insert_timing_header_right_before_head_close_if_ua_compatible_found
55
- @doc = <<-EOL
90
+ TestApp.doc = <<-EOL
56
91
  <html>
57
92
  <head>
58
93
  <title>im a title</title>
@@ -66,19 +101,40 @@ EOL
66
101
  EOL
67
102
  get '/'
68
103
 
69
- assert(last_response.body.include?("#{NewRelic::Agent.browser_timing_header}</head>"), last_response.body)
104
+ assert(last_response.body.include?("#{NewRelic::Agent.browser_timing_header}</head>"),
105
+ last_response.body)
70
106
  end
71
107
 
72
108
  def test_insert_timing_footer_right_before_html_body_close
73
109
  get '/'
74
110
 
75
- assert(last_response.body.include?("#{NewRelic::Agent.browser_timing_footer}</body>"), last_response.body)
111
+ assert_match(/.*NREUMQ\.push.*new Date\(\)\.getTime\(\),"","","","",""\]\)<\/script><\/body>/,
112
+ last_response.body)
76
113
  end
77
-
114
+
78
115
  def test_should_not_throw_exception_on_empty_reponse
79
- @doc = ''
116
+ TestApp.doc = ''
80
117
  get '/'
81
118
 
82
119
  assert last_response.ok?
83
120
  end
121
+
122
+ def test_token_is_set_in_footer_when_set_by_cookie
123
+ token = '1234567890987654321'
124
+ set_cookie "NRAGENT=tk=#{token}"
125
+ get '/'
126
+
127
+ assert(last_response.body.include?(token), last_response.body)
128
+ end
129
+
130
+ def test_guid_is_set_in_footer_when_token_is_set
131
+ guid = 'abcdefgfedcba'
132
+ NewRelic::TransactionSample.any_instance.stubs(:generate_guid).returns(guid)
133
+ NewRelic::Control.instance.stubs(:apdex_t).returns(0.0001)
134
+ set_cookie "NRAGENT=tk=token"
135
+ get '/'
136
+
137
+ assert(last_response.body.include?(guid), last_response.body)
138
+ end
139
+ end
84
140
  end
data/test/test_helper.rb CHANGED
@@ -14,6 +14,7 @@ require 'rubygems'
14
14
 
15
15
  begin
16
16
  require 'config/environment'
17
+ # require File.join(File.dirname(__FILE__),'..','..','rpm_test_app','config','environment')
17
18
  begin
18
19
  require 'test_help'
19
20
  rescue LoadError
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_rpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.1.beta1
4
+ version: 3.3.1.beta2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -12,11 +12,11 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2011-11-11 00:00:00.000000000 Z
15
+ date: 2011-11-29 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: jeweler
19
- requirement: &2152161920 !ruby/object:Gem::Requirement
19
+ requirement: &2153088200 !ruby/object:Gem::Requirement
20
20
  none: false
21
21
  requirements:
22
22
  - - ! '>='
@@ -24,10 +24,10 @@ dependencies:
24
24
  version: '0'
25
25
  type: :development
26
26
  prerelease: false
27
- version_requirements: *2152161920
27
+ version_requirements: *2153088200
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: mocha
30
- requirement: &2152161440 !ruby/object:Gem::Requirement
30
+ requirement: &2153087680 !ruby/object:Gem::Requirement
31
31
  none: false
32
32
  requirements:
33
33
  - - ! '>='
@@ -35,10 +35,10 @@ dependencies:
35
35
  version: '0'
36
36
  type: :development
37
37
  prerelease: false
38
- version_requirements: *2152161440
38
+ version_requirements: *2153087680
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: shoulda
41
- requirement: &2152160940 !ruby/object:Gem::Requirement
41
+ requirement: &2153087180 !ruby/object:Gem::Requirement
42
42
  none: false
43
43
  requirements:
44
44
  - - ! '>='
@@ -46,7 +46,7 @@ dependencies:
46
46
  version: '0'
47
47
  type: :development
48
48
  prerelease: false
49
- version_requirements: *2152160940
49
+ version_requirements: *2153087180
50
50
  description: ! 'New Relic is a performance management system, developed by New Relic,
51
51
 
52
52
  Inc (http://www.newrelic.com). New Relic provides you with deep