right_support 2.11.3 → 2.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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