newrelic_rpm 2.13.4 → 2.13.5.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.
- data/CHANGELOG +9 -0
- data/lib/new_relic/agent.rb +2 -1
- data/lib/new_relic/agent/agent.rb +393 -204
- data/lib/new_relic/agent/error_collector.rb +113 -43
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +14 -16
- data/lib/new_relic/agent/instrumentation/queue_time.rb +201 -0
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sequel.rb +95 -0
- data/lib/new_relic/agent/method_tracer.rb +391 -313
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +43 -41
- data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +2 -0
- data/lib/new_relic/agent/samplers/memory_sampler.rb +122 -120
- data/lib/new_relic/agent/samplers/object_sampler.rb +2 -0
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +0 -1
- data/lib/new_relic/agent/stats_engine/samplers.rb +20 -14
- data/lib/new_relic/agent/stats_engine/transactions.rb +35 -7
- data/lib/new_relic/control.rb +12 -17
- data/lib/new_relic/control/configuration.rb +1 -0
- data/lib/new_relic/control/frameworks/rails.rb +7 -4
- data/lib/new_relic/control/frameworks/rails3.rb +1 -1
- data/lib/new_relic/control/instrumentation.rb +2 -18
- data/lib/new_relic/local_environment.rb +117 -59
- data/lib/new_relic/rack/developer_mode.rb +212 -207
- data/lib/new_relic/recipes.rb +0 -9
- data/lib/new_relic/stats.rb +87 -81
- data/lib/new_relic/transaction_analysis.rb +1 -1
- data/lib/new_relic/version.rb +2 -2
- data/lib/newrelic_rpm.rb +2 -3
- data/lib/tasks/tests.rake +5 -1
- data/newrelic_rpm.gemspec +14 -5
- data/test/config/test_control.rb +14 -2
- data/test/new_relic/agent/active_record_instrumentation_test.rb +342 -119
- data/test/new_relic/agent/add_method_tracer_test.rb +158 -0
- data/test/new_relic/agent/agent_connect_test.rb +295 -0
- data/test/new_relic/agent/agent_controller_test.rb +86 -18
- data/test/new_relic/agent/agent_start_test.rb +326 -0
- data/test/new_relic/agent/agent_start_worker_thread_test.rb +157 -0
- data/test/new_relic/agent/apdex_from_server_test.rb +9 -0
- data/test/new_relic/agent/collection_helper_test.rb +3 -1
- data/test/new_relic/agent/error_collector_notice_error_test.rb +255 -0
- data/test/new_relic/agent/error_collector_test.rb +6 -0
- data/test/new_relic/agent/method_tracer_test.rb +2 -2
- data/test/new_relic/agent/method_tracer_trace_execution_scoped_test.rb +233 -0
- data/test/new_relic/agent/net_instrumentation_test.rb +17 -12
- data/test/new_relic/agent/queue_time_test.rb +333 -0
- data/test/new_relic/agent/rpm_agent_test.rb +4 -2
- data/test/new_relic/agent/stats_engine/samplers_test.rb +27 -1
- data/test/new_relic/agent/transaction_sample_subtest_test.rb +56 -0
- data/test/new_relic/agent/transaction_sample_test.rb +103 -174
- data/test/new_relic/agent/transaction_sampler_test.rb +9 -2
- data/test/new_relic/control_test.rb +7 -2
- data/test/new_relic/metric_spec_test.rb +1 -1
- data/test/new_relic/stats_test.rb +112 -15
- data/test/test_helper.rb +79 -16
- data/ui/helpers/developer_mode_helper.rb +2 -0
- metadata +19 -7
- data/lib/new_relic_api.rb +0 -276
@@ -134,10 +134,10 @@ class NewRelic::Agent::MethodTracerTest < Test::Unit::TestCase
|
|
134
134
|
def test_tt_only
|
135
135
|
|
136
136
|
assert_nil @scope_listener.scope["c2"]
|
137
|
-
self.class.add_method_tracer :method_c1, "c1", true
|
137
|
+
self.class.add_method_tracer :method_c1, "c1", :push_scope => true
|
138
138
|
|
139
139
|
self.class.add_method_tracer :method_c2, "c2", :metric => false
|
140
|
-
self.class.add_method_tracer :method_c3, "c3", false
|
140
|
+
self.class.add_method_tracer :method_c3, "c3", :push_scope => false
|
141
141
|
|
142
142
|
method_c1
|
143
143
|
|
@@ -0,0 +1,233 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
class NewRelic::Agent::MethodTracer::TraceExecutionScopedTest < Test::Unit::TestCase
|
3
|
+
require 'new_relic/agent/method_tracer'
|
4
|
+
include NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScoped
|
5
|
+
|
6
|
+
def test_trace_disabled_negative
|
7
|
+
self.expects(:traced?).returns(false)
|
8
|
+
options = {:force => false}
|
9
|
+
assert trace_disabled?(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_trace_disabled_forced
|
13
|
+
self.expects(:traced?).returns(false)
|
14
|
+
options = {:force => true}
|
15
|
+
assert !(trace_disabled?(options))
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_trace_disabled_positive
|
19
|
+
self.expects(:traced?).returns(true)
|
20
|
+
options = {:force => false}
|
21
|
+
assert !(trace_disabled?(options))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_get_stats_unscoped
|
25
|
+
fake_engine = mocked_object('stat_engine')
|
26
|
+
fake_engine.expects(:get_stats_no_scope).with('foob').returns('fakestats')
|
27
|
+
assert_equal 'fakestats', get_stats_unscoped('foob')
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_get_stats_scoped_scoped_only
|
31
|
+
fake_engine = mocked_object('stat_engine')
|
32
|
+
fake_engine.expects(:get_stats).with('foob', true, true).returns('fakestats')
|
33
|
+
assert_equal 'fakestats', get_stats_scoped('foob', true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_get_stats_scoped_no_scoped_only
|
37
|
+
fake_engine = mocked_object('stat_engine')
|
38
|
+
fake_engine.expects(:get_stats).with('foob', true, false).returns('fakestats')
|
39
|
+
assert_equal 'fakestats', get_stats_scoped('foob', false)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_stat_engine
|
43
|
+
assert_equal agent_instance.stats_engine, stat_engine
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_agent_instance
|
47
|
+
assert_equal NewRelic::Agent.instance, agent_instance
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_main_stat
|
51
|
+
self.expects(:get_stats_scoped).with('hello', true)
|
52
|
+
opts = {:scoped_metric_only => true}
|
53
|
+
main_stat('hello', opts)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_get_metric_stats_metric
|
57
|
+
metrics = ['foo', 'bar', 'baz']
|
58
|
+
opts = {:metric => true}
|
59
|
+
self.expects(:get_stats_unscoped).twice
|
60
|
+
self.expects(:main_stat).with('foo', opts)
|
61
|
+
first_name, stats = get_metric_stats(metrics, opts)
|
62
|
+
assert_equal 'foo', first_name
|
63
|
+
assert_equal 3, stats.length
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_get_metric_stats_no_metric
|
67
|
+
metrics = ['foo', 'bar', 'baz']
|
68
|
+
opts = {:metric => false}
|
69
|
+
self.expects(:get_stats_unscoped).twice
|
70
|
+
first_name, stats = get_metric_stats(metrics, opts)
|
71
|
+
assert_equal 'foo', first_name
|
72
|
+
assert_equal 2, stats.length
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_set_if_nil
|
76
|
+
h = {}
|
77
|
+
set_if_nil(h, :foo)
|
78
|
+
assert h[:foo]
|
79
|
+
h[:bar] = false
|
80
|
+
set_if_nil(h, :bar)
|
81
|
+
assert !h[:bar]
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_push_flag_true
|
85
|
+
fake_agent = mocked_object('agent_instance')
|
86
|
+
fake_agent.expects(:push_trace_execution_flag).with(true)
|
87
|
+
push_flag!(true)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_push_flag_false
|
91
|
+
self.expects(:agent_instance).never
|
92
|
+
push_flag!(false)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_pop_flag_true
|
96
|
+
fake_agent = mocked_object('agent_instance')
|
97
|
+
fake_agent.expects(:pop_trace_execution_flag)
|
98
|
+
pop_flag!(true)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_pop_flag_false
|
102
|
+
self.expects(:agent_instance).never
|
103
|
+
pop_flag!(false)
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_log_errors_base
|
107
|
+
self.expects(:log).never
|
108
|
+
ran = false
|
109
|
+
log_errors("name", "metric") do
|
110
|
+
ran = true
|
111
|
+
end
|
112
|
+
assert ran, "should run the contents of the block"
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_log_errors_with_return
|
116
|
+
self.expects(:log).never
|
117
|
+
ran = false
|
118
|
+
return_val = log_errors('name', 'metric') do
|
119
|
+
ran = true
|
120
|
+
'happy trees'
|
121
|
+
end
|
122
|
+
|
123
|
+
assert ran, "should run contents of block"
|
124
|
+
assert_equal 'happy trees', return_val, "should return contents of the block"
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_log_errors_with_error
|
128
|
+
fakelog = mocked_log
|
129
|
+
# normally I don't do this, but we really don't care what the
|
130
|
+
# backtrace looks like, beyond that it actually gets logged. Also,
|
131
|
+
# the mocks are reversed because apparently order matters.
|
132
|
+
fakelog.expects(:error).with(any_parameters)
|
133
|
+
fakelog.expects(:error).with("Caught exception in name. Metric name = metric, exception = should not propagate out of block")
|
134
|
+
|
135
|
+
log_errors("name", "metric") do
|
136
|
+
raise "should not propagate out of block"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_trace_execution_scoped_header
|
141
|
+
options = {:force => false, :deduct_call_time_from_parent => false}
|
142
|
+
self.expects(:log_errors).with('trace_execution_scoped header', 'foo').yields
|
143
|
+
self.expects(:push_flag!).with(false)
|
144
|
+
fakestats = mocked_object('stat_engine')
|
145
|
+
fakestats.expects(:push_scope).with('foo', 1.0, false)
|
146
|
+
trace_execution_scoped_header('foo', options, 1.0)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_trace_execution_scoped_footer
|
150
|
+
t0 = 1.0
|
151
|
+
t1 = 2.0
|
152
|
+
metric = 'foo'
|
153
|
+
metric_stats = [mock('fakestat')]
|
154
|
+
metric_stats.first.expects(:trace_call).with(1.0, 0.5)
|
155
|
+
expected_scope = 'an expected scope'
|
156
|
+
engine = mocked_object('stat_engine')
|
157
|
+
scope = mock('scope')
|
158
|
+
engine.expects(:pop_scope).with('an expected scope', 1.0, 2.0).returns(scope)
|
159
|
+
scope.expects(:children_time).returns(0.5)
|
160
|
+
self.expects(:pop_flag!).with(false)
|
161
|
+
self.expects(:log_errors).with('trace_method_execution footer', 'foo').yields
|
162
|
+
|
163
|
+
trace_execution_scoped_footer(t0, metric, metric_stats, expected_scope, false, t1)
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_trace_execution_scoped_disabled
|
167
|
+
self.expects(:trace_disabled?).returns(true)
|
168
|
+
# make sure the method doesn't beyond the abort
|
169
|
+
self.expects(:set_if_nil).never
|
170
|
+
ran = false
|
171
|
+
value = trace_execution_scoped(nil, {:options => 'hash'}) do
|
172
|
+
ran = true
|
173
|
+
1172
|
174
|
+
end
|
175
|
+
|
176
|
+
assert ran, 'should run contents of block'
|
177
|
+
assert_equal 1172, value, 'should return contents of block'
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_trace_execution_scoped_default
|
181
|
+
passed_in_opts = {}
|
182
|
+
opts_after_correction = {:metric => true, :deduct_call_time_from_parent => true}
|
183
|
+
self.expects(:trace_disabled?).returns(false)
|
184
|
+
self.expects(:get_metric_stats).with(['metric', 'array'], opts_after_correction).returns(['metric', ['stats']])
|
185
|
+
self.expects(:trace_execution_scoped_header).with('metric', opts_after_correction).returns(['start_time', 'expected_scope'])
|
186
|
+
self.expects(:trace_execution_scoped_footer).with('start_time', 'metric', ['stats'], 'expected_scope', nil)
|
187
|
+
ran = false
|
188
|
+
value = trace_execution_scoped(['metric', 'array'], passed_in_opts) do
|
189
|
+
ran = true
|
190
|
+
1172
|
191
|
+
end
|
192
|
+
|
193
|
+
assert ran, 'should run contents of the block'
|
194
|
+
assert_equal 1172, value, 'should return the contents of the block'
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_trace_execution_scoped_with_error
|
198
|
+
passed_in_opts = {}
|
199
|
+
opts_after_correction = {:metric => true, :deduct_call_time_from_parent => true}
|
200
|
+
self.expects(:trace_disabled?).returns(false)
|
201
|
+
self.expects(:get_metric_stats).with(['metric', 'array'], opts_after_correction).returns(['metric', ['stats']])
|
202
|
+
self.expects(:trace_execution_scoped_header).with('metric', opts_after_correction).returns(['start_time', 'expected_scope'])
|
203
|
+
self.expects(:trace_execution_scoped_footer).with('start_time', 'metric', ['stats'], 'expected_scope', nil)
|
204
|
+
ran = false
|
205
|
+
assert_raises(RuntimeError) do
|
206
|
+
trace_execution_scoped(['metric', 'array'], passed_in_opts) do
|
207
|
+
ran = true
|
208
|
+
raise 'wtfmate'
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
assert ran, 'should run contents of the block'
|
213
|
+
end
|
214
|
+
|
215
|
+
private
|
216
|
+
|
217
|
+
def mocked_object(name)
|
218
|
+
object = mock(name)
|
219
|
+
self.stubs(name).returns(object)
|
220
|
+
object
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
def mocked_log
|
225
|
+
mocked_object('log')
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
def mocked_control
|
230
|
+
mocked_object('control')
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
@@ -7,6 +7,13 @@ class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
|
|
7
7
|
@engine = NewRelic::Agent.instance.stats_engine
|
8
8
|
@engine.clear_stats
|
9
9
|
end
|
10
|
+
|
11
|
+
def metrics_without_gc
|
12
|
+
@engine.metrics - ['GC/cumulative']
|
13
|
+
end
|
14
|
+
|
15
|
+
private :metrics_without_gc
|
16
|
+
|
10
17
|
def test_get
|
11
18
|
url = URI.parse('http://www.google.com/index.html')
|
12
19
|
res = Net::HTTP.start(url.host, url.port) {|http|
|
@@ -14,7 +21,7 @@ class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
|
|
14
21
|
}
|
15
22
|
assert_match /<head>/, res.body
|
16
23
|
assert_equal %w[External/www.google.com/Net::HTTP/GET External/allOther External/www.google.com/all].sort,
|
17
|
-
|
24
|
+
metrics_without_gc.sort
|
18
25
|
end
|
19
26
|
|
20
27
|
def test_background
|
@@ -25,9 +32,8 @@ class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
|
|
25
32
|
}
|
26
33
|
assert_match /<head>/, res.body
|
27
34
|
end
|
28
|
-
assert_equal
|
29
|
-
|
30
|
-
External/www.google.com/Net::HTTP/GET:OtherTransaction/Background/NewRelic::Agent::NetInstrumentationTest/task].sort
|
35
|
+
assert_equal %w[External/www.google.com/Net::HTTP/GET External/allOther External/www.google.com/all
|
36
|
+
External/www.google.com/Net::HTTP/GET:OtherTransaction/Background/NewRelic::Agent::NetInstrumentationTest/task].sort, metrics_without_gc.select{|m| m =~ /^External/}.sort
|
31
37
|
end
|
32
38
|
|
33
39
|
def test_transactional
|
@@ -38,14 +44,13 @@ class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
|
|
38
44
|
}
|
39
45
|
assert_match /<head>/, res.body
|
40
46
|
end
|
41
|
-
assert_equal
|
42
|
-
|
43
|
-
External/www.google.com/Net::HTTP/GET:Controller/NewRelic::Agent::NetInstrumentationTest/task].sort
|
47
|
+
assert_equal %w[External/www.google.com/Net::HTTP/GET External/allWeb External/www.google.com/all
|
48
|
+
External/www.google.com/Net::HTTP/GET:Controller/NewRelic::Agent::NetInstrumentationTest/task].sort, metrics_without_gc.select{|m| m =~ /^External/}.sort
|
44
49
|
end
|
45
50
|
def test_get__simple
|
46
51
|
Net::HTTP.get URI.parse('http://www.google.com/index.html')
|
47
|
-
assert_equal
|
48
|
-
|
52
|
+
assert_equal metrics_without_gc.sort,
|
53
|
+
%w[External/www.google.com/Net::HTTP/GET External/allOther External/www.google.com/all].sort
|
49
54
|
end
|
50
55
|
def test_ignore
|
51
56
|
NewRelic::Agent.disable_all_tracing do
|
@@ -54,7 +59,7 @@ class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
|
|
54
59
|
http.post('/index.html','data')
|
55
60
|
}
|
56
61
|
end
|
57
|
-
assert_equal 0,
|
62
|
+
assert_equal 0, metrics_without_gc.size
|
58
63
|
end
|
59
64
|
def test_head
|
60
65
|
url = URI.parse('http://www.google.com/index.html')
|
@@ -62,7 +67,7 @@ class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
|
|
62
67
|
http.head('/index.html')
|
63
68
|
}
|
64
69
|
assert_equal %w[External/www.google.com/Net::HTTP/HEAD External/allOther External/www.google.com/all].sort,
|
65
|
-
|
70
|
+
metrics_without_gc.sort
|
66
71
|
end
|
67
72
|
|
68
73
|
def test_post
|
@@ -71,7 +76,7 @@ class NewRelic::Agent::NetInstrumentationTest < Test::Unit::TestCase
|
|
71
76
|
http.post('/index.html','data')
|
72
77
|
}
|
73
78
|
assert_equal %w[External/www.google.com/Net::HTTP/POST External/allOther External/www.google.com/all].sort,
|
74
|
-
|
79
|
+
metrics_without_gc.sort
|
75
80
|
end
|
76
81
|
|
77
82
|
end
|
@@ -0,0 +1,333 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
|
2
|
+
class NewRelic::Agent::Instrumentation::QueueTimeTest < Test::Unit::TestCase
|
3
|
+
require 'new_relic/agent/instrumentation/queue_time'
|
4
|
+
include NewRelic::Agent::Instrumentation::QueueTime
|
5
|
+
|
6
|
+
def setup
|
7
|
+
NewRelic::Agent.instance.stats_engine.clear_stats
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_test_start_time(env)
|
11
|
+
env[APP_HEADER] = "t=#{convert_to_microseconds(Time.at(1002))}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_parse_frontend_headers
|
15
|
+
self.expects(:current_time).returns('END_TIME')
|
16
|
+
self.expects(:add_end_time_header).with('END_TIME', {:env => 'hash'})
|
17
|
+
# ordering is important here, unfortunately, the mocks don't
|
18
|
+
# support that kind of checking.
|
19
|
+
self.expects(:parse_middleware_time_from).with({:env => 'hash'})
|
20
|
+
self.expects(:parse_queue_time_from).with({:env => 'hash'})
|
21
|
+
self.expects(:parse_server_time_from).with({:env => 'hash'})
|
22
|
+
parse_frontend_headers({:env => 'hash'})
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_all_combined_frontend_headers
|
26
|
+
env = {}
|
27
|
+
env[MAIN_HEADER] = "t=#{convert_to_microseconds(Time.at(1000))}"
|
28
|
+
env[QUEUE_HEADER] = "t=#{convert_to_microseconds(Time.at(1001))}"
|
29
|
+
env[MIDDLEWARE_HEADER] = "t=#{convert_to_microseconds(Time.at(1002))}"
|
30
|
+
|
31
|
+
env[APP_HEADER] = "t=#{convert_to_microseconds(Time.at(1003))}"
|
32
|
+
|
33
|
+
assert_calls_metrics('WebFrontend/WebServer/all', 'WebFrontend/QueueTime', 'Middleware/all') do
|
34
|
+
parse_middleware_time_from(env)
|
35
|
+
parse_queue_time_from(env)
|
36
|
+
parse_server_time_from(env)
|
37
|
+
end
|
38
|
+
|
39
|
+
check_metric_time('WebFrontend/WebServer/all', 1.0, 0.001)
|
40
|
+
check_metric_time('WebFrontend/QueueTime', 1.0, 0.001)
|
41
|
+
check_metric_time('Middleware/all', 1.0, 0.001)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_combined_middleware_and_queue
|
45
|
+
env = {}
|
46
|
+
env[QUEUE_HEADER] = "t=#{convert_to_microseconds(Time.at(1000))}"
|
47
|
+
env[MIDDLEWARE_HEADER] = "t=#{convert_to_microseconds(Time.at(1001))}"
|
48
|
+
create_test_start_time(env)
|
49
|
+
|
50
|
+
assert_calls_metrics('Middleware/all', 'WebFrontend/QueueTime') do
|
51
|
+
parse_middleware_time_from(env)
|
52
|
+
parse_queue_time_from(env)
|
53
|
+
end
|
54
|
+
|
55
|
+
check_metric_time('Middleware/all', 1.0, 0.001)
|
56
|
+
check_metric_time('WebFrontend/QueueTime', 1.0, 0.001)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_combined_queue_and_server
|
60
|
+
env = {}
|
61
|
+
env[MAIN_HEADER] = "t=#{convert_to_microseconds(Time.at(1000))}"
|
62
|
+
env[QUEUE_HEADER] = "t=#{convert_to_microseconds(Time.at(1001))}"
|
63
|
+
create_test_start_time(env)
|
64
|
+
|
65
|
+
assert_calls_metrics('WebFrontend/WebServer/all', 'WebFrontend/QueueTime') do
|
66
|
+
parse_queue_time_from(env)
|
67
|
+
parse_server_time_from(env)
|
68
|
+
end
|
69
|
+
|
70
|
+
check_metric_time('WebFrontend/WebServer/all', 1.0, 0.001)
|
71
|
+
check_metric_time('WebFrontend/QueueTime', 1.0, 0.001)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_combined_middleware_and_server
|
75
|
+
env = {}
|
76
|
+
env[MAIN_HEADER] = "t=#{convert_to_microseconds(Time.at(1000))}"
|
77
|
+
env[MIDDLEWARE_HEADER] = "t=#{convert_to_microseconds(Time.at(1001))}"
|
78
|
+
create_test_start_time(env)
|
79
|
+
|
80
|
+
assert_calls_metrics('WebFrontend/WebServer/all', 'Middleware/all') do
|
81
|
+
parse_middleware_time_from(env)
|
82
|
+
parse_server_time_from(env)
|
83
|
+
end
|
84
|
+
|
85
|
+
check_metric_time('WebFrontend/WebServer/all', 1.0, 0.001)
|
86
|
+
check_metric_time('Middleware/all', 1.0, 0.001)
|
87
|
+
end
|
88
|
+
|
89
|
+
# initial base case, a router and a static content server
|
90
|
+
def test_parse_server_time_from_initial
|
91
|
+
env = {}
|
92
|
+
create_test_start_time(env)
|
93
|
+
time1 = convert_to_microseconds(Time.at(1000))
|
94
|
+
time2 = convert_to_microseconds(Time.at(1001))
|
95
|
+
env['HTTP_X_REQUEST_START'] = "servera t=#{time1}, serverb t=#{time2}"
|
96
|
+
assert_calls_metrics('WebFrontend/WebServer/all', 'WebFrontend/WebServer/servera', 'WebFrontend/WebServer/serverb') do
|
97
|
+
parse_server_time_from(env)
|
98
|
+
end
|
99
|
+
check_metric_time('WebFrontend/WebServer/all', 2.0, 0.1)
|
100
|
+
check_metric_time('WebFrontend/WebServer/servera', 1.0, 0.1)
|
101
|
+
check_metric_time('WebFrontend/WebServer/serverb', 1.0, 0.1)
|
102
|
+
end
|
103
|
+
|
104
|
+
# test for backwards compatibility with old header
|
105
|
+
def test_parse_server_time_from_with_no_server_name
|
106
|
+
env = {'HTTP_X_REQUEST_START' => "t=#{convert_to_microseconds(Time.at(1001))}"}
|
107
|
+
create_test_start_time(env)
|
108
|
+
assert_calls_metrics('WebFrontend/WebServer/all') do
|
109
|
+
parse_server_time_from(env)
|
110
|
+
end
|
111
|
+
check_metric_time('WebFrontend/WebServer/all', 1.0, 0.1)
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_parse_server_time_from_with_bad_header
|
115
|
+
env = {'HTTP_X_REQUEST_START' => 't=t=t=t='}
|
116
|
+
create_test_start_time(env)
|
117
|
+
assert_calls_metrics('WebFrontend/WebServer/all') do
|
118
|
+
parse_server_time_from(env)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_parse_server_time_from_with_no_header
|
123
|
+
assert_calls_metrics('WebFrontend/WebServer/all') do
|
124
|
+
parse_server_time_from({})
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_parse_middleware_time
|
129
|
+
env = {}
|
130
|
+
create_test_start_time(env)
|
131
|
+
time1 = convert_to_microseconds(Time.at(1000))
|
132
|
+
time2 = convert_to_microseconds(Time.at(1001))
|
133
|
+
|
134
|
+
env['HTTP_X_MIDDLEWARE_START'] = "base t=#{time1}, second t=#{time2}"
|
135
|
+
assert_calls_metrics('Middleware/all', 'Middleware/base', 'Middleware/second') do
|
136
|
+
parse_middleware_time_from(env)
|
137
|
+
end
|
138
|
+
check_metric_time('Middleware/all', 2.0, 0.1)
|
139
|
+
check_metric_time('Middleware/base', 1.0, 0.1)
|
140
|
+
check_metric_time('Middleware/second', 1.0, 0.1)
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_parse_queue_time
|
144
|
+
env = {}
|
145
|
+
create_test_start_time(env)
|
146
|
+
time1 = convert_to_microseconds(Time.at(1000))
|
147
|
+
|
148
|
+
env['HTTP_X_QUEUE_START'] = "t=#{time1}"
|
149
|
+
assert_calls_metrics('WebFrontend/QueueTime') do
|
150
|
+
parse_queue_time_from(env)
|
151
|
+
end
|
152
|
+
|
153
|
+
check_metric_time('WebFrontend/QueueTime', 2.0, 0.1)
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_check_for_alternate_queue_length
|
157
|
+
env = {}
|
158
|
+
create_test_start_time(env)
|
159
|
+
env['HTTP_X_QUEUE_TIME'] = '1000000'
|
160
|
+
assert_calls_metrics('WebFrontend/QueueTime') do
|
161
|
+
parse_queue_time_from(env)
|
162
|
+
end
|
163
|
+
|
164
|
+
check_metric_time('WebFrontend/QueueTime', 1.0, 0.001)
|
165
|
+
end
|
166
|
+
|
167
|
+
# each server should be one second, and the total would be 2 seconds
|
168
|
+
def test_record_individual_server_stats
|
169
|
+
matches = [['foo', Time.at(1000)], ['bar', Time.at(1001)]]
|
170
|
+
assert_calls_metrics('WebFrontend/WebServer/foo', 'WebFrontend/WebServer/bar') do
|
171
|
+
record_individual_server_stats(Time.at(1002), matches)
|
172
|
+
end
|
173
|
+
check_metric_time('WebFrontend/WebServer/foo', 1.0, 0.1)
|
174
|
+
check_metric_time('WebFrontend/WebServer/bar', 1.0, 0.1)
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_record_rollup_server_stat
|
178
|
+
assert_calls_metrics('WebFrontend/WebServer/all') do
|
179
|
+
record_rollup_server_stat(Time.at(1001), [['a', Time.at(1000)]])
|
180
|
+
end
|
181
|
+
check_metric_time('WebFrontend/WebServer/all', 1.0, 0.1)
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_record_rollup_server_stat_no_data
|
185
|
+
assert_calls_metrics('WebFrontend/WebServer/all') do
|
186
|
+
record_rollup_server_stat(Time.at(1001), [])
|
187
|
+
end
|
188
|
+
check_metric_time('WebFrontend/WebServer/all', 0.0, 0.001)
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_record_rollup_middleware_stat
|
192
|
+
assert_calls_metrics('Middleware/all') do
|
193
|
+
record_rollup_middleware_stat(Time.at(1001), [['a', Time.at(1000)]])
|
194
|
+
end
|
195
|
+
check_metric_time('Middleware/all', 1.0, 0.1)
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_record_rollup_middleware_stat_no_data
|
199
|
+
assert_calls_metrics('Middleware/all') do
|
200
|
+
record_rollup_middleware_stat(Time.at(1001), [])
|
201
|
+
end
|
202
|
+
check_metric_time('Middleware/all', 0.0, 0.001)
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_record_rollup_queue_stat
|
206
|
+
assert_calls_metrics('WebFrontend/QueueTime') do
|
207
|
+
record_rollup_queue_stat(Time.at(1001), [[nil, Time.at(1000)]])
|
208
|
+
end
|
209
|
+
check_metric_time('WebFrontend/QueueTime', 1.0, 0.1)
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_record_rollup_queue_stat_no_data
|
213
|
+
assert_calls_metrics('WebFrontend/QueueTime') do
|
214
|
+
record_rollup_queue_stat(Time.at(1001), [])
|
215
|
+
end
|
216
|
+
check_metric_time('WebFrontend/QueueTime', 0.0, 0.001)
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
# check all the combinations to make sure that ordering doesn't
|
221
|
+
# affect the return value
|
222
|
+
def test_find_oldest_time
|
223
|
+
test_arrays = [
|
224
|
+
['a', Time.at(1000)],
|
225
|
+
['b', Time.at(1001)],
|
226
|
+
['c', Time.at(1002)],
|
227
|
+
['d', Time.at(1000)],
|
228
|
+
]
|
229
|
+
test_arrays = test_arrays.permutation
|
230
|
+
test_arrays.each do |test_array|
|
231
|
+
assert_equal find_oldest_time(test_array), Time.at(1000), "Should be the oldest time in the array"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# trivial test but the method doesn't do much
|
236
|
+
def test_record_server_time_for
|
237
|
+
name = 'foo'
|
238
|
+
time = Time.at(1000)
|
239
|
+
start_time = Time.at(1001)
|
240
|
+
self.expects(:record_time_stat).with('WebFrontend/WebServer/foo', time, start_time)
|
241
|
+
record_server_time_for(name, time, start_time)
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_record_time_stat
|
245
|
+
assert_calls_metrics('WebFrontend/WebServer/foo') do
|
246
|
+
record_time_stat('WebFrontend/WebServer/foo', Time.at(1000), Time.at(1001))
|
247
|
+
end
|
248
|
+
check_metric_time('WebFrontend/WebServer/foo', 1.0, 0.1)
|
249
|
+
assert_raises(RuntimeError) do
|
250
|
+
record_time_stat('foo', Time.at(1001), Time.at(1000))
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_record_time_stat_with_end_after_start
|
255
|
+
record_time_stat('WebFrontend/WebServer/foo', 2, 1)
|
256
|
+
rescue RuntimeError => e
|
257
|
+
assert_equal("should not provide an end time less than start time: 1 is less than 2", e.message)
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_convert_to_microseconds
|
261
|
+
assert_equal((1_000_000_000), convert_to_microseconds(Time.at(1000)), 'time at 1000 seconds past epoch should be 1,000,000,000 usec')
|
262
|
+
assert_equal 1_000_000_000, convert_to_microseconds(1_000_000_000), 'should not mess with a number if passed in'
|
263
|
+
assert_raises(TypeError) do
|
264
|
+
convert_to_microseconds('whoo yeah buddy')
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_convert_from_microseconds
|
269
|
+
assert_equal Time.at(1000), convert_from_microseconds(1_000_000_000), 'time at 1,000,000,000 usec should be 1000 seconds after epoch'
|
270
|
+
assert_equal Time.at(1000), convert_from_microseconds(Time.at(1000)), 'should not mess with a time passed in'
|
271
|
+
assert_raises(TypeError) do
|
272
|
+
convert_from_microseconds('10000000000')
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_add_end_time_header
|
277
|
+
env = {}
|
278
|
+
start_time = Time.at(1)
|
279
|
+
add_end_time_header(start_time, env)
|
280
|
+
assert_equal({'HTTP_X_APPLICATION_START' => "t=#{convert_to_microseconds(Time.at(1))}"}, env, "should add the header to the env hash")
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_parse_end_time_base
|
284
|
+
env = {}
|
285
|
+
env['HTTP_X_APPLICATION_START'] = "t=#{convert_to_microseconds(Time.at(1))}"
|
286
|
+
start_time = parse_end_time(env)
|
287
|
+
assert_equal(Time.at(1), start_time, "should pull the correct start time from the app header")
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_get_matches_from_header
|
291
|
+
env = {'A HEADER' => 't=1000000'}
|
292
|
+
self.expects(:convert_from_microseconds).with(1000000).returns(Time.at(1))
|
293
|
+
matches = get_matches_from_header('A HEADER', env)
|
294
|
+
assert_equal [[nil, Time.at(1)]], matches, "should pull the correct time from the string"
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_convert_to_name_time_pair
|
298
|
+
name = :foo
|
299
|
+
time = "1000000"
|
300
|
+
|
301
|
+
pair = convert_to_name_time_pair(name, time)
|
302
|
+
assert_equal [:foo, Time.at(1)], pair
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_get_matches
|
306
|
+
str = "servera t=1000000, serverb t=1000000"
|
307
|
+
matches = get_matches(str) # start a fire
|
308
|
+
assert_equal [['servera', '1000000'], ['serverb', '1000000']], matches
|
309
|
+
end
|
310
|
+
|
311
|
+
def test_matches_with_bad_data
|
312
|
+
str = "stephan is a dumb lol"
|
313
|
+
matches = get_matches(str)
|
314
|
+
assert_equal [], matches
|
315
|
+
|
316
|
+
str = "t=100"
|
317
|
+
matches = get_matches(str)
|
318
|
+
assert_equal [[nil, '100']], matches
|
319
|
+
|
320
|
+
str = nil
|
321
|
+
matches = get_matches(str)
|
322
|
+
assert_equal [], matches
|
323
|
+
end
|
324
|
+
# each server should be one second, and the total would be 2 seconds
|
325
|
+
def test_record_individual_middleware_stats
|
326
|
+
matches = [['foo', Time.at(1000)], ['bar', Time.at(1001)]]
|
327
|
+
assert_calls_metrics('Middleware/foo', 'Middleware/bar') do
|
328
|
+
record_individual_middleware_stats(Time.at(1002), matches)
|
329
|
+
end
|
330
|
+
check_metric_time('Middleware/foo', 1.0, 0.1)
|
331
|
+
check_metric_time('Middleware/bar', 1.0, 0.1)
|
332
|
+
end
|
333
|
+
end
|