right_support 2.7.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,151 +43,263 @@ describe RightSupport::Stats::Activity do
43
43
  @stats = RightSupport::Stats::Activity.new
44
44
  end
45
45
 
46
- it "initializes stats data" do
47
- @stats.instance_variable_get(:@interval).should == 0.0
48
- @stats.instance_variable_get(:@last_start_time).should == @now
49
- @stats.instance_variable_get(:@avg_duration).should be_nil
50
- @stats.instance_variable_get(:@total).should == 0
51
- @stats.instance_variable_get(:@count_per_type).should == {}
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_duration).should be_nil
51
+ @stats.instance_variable_get(:@total).should == 0
52
+ @stats.instance_variable_get(:@count_per_type).should == {}
53
+ end
52
54
  end
53
55
 
54
- it "updates count and interval information" do
55
- flexmock(Time).should_receive(:now).and_return(1000010)
56
- @stats.update
57
- @stats.instance_variable_get(:@interval).should == 1.0
58
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
59
- @stats.instance_variable_get(:@avg_duration).should be_nil
60
- @stats.instance_variable_get(:@total).should == 1
61
- @stats.instance_variable_get(:@count_per_type).should == {}
62
- end
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_duration).should be_nil
63
+ @stats.instance_variable_get(:@total).should == 1
64
+ @stats.instance_variable_get(:@count_per_type).should == {}
65
+ end
63
66
 
64
- it "updates weight the average interval toward recent activity" do
65
- end
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_duration).should be_nil
73
+ @stats.instance_variable_get(:@total).should == 1
74
+ @stats.instance_variable_get(:@count_per_type).should == {"test" => 1}
75
+ end
66
76
 
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_duration).should be_nil
73
- @stats.instance_variable_get(:@total).should == 1
74
- @stats.instance_variable_get(:@count_per_type).should == {"test" => 1}
75
- end
77
+ it "doesn't update counts when type contains 'stats'" do
78
+ flexmock(Time).should_receive(:now).and_return(1000010)
79
+ @stats.update("my stats")
80
+ @stats.instance_variable_get(:@interval).should == 0.0
81
+ @stats.instance_variable_get(:@last_start_time).should == @now
82
+ @stats.instance_variable_get(:@avg_duration).should be_nil
83
+ @stats.instance_variable_get(:@total).should == 0
84
+ @stats.instance_variable_get(:@count_per_type).should == {}
85
+ end
76
86
 
77
- it "doesn't update counts when type contains 'stats'" do
78
- flexmock(Time).should_receive(:now).and_return(1000010)
79
- @stats.update("my stats")
80
- @stats.instance_variable_get(:@interval).should == 0.0
81
- @stats.instance_variable_get(:@last_start_time).should == @now
82
- @stats.instance_variable_get(:@avg_duration).should be_nil
83
- @stats.instance_variable_get(:@total).should == 0
84
- @stats.instance_variable_get(:@count_per_type).should == {}
85
- end
87
+ it "limits length of type string when submitting update" do
88
+ flexmock(Time).should_receive(:now).and_return(1000010)
89
+ @stats.update("test 12345678901234567890123456789012345678901234567890123456789")
90
+ @stats.instance_variable_get(:@total).should == 1
91
+ @stats.instance_variable_get(:@count_per_type).should ==
92
+ {"test 1234567890123456789012345678901234567890123456789012..." => 1}
93
+ end
86
94
 
87
- it "limits length of type string when submitting update" do
88
- flexmock(Time).should_receive(:now).and_return(1000010)
89
- @stats.update("test 12345678901234567890123456789012345678901234567890123456789")
90
- @stats.instance_variable_get(:@total).should == 1
91
- @stats.instance_variable_get(:@count_per_type).should ==
92
- {"test 1234567890123456789012345678901234567890123456789012..." => 1}
93
- end
95
+ it "doesn't convert symbol or boolean to string when submitting update" do
96
+ flexmock(Time).should_receive(:now).and_return(1000010)
97
+ @stats.update(:test)
98
+ @stats.update(true)
99
+ @stats.update(false)
100
+ @stats.instance_variable_get(:@total).should == 3
101
+ @stats.instance_variable_get(:@count_per_type).should == {:test => 1, true => 1, false => 1}
102
+ end
94
103
 
95
- it "doesn't convert symbol or boolean to string when submitting update" do
96
- flexmock(Time).should_receive(:now).and_return(1000010)
97
- @stats.update(:test)
98
- @stats.update(true)
99
- @stats.update(false)
100
- @stats.instance_variable_get(:@total).should == 3
101
- @stats.instance_variable_get(:@count_per_type).should == {:test => 1, true => 1, false => 1}
102
- end
104
+ it "converts arbitrary type value to limited-length string when submitting update" do
105
+ flexmock(Time).should_receive(:now).and_return(1000010)
106
+ @stats.update({1 => 11, 2 => 22})
107
+ @stats.update({1 => 11, 2 => 22, 3 => 12345678901234567890123456789012345678901234567890123456789})
108
+ @stats.instance_variable_get(:@total).should == 2
109
+ @stats.instance_variable_get(:@count_per_type).should == {"{1=>11, 2=>22}" => 1,
110
+ "{1=>11, 2=>22, 3=>123456789012345678901234567890123456789..." => 1}
111
+ end
103
112
 
104
- it "converts arbitrary type value to limited-length string when submitting update" do
105
- flexmock(Time).should_receive(:now).and_return(1000010)
106
- @stats.update({1 => 11, 2 => 22})
107
- @stats.update({1 => 11, 2 => 22, 3 => 12345678901234567890123456789012345678901234567890123456789})
108
- @stats.instance_variable_get(:@total).should == 2
109
- @stats.instance_variable_get(:@count_per_type).should == {"{1=>11, 2=>22}" => 1,
110
- "{1=>11, 2=>22, 3=>123456789012345678901234567890123456789..." => 1}
113
+ it "doesn't measure rate if disabled" do
114
+ @stats = RightSupport::Stats::Activity.new(false)
115
+ flexmock(Time).should_receive(:now).and_return(1000010)
116
+ @stats.update
117
+ @stats.instance_variable_get(:@interval).should == 0.0
118
+ @stats.instance_variable_get(:@last_start_time).should == @now + 10
119
+ @stats.instance_variable_get(:@avg_duration).should be_nil
120
+ @stats.instance_variable_get(:@total).should == 1
121
+ @stats.instance_variable_get(:@count_per_type).should == {}
122
+ end
111
123
  end
112
124
 
113
- it "doesn't measure rate if disabled" do
114
- @stats = RightSupport::Stats::Activity.new(false)
115
- flexmock(Time).should_receive(:now).and_return(1000010)
116
- @stats.update
117
- @stats.instance_variable_get(:@interval).should == 0.0
118
- @stats.instance_variable_get(:@last_start_time).should == @now + 10
119
- @stats.instance_variable_get(:@avg_duration).should be_nil
120
- @stats.instance_variable_get(:@total).should == 1
121
- @stats.instance_variable_get(:@count_per_type).should == {}
122
- @stats.all.should == {"last" => {"elapsed"=>0}, "total" => 1}
123
- end
125
+ context :finish do
126
+ it "updates duration when finish using internal start time by default" do
127
+ flexmock(Time).should_receive(:now).and_return(1000010)
128
+ @stats.avg_duration.should be_nil
129
+ @stats.finish
130
+ @stats.instance_variable_get(:@interval).should == 0.0
131
+ @stats.instance_variable_get(:@last_start_time).should == @now
132
+ @stats.instance_variable_get(:@avg_duration).should == 1.0
133
+ @stats.instance_variable_get(:@total).should == 0
134
+ @stats.instance_variable_get(:@count_per_type).should == {}
135
+ end
124
136
 
125
- it "updates duration when finish using internal start time by default" do
126
- flexmock(Time).should_receive(:now).and_return(1000010)
127
- @stats.finish
128
- @stats.instance_variable_get(:@interval).should == 0.0
129
- @stats.instance_variable_get(:@last_start_time).should == @now
130
- @stats.instance_variable_get(:@avg_duration).should == 1.0
131
- @stats.instance_variable_get(:@total).should == 0
132
- @stats.instance_variable_get(:@count_per_type).should == {}
137
+ it "updates duration when finish using specified start time" do
138
+ flexmock(Time).should_receive(:now).and_return(1000030)
139
+ @stats.avg_duration.should be_nil
140
+ @stats.finish(1000010)
141
+ @stats.instance_variable_get(:@interval).should == 0.0
142
+ @stats.instance_variable_get(:@last_start_time).should == @now
143
+ @stats.instance_variable_get(:@avg_duration).should == 2.0
144
+ @stats.instance_variable_get(:@total).should == 0
145
+ @stats.instance_variable_get(:@count_per_type).should == {}
146
+ end
133
147
  end
134
148
 
135
- it "updates duration when finish using specified start time" do
136
- flexmock(Time).should_receive(:now).and_return(1000030)
137
- @stats.avg_duration.should be_nil
138
- @stats.finish(1000010)
139
- @stats.instance_variable_get(:@interval).should == 0.0
140
- @stats.instance_variable_get(:@last_start_time).should == @now
141
- @stats.instance_variable_get(:@avg_duration).should == 2.0
142
- @stats.instance_variable_get(:@total).should == 0
143
- @stats.instance_variable_get(:@count_per_type).should == {}
149
+ context :avg_rate do
150
+ it "converts interval to rate" do
151
+ flexmock(Time).should_receive(:now).and_return(1000020)
152
+ @stats.avg_rate.should be_nil
153
+ @stats.update
154
+ @stats.instance_variable_get(:@interval).should == 2.0
155
+ @stats.avg_rate.should == 0.5
156
+ end
144
157
  end
145
158
 
146
- it "converts interval to rate" do
147
- flexmock(Time).should_receive(:now).and_return(1000020)
148
- @stats.avg_rate.should be_nil
149
- @stats.update
150
- @stats.instance_variable_get(:@interval).should == 2.0
151
- @stats.avg_rate.should == 0.5
159
+ context :last do
160
+ it "reports number of seconds since last update or nil if no updates" do
161
+ flexmock(Time).should_receive(:now).and_return(1000010)
162
+ @stats.last.should be_nil
163
+ @stats.update
164
+ @stats.last.should == {"elapsed" => 0}
165
+ end
166
+
167
+ it "reports number of seconds since last update and last type" do
168
+ @stats.update("test")
169
+ flexmock(Time).should_receive(:now).and_return(1000010)
170
+ @stats.last.should == {"elapsed" => 10, "type" => "test"}
171
+ end
172
+
173
+ it "reports whether last activity is still active" do
174
+ @stats.update("test", "token")
175
+ flexmock(Time).should_receive(:now).and_return(1000010)
176
+ @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => true}
177
+ @stats.finish(@now - 10, "token")
178
+ @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => false}
179
+ @stats.instance_variable_get(:@avg_duration).should == 2.0
180
+ end
152
181
  end
153
182
 
154
- it "reports number of seconds since last update or nil if no updates" do
155
- flexmock(Time).should_receive(:now).and_return(1000010)
156
- @stats.last.should be_nil
157
- @stats.update
158
- @stats.last.should == {"elapsed" => 0}
183
+ context :percentage do
184
+ it "converts count per type to percentages" do
185
+ flexmock(Time).should_receive(:now).and_return(1000010)
186
+ @stats.update("foo")
187
+ @stats.instance_variable_get(:@total).should == 1
188
+ @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1}
189
+ @stats.percentage.should == {"total" => 1, "percent" => {"foo" => 100.0}}
190
+ @stats.update("bar")
191
+ @stats.instance_variable_get(:@total).should == 2
192
+ @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1, "bar" => 1}
193
+ @stats.percentage.should == {"total" => 2, "percent" => {"foo" => 50.0, "bar" => 50.0}}
194
+ @stats.update("foo")
195
+ @stats.update("foo")
196
+ @stats.instance_variable_get(:@total).should == 4
197
+ @stats.instance_variable_get(:@count_per_type).should == {"foo" => 3, "bar" => 1}
198
+ @stats.percentage.should == {"total" => 4, "percent" => {"foo" => 75.0, "bar" => 25.0}}
199
+ end
159
200
  end
160
201
 
161
- it "reports number of seconds since last update and last type" do
162
- @stats.update("test")
163
- flexmock(Time).should_receive(:now).and_return(1000010)
164
- @stats.last.should == {"elapsed" => 10, "type" => "test"}
202
+ context :all do
203
+ it "returns all activity aspects that were measured except duration" do
204
+ flexmock(Time).should_receive(:now).and_return(1000010)
205
+ @stats.update
206
+ @stats.all.should == {"last" => {"elapsed" => 0}, "total" => 1, "rate" => 1.0}
207
+ end
208
+
209
+ it "excludes rate if it is not being measured" do
210
+ @stats = RightSupport::Stats::Activity.new(false)
211
+ flexmock(Time).should_receive(:now).and_return(1000010)
212
+ @stats.update
213
+ @stats.all.should == {"last" => {"elapsed" => 0}, "total" => 1}
214
+ end
215
+
216
+ it "includes percentage breakdown when update recorded per type" do
217
+ @stats = RightSupport::Stats::Activity.new(false)
218
+ flexmock(Time).should_receive(:now).and_return(1000010, 1000010, 1000020, 1000020, 1000030, 1000030, 1000040)
219
+ @stats.update("foo")
220
+ @stats.all.should == {"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}}
221
+ @stats.update("bar")
222
+ @stats.all.should == {"last" => {"elapsed" => 0, "type" => "bar"}, "total" => 2, "percent" => {"foo" => 50.0, "bar" => 50.0}}
223
+ @stats.update("bar")
224
+ @stats.update("foo")
225
+ @stats.all.should == {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 4, "percent" => {"foo" => 50.0, "bar" => 50.0}}
226
+ end
227
+
228
+ it "returns nil if there was no activity" do
229
+ @stats.all.should be_nil
230
+ end
165
231
  end
166
232
 
167
- it "reports whether last activity is still active" do
168
- @stats.update("test", "token")
169
- flexmock(Time).should_receive(:now).and_return(1000010)
170
- @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => true}
171
- @stats.finish(@now - 10, "token")
172
- @stats.last.should == {"elapsed" => 10, "type" => "test", "active" => false}
173
- @stats.instance_variable_get(:@avg_duration).should == 2.0
233
+ context :average do
234
+ it "weights average toward past activity" do
235
+ @stats.send(:average, 0.0, 10.0).should == 1.0
236
+ @stats.send(:average, 1.0, 10.0).should == 1.9
237
+ @stats.send(:average, 1.9, 10.0).should == 2.71
238
+ @stats.send(:average, 2.71, 10.0).should == 3.439
239
+ @stats.send(:average, 3.439, 10.0).should == 4.0951
240
+ @stats.send(:average, 4.0951, 10.0).should == 4.68559
241
+ @stats.send(:average, 4.68559, 10.0).should == 5.217031
242
+ end
174
243
  end
175
244
 
176
- it "converts count per type to percentages" do
177
- flexmock(Time).should_receive(:now).and_return(1000010)
178
- @stats.update("foo")
179
- @stats.instance_variable_get(:@total).should == 1
180
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1}
181
- @stats.percentage.should == {"total" => 1, "percent" => {"foo" => 100.0}}
182
- @stats.update("bar")
183
- @stats.instance_variable_get(:@total).should == 2
184
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 1, "bar" => 1}
185
- @stats.percentage.should == {"total" => 2, "percent" => {"foo" => 50.0, "bar" => 50.0}}
186
- @stats.update("foo")
187
- @stats.update("foo")
188
- @stats.instance_variable_get(:@total).should == 4
189
- @stats.instance_variable_get(:@count_per_type).should == {"foo" => 3, "bar" => 1}
190
- @stats.percentage.should == {"total" => 4, "percent" => {"foo" => 75.0, "bar" => 25.0}}
245
+ describe "class methods" do
246
+
247
+ context :all do
248
+ it "aggregates stats from multiple all calls" do
249
+ stats = [{"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}},
250
+ {"last" => {"elapsed" => 20, "type" => "bar"}, "total" => 4, "percent" => {"bar" => 100.0}}]
251
+ RightSupport::Stats::Activity.all(stats).should ==
252
+ {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 5, "percent" => {"foo" => 20.0, "bar" => 80.0}}
253
+ end
254
+
255
+ it "includes rate if provided" do
256
+ stats = [{"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}, "rate" => 0.5},
257
+ {"last" => {"elapsed" => 20, "type" => "bar"}, "total" => 4, "percent" => {"bar" => 100.0}, "rate" => 0.1}]
258
+ RightSupport::Stats::Activity.all(stats).should ==
259
+ {"last" => {"elapsed" => 10, "type" => "foo"}, "total" => 5, "percent" => {"foo" => 20.0, "bar" => 80.0}, "rate" => 0.18}
260
+ end
261
+
262
+ it "returns nil if there are no stats" do
263
+ RightSupport::Stats::Activity.all([]).should be_nil
264
+ end
265
+ end
266
+
267
+ context :percentage do
268
+ it "aggregates multiple percentage stats" do
269
+ stats = [{"total" => 1, "percent" => {"foo" => 100.0}},
270
+ {"total" => 5, "percent" => {"bar" => 100.0}},
271
+ {"total" => 4, "percent" => {"foo" => 75.0, "bar" => 25.0}}]
272
+ RightSupport::Stats::Activity.percentage(stats, 10).should == {"total" => 10, "percent" => {"foo" => 40.0, "bar" => 60.0}}
273
+ end
274
+
275
+ it "returns only total if there is no data" do
276
+ RightSupport::Stats::Activity.percentage([], 0).should == {"total" => 0}
277
+ end
278
+ end
279
+
280
+ context :avg_rate do
281
+ it "computes average rate from multiple average rates" do
282
+ stats = [{"total" => 1, "rate" => 0.5},
283
+ {"total" => 5, "rate" => 0.1},
284
+ {"total" => 4, "rate" => 0.2}]
285
+ RightSupport::Stats::Activity.avg_rate(stats, 10).should == 0.18
286
+ end
287
+
288
+ it "returns nil if there is no data" do
289
+ RightSupport::Stats::Activity.avg_rate([], 0).should be_nil
290
+ end
291
+ end
292
+
293
+ context :last do
294
+ it "determines last activity from multiple last activity stats" do
295
+ stats = [{"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}},
296
+ {"last" => {"elapsed" => 0, "type" => "foo"}, "total" => 1, "percent" => {"foo" => 100.0}}]
297
+ end
298
+
299
+ it "returns nil if there is no data" do
300
+ RightSupport::Stats::Activity.last([]).should be_nil
301
+ end
302
+ end
191
303
  end
192
304
 
193
305
  end # RightSupport::Stats::Activity
@@ -33,90 +33,196 @@ describe RightSupport::Stats::Exceptions do
33
33
  @exception = Exception.new("Test error")
34
34
  end
35
35
 
36
- it "initializes stats data" do
37
- @stats.stats.should be_nil
38
- @stats.instance_variable_get(:@callback).should be_nil
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
39
41
  end
40
42
 
41
- it "tracks submitted exception information by category" do
42
- @stats.track("testing", @exception)
43
- @stats.stats.should == {"testing" => {"total" => 1,
44
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
45
- "when" => @now, "where" => nil}]}}
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
46
50
  end
47
51
 
48
- it "recognizes and counts repeated exceptions" do
49
- @stats.track("testing", @exception)
50
- @stats.stats.should == {"testing" => {"total" => 1,
51
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
52
- "when" => @now, "where" => nil}]}}
53
- flexmock(Time).should_receive(:now).and_return(1000010)
54
- category = "another"
55
- backtrace = ["here", "and", "there"]
56
- 4.times do |i|
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
57
61
  begin
58
- raise ArgumentError, "badarg"
62
+ raise Exception.new("Test error")
59
63
  rescue Exception => e
60
- flexmock(e).should_receive(:backtrace).and_return(backtrace)
61
- @stats.track(category, e)
62
- backtrace.shift(2) if i == 1
63
- category = "testing" if i == 2
64
+ @exception = e
64
65
  end
66
+ @stats.track("testing", @exception)
67
+ @stats.stats["testing"]["recent"][0]["where"].should =~ /right_support\/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
65
129
  end
66
- @stats.stats.should == {"testing" => {"total" => 2,
67
- "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
68
- "when" => @now, "where" => nil},
69
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
70
- "when" => @now + 10, "where" => "there"}]},
71
- "another" => {"total" => 3,
72
- "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
73
- "when" => @now + 10, "where" => "here"},
74
- {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
75
- "when" => @now + 10, "where" => "there"}]}}
76
- end
77
130
 
78
- it "limits the number of exceptions stored by eliminating older exceptions" do
79
- (RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS + 1).times do |i|
131
+ it "catches any exceptions raised internally and log them" do
80
132
  begin
81
- raise ArgumentError, "badarg"
82
- rescue Exception => e
83
- flexmock(e).should_receive(:backtrace).and_return([i.to_s])
84
- @stats.track("testing", e)
133
+ logger = flexmock("logger")
134
+ logger.should_receive(:error).with(/Failed to track exception 'Test error' \(Exception: bad IN/).once
135
+ RightSupport::Log::Mixin.default_logger = logger
136
+ flexmock(@exception).should_receive(:backtrace).and_raise(Exception.new("bad"))
137
+ @stats = RightSupport::Stats::Exceptions.new
138
+ @stats.track("testing", @exception, "message")
139
+ @stats.stats["testing"]["total"].should == 1
140
+ ensure
141
+ RightSupport::Log::Mixin.default_logger = nil
85
142
  end
86
143
  end
87
- stats = @stats.stats
88
- stats["testing"]["total"].should == RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS + 1
89
- stats["testing"]["recent"].size.should == RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS
90
- stats["testing"]["recent"][0]["where"].should == "1"
91
144
  end
92
145
 
93
- it "makes callback if callback and message defined" do
94
- called = 0
95
- callback = lambda do |exception, message, server|
96
- called += 1
97
- exception.should == @exception
98
- message.should == "message"
99
- server.should == "server"
100
- end
101
- @stats = RightSupport::Stats::Exceptions.new("server", callback)
102
- @stats.track("testing", @exception, "message")
103
- @stats.stats.should == {"testing" => {"total" => 1,
146
+ context :all do
147
+ it "returns current stats" do
148
+ @stats.track("testing", @exception)
149
+ @stats.all.should == {"testing" => {"total" => 1,
104
150
  "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
105
151
  "when" => @now, "where" => nil}]}}
106
- called.should == 1
152
+ end
153
+
154
+ it "returns nil if there are no stats" do
155
+ @stats.all.should be_nil
156
+ end
107
157
  end
108
158
 
109
- it "catches any exceptions raised internally and log them" do
110
- begin
111
- logger = flexmock("logger")
112
- logger.should_receive(:error).with(/Failed to track exception 'Test error' \(Exception: bad IN/).once
113
- RightSupport::Log::Mixin.default_logger = logger
114
- flexmock(@exception).should_receive(:backtrace).and_raise(Exception.new("bad"))
115
- @stats = RightSupport::Stats::Exceptions.new
116
- @stats.track("testing", @exception, "message")
117
- @stats.stats["testing"]["total"].should == 1
118
- ensure
119
- RightSupport::Log::Mixin.default_logger = nil
159
+ describe "class methods" do
160
+
161
+ context :all do
162
+ before(:each) do
163
+
164
+ end
165
+
166
+ it "aggregates the stats from multiple all calls" do
167
+ stats = [{"testing" => {"total" => 3,
168
+ "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
169
+ "when" => @now, "where" => nil},
170
+ {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
171
+ "when" => @now + 20, "where" => "there"},
172
+ {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
173
+ "when" => @now + 30, "where" => "everywhere"}]}},
174
+ {"testing" => {"total" => 5,
175
+ "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
176
+ "when" => @now + 10, "where" => "here"},
177
+ {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
178
+ "when" => @now + 15, "where" => "there"},
179
+ {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
180
+ "when" => @now + 30, "where" => "everywhere"}]}},
181
+ {"testing" => {"total" => 1,
182
+ "recent" => [{"count" => 1, "type" => "ArgumentError", "message" => "awfularg",
183
+ "when" => @now + 10, "where" => "here"}]}},
184
+ {"another" => {"total" => 3,
185
+ "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
186
+ "when" => @now + 10, "where" => "here"},
187
+ {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
188
+ "when" => @now + 10, "where" => "there"}]}}]
189
+
190
+ RightSupport::Stats::Exceptions.all(stats).should ==
191
+ {"testing" => {"total" => 9,
192
+ "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
193
+ "when" => @now, "where" => nil},
194
+ {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
195
+ "when" => @now + 10, "where" => "here"},
196
+ {"count" => 1, "type" => "ArgumentError", "message" => "awfularg",
197
+ "when" => @now + 10, "where" => "here"},
198
+ {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
199
+ "when" => @now + 15, "where" => "there"},
200
+ {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
201
+ "when" => @now + 20, "where" => "there"},
202
+ {"count" => 3, "type" => "ArgumentError", "message" => "badarg",
203
+ "when" => @now + 30, "where" => "everywhere"}]},
204
+ "another" => {"total" => 3,
205
+ "recent" => [{"count" => 2, "type" => "ArgumentError", "message" => "badarg",
206
+ "when" => @now + 10, "where" => "here"},
207
+ {"count" => 1, "type" => "ArgumentError", "message" => "badarg",
208
+ "when" => @now + 10, "where" => "there"}]}}
209
+ end
210
+
211
+ it "does not allow max exceptions to exceed set limit" do
212
+ max = RightSupport::Stats::Exceptions::MAX_RECENT_EXCEPTIONS
213
+ stats = []
214
+ ((max / 2) + 1).times do |i|
215
+ stats << {"testing" => {"total" => 1,
216
+ "recent" => [{"count" => 1, "type" => "Exception", "message" => "Test error",
217
+ "when" => @now + i, "where" => nil},
218
+ {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
219
+ "when" => @now + i, "where" => "here"}]}}
220
+ end
221
+ all = RightSupport::Stats::Exceptions.all(stats)
222
+ all["testing"]["recent"].size.should == max
223
+ all["testing"]["recent"][max - 1].should == {"count" => 2, "type" => "ArgumentError", "message" => "badarg",
224
+ "when" => @now + (max / 2), "where" => "here"}
225
+ end
120
226
  end
121
227
  end
122
228