newrelic_rpm 2.14.1 → 3.0.0.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 (123) hide show
  1. data/CHANGELOG +8 -0
  2. data/README.rdoc +2 -0
  3. data/install.rb +2 -2
  4. data/lib/new_relic/agent.rb +34 -1
  5. data/lib/new_relic/agent/agent.rb +34 -25
  6. data/lib/new_relic/agent/browser_monitoring.rb +111 -0
  7. data/lib/new_relic/agent/error_collector.rb +4 -4
  8. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +3 -3
  9. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +5 -7
  10. data/lib/new_relic/agent/instrumentation/data_mapper.rb +8 -8
  11. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +1 -1
  12. data/lib/new_relic/agent/instrumentation/memcache.rb +1 -1
  13. data/lib/new_relic/agent/instrumentation/merb/controller.rb +1 -1
  14. data/lib/new_relic/agent/instrumentation/merb/errors.rb +1 -1
  15. data/lib/new_relic/agent/instrumentation/metric_frame.rb +1 -0
  16. data/lib/new_relic/agent/instrumentation/queue_time.rb +26 -26
  17. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/rails/errors.rb +1 -1
  19. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +2 -2
  20. data/lib/new_relic/agent/instrumentation/sinatra.rb +1 -1
  21. data/lib/new_relic/agent/method_tracer.rb +15 -15
  22. data/lib/new_relic/agent/shim_agent.rb +2 -0
  23. data/lib/new_relic/agent/stats_engine/metric_stats.rb +3 -3
  24. data/lib/new_relic/agent/stats_engine/samplers.rb +2 -2
  25. data/lib/new_relic/agent/stats_engine/transactions.rb +2 -1
  26. data/lib/new_relic/agent/transaction_sample_builder.rb +101 -0
  27. data/lib/new_relic/agent/transaction_sampler.rb +299 -251
  28. data/lib/new_relic/control.rb +2 -2
  29. data/lib/new_relic/control/class_methods.rb +0 -5
  30. data/lib/new_relic/control/configuration.rb +4 -3
  31. data/lib/new_relic/control/frameworks/rails.rb +9 -12
  32. data/lib/new_relic/control/instance_methods.rb +2 -2
  33. data/lib/new_relic/control/instrumentation.rb +1 -1
  34. data/lib/new_relic/control/server_methods.rb +2 -2
  35. data/lib/new_relic/delayed_job_injection.rb +1 -1
  36. data/lib/new_relic/local_environment.rb +7 -7
  37. data/lib/new_relic/rack/browser_monitoring.rb +61 -0
  38. data/lib/new_relic/stats.rb +6 -6
  39. data/lib/new_relic/version.rb +4 -4
  40. data/newrelic.yml +19 -0
  41. data/newrelic_rpm.gemspec +9 -4
  42. data/test/active_record_fixtures.rb +5 -5
  43. data/test/config/test_control.rb +3 -3
  44. data/test/new_relic/agent/agent/connect_test.rb +27 -6
  45. data/test/new_relic/agent/agent/start_test.rb +13 -13
  46. data/test/new_relic/agent/agent/start_worker_thread_test.rb +8 -8
  47. data/test/new_relic/agent/agent_test.rb +85 -0
  48. data/test/new_relic/agent/agent_test_controller.rb +9 -9
  49. data/test/new_relic/agent/agent_test_controller_test.rb +37 -37
  50. data/test/new_relic/agent/browser_monitoring_test.rb +124 -0
  51. data/test/new_relic/agent/busy_calculator_test.rb +7 -7
  52. data/test/new_relic/agent/error_collector/notice_error_test.rb +9 -9
  53. data/test/new_relic/agent/error_collector_test.rb +54 -54
  54. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +69 -69
  55. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +36 -0
  56. data/test/new_relic/agent/instrumentation/metric_frame_test.rb +3 -3
  57. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +11 -11
  58. data/test/new_relic/agent/instrumentation/queue_time_test.rb +38 -35
  59. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +18 -18
  60. data/test/new_relic/agent/memcache_instrumentation_test.rb +12 -12
  61. data/test/new_relic/agent/method_tracer/class_methods/add_method_tracer_test.rb +1 -1
  62. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +16 -15
  63. data/test/new_relic/agent/method_tracer_test.rb +60 -60
  64. data/test/new_relic/agent/mock_scope_listener.rb +8 -8
  65. data/test/new_relic/agent/rpm_agent_test.rb +26 -26
  66. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +17 -17
  67. data/test/new_relic/agent/stats_engine/samplers_test.rb +4 -4
  68. data/test/new_relic/agent/stats_engine/stats_engine_test.rb +51 -51
  69. data/test/new_relic/agent/transaction_sample_builder_test.rb +36 -36
  70. data/test/new_relic/agent/transaction_sampler_test.rb +727 -178
  71. data/test/new_relic/agent/worker_loop_test.rb +4 -4
  72. data/test/new_relic/collection_helper_test.rb +15 -15
  73. data/test/new_relic/command/deployments_test.rb +5 -5
  74. data/test/new_relic/control_test.rb +25 -25
  75. data/test/new_relic/local_environment_test.rb +11 -11
  76. data/test/new_relic/metric_spec_test.rb +21 -21
  77. data/test/new_relic/rack/episodes_test.rb +35 -35
  78. data/test/new_relic/stats_test.rb +61 -43
  79. data/test/new_relic/transaction_sample_subtest_test.rb +15 -15
  80. data/test/new_relic/transaction_sample_test.rb +25 -25
  81. data/test/new_relic/version_number_test.rb +11 -11
  82. data/test/test_contexts.rb +7 -7
  83. data/test/test_helper.rb +6 -6
  84. data/ui/helpers/developer_mode_helper.rb +67 -67
  85. data/ui/helpers/google_pie_chart.rb +4 -4
  86. data/vendor/gems/dependency_detection-0.0.1.build/lib/dependency_detection.rb +4 -4
  87. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/action_mailer.rb +3 -3
  88. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_merchant.rb +7 -7
  89. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_record.rb +1 -1
  90. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/apdex.rb +9 -9
  91. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/background_transaction.rb +1 -1
  92. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/client.rb +8 -8
  93. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller.rb +9 -9
  94. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_cpu.rb +4 -4
  95. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_ext.rb +2 -2
  96. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database.rb +8 -8
  97. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database_pool.rb +3 -3
  98. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net.rb +6 -6
  99. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net_parser.rb +3 -3
  100. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/external.rb +2 -2
  101. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/frontend.rb +6 -6
  102. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/gc.rb +2 -2
  103. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/hibernate_session.rb +1 -1
  104. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +4 -4
  105. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java_parser.rb +3 -3
  106. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp.rb +4 -4
  107. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp_tag.rb +1 -1
  108. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/mem_cache.rb +1 -1
  109. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/metric_parser.rb +21 -21
  110. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/orm.rb +2 -2
  111. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/other_transaction.rb +6 -6
  112. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet.rb +2 -2
  113. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_context_listener.rb +1 -1
  114. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_filter.rb +1 -1
  115. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr.rb +3 -3
  116. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr_request_handler.rb +1 -1
  117. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring.rb +8 -8
  118. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_action.rb +3 -3
  119. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_result.rb +3 -3
  120. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +5 -5
  121. data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_transaction.rb +20 -20
  122. metadata +15 -9
  123. data/lib/new_relic/agent/instrumentation/sequel.rb +0 -109
@@ -1,11 +1,11 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
2
2
 
3
3
  class NewRelic::Agent::TransationSampleBuilderTest < Test::Unit::TestCase
4
-
4
+
5
5
  def setup
6
6
  @builder = NewRelic::Agent::TransactionSampleBuilder.new
7
7
  end
8
-
8
+
9
9
  def test_build_sample
10
10
  build_segment("a") do
11
11
  build_segment("aa") do
@@ -24,32 +24,32 @@ class NewRelic::Agent::TransationSampleBuilderTest < Test::Unit::TestCase
24
24
  end
25
25
  build_segment "b"
26
26
  build_segment "c" do
27
- build_segment "ca"
27
+ build_segment "ca"
28
28
  build_segment "cb" do
29
29
  build_segment "cba"
30
30
  end
31
31
  end
32
-
32
+
33
33
  @builder.finish_trace(Time.now.to_f)
34
34
  validate_builder
35
35
  end
36
-
36
+
37
37
  def test_freeze
38
38
  build_segment "a" do
39
39
  build_segment "aa"
40
40
  end
41
-
42
- begin
41
+
42
+ begin
43
43
  builder.sample
44
44
  assert false
45
45
  rescue Exception => e
46
46
  # expected
47
47
  end
48
-
48
+
49
49
  @builder.finish_trace(Time.now.to_f)
50
-
50
+
51
51
  validate_builder
52
-
52
+
53
53
  begin
54
54
  build_segment "b"
55
55
  assert_false
@@ -57,20 +57,20 @@ class NewRelic::Agent::TransationSampleBuilderTest < Test::Unit::TestCase
57
57
  # expected
58
58
  end
59
59
  end
60
-
60
+
61
61
  # this is really a test for transaction sample
62
62
  def test_omit_segments_with
63
63
  build_segment "Controller/my_controller/index" do
64
64
  sleep 0.010
65
-
65
+
66
66
  build_segment "Rails/Application Code Loading" do
67
67
  sleep 0.020
68
-
68
+
69
69
  build_segment "foo/bar" do
70
70
  sleep 0.010
71
71
  end
72
72
  end
73
-
73
+
74
74
  build_segment "a" do
75
75
  build_segment "ab"
76
76
  sleep 0.010
@@ -87,29 +87,29 @@ class NewRelic::Agent::TransationSampleBuilderTest < Test::Unit::TestCase
87
87
  build_segment "c"
88
88
  end
89
89
  @builder.finish_trace(Time.now.to_f)
90
-
90
+
91
91
  validate_builder false
92
-
92
+
93
93
  sample = @builder.sample
94
-
94
+
95
95
  should_be_a_copy = sample.omit_segments_with('OMIT NOTHING')
96
96
  validate_segment should_be_a_copy.root_segment, false
97
-
97
+
98
98
  assert sample.to_s == should_be_a_copy.to_s
99
-
99
+
100
100
  without_code_loading = sample.omit_segments_with('Rails/Application Code Loading')
101
101
  validate_segment without_code_loading.root_segment, false
102
-
102
+
103
103
  # after we take out code loading, the delta should be approximately
104
104
  # 30 milliseconds
105
105
  delta = (sample.duration - without_code_loading.duration) * 1000
106
-
107
- # Need to allow substantial headroom on the upper bound to prevent
106
+
107
+ # Need to allow substantial headroom on the upper bound to prevent
108
108
  # spurious errors.
109
109
  assert delta >= 28, "delta #{delta} should be between 28 and 100"
110
110
  # disable this test for a couple days:
111
111
  assert delta <= 100, "delta #{delta} should be between 28 and 100"
112
-
112
+
113
113
  # ensure none of the segments have this regex
114
114
  without_code_loading.each_segment do |segment|
115
115
  assert_nil segment.metric_name =~ /Rails\/Application Code Loading/
@@ -140,53 +140,53 @@ class NewRelic::Agent::TransationSampleBuilderTest < Test::Unit::TestCase
140
140
  end
141
141
  end
142
142
  build_segment "c"
143
-
143
+
144
144
  @builder.finish_trace(Time.now.to_f)
145
145
  validate_builder
146
-
146
+
147
147
  dump = Marshal.dump @builder.sample
148
148
  sample = Marshal.restore(dump)
149
149
  validate_segment(sample.root_segment)
150
150
  end
151
-
151
+
152
152
  def test_parallel_first_level_segments
153
153
  build_segment "a" do
154
154
  build_segment "ab"
155
155
  end
156
156
  build_segment "b"
157
157
  build_segment "c"
158
-
158
+
159
159
  @builder.finish_trace(Time.now.to_f)
160
160
  validate_builder
161
161
  end
162
-
162
+
163
163
  def validate_builder(check_names = true)
164
164
  validate_segment @builder.sample.root_segment, check_names
165
165
  end
166
-
166
+
167
167
  def validate_segment(s, check_names = true)
168
168
  p = s.parent_segment
169
-
169
+
170
170
  unless p.nil? || p.metric_name == 'ROOT'
171
- assert p.called_segments.include?(s)
171
+ assert p.called_segments.include?(s)
172
172
  assert_equal p.metric_name.length, s.metric_name.length - 1, "p: #{p.metric_name}, s: #{s.metric_name}" if check_names
173
173
  assert p.metric_name < s.metric_name if check_names
174
174
  assert p.entry_timestamp <= s.entry_timestamp
175
175
  end
176
-
176
+
177
177
  assert s.exit_timestamp >= s.entry_timestamp
178
-
178
+
179
179
  children = s.called_segments
180
180
  last_segment = s
181
181
  children.each do |child|
182
182
  assert child.metric_name > last_segment.metric_name if check_names
183
183
  assert child.entry_timestamp >= last_segment.entry_timestamp
184
184
  last_metric = child
185
-
185
+
186
186
  validate_segment(child, check_names)
187
187
  end
188
188
  end
189
-
189
+
190
190
  def build_segment(metric, time = 0, &proc)
191
191
  @builder.trace_entry(metric, Time.now.to_f)
192
192
  proc.call if proc
@@ -1,9 +1,9 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
2
2
 
3
3
  class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
4
-
4
+
5
5
  module MockGCStats
6
-
6
+
7
7
  def time
8
8
  return 0 if @@values.empty?
9
9
  raise "too many calls" if @@index >= @@values.size
@@ -12,12 +12,12 @@ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
12
12
  @@index += 1
13
13
  @@curtime
14
14
  end
15
-
15
+
16
16
  def self.mock_values= array
17
17
  @@values = array
18
18
  @@index = 0
19
19
  end
20
-
20
+
21
21
  end
22
22
 
23
23
  def setup
@@ -31,17 +31,640 @@ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
31
31
 
32
32
  def teardown
33
33
  super
34
- @sampler.send(:clear_builder)
34
+ Thread.current[:transaction_sample_builder] = nil
35
+ end
36
+
37
+ def test_initialize
38
+ defaults = {
39
+ :samples => [],
40
+ :harvest_count => 0,
41
+ :max_samples => 100,
42
+ :random_sample => nil,
43
+ }
44
+ defaults.each do |variable, default_value|
45
+ assert_equal(default_value, @sampler.instance_variable_get('@' + variable.to_s))
46
+ end
47
+
48
+ segment_limit = @sampler.instance_variable_get('@segment_limit')
49
+ assert(segment_limit.is_a?(Numeric), "Segment limit should be numeric")
50
+ assert(segment_limit > 0, "Segment limit should be above zero")
51
+
52
+ stack_trace_threshold = @sampler.instance_variable_get('@stack_trace_threshold')
53
+ assert(stack_trace_threshold.is_a?((0.1).class), "Stack trace threshold should be a #{(0.1).class.inspect}, but is #{stack_trace_threshold.inspect}")
54
+ assert(stack_trace_threshold > 0.0, "Stack trace threshold should be above zero")
55
+
56
+ lock = @sampler.instance_variable_get('@samples_lock')
57
+ assert(lock.is_a?(Mutex), "Samples lock should be a mutex, is: #{lock.inspect}")
58
+ end
59
+
60
+ def test_current_sample_id_default
61
+ builder = mock('builder')
62
+ builder.expects(:sample_id).returns(11111)
63
+ @sampler.expects(:builder).returns(builder)
64
+ assert_equal(11111, @sampler.current_sample_id)
65
+ end
66
+
67
+ def test_current_sample_id_no_builder
68
+ @sampler.expects(:builder).returns(nil)
69
+ assert_equal(nil, @sampler.current_sample_id)
70
+ end
71
+
72
+ def test_enable
73
+ assert_equal(nil, @sampler.instance_variable_get('@disabled'))
74
+ @sampler.enable
75
+ assert_equal(false, @sampler.instance_variable_get('@disabled'))
76
+ assert_equal(@sampler, NewRelic::Agent.instance.stats_engine.instance_variable_get('@transaction_sampler'))
77
+ end
78
+
79
+ def test_disable
80
+ assert_equal(nil, @sampler.instance_variable_get('@disabled'))
81
+ @sampler.disable
82
+ assert_equal(true, @sampler.instance_variable_get('@disabled'))
83
+ assert_equal(nil, NewRelic::Agent.instance.stats_engine.instance_variable_get('@transaction_sampler'))
84
+ end
85
+
86
+ def test_sampling_rate_equals_default
87
+ @sampler.sampling_rate = 1
88
+ assert_equal(1, @sampler.instance_variable_get('@sampling_rate'))
89
+ # rand(1) is always zero, so we can be sure here
90
+ assert_equal(0, @sampler.instance_variable_get('@harvest_count'))
91
+ end
92
+
93
+ def test_sampling_rate_equals_with_a_float
94
+ @sampler.sampling_rate = 5.5
95
+ assert_equal(5, @sampler.instance_variable_get('@sampling_rate'))
96
+ harvest_count = @sampler.instance_variable_get('@harvest_count')
97
+ assert((0..4).include?(harvest_count), "should be in the range 0..4")
98
+ end
99
+
100
+ def test_notice_first_scope_push_default
101
+ @sampler.expects(:disabled).returns(false)
102
+ @sampler.expects(:start_builder).with(100.0)
103
+ @sampler.notice_first_scope_push(Time.at(100))
104
+ end
105
+
106
+ def test_notice_first_scope_push_disabled
107
+ @sampler.expects(:disabled).returns(true)
108
+ @sampler.expects(:start_builder).never
109
+ @sampler.notice_first_scope_push(Time.at(100))
110
+ end
111
+
112
+ def test_notice_push_scope_no_builder
113
+ @sampler.expects(:builder)
114
+ assert_equal(nil, @sampler.notice_push_scope('a scope'))
115
+ end
116
+
117
+ def test_notice_push_scope_with_builder
118
+ NewRelic::Control.instance.expects(:developer_mode?).returns(false)
119
+ builder = mock('builder')
120
+ builder.expects(:trace_entry).with('a scope', 100.0)
121
+ @sampler.expects(:builder).returns(builder).twice
122
+
123
+ @sampler.notice_push_scope('a scope', Time.at(100))
124
+ end
125
+
126
+ def test_notice_push_scope_in_dev_mode
127
+ NewRelic::Control.instance.expects(:developer_mode?).returns(true)
128
+
129
+ builder = mock('builder')
130
+ builder.expects(:trace_entry).with('a scope', 100.0)
131
+ @sampler.expects(:builder).returns(builder).twice
132
+ @sampler.expects(:capture_segment_trace)
133
+
134
+ @sampler.notice_push_scope('a scope', Time.at(100))
135
+ end
136
+
137
+ def test_scope_depth_no_builder
138
+ @sampler.expects(:builder).returns(nil)
139
+ assert_equal(0, @sampler.scope_depth, "should default to zero with no builder")
140
+ end
141
+
142
+ def test_scope_depth_with_builder
143
+ builder = mock('builder')
144
+ builder.expects(:scope_depth).returns('scope_depth')
145
+ @sampler.expects(:builder).returns(builder).twice
146
+
147
+ assert_equal('scope_depth', @sampler.scope_depth, "should delegate scope depth to the builder")
148
+ end
149
+
150
+ def test_notice_pop_scope_no_builder
151
+ @sampler.expects(:builder).returns(nil)
152
+ assert_equal(nil, @sampler.notice_pop_scope('a scope', Time.at(100)))
153
+ end
154
+
155
+ def test_notice_pop_scope_with_frozen_sample
156
+ builder = mock('builder')
157
+ sample = mock('sample')
158
+ builder.expects(:sample).returns(sample)
159
+ sample.expects(:frozen?).returns(true)
160
+ @sampler.expects(:builder).returns(builder).twice
161
+
162
+ assert_raise(RuntimeError) do
163
+ @sampler.notice_pop_scope('a scope', Time.at(100))
164
+ end
165
+ end
166
+
167
+ def test_notice_pop_scope_builder_delegation
168
+ builder = mock('builder')
169
+ builder.expects(:trace_exit).with('a scope', 100.0)
170
+ sample = mock('sample')
171
+ builder.expects(:sample).returns(sample)
172
+ sample.expects(:frozen?).returns(false)
173
+ @sampler.expects(:builder).returns(builder).times(3)
174
+
175
+ @sampler.notice_pop_scope('a scope', Time.at(100))
176
+ end
177
+
178
+ def test_notice_scope_empty_no_builder
179
+ @sampler.expects(:builder).returns(nil)
180
+ assert_equal(nil, @sampler.notice_scope_empty)
181
+ end
182
+
183
+ def test_notice_scope_empty_ignored_transaction
184
+ builder = mock('builder')
185
+ # the builder should be cached, so only called once
186
+ @sampler.expects(:builder).returns(builder).once
187
+
188
+ builder.expects(:finish_trace).with(100.0)
189
+
190
+ @sampler.expects(:clear_builder)
191
+
192
+ builder.expects(:ignored?).returns(true)
193
+
194
+ assert_equal(nil, @sampler.notice_scope_empty(Time.at(100)))
195
+ end
196
+
197
+ def test_notice_scope_empty_with_builder
198
+ builder = mock('builder')
199
+ # the builder should be cached, so only called once
200
+ @sampler.expects(:builder).returns(builder).once
201
+
202
+
203
+ builder.expects(:finish_trace).with(100.0)
204
+ @sampler.expects(:clear_builder)
205
+
206
+ builder.expects(:ignored?).returns(false)
207
+
208
+ sample = mock('sample')
209
+ builder.expects(:sample).returns(sample)
210
+ @sampler.expects(:store_sample).with(sample)
211
+
212
+ @sampler.notice_scope_empty(Time.at(100))
213
+
214
+ assert_equal(sample, @sampler.instance_variable_get('@last_sample'))
215
+ end
216
+
217
+ def test_store_random_sample_no_random_sampling
218
+ @sampler.instance_eval { @random_sampling = false }
219
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
220
+ @sampler.store_random_sample(mock('sample'))
221
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
222
+ end
223
+
224
+ def test_store_random_sample_random_sampling
225
+ @sampler.instance_eval { @random_sampling = true }
226
+ sample = mock('sample')
227
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
228
+ @sampler.store_random_sample(sample)
229
+ assert_equal(sample, @sampler.instance_variable_get('@random_sample'))
230
+ end
231
+
232
+ def test_store_sample_for_developer_mode_in_dev_mode
233
+ NewRelic::Control.instance.expects(:developer_mode?).returns(true)
234
+ sample = mock('sample')
235
+ @sampler.expects(:truncate_samples)
236
+ @sampler.store_sample_for_developer_mode(sample)
237
+ assert_equal([sample], @sampler.instance_variable_get('@samples'))
238
+ end
239
+
240
+ def test_store_sample_for_developer_mode_no_dev
241
+ NewRelic::Control.instance.expects(:developer_mode?).returns(false)
242
+ sample = mock('sample')
243
+ @sampler.store_sample_for_developer_mode(sample)
244
+ assert_equal([], @sampler.instance_variable_get('@samples'))
245
+ end
246
+
247
+ def test_store_slowest_sample_new_is_slowest
248
+ old_sample = mock('old_sample')
249
+ new_sample = mock('new_sample')
250
+ @sampler.instance_eval { @slowest_sample = old_sample }
251
+ @sampler.expects(:slowest_sample?).with(old_sample, new_sample).returns(true)
252
+
253
+ @sampler.store_slowest_sample(new_sample)
254
+
255
+ assert_equal(new_sample, @sampler.instance_variable_get('@slowest_sample'))
256
+ end
257
+
258
+
259
+ def test_store_slowest_sample_not_slowest
260
+ old_sample = mock('old_sample')
261
+ new_sample = mock('new_sample')
262
+ @sampler.instance_eval { @slowest_sample = old_sample }
263
+ @sampler.expects(:slowest_sample?).with(old_sample, new_sample).returns(false)
264
+
265
+ @sampler.store_slowest_sample(new_sample)
266
+
267
+ assert_equal(old_sample, @sampler.instance_variable_get('@slowest_sample'))
268
+ end
269
+
270
+ def test_slowest_sample_no_sample
271
+ old_sample = nil
272
+ new_sample = mock('new_sample')
273
+ assert_equal(true, @sampler.slowest_sample?(old_sample, new_sample))
274
+ end
275
+
276
+ def test_slowest_sample_faster_sample
277
+ old_sample = mock('old_sample')
278
+ new_sample = mock('new_sample')
279
+ old_sample.expects(:duration).returns(1.0)
280
+ new_sample.expects(:duration).returns(0.5)
281
+ assert_equal(false, @sampler.slowest_sample?(old_sample, new_sample))
282
+ end
283
+
284
+ def test_slowest_sample_slower_sample
285
+ old_sample = mock('old_sample')
286
+ new_sample = mock('new_sample')
287
+ old_sample.expects(:duration).returns(0.5)
288
+ new_sample.expects(:duration).returns(1.0)
289
+ assert_equal(true, @sampler.slowest_sample?(old_sample, new_sample))
290
+ end
291
+
292
+ def test_truncate_samples_no_samples
293
+ @sampler.instance_eval { @max_samples = 10 }
294
+ @sampler.instance_eval { @samples = [] }
295
+ @sampler.truncate_samples
296
+ assert_equal([], @sampler.instance_variable_get('@samples'))
297
+ end
298
+
299
+ def test_truncate_samples_equal_samples
300
+ @sampler.instance_eval { @max_samples = 2 }
301
+ @sampler.instance_eval { @samples = [1, 2] }
302
+ @sampler.truncate_samples
303
+ assert_equal([1, 2], @sampler.instance_variable_get('@samples'))
304
+ end
305
+
306
+ def test_truncate_samples_extra_samples
307
+ @sampler.instance_eval { @max_samples = 2 }
308
+ @sampler.instance_eval { @samples = [1, 2, 3] }
309
+ @sampler.truncate_samples
310
+ assert_equal([2, 3], @sampler.instance_variable_get('@samples'))
311
+ end
312
+
313
+ def test_notice_transaction_disabled
314
+ @sampler.expects(:disabled).returns(true)
315
+ @sampler.expects(:builder).never # since we're disabled
316
+ @sampler.notice_transaction('foo')
317
+ end
318
+
319
+ def test_notice_transaction_no_builder
320
+ @sampler.expects(:disabled).returns(false)
321
+ @sampler.expects(:builder).returns(nil).once
322
+ @sampler.notice_transaction('foo')
323
+ end
324
+
325
+ def test_notice_transaction_with_builder
326
+ builder = mock('builder')
327
+ builder.expects(:set_transaction_info).with('a path', 'a uri', {:some => :params})
328
+ @sampler.expects(:builder).returns(builder).twice
329
+ @sampler.expects(:disabled).returns(false)
330
+ @sampler.notice_transaction('a path', 'a uri', {:some => :params})
331
+ end
332
+
333
+ def test_ignore_transaction_no_builder
334
+ @sampler.expects(:builder).returns(nil).once
335
+ @sampler.ignore_transaction
336
+ end
337
+
338
+ def test_ignore_transaction_with_builder
339
+ builder = mock('builder')
340
+ builder.expects(:ignore_transaction)
341
+ @sampler.expects(:builder).returns(builder).twice
342
+ @sampler.ignore_transaction
343
+ end
344
+
345
+ def test_notice_profile_no_builder
346
+ @sampler.expects(:builder).returns(nil).once
347
+ @sampler.notice_profile(nil)
348
+ end
349
+
350
+ def test_notice_profile_with_builder
351
+ profile = mock('profile')
352
+ builder = mock('builder')
353
+ @sampler.expects(:builder).returns(builder).twice
354
+ builder.expects(:set_profile).with(profile)
355
+
356
+ @sampler.notice_profile(profile)
357
+ end
358
+
359
+ def test_notice_transaction_cpu_time_no_builder
360
+ @sampler.expects(:builder).returns(nil).once
361
+ @sampler.notice_transaction_cpu_time(0.0)
362
+ end
363
+
364
+ def test_notice_transaction_cpu_time_with_builder
365
+ cpu_time = mock('cpu_time')
366
+ builder = mock('builder')
367
+ @sampler.expects(:builder).returns(builder).twice
368
+ builder.expects(:set_transaction_cpu_time).with(cpu_time)
369
+
370
+ @sampler.notice_transaction_cpu_time(cpu_time)
371
+ end
372
+
373
+ def test_notice_extra_data_no_builder
374
+ @sampler.expects(:builder).returns(nil).once
375
+ @sampler.send(:notice_extra_data, nil, nil, nil)
376
+ end
377
+
378
+ def test_notice_extra_data_no_segment
379
+ builder = mock('builder')
380
+ @sampler.expects(:builder).returns(builder).twice
381
+ builder.expects(:current_segment).returns(nil)
382
+ @sampler.send(:notice_extra_data, nil, nil, nil)
383
+ end
384
+
385
+ def test_notice_extra_data_with_segment_no_old_message_no_config_key
386
+ key = :a_key
387
+ builder = mock('builder')
388
+ segment = mock('segment')
389
+ @sampler.expects(:builder).returns(builder).twice
390
+ builder.expects(:current_segment).returns(segment)
391
+ segment.expects(:[]).with(key).returns(nil)
392
+ @sampler.expects(:append_new_message).with(nil, 'a message').returns('a message')
393
+ @sampler.expects(:truncate_message).with('a message').returns('truncated_message')
394
+ segment.expects(:[]=).with(key, 'truncated_message')
395
+ @sampler.expects(:append_backtrace).with(segment, 1.0)
396
+ @sampler.send(:notice_extra_data, 'a message', 1.0, key)
397
+ end
398
+
399
+ def test_truncate_message_short_message
400
+ message = 'a message'
401
+ assert_equal(message, @sampler.truncate_message(message))
402
+ end
403
+
404
+ def test_truncate_message_long_message
405
+ message = 'a' * 16384
406
+ truncated_message = @sampler.truncate_message(message)
407
+ assert_equal(16384, truncated_message.length)
408
+ assert_equal('a' * 16381 + '...', truncated_message)
409
+ end
410
+
411
+ def test_append_new_message_no_old_message
412
+ old_message = nil
413
+ new_message = 'a message'
414
+ assert_equal(new_message, @sampler.append_new_message(old_message, new_message))
415
+ end
416
+
417
+ def test_append_new_message_with_old_message
418
+ old_message = 'old message'
419
+ new_message = ' a message'
420
+ assert_equal("old message;\n a message", @sampler.append_new_message(old_message, new_message))
421
+ end
422
+
423
+ def test_append_backtrace_under_duration
424
+ @sampler.instance_eval { @stack_trace_threshold = 2.0 }
425
+ segment = mock('segment')
426
+ segment.expects(:[]=).with(:backtrace, any_parameters).never
427
+ @sampler.append_backtrace(mock('segment'), 1.0)
428
+ end
429
+
430
+ def test_append_backtrace_over_duration
431
+ @sampler.instance_eval { @stack_trace_threshold = 2.0 }
432
+ segment = mock('segment')
433
+ # note the mocha expectation matcher - you can't hardcode a
434
+ # backtrace so we match on any string, which should be okay.
435
+ segment.expects(:[]=).with(:backtrace, instance_of(String))
436
+ @sampler.append_backtrace(segment, 2.5)
35
437
  end
36
-
37
-
438
+
439
+ def test_notice_sql_recording_sql
440
+ Thread.current[:record_sql] = true
441
+ @sampler.expects(:notice_extra_data).with('some sql', 1.0, :sql, 'a config', :connection_config)
442
+ @sampler.notice_sql('some sql', 'a config', 1.0)
443
+ end
444
+
445
+ def test_notice_sql_not_recording
446
+ Thread.current[:record_sql] = false
447
+ @sampler.expects(:notice_extra_data).with('some sql', 1.0, :sql, 'a config', :connection_config).never # <--- important
448
+ @sampler.notice_sql('some sql', 'a config', 1.0)
449
+ end
450
+
451
+ def test_notice_nosql
452
+ @sampler.expects(:notice_extra_data).with('a key', 1.0, :key)
453
+ @sampler.notice_nosql('a key', 1.0)
454
+ end
455
+
456
+ def test_harvest_when_disabled
457
+ @sampler.expects(:disabled).returns(true)
458
+ assert_equal([], @sampler.harvest)
459
+ end
460
+
461
+ def test_harvest_defaults
462
+ # making sure the sampler clears out the old samples
463
+ @sampler.instance_eval do
464
+ @slowest_sample = 'a sample'
465
+ @random_sample = 'a sample'
466
+ @last_sample = 'a sample'
467
+ end
468
+
469
+ @sampler.expects(:disabled).returns(false)
470
+ @sampler.expects(:add_samples_to).with([], 2.0).returns([])
471
+
472
+ assert_equal([], @sampler.harvest)
473
+
474
+ # make sure the samples have been cleared
475
+ assert_equal(nil, @sampler.instance_variable_get('@slowest_sample'))
476
+ assert_equal(nil, @sampler.instance_variable_get('@random_sample'))
477
+ assert_equal(nil, @sampler.instance_variable_get('@last_sample'))
478
+ end
479
+
480
+ def test_harvest_with_previous_samples
481
+ sample = mock('sample')
482
+ @sampler.expects(:disabled).returns(false)
483
+ @sampler.expects(:add_samples_to).with([sample], 2.0).returns([sample])
484
+ @sampler.instance_eval { @segment_limit = 2000 }
485
+ sample.expects(:truncate).with(2000)
486
+ assert_equal([sample], @sampler.harvest([sample]))
487
+ end
488
+
489
+ def test_add_random_sample_to_not_random_sampling
490
+ @sampler.instance_eval { @random_sampling = false }
491
+ result = []
492
+ @sampler.add_random_sample_to(result)
493
+ assert_equal([], result, "should not add anything to the array if we are not random sampling")
494
+ end
495
+
496
+ def test_add_random_sample_to_no_random_sample
497
+ @sampler.instance_eval { @random_sampling = true }
498
+ @sampler.instance_eval {
499
+ @harvest_count = 1
500
+ @sampling_rate = 2
501
+ @random_sample = nil
502
+ }
503
+ result = []
504
+ @sampler.add_random_sample_to(result)
505
+ assert_equal([], result, "should not add sample to the array when it is nil")
506
+ end
507
+
508
+ def test_add_random_sample_to_not_active
509
+ @sampler.instance_eval { @random_sampling = true }
510
+ sample = mock('sample')
511
+ @sampler.instance_eval {
512
+ @harvest_count = 4
513
+ @sampling_rate = 40 # 4 % 40 = 4, so the sample should not be added
514
+ @random_sample = sample
515
+ }
516
+ result = []
517
+ @sampler.add_random_sample_to(result)
518
+ assert_equal([], result, "should not add samples to the array when harvest count is not moduli sampling rate")
519
+ end
520
+
521
+ def test_add_random_sample_to_duplicate
522
+ @sampler.instance_eval { @random_sampling = true }
523
+ sample = mock('sample')
524
+ @sampler.instance_eval {
525
+ @harvest_count = 1
526
+ @sampling_rate = 2
527
+ @random_sample = sample
528
+ }
529
+ result = [sample]
530
+ @sampler.add_random_sample_to(result)
531
+ assert_equal([sample], result, "should not add duplicate samples to the array")
532
+ end
533
+
534
+ def test_add_random_sample_to_activated
535
+ @sampler.instance_eval { @random_sampling = true }
536
+ sample = mock('sample')
537
+ @sampler.instance_eval {
538
+ @harvest_count = 3
539
+ @sampling_rate = 1
540
+ @random_sample = sample
541
+ }
542
+ result = []
543
+ @sampler.add_random_sample_to(result)
544
+ assert_equal([sample], result, "should add the random sample to the array")
545
+ end
546
+
547
+ def test_add_random_sample_to_sampling_rate_zero
548
+ @sampler.instance_eval { @random_sampling = true }
549
+ sample = mock('sample')
550
+ @sampler.instance_eval {
551
+ @harvest_count = 3
552
+ @sampling_rate = 0
553
+ @random_sample = sample
554
+ }
555
+ result = []
556
+ @sampler.add_random_sample_to(result)
557
+ assert_equal([], result, "should not add the sample to the array")
558
+ end
559
+
560
+
561
+ def test_add_samples_to_no_data
562
+ result = []
563
+ slow_threshold = 2.0
564
+ @sampler.instance_eval { @slowest_sample = nil }
565
+ @sampler.expects(:add_random_sample_to).with([])
566
+ assert_equal([], @sampler.add_samples_to(result, slow_threshold))
567
+ end
568
+
569
+ def test_add_samples_to_one_result
570
+ sample = mock('sample')
571
+ sample.expects(:duration).returns(1).at_least_once
572
+ result = [sample]
573
+ slow_threshold = 2.0
574
+ @sampler.instance_eval { @slowest_sample = nil }
575
+ @sampler.expects(:add_random_sample_to).with([sample])
576
+ assert_equal([sample], @sampler.add_samples_to(result, slow_threshold))
577
+ end
578
+
579
+ def test_add_samples_to_adding_slowest
580
+ sample = mock('sample')
581
+ sample.expects(:duration).returns(2.5).at_least_once
582
+ result = []
583
+ slow_threshold = 2.0
584
+ @sampler.instance_eval { @slowest_sample = sample }
585
+ @sampler.expects(:add_random_sample_to).with([sample])
586
+ assert_equal([sample], @sampler.add_samples_to(result, slow_threshold))
587
+ end
588
+
589
+ def test_add_samples_to_under_threshold
590
+ result = []
591
+ slow_threshold = 2.0
592
+ sample = mock('sample')
593
+ sample.expects(:duration).returns(1.0).at_least_once
594
+ @sampler.instance_eval { @slowest_sample = sample }
595
+ @sampler.expects(:add_random_sample_to).with([])
596
+ assert_equal([], @sampler.add_samples_to(result, slow_threshold))
597
+ end
598
+
599
+ def test_add_samples_to_two_sample_enter_one_sample_leave
600
+ slower_sample = mock('slower')
601
+ slower_sample.expects(:duration).returns(10.0).at_least_once
602
+ faster_sample = mock('faster')
603
+ faster_sample.expects(:duration).returns(5.0).at_least_once
604
+ result = [faster_sample]
605
+ slow_threshold = 2.0
606
+ @sampler.instance_eval { @slowest_sample = slower_sample }
607
+ @sampler.expects(:add_random_sample_to).with([slower_sample])
608
+ assert_equal([slower_sample], @sampler.add_samples_to(result, slow_threshold))
609
+ end
610
+
611
+ def test_add_samples_to_keep_older_slower_sample
612
+ slower_sample = mock('slower')
613
+ slower_sample.expects(:duration).returns(10.0).at_least_once
614
+ faster_sample = mock('faster')
615
+ faster_sample.expects(:duration).returns(5.0).at_least_once
616
+ result = [slower_sample]
617
+ slow_threshold = 2.0
618
+ @sampler.instance_eval { @slowest_sample = faster_sample }
619
+ @sampler.expects(:add_random_sample_to).with([slower_sample])
620
+ assert_equal([slower_sample], @sampler.add_samples_to(result, slow_threshold))
621
+ end
622
+
623
+ def test_start_builder_default
624
+ Thread.current[:record_tt] = true
625
+ @sampler.expects(:disabled).returns(false)
626
+ NewRelic::Agent.expects(:is_execution_traced?).returns(true)
627
+ @sampler.send(:start_builder)
628
+ assert(Thread.current[:transaction_sample_builder].is_a?(NewRelic::Agent::TransactionSampleBuilder), "should set up a new builder by default")
629
+ end
630
+
631
+ def test_start_builder_disabled
632
+ Thread.current[:transaction_sample_builder] = 'not nil.'
633
+ @sampler.expects(:disabled).returns(true)
634
+ @sampler.send(:start_builder)
635
+ assert_equal(nil, Thread.current[:transaction_sample_builder], "should clear the transaction builder when disabled")
636
+ end
637
+
638
+ def test_start_builder_dont_replace_existing_builder
639
+ fake_builder = mock('transaction sample builder')
640
+ Thread.current[:transaction_sample_builder] = fake_builder
641
+ @sampler.expects(:disabled).returns(false)
642
+ @sampler.send(:start_builder)
643
+ assert_equal(fake_builder, Thread.current[:transaction_sample_builder], "should not overwrite an existing transaction sample builder")
644
+ end
645
+
646
+ def test_builder
647
+ Thread.current[:transaction_sample_builder] = 'shamalamadingdong, brother.'
648
+ assert_equal('shamalamadingdong, brother.', @sampler.send(:builder), 'should return the value from the thread local variable')
649
+ Thread.current[:transaction_sample_builder] = nil
650
+ end
651
+
652
+ def test_clear_builder
653
+ Thread.current[:transaction_sample_builder] = 'shamalamadingdong, brother.'
654
+ assert_equal(nil, @sampler.send(:clear_builder), 'should clear the thread local variable')
655
+ end
656
+
657
+ # Tests below this line are functional tests for the sampler, not
658
+ # unit tests per se - some overlap with the tests above, but
659
+ # generally usefully so
660
+
38
661
  def test_multiple_samples
39
-
662
+
40
663
  run_sample_trace
41
664
  run_sample_trace
42
665
  run_sample_trace
43
666
  run_sample_trace
44
-
667
+
45
668
  samples = @sampler.samples
46
669
  assert_equal 4, samples.length
47
670
  assert_equal "a", samples.first.root_segment.called_segments[0].metric_name
@@ -50,24 +673,24 @@ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
50
673
 
51
674
  def test_sample_tree
52
675
  assert_equal 0, @sampler.scope_depth
53
-
676
+
54
677
  @sampler.notice_first_scope_push Time.now.to_f
55
678
  @sampler.notice_transaction "/path", nil, {}
56
679
  @sampler.notice_push_scope "a"
57
-
680
+
58
681
  @sampler.notice_push_scope "b"
59
682
  @sampler.notice_pop_scope "b"
60
-
683
+
61
684
  @sampler.notice_push_scope "c"
62
685
  @sampler.notice_push_scope "d"
63
686
  @sampler.notice_pop_scope "d"
64
687
  @sampler.notice_pop_scope "c"
65
-
688
+
66
689
  @sampler.notice_pop_scope "a"
67
690
  @sampler.notice_scope_empty
68
691
  sample = @sampler.harvest([],0.0).first
69
692
  assert_equal "ROOT{a{b,c{d}}}", sample.to_s_compact
70
-
693
+
71
694
  end
72
695
 
73
696
  def test_sample__gc_stats
@@ -76,7 +699,7 @@ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
76
699
  # called by the transaction sampler. One time value in seconds for each call.
77
700
  MockGCStats.mock_values = [0,0,0,1,0,0,1,0,0,0,0,0,0,0,0]
78
701
  assert_equal 0, @sampler.scope_depth
79
-
702
+
80
703
  @sampler.notice_first_scope_push Time.now.to_f
81
704
  @sampler.notice_transaction "/path", nil, {}
82
705
  @sampler.notice_push_scope "a"
@@ -91,96 +714,100 @@ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
91
714
 
92
715
  @sampler.notice_pop_scope "a"
93
716
  @sampler.notice_scope_empty
94
-
717
+
95
718
  sample = @sampler.harvest([],0.0).first
96
719
  assert_equal "ROOT{a{b,c{d}}}", sample.to_s_compact
97
720
  ensure
98
721
  MockGCStats.mock_values = []
99
722
  end
100
723
 
101
- def test_sample_id
102
- run_sample_trace do
724
+ def test_sample_id
725
+ run_sample_trace do
103
726
  assert((@sampler.current_sample_id && @sampler.current_sample_id != 0), @sampler.current_sample_id.to_s + ' should not be zero')
104
727
  end
105
728
  end
106
-
729
+
730
+
731
+ # NB this test occasionally fails due to a GC during one of the
732
+ # sample traces, for example. It's unfortunate, but we can't
733
+ # reliably turn off GC on all versions of ruby under test
107
734
  def test_harvest_slowest
108
-
735
+
109
736
  run_sample_trace
110
737
  run_sample_trace
111
- run_sample_trace { sleep 0.51 }
738
+ run_sample_trace { sleep 0.06 }
112
739
  run_sample_trace
113
740
  run_sample_trace
114
-
741
+
115
742
  slowest = @sampler.harvest(nil, 0)[0]
116
- assert slowest.duration >= 0.5, "sample duration: #{slowest.duration}"
117
-
118
- run_sample_trace { sleep 0.2 }
743
+ assert slowest.duration >= 0.06, "sample duration: #{slowest.duration}"
744
+
745
+ run_sample_trace { sleep 0.001 }
119
746
  not_as_slow = @sampler.harvest(slowest, 0)[0]
120
747
  assert not_as_slow == slowest
121
-
122
- run_sample_trace { sleep 0.601 }
748
+
749
+ run_sample_trace { sleep 0.07 }
123
750
  new_slowest = @sampler.harvest(slowest, 0)[0]
124
751
  assert new_slowest != slowest
125
- assert new_slowest.duration >= 0.600, "Slowest duration must be > 0.6: #{new_slowest.duration}"
752
+ assert new_slowest.duration >= 0.06, "Slowest duration must be > 0.06: #{new_slowest.duration}"
126
753
  end
127
-
128
-
129
- def test_preare_to_send
130
-
131
- run_sample_trace { sleep 0.2 }
754
+
755
+
756
+ def test_prepare_to_send
757
+
758
+ run_sample_trace { sleep 0.002 }
132
759
  sample = @sampler.harvest(nil, 0)[0]
133
-
760
+
134
761
  ready_to_send = sample.prepare_to_send
135
762
  assert sample.duration == ready_to_send.duration
136
-
763
+
137
764
  assert ready_to_send.start_time.is_a?(Time)
138
765
  end
139
-
766
+
140
767
  def test_multithread
141
768
  threads = []
142
-
143
- 20.times do
769
+
770
+ 5.times do
144
771
  t = Thread.new(@sampler) do |the_sampler|
145
772
  @sampler = the_sampler
146
- 100.times do
147
- run_sample_trace { sleep 0.01 }
773
+ 10.times do
774
+ run_sample_trace { sleep 0.0001 }
148
775
  end
149
776
  end
150
-
777
+
151
778
  threads << t
152
779
  end
153
780
  threads.each {|t| t.join }
154
781
  end
155
-
782
+
156
783
  def test_sample_with_parallel_paths
157
-
784
+
158
785
  assert_equal 0, @sampler.scope_depth
159
-
786
+
160
787
  @sampler.notice_first_scope_push Time.now.to_f
161
788
  @sampler.notice_transaction "/path", nil, {}
162
789
  @sampler.notice_push_scope "a"
163
-
164
- assert_equal 1, @sampler.scope_depth
165
-
790
+
791
+ assert_equal 1, @sampler.scope_depth
792
+
166
793
  @sampler.notice_pop_scope "a"
167
794
  @sampler.notice_scope_empty
168
-
169
- assert_equal 0, @sampler.scope_depth
170
-
795
+
796
+ assert_equal 0, @sampler.scope_depth
797
+
171
798
  @sampler.notice_first_scope_push Time.now.to_f
172
799
  @sampler.notice_transaction "/path", nil, {}
173
800
  @sampler.notice_push_scope "a"
174
801
  @sampler.notice_pop_scope "a"
175
802
  @sampler.notice_scope_empty
176
-
803
+
177
804
  assert_equal 0, @sampler.scope_depth
178
805
  sample = @sampler.harvest(nil, 0.0).first
179
806
  assert_equal "ROOT{a}", sample.to_s_compact
180
807
  end
181
-
808
+
182
809
  def test_double_scope_stack_empty
183
-
810
+
184
811
  @sampler.notice_first_scope_push Time.now.to_f
185
812
  @sampler.notice_transaction "/path", nil, {}
186
813
  @sampler.notice_push_scope "a"
@@ -189,191 +816,113 @@ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
189
816
  @sampler.notice_scope_empty
190
817
  @sampler.notice_scope_empty
191
818
  @sampler.notice_scope_empty
192
-
819
+
193
820
  assert_not_nil @sampler.harvest(nil, 0)[0]
194
821
  end
195
-
196
-
822
+
823
+
197
824
  def test_record_sql_off
198
-
825
+
199
826
  @sampler.notice_first_scope_push Time.now.to_f
200
-
827
+
201
828
  Thread::current[:record_sql] = false
202
-
829
+
203
830
  @sampler.notice_sql("test", nil, 0)
204
-
831
+
205
832
  segment = @sampler.send(:builder).current_segment
206
-
833
+
207
834
  assert_nil segment[:sql]
208
835
  end
209
-
836
+
210
837
  def test_stack_trace__sql
211
838
  @sampler.stack_trace_threshold = 0
212
-
839
+
213
840
  @sampler.notice_first_scope_push Time.now.to_f
214
-
841
+
215
842
  @sampler.notice_sql("test", nil, 1)
216
-
843
+
217
844
  segment = @sampler.send(:builder).current_segment
218
-
845
+
219
846
  assert segment[:sql]
220
847
  assert segment[:backtrace]
221
848
  end
222
849
  def test_stack_trace__scope
223
-
850
+
224
851
  @sampler.stack_trace_threshold = 0
225
852
  t = Time.now
226
853
  @sampler.notice_first_scope_push t.to_f
227
854
  @sampler.notice_push_scope 'Bill', (t+1).to_f
228
-
855
+
229
856
  segment = @sampler.send(:builder).current_segment
230
857
  assert segment[:backtrace]
231
858
  end
232
-
859
+
233
860
  def test_nil_stacktrace
234
-
861
+
235
862
  @sampler.stack_trace_threshold = 2
236
-
863
+
237
864
  @sampler.notice_first_scope_push Time.now.to_f
238
-
865
+
239
866
  @sampler.notice_sql("test", nil, 1)
240
-
867
+
241
868
  segment = @sampler.send(:builder).current_segment
242
-
869
+
243
870
  assert segment[:sql]
244
871
  assert_nil segment[:backtrace]
245
872
  end
246
-
873
+
247
874
  def test_big_sql
248
-
875
+
249
876
  @sampler.notice_first_scope_push Time.now.to_f
250
-
877
+
251
878
  sql = "SADJKHASDHASD KAJSDH ASKDH ASKDHASDK JASHD KASJDH ASKDJHSAKDJHAS DKJHSADKJSAH DKJASHD SAKJDH SAKDJHS"
252
-
879
+
253
880
  len = 0
254
- while len <= NewRelic::Agent::TransactionSampler::MAX_SQL_LENGTH
881
+ while len <= 16384
255
882
  @sampler.notice_sql(sql, nil, 0)
256
883
  len += sql.length
257
884
  end
258
-
885
+
259
886
  segment = @sampler.send(:builder).current_segment
260
-
887
+
261
888
  sql = segment[:sql]
262
-
263
- assert sql.length <= NewRelic::Agent::TransactionSampler::MAX_SQL_LENGTH
889
+
890
+ assert sql.length <= 16384
264
891
  end
265
-
266
-
892
+
893
+
267
894
  def test_segment_obfuscated
268
-
895
+
269
896
  @sampler.notice_first_scope_push Time.now.to_f
270
897
  @sampler.notice_push_scope "foo"
271
-
898
+
272
899
  orig_sql = "SELECT * from Jim where id=66"
273
-
900
+
274
901
  @sampler.notice_sql(orig_sql, nil, 0)
275
-
902
+
276
903
  segment = @sampler.send(:builder).current_segment
277
-
904
+
278
905
  assert_equal orig_sql, segment[:sql]
279
906
  assert_equal "SELECT * from Jim where id=?", segment.obfuscated_sql
280
907
  @sampler.notice_pop_scope "foo"
281
908
  end
282
-
283
-
909
+
910
+
284
911
  def test_param_capture
285
- [true, false].each do |capture|
912
+ [true, false].each do |capture|
286
913
  NewRelic::Control.instance.stubs(:capture_params).returns(capture)
287
914
  @sampler.notice_first_scope_push Time.now.to_f
288
915
  @sampler.notice_transaction('/path', nil, {:param => 'hi'})
289
916
  @sampler.notice_scope_empty
290
-
917
+
291
918
  tt = @sampler.harvest(nil,0)[0]
292
-
919
+
293
920
  assert_equal (capture) ? 1 : 0, tt.params[:request_params].length
294
921
  end
295
922
  end
296
-
297
-
298
- def test_sql_normalization
299
-
300
- # basic statement
301
- assert_equal "INSERT INTO X values(?,?, ? , ?)",
302
- NewRelic::Agent.instance.send(:default_sql_obfuscator, "INSERT INTO X values('test',0, 1 , 2)")
303
-
304
- # escaped literals
305
- assert_equal "INSERT INTO X values(?, ?,?, ? , ?)",
306
- NewRelic::Agent.instance.send(:default_sql_obfuscator, "INSERT INTO X values('', 'jim''s ssn',0, 1 , 'jim''s son''s son')")
307
-
308
- # multiple string literals
309
- assert_equal "INSERT INTO X values(?,?,?, ? , ?)",
310
- NewRelic::Agent.instance.send(:default_sql_obfuscator, "INSERT INTO X values('jim''s ssn','x',0, 1 , 2)")
311
-
312
- # empty string literal
313
- # NOTE: the empty string literal resolves to empty string, which for our purposes is acceptable
314
- assert_equal "INSERT INTO X values(?,?,?, ? , ?)",
315
- NewRelic::Agent.instance.send(:default_sql_obfuscator, "INSERT INTO X values('','x',0, 1 , 2)")
316
-
317
- # try a select statement
318
- assert_equal "select * from table where name=? and ssn=?",
319
- NewRelic::Agent.instance.send(:default_sql_obfuscator, "select * from table where name='jim gochee' and ssn=0012211223")
320
-
321
- # number literals embedded in sql - oh well
322
- assert_equal "select * from table_? where name=? and ssn=?",
323
- NewRelic::Agent.instance.send(:default_sql_obfuscator, "select * from table_007 where name='jim gochee' and ssn=0012211223")
324
- end
325
-
326
- def test_sql_normalization__single_quotes
327
- assert_equal "INSERT ? into table",
328
- NewRelic::Agent.instance.send(:default_sql_obfuscator, "INSERT 'this isn''t a real value' into table")
329
- assert_equal "INSERT ? into table",
330
- NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT '"' into table])
331
- assert_equal "INSERT ? into table",
332
- NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT ' "some text" \" ' into table])
333
- # could not get this one licked. no biggie
334
- # assert_equal "INSERT ? into table",
335
- # NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT '\'' into table])
336
- assert_equal "INSERT ? into table",
337
- NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT ''' ' into table])
338
- end
339
- def test_sql_normalization__double_quotes
340
- assert_equal "INSERT ? into table",
341
- NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT "this isn't a real value" into table])
342
- assert_equal "INSERT ? into table",
343
- NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT "'" into table])
344
- assert_equal "INSERT ? into table",
345
- NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT " \" " into table])
346
- assert_equal "INSERT ? into table",
347
- NewRelic::Agent.instance.send(:default_sql_obfuscator, %q[INSERT " 'some text' " into table])
348
- end
349
- def test_sql_obfuscation_filters
350
- orig = NewRelic::Agent.agent.obfuscator
351
-
352
- NewRelic::Agent.set_sql_obfuscator(:replace) do |sql|
353
- sql = "1" + sql
354
- end
355
-
356
- sql = "SELECT * FROM TABLE 123 'jim'"
357
-
358
- assert_equal "1" + sql, NewRelic::Agent.instance.obfuscator.call(sql)
359
-
360
- NewRelic::Agent.set_sql_obfuscator(:before) do |sql|
361
- sql = "2" + sql
362
- end
363
-
364
- assert_equal "12" + sql, NewRelic::Agent.instance.obfuscator.call(sql)
365
-
366
- NewRelic::Agent.set_sql_obfuscator(:after) do |sql|
367
- sql = sql + "3"
368
- end
369
-
370
- assert_equal "12" + sql + "3", NewRelic::Agent.instance.obfuscator.call(sql)
371
-
372
- NewRelic::Agent.agent.set_sql_obfuscator(:replace, &orig)
373
- end
374
-
375
-
376
- private
923
+
924
+
925
+ private
377
926
  def run_sample_trace(&proc)
378
927
  @sampler.notice_first_scope_push Time.now.to_f
379
928
  @sampler.notice_transaction '/path', nil, {}
@@ -389,5 +938,5 @@ class NewRelic::Agent::TransactionSamplerTest < Test::Unit::TestCase
389
938
  @sampler.notice_pop_scope "a"
390
939
  @sampler.notice_scope_empty
391
940
  end
392
-
941
+
393
942
  end