right_support 2.11.3 → 2.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -0
  3. data/VERSION +1 -1
  4. data/lib/right_support/notifiers/airbrake.rb +194 -0
  5. data/lib/right_support/notifiers/base.rb +73 -0
  6. data/lib/right_support/notifiers/blacklisters/base.rb +48 -0
  7. data/lib/right_support/notifiers/blacklisters/canonical.rb +60 -0
  8. data/lib/right_support/notifiers/blacklisters/regular_expression.rb +86 -0
  9. data/{features/support/file_utils_bundler_mixin.rb → lib/right_support/notifiers/blacklisters/simple.rb} +21 -20
  10. data/lib/right_support/notifiers/blacklisters/snake_case.rb +60 -0
  11. data/lib/right_support/notifiers/blacklisters/wildcard.rb +65 -0
  12. data/lib/right_support/notifiers/blacklisters.rb +34 -0
  13. data/lib/right_support/notifiers/logger.rb +94 -0
  14. data/lib/right_support/notifiers/notification.rb +57 -0
  15. data/lib/right_support/notifiers/utilities/backtrace_decoder.rb +234 -0
  16. data/lib/right_support/notifiers/utilities.rb +29 -0
  17. data/lib/right_support/notifiers.rb +32 -0
  18. data/lib/right_support/rack/request_logger.rb +13 -9
  19. data/lib/right_support.rb +1 -0
  20. data/right_support.gemspec +19 -70
  21. metadata +17 -69
  22. data/.coveralls.yml +0 -2
  23. data/.rspec +0 -3
  24. data/.simplecov +0 -6
  25. data/.travis.yml +0 -13
  26. data/Gemfile +0 -51
  27. data/Gemfile.lock +0 -153
  28. data/features/balancer_error_handling.feature +0 -34
  29. data/features/balancer_health_check.feature +0 -33
  30. data/features/hash_tools.feature +0 -27
  31. data/features/http_client_timeout.feature +0 -19
  32. data/features/serialization.feature +0 -113
  33. data/features/step_definitions/hash_tools_steps.rb +0 -41
  34. data/features/step_definitions/http_client_steps.rb +0 -27
  35. data/features/step_definitions/request_balancer_steps.rb +0 -93
  36. data/features/step_definitions/ruby_steps.rb +0 -176
  37. data/features/step_definitions/serialization_steps.rb +0 -133
  38. data/features/step_definitions/server_steps.rb +0 -134
  39. data/features/support/env.rb +0 -148
  40. data/right_support.rconf +0 -9
  41. data/spec/config/feature_set_spec.rb +0 -83
  42. data/spec/crypto/signed_hash_spec.rb +0 -73
  43. data/spec/data/hash_tools_spec.rb +0 -602
  44. data/spec/data/mash_spec.rb +0 -313
  45. data/spec/data/token_spec.rb +0 -21
  46. data/spec/data/uuid_spec.rb +0 -45
  47. data/spec/db/cassandra_model_part1_spec.rb +0 -84
  48. data/spec/db/cassandra_model_part2_spec.rb +0 -73
  49. data/spec/db/cassandra_model_spec.rb +0 -375
  50. data/spec/fixtures/encrypted_priv_rsa.pem +0 -30
  51. data/spec/fixtures/good_priv_dsa.pem +0 -12
  52. data/spec/fixtures/good_priv_rsa.pem +0 -15
  53. data/spec/fixtures/good_pub_dsa.ssh +0 -1
  54. data/spec/fixtures/good_pub_rsa.pem +0 -5
  55. data/spec/fixtures/good_pub_rsa.ssh +0 -1
  56. data/spec/log/exception_logger_spec.rb +0 -76
  57. data/spec/log/filter_logger_spec.rb +0 -66
  58. data/spec/log/mixin_spec.rb +0 -141
  59. data/spec/log/multiplexer_spec.rb +0 -54
  60. data/spec/log/null_logger_spec.rb +0 -36
  61. data/spec/log/step_level_logger_spec.rb +0 -49
  62. data/spec/log/system_logger_spec.rb +0 -172
  63. data/spec/net/address_helper_spec.rb +0 -57
  64. data/spec/net/dns_spec.rb +0 -187
  65. data/spec/net/http_client_spec.rb +0 -181
  66. data/spec/net/lb/health_check_spec.rb +0 -417
  67. data/spec/net/lb/round_robin_spec.rb +0 -15
  68. data/spec/net/lb/sticky_spec.rb +0 -92
  69. data/spec/net/request_balancer_spec.rb +0 -690
  70. data/spec/net/s3_helper_spec.rb +0 -160
  71. data/spec/net/ssl_spec.rb +0 -42
  72. data/spec/net/string_encoder_spec.rb +0 -58
  73. data/spec/rack/log_setter_spec.rb +0 -5
  74. data/spec/rack/request_logger_spec.rb +0 -225
  75. data/spec/rack/request_tracker_spec.rb +0 -115
  76. data/spec/rack/runtime_spec.rb +0 -49
  77. data/spec/ruby/easy_singleton_spec.rb +0 -72
  78. data/spec/ruby/object_extensions_spec.rb +0 -27
  79. data/spec/ruby/string_extensions_spec.rb +0 -98
  80. data/spec/spec_helper.rb +0 -188
  81. data/spec/stats/activity_spec.rb +0 -425
  82. data/spec/stats/exceptions_spec.rb +0 -247
  83. data/spec/stats/helpers_spec.rb +0 -685
  84. data/spec/validation/openssl_spec.rb +0 -37
  85. data/spec/validation/ssh_spec.rb +0 -39
@@ -1,425 +0,0 @@
1
- #
2
- # Copyright (c) 2009-2012 RightScale Inc
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
-
23
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
24
-
25
- describe RightSupport::Stats::Activity do
26
-
27
- include FlexMock::ArgumentTypes
28
-
29
- before(:all) do
30
- @original_recent_size = RightSupport::Stats::Activity::RECENT_SIZE
31
- RightSupport::Stats::Activity.instance_eval { remove_const(:RECENT_SIZE) }
32
- RightSupport::Stats::Activity.const_set(:RECENT_SIZE, 10)
33
- end
34
-
35
- after(:all) do
36
- RightSupport::Stats::Activity.instance_eval { remove_const(:RECENT_SIZE) }
37
- RightSupport::Stats::Activity.const_set(:RECENT_SIZE, @original_recent_size)
38
- end
39
-
40
- before(:each) do
41
- @now = 1000000
42
- flexmock(Time).should_receive(:now).and_return(@now).by_default
43
- @stats = RightSupport::Stats::Activity.new
44
- end
45
-
46
- context :initialize do
47
- it "initializes stats data" do
48
- @stats.instance_variable_get(:@interval).should == 0.0
49
- @stats.instance_variable_get(:@last_start_time).should == @now
50
- @stats.instance_variable_get(:@avg_latency).should be_nil
51
- @stats.instance_variable_get(:@total).should == 0
52
- @stats.instance_variable_get(:@count_per_type).should == {}
53
- end
54
- end
55
-
56
- context :update do
57
- it "updates count and interval information" do
58
- flexmock(Time).should_receive(:now).and_return(1000010)
59
- @stats.update
60
- @stats.instance_variable_get(:@interval).should == 1.0
61
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
62
- @stats.instance_variable_get(:@avg_latency).should be_nil
63
- @stats.instance_variable_get(:@total).should == 1
64
- @stats.instance_variable_get(:@count_per_type).should == {}
65
- end
66
-
67
- it "updates counts per type when type provided" do
68
- flexmock(Time).should_receive(:now).and_return(1000010)
69
- @stats.update("test")
70
- @stats.instance_variable_get(:@interval).should == 1.0
71
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
72
- @stats.instance_variable_get(:@avg_latency).should be_nil
73
- @stats.instance_variable_get(:@total).should == 1
74
- @stats.instance_variable_get(:@count_per_type).should == {"test" => 1}
75
- end
76
-
77
- it "limits length of type string when submitting update" do
78
- flexmock(Time).should_receive(:now).and_return(1000010)
79
- @stats.update("test 12345678901234567890123456789012345678901234567890123456789")
80
- @stats.instance_variable_get(:@total).should == 1
81
- @stats.instance_variable_get(:@count_per_type).should ==
82
- {"test 1234567890123456789012345678901234567890123456789012..." => 1}
83
- end
84
-
85
- it "doesn't convert symbol or boolean to string when submitting update" do
86
- flexmock(Time).should_receive(:now).and_return(1000010)
87
- @stats.update(:test)
88
- @stats.update(true)
89
- @stats.update(false)
90
- @stats.instance_variable_get(:@total).should == 3
91
- @stats.instance_variable_get(:@count_per_type).should == {:test => 1, true => 1, false => 1}
92
- end
93
-
94
- it "converts arbitrary type value to limited-length string when submitting update" do
95
- flexmock(Time).should_receive(:now).and_return(1000010)
96
- @stats.update({1 => 11, 2 => 22})
97
- @stats.update({1 => 11, 2 => 22, 3 => 12345678901234567890123456789012345678901234567890123456789})
98
- @stats.instance_variable_get(:@total).should == 2
99
- @stats.instance_variable_get(:@count_per_type).should == {"{1=>11, 2=>22}" => 1,
100
- "{1=>11, 2=>22, 3=>123456789012345678901234567890123456789..." => 1}
101
- end
102
-
103
- it "doesn't measure rate if disabled" do
104
- @stats = RightSupport::Stats::Activity.new(false)
105
- flexmock(Time).should_receive(:now).and_return(1000010)
106
- @stats.update
107
- @stats.instance_variable_get(:@interval).should == 0.0
108
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
109
- @stats.instance_variable_get(:@avg_latency).should be_nil
110
- @stats.instance_variable_get(:@total).should == 1
111
- @stats.instance_variable_get(:@count_per_type).should == {}
112
- end
113
-
114
- it "tracks the id associated with the update" do
115
- @stats.update("test", "id")
116
- @stats.instance_variable_get(:@last_id).should == "id"
117
- end
118
- end
119
-
120
- context :finish do
121
- it "updates latency when finish using internal start time by default" do
122
- flexmock(Time).should_receive(:now).and_return(1000010)
123
- @stats.avg_latency.should be_nil
124
- @stats.finish
125
- @stats.instance_variable_get(:@interval).should == 0.0
126
- @stats.instance_variable_get(:@last_start_time).should == @now
127
- @stats.instance_variable_get(:@avg_latency).should == 1.0
128
- @stats.instance_variable_get(:@total).should == 0
129
- @stats.instance_variable_get(:@count_per_type).should == {}
130
- end
131
-
132
- it "updates latency when finish using specified start time" do
133
- flexmock(Time).should_receive(:now).and_return(1000030)
134
- @stats.avg_latency.should be_nil
135
- @stats.finish(1000010)
136
- @stats.instance_variable_get(:@interval).should == 0.0
137
- @stats.instance_variable_get(:@last_start_time).should == @now
138
- @stats.instance_variable_get(:@avg_latency).should == 2.0
139
- @stats.instance_variable_get(:@total).should == 0
140
- @stats.instance_variable_get(:@count_per_type).should == {}
141
- end
142
- end
143
-
144
- context :measure do
145
- it "updates and finishes the activity" do
146
- flexmock(Time).should_receive(:now).and_return(1000010, 1000020)
147
- @stats.measure("test", "id") { }
148
- @stats.instance_variable_get(:@interval).should == 1.0
149
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
150
- @stats.instance_variable_get(:@total).should == 1
151
- @stats.instance_variable_get(:@count_per_type).should == {"test" => 1}
152
- @stats.instance_variable_get(:@last_id).should == 0
153
- @stats.instance_variable_get(:@avg_latency).should == 1.0
154
- end
155
-
156
- it "yields to the block" do
157
- called = 0
158
- flexmock(Time).should_receive(:now).and_return(1000010, 1000030)
159
- @stats.measure("test", "id") { called += 1}
160
- called.should == 1
161
- end
162
-
163
- it "returns the result of the yield" do
164
- @stats.measure("test", "id") { 99 }.should == 99
165
- end
166
-
167
- it "raises exception if block is missing" do
168
- lambda { @stats.measure("test", "id") }.should raise_error(ArgumentError, "block missing")
169
- end
170
- end
171
-
172
- context :avg_rate do
173
- it "converts interval to rate" do
174
- flexmock(Time).should_receive(:now).and_return(1000020, 1000042)
175
- @stats.avg_rate.should be_nil
176
- @stats.update
177
- @stats.instance_variable_get(:@interval).should == 2.0
178
- @stats.avg_rate.should == 0.25
179
- end
180
-
181
- it "adjusts rate based on interval since last event" do
182
- flexmock(Time).should_receive(:now).and_return(1000020, 1000042, 1000086)
183
- @stats.avg_rate.should be_nil
184
- @stats.update
185
- @stats.update
186
- @stats.instance_variable_get(:@interval).should == 4.0
187
- @stats.avg_rate.should == 0.125
188
- end
189
-
190
- it "sets rate to 0 if interval is 0" do
191
- flexmock(Time).should_receive(:now).and_return(1000000, 1000000)
192
- @stats.avg_rate.should be_nil
193
- @stats.update
194
- @stats.instance_variable_get(:@interval).should == 0.0
195
- @stats.avg_rate.should == 0.0
196
- end
197
-
198
- it "does not compute average unless measuring rate is enabled" do
199
- @stats = RightSupport::Stats::Activity.new(false)
200
- flexmock(Time).should_receive(:now).and_return(1000010)
201
- @stats.update
202
- @stats.avg_rate.should be_nil
203
- end
204
-
205
- it "does not compute average if there have been no events" do
206
- @stats.avg_rate.should be_nil
207
- end
208
- end
209
-
210
- context :last do
211
- it "reports number of seconds since last update or nil if no updates" do
212
- flexmock(Time).should_receive(:now).and_return(1000010)
213
- @stats.last.should be_nil
214
- @stats.update
215
- @stats.last.should == {"elapsed" => 0}
216
- end
217
-
218
- it "reports number of seconds since last update and last type" do
219
- @stats.update("test")
220
- flexmock(Time).should_receive(:now).and_return(1000010)
221
- @stats.last.should == {"elapsed" => 10, "type" => "test"}
222
- end
223
-
224
- it "reports whether last activity is still active" do
225
- @stats.update("test", "token")
226
- flexmock(Time).should_receive(:now).and_return(1000010)
227
- @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => true}
228
- @stats.finish(@now - 10, "token")
229
- @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => false}
230
- @stats.instance_variable_get(:@avg_latency).should == 2.0
231
- end
232
- end
233
-
234
- context :percentage do
235
- it "converts count per type to percentages" do
236
- flexmock(Time).should_receive(:now).and_return(1000010)
237
- @stats.update("foo")
238
- @stats.instance_variable_get(:@total).should == 1
239
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1}
240
- @stats.percentage.should == {"total" => 1, "percent" => {"foo" => 100.0}}
241
- @stats.update("bar")
242
- @stats.instance_variable_get(:@total).should == 2
243
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1, "bar" => 1}
244
- @stats.percentage.should == {"total" => 2, "percent" => {"foo" => 50.0, "bar" => 50.0}}
245
- @stats.update("foo")
246
- @stats.update("foo")
247
- @stats.instance_variable_get(:@total).should == 4
248
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 3, "bar" => 1}
249
- @stats.percentage.should == {"total" => 4, "percent" => {"foo" => 75.0, "bar" => 25.0}}
250
- end
251
- end
252
-
253
- context :all do
254
- it "returns all activity aspects that were measured" do
255
- flexmock(Time).should_receive(:now).and_return(1000020, 1000042)
256
- @stats.update
257
- @stats.finish
258
- @stats.all.should == {"last" => {"elapsed" => 22}, "total" => 1, "rate" => 0.25, "latency" => 2.2}
259
- end
260
-
261
- it "excludes rate if it is not being measured" do
262
- @stats = RightSupport::Stats::Activity.new(false)
263
- flexmock(Time).should_receive(:now).and_return(1000020, 1000042)
264
- @stats.update
265
- @stats.finish
266
- @stats.all.should == {"last" => {"elapsed" => 22}, "total" => 1, "latency" => 2.2}
267
- end
268
-
269
- it "excludes latency if it is not being measured" do
270
- flexmock(Time).should_receive(:now).and_return(1000020, 1000042)
271
- @stats.update
272
- @stats.all.should == {"last" => {"elapsed" => 22}, "total" => 1, "rate" => 0.25}
273
- end
274
-
275
- it "includes percentage breakdown when update recorded per type" do
276
- @stats = RightSupport::Stats::Activity.new(false)
277
- flexmock(Time).should_receive(:now).and_return(1000010, 1000010, 1000020, 1000020, 1000030, 1000030, 1000040)
278
- @stats.update("foo")
279
- @stats.all.should == {"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}}
280
- @stats.update("bar")
281
- @stats.all.should == {"last" => {"elapsed" => 0, "type" => "bar"}, "total" => 2, "percent" => {"foo" => 50.0, "bar" => 50.0}}
282
- @stats.update("bar")
283
- @stats.update("foo")
284
- @stats.all.should == {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 4, "percent" => {"foo" => 50.0, "bar" => 50.0}}
285
- end
286
-
287
- it "returns nil if there was no activity" do
288
- @stats.all.should be_nil
289
- end
290
- end
291
-
292
- context :average do
293
- it "weights average toward past activity" do
294
- @stats.send(:average, 0.0, 10.0).should == 1.0
295
- @stats.send(:average, 1.0, 10.0).should == 1.9
296
- @stats.send(:average, 1.9, 10.0).should == 2.71
297
- @stats.send(:average, 2.71, 10.0).should == 3.439
298
- @stats.send(:average, 3.439, 10.0).should == 4.0951
299
- @stats.send(:average, 4.0951, 10.0).should == 4.68559
300
- @stats.send(:average, 4.68559, 10.0).should == 5.217031
301
- end
302
- end
303
-
304
- describe "class methods" do
305
-
306
- context :all do
307
- it "aggregates stats from multiple all calls" do
308
- stats = [{"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}},
309
- {"last" => {"elapsed" => 20, "type" => "bar"}, "total" => 4, "percent" => {"bar" => 100.0}}]
310
- RightSupport::Stats::Activity.all(stats).should ==
311
- {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 5, "percent" => {"foo" => 20.0, "bar" => 80.0}}
312
- end
313
-
314
- it "includes rate if provided" do
315
- stats = [{"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}, "rate" => 0.5},
316
- {"last" => {"elapsed" => 20, "type" => "bar"}, "total" => 4, "percent" => {"bar" => 100.0}, "rate" => 0.1}]
317
- RightSupport::Stats::Activity.all(stats).should ==
318
- {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 5, "percent" => {"foo" => 20.0, "bar" => 80.0}, "rate" => 0.18}
319
- end
320
-
321
- it "includes latency if provided" do
322
- stats = [{"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}, "rate" => 0.5, "latency" => 0.5},
323
- {"last" => {"elapsed" => 20, "type" => "bar"}, "total" => 4, "percent" => {"bar" => 100.0}, "rate" => 0.1, "latency" => 0.1}]
324
- RightSupport::Stats::Activity.all(stats).should ==
325
- {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 5, "percent" => {"foo" => 20.0, "bar" => 80.0}, "rate" => 0.18, "latency" => 0.18}
326
- end
327
-
328
- it "handles nil stat" do
329
- stats = [{"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}},
330
- nil,
331
- {"last" => {"elapsed" => 20, "type" => "bar"}, "total" => 4, "percent" => {"bar" => 100.0}}]
332
- RightSupport::Stats::Activity.all(stats).should ==
333
- {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 5, "percent" => {"foo" => 20.0, "bar" => 80.0}}
334
- end
335
-
336
- it "returns nil if there are no stats" do
337
- RightSupport::Stats::Activity.all([]).should be_nil
338
- end
339
- end
340
-
341
- context :percentage do
342
- it "aggregates multiple percentage stats" do
343
- stats = [{"total" => 1, "percent" => {"foo" => 100.0}},
344
- {"total" => 5, "percent" => {"bar" => 100.0}},
345
- {"total" => 4, "percent" => {"foo" => 75.0, "bar" => 25.0}}]
346
- RightSupport::Stats::Activity.percentage(stats, 10).should == {"total" => 10, "percent" => {"foo" => 40.0, "bar" => 60.0}}
347
- end
348
-
349
- it "handles nil stat" do
350
- stats = [{"total" => 1, "percent" => {"foo" => 100.0}},
351
- nil,
352
- {"total" => 5, "percent" => {"bar" => 100.0}},
353
- nil,
354
- {"total" => 4, "percent" => {"foo" => 75.0, "bar" => 25.0}}]
355
- RightSupport::Stats::Activity.percentage(stats, 10).should == {"total" => 10, "percent" => {"foo" => 40.0, "bar" => 60.0}}
356
- end
357
-
358
- it "returns only total if there is no data" do
359
- RightSupport::Stats::Activity.percentage([], 0).should == {"total" => 0}
360
- end
361
- end
362
-
363
- context :avg_rate do
364
- it "computes average rate from multiple average rates" do
365
- stats = [{"total" => 1, "rate" => 0.5},
366
- {"total" => 5, "rate" => 0.1},
367
- {"total" => 4, "rate" => 0.2}]
368
- RightSupport::Stats::Activity.avg_rate(stats, 10).should == 0.18
369
- end
370
-
371
- it "handles nil stat" do
372
- stats = [{"total" => 1, "rate" => 0.5},
373
- nil,
374
- {"total" => 5, "rate" => 0.1},
375
- nil,
376
- {"total" => 4, "rate" => 0.2}]
377
- RightSupport::Stats::Activity.avg_rate(stats, 10).should == 0.18
378
- end
379
-
380
- it "returns nil if there is no data" do
381
- RightSupport::Stats::Activity.avg_rate([], 0).should be_nil
382
- end
383
- end
384
-
385
- context :avg_latency do
386
- it "computes average latency from multiple average latencies" do
387
- stats = [{"total" => 1, "latency" => 0.5},
388
- {"total" => 5, "latency" => 0.1},
389
- {"total" => 4, "latency" => 0.2}]
390
- RightSupport::Stats::Activity.avg_latency(stats, 10).should == 0.18
391
- end
392
-
393
- it "handles nil stat" do
394
- stats = [{"total" => 1, "latency" => 0.5},
395
- nil,
396
- {"total" => 5, "latency" => 0.1},
397
- nil,
398
- {"total" => 4, "latency" => 0.2}]
399
- RightSupport::Stats::Activity.avg_latency(stats, 10).should == 0.18
400
- end
401
-
402
- it "returns nil if there is no data" do
403
- RightSupport::Stats::Activity.avg_latency([], 0).should be_nil
404
- end
405
- end
406
-
407
- context :last do
408
- it "determines last activity from multiple last activity stats" do
409
- stats = [{"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}},
410
- {"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}}]
411
- end
412
-
413
- it "handles nil stat" do
414
- stats = [{"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}},
415
- nil,
416
- {"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}}]
417
- end
418
-
419
- it "returns nil if there is no data" do
420
- RightSupport::Stats::Activity.last([]).should be_nil
421
- end
422
- end
423
- end
424
-
425
- end # RightSupport::Stats::Activity
@@ -1,247 +0,0 @@
1
- #
2
- # Copyright (c) 2009-2012 RightScale Inc
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
-
23
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
24
-
25
- describe RightSupport::Stats::Exceptions do
26
-
27
- include FlexMock::ArgumentTypes
28
-
29
- before(:each) do
30
- @now = 1000000
31
- flexmock(Time).should_receive(:now).and_return(@now).by_default
32
- @stats = RightSupport::Stats::Exceptions.new
33
- @exception = Exception.new("Test error")
34
- end
35
-
36
- context :initialize do
37
- it "initializes stats data" do
38
- @stats.stats.should be_nil
39
- @stats.instance_variable_get(:@callback).should be_nil
40
- end
41
- end
42
-
43
- context :reset do
44
- it "clears any currently stored exceptions" do
45
- @stats.track("testing", @exception)
46
- @stats.stats.should_not be_nil
47
- @stats.reset
48
- @stats.stats.should be_nil
49
- end
50
- end
51
-
52
- context :track do
53
- it "tracks submitted exception information by category" do
54
- @stats.track("testing", @exception)
55
- @stats.stats.should == {"testing" => {"total" => 1,
56
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
57
- "when" => @now, "where" => nil}]}}
58
- end
59
-
60
- it "tracks where exception occurred if it has a backtrace" do
61
- begin
62
- raise Exception.new("Test error")
63
- rescue Exception => e
64
- @exception = e
65
- end
66
- @stats.track("testing", @exception)
67
- @stats.stats["testing"]["recent"][0]["where"].should =~ /spec\/stats\/exceptions_spec.rb/
68
- end
69
-
70
- it "recognizes and counts repeated exceptions" do
71
- @stats.track("testing", @exception)
72
- @stats.stats.should == {"testing" => {"total" => 1,
73
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
74
- "when" => @now, "where" => nil}]}}
75
- flexmock(Time).should_receive(:now).and_return(1000010)
76
- category = "another"
77
- backtrace = ["here", "and", "there"]
78
- 4.times do |i|
79
- begin
80
- raise ArgumentError, "badarg"
81
- rescue Exception => e
82
- flexmock(e).should_receive(:backtrace).and_return(backtrace)
83
- @stats.track(category, e)
84
- backtrace.shift(2) if i == 1
85
- category = "testing" if i == 2
86
- end
87
- end
88
- @stats.stats.should == {"testing" => {"total" => 2,
89
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
90
- "when" => @now, "where" => nil},
91
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
92
- "when" => @now + 10, "where" => "there"}]},
93
- "another" => {"total" => 3,
94
- "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
95
- "when" => @now + 10, "where" => "here"},
96
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
97
- "when" => @now + 10, "where" => "there"}]}}
98
- end
99
-
100
- it "limits the number of exceptions stored by eliminating older exceptions" do
101
- (RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS + 1).times do |i|
102
- begin
103
- raise ArgumentError, "badarg"
104
- rescue Exception => e
105
- flexmock(e).should_receive(:backtrace).and_return([i.to_s])
106
- @stats.track("testing", e)
107
- end
108
- end
109
- stats = @stats.stats
110
- stats["testing"]["total"].should == RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS + 1
111
- stats["testing"]["recent"].size.should == RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS
112
- stats["testing"]["recent"][0]["where"].should == "1"
113
- end
114
-
115
- it "makes callback if callback and message defined" do
116
- called = 0
117
- callback = lambda do |exception, message, server|
118
- called += 1
119
- exception.should == @exception
120
- message.should == "message"
121
- server.should == "server"
122
- end
123
- @stats = RightSupport::Stats::Exceptions.new("server", callback)
124
- @stats.track("testing", @exception, "message")
125
- @stats.stats.should == {"testing" => {"total" => 1,
126
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
127
- "when" => @now, "where" => nil}]}}
128
- called.should == 1
129
- end
130
-
131
- it "includes category parameter in callback if callback supports it" do
132
- called = 0
133
- callback = lambda do |exception, message, server, category|
134
- called += 1
135
- exception.should == @exception
136
- message.should == "message"
137
- server.should == "server"
138
- category.should == "testing"
139
- end
140
- @stats = RightSupport::Stats::Exceptions.new("server", callback)
141
- @stats.track("testing", @exception, "message")
142
- @stats.stats.should == {"testing" => {"total" => 1,
143
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
144
- "when" => @now, "where" => nil}]}}
145
- called.should == 1
146
- end
147
-
148
- it "catches any exceptions raised internally and log them" do
149
- begin
150
- logger = flexmock("logger")
151
- logger.should_receive(:error).with(/Failed to track exception 'Test error' \(Exception: bad IN/).once
152
- RightSupport::Log::Mixin.default_logger = logger
153
- flexmock(@exception).should_receive(:backtrace).and_raise(Exception.new("bad"))
154
- @stats = RightSupport::Stats::Exceptions.new
155
- @stats.track("testing", @exception, "message")
156
- @stats.stats["testing"]["total"].should == 1
157
- ensure
158
- RightSupport::Log::Mixin.default_logger = nil
159
- end
160
- end
161
- end
162
-
163
- context :all do
164
- it "returns current stats" do
165
- @stats.track("testing", @exception)
166
- @stats.all.should == {"testing" => {"total" => 1,
167
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
168
- "when" => @now, "where" => nil}]}}
169
- end
170
-
171
- it "returns nil if there are no stats" do
172
- @stats.all.should be_nil
173
- end
174
- end
175
-
176
- describe "class methods" do
177
-
178
- context :all do
179
- before(:each) do
180
-
181
- end
182
-
183
- it "aggregates the stats from multiple all calls" do
184
- stats = [{"testing" => {"total" => 3,
185
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
186
- "when" => @now, "where" => nil},
187
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
188
- "when" => @now + 20, "where" => "there"},
189
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
190
- "when" => @now + 30, "where" => "everywhere"}]}},
191
- {"testing" => {"total" => 5,
192
- "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
193
- "when" => @now + 10, "where" => "here"},
194
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
195
- "when" => @now + 15, "where" => "there"},
196
- {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
197
- "when" => @now + 30, "where" => "everywhere"}]}},
198
- nil,
199
- {"testing" => {"total" => 1,
200
- "recent" => [{"count" => 1, "type" => "ArgumentError", "message" => "awfularg",
201
- "when" => @now + 10, "where" => "here"}]}},
202
- {"another" => {"total" => 3,
203
- "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
204
- "when" => @now + 10, "where" => "here"},
205
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
206
- "when" => @now + 10, "where" => "there"}]}}]
207
-
208
- RightSupport::Stats::Exceptions.all(stats).should ==
209
- {"testing" => {"total" => 9,
210
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
211
- "when" => @now, "where" => nil},
212
- {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
213
- "when" => @now + 10, "where" => "here"},
214
- {"count" => 1, "type" => "ArgumentError", "message" => "awfularg",
215
- "when" => @now + 10, "where" => "here"},
216
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
217
- "when" => @now + 15, "where" => "there"},
218
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
219
- "when" => @now + 20, "where" => "there"},
220
- {"count" => 3, "type" => "ArgumentError", "message" => "badarg",
221
- "when" => @now + 30, "where" => "everywhere"}]},
222
- "another" => {"total" => 3,
223
- "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
224
- "when" => @now + 10, "where" => "here"},
225
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
226
- "when" => @now + 10, "where" => "there"}]}}
227
- end
228
-
229
- it "does not allow max exceptions to exceed set limit" do
230
- max = RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS
231
- stats = []
232
- ((max / 2) + 1).times do |i|
233
- stats << {"testing" => {"total" => 1,
234
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
235
- "when" => @now + i, "where" => nil},
236
- {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
237
- "when" => @now + i, "where" => "here"}]}}
238
- end
239
- all = RightSupport::Stats::Exceptions.all(stats)
240
- all["testing"]["recent"].size.should == max
241
- all["testing"]["recent"][max - 1].should == {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
242
- "when" => @now + (max / 2), "where" => "here"}
243
- end
244
- end
245
- end
246
-
247
- end # RightSupport::Stats::Exceptions