fnordmetric 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.travis.yml +1 -0
  2. data/VERSION +1 -1
  3. data/doc/preview1.png +0 -0
  4. data/doc/preview2.png +0 -0
  5. data/doc/ulm_stats.rb +622 -0
  6. data/doc/version +1 -0
  7. data/fnordmetric.gemspec +16 -38
  8. data/haml/app.haml +12 -5
  9. data/lib/fnordmetric.rb +3 -0
  10. data/lib/fnordmetric/app.rb +19 -10
  11. data/lib/fnordmetric/bars_widget.rb +26 -0
  12. data/lib/fnordmetric/context.rb +3 -3
  13. data/lib/fnordmetric/gauge.rb +20 -0
  14. data/lib/fnordmetric/gauge_calculations.rb +28 -4
  15. data/lib/fnordmetric/gauge_modifiers.rb +39 -6
  16. data/lib/fnordmetric/logger.rb +19 -0
  17. data/lib/fnordmetric/numbers_widget.rb +5 -15
  18. data/lib/fnordmetric/pie_widget.rb +23 -0
  19. data/lib/fnordmetric/standalone.rb +1 -1
  20. data/lib/fnordmetric/timeline_widget.rb +16 -23
  21. data/lib/fnordmetric/toplist_widget.rb +25 -0
  22. data/lib/fnordmetric/widget.rb +3 -3
  23. data/pub/{fnordmetric/fnordmetric.css → fnordmetric.css} +46 -36
  24. data/pub/fnordmetric.js +1069 -0
  25. data/pub/loader.gif +0 -0
  26. data/pub/{highcharts → vendor}/highcharts.js +0 -0
  27. data/pub/{jquery-1.6.1.min.js → vendor/jquery-1.6.1.min.js} +0 -0
  28. data/readme.rdoc +228 -311
  29. data/spec/app_spec.rb +63 -3
  30. data/spec/gauge_modifiers_spec.rb +157 -2
  31. data/spec/gauge_spec.rb +143 -12
  32. data/spec/widget_spec.rb +18 -18
  33. metadata +33 -58
  34. data/.document +0 -5
  35. data/_spec/app_spec.rb +0 -178
  36. data/_spec/cache_spec.rb +0 -53
  37. data/_spec/combine_metric_spec.rb +0 -19
  38. data/_spec/core_spec.rb +0 -50
  39. data/_spec/count_metric_spec.rb +0 -32
  40. data/_spec/dashboard_spec.rb +0 -67
  41. data/_spec/event_spec.rb +0 -46
  42. data/_spec/metric_spec.rb +0 -118
  43. data/_spec/report_spec.rb +0 -87
  44. data/_spec/sum_metric_spec.rb +0 -33
  45. data/_spec/widget_spec.rb +0 -107
  46. data/doc/example_server.rb +0 -56
  47. data/doc/import_dump.rb +0 -26
  48. data/pub/fnordmetric/fnordmetric.js +0 -543
  49. data/pub/fnordmetric/widget_numbers.js +0 -71
  50. data/pub/fnordmetric/widget_timeline.css +0 -0
  51. data/pub/fnordmetric/widget_timeline.js +0 -110
  52. data/pub/highcharts/adapters/mootools-adapter.js +0 -12
  53. data/pub/highcharts/adapters/mootools-adapter.src.js +0 -243
  54. data/pub/highcharts/adapters/prototype-adapter.js +0 -14
  55. data/pub/highcharts/adapters/prototype-adapter.src.js +0 -284
  56. data/pub/highcharts/highcharts.src.js +0 -11103
  57. data/pub/highcharts/modules/exporting.js +0 -22
  58. data/pub/highcharts/modules/exporting.src.js +0 -703
  59. data/pub/highcharts/themes/dark-blue.js +0 -268
  60. data/pub/highcharts/themes/dark-green.js +0 -268
  61. data/pub/highcharts/themes/gray.js +0 -262
  62. data/pub/highcharts/themes/grid.js +0 -97
  63. data/pub/raphael-min.js +0 -8
  64. data/pub/raphael-utils.js +0 -221
  65. data/ulm_stats.rb +0 -198
@@ -21,6 +21,10 @@ describe "app" do
21
21
  @app ||= FnordMetric::App.new({
22
22
  :foospace => proc{
23
23
  widget 'Blubb', nil
24
+
25
+ gauge :testgauge, :tick => 1.hour.to_i, :progressive => true
26
+ gauge :test3gauge, :tick => 1.hour.to_i, :three_dimensional => true
27
+
24
28
  }
25
29
  }, @opts)
26
30
  end
@@ -407,14 +411,70 @@ describe "app" do
407
411
  #FnordMetric::Event.last.blubb.should == 42.23
408
412
  end
409
413
 
414
+ end
410
415
 
416
+ describe "gauges api" do
411
417
 
418
+ before(:all) do
419
+ @redis.keys("fnordmetric-foospace*").each { |k| @redis.del(k) }
420
+ gauge_key = "fnordmetric-foospace-gauge-testgauge-#{1.hour.to_i}"
421
+ @redis.hset(gauge_key, 1323687600, "18")
422
+ @redis.hset(gauge_key, 1323691200, "23")
423
+ end
412
424
 
413
- end
425
+ it "should return the right answer for: /metric/:name?at=timestamp" do
426
+ get "/foospace/gauge/testgauge?at=1323691205"
427
+ JSON.parse(last_response.body).first.last.to_i.should == 23
428
+ end
429
+
430
+ it "should return the right answer for: /metric/:name?at=timestamp" do
431
+ get "/foospace/gauge/testgauge?at=1323691200"
432
+ JSON.parse(last_response.body).first.last.to_i.should == 23
433
+ end
434
+
435
+ it "should return the right answer for: /metric/:name?at=timestamp-timstamp" do
436
+ get "/foospace/gauge/testgauge?at=1323691200-1323691205"
437
+ JSON.parse(last_response.body).first.last.to_i.should == 18
438
+ end
439
+
440
+ it "should return the right answer for: /metric/:name?at=timestamp-timstamp" do
441
+ get "/foospace/gauge/testgauge?at=1323691201-1323695205"
442
+ JSON.parse(last_response.body).keys.length
443
+ end
444
+
445
+ it "should return the right answer for: /metric/:name?at=timestamp-timstamp" do
446
+ get "/foospace/gauge/testgauge?at=1323691199-1323701201"
447
+ JSON.parse(last_response.body).keys.length.should == 4
448
+ JSON.parse(last_response.body)["1323687600"].to_i.should == 18
449
+ JSON.parse(last_response.body)["1323691200"].to_i.should == 23
450
+ end
451
+
452
+ it "should return the right answer for: /metric/:name?at=timestamp-timstamp&sum=true" do
453
+ get "/foospace/gauge/testgauge?at=1323691199-1323701201&sum=true"
454
+ JSON.parse(last_response.body).keys.length.should == 1
455
+ JSON.parse(last_response.body)["sum"].to_i.should == 18+23
456
+ end
414
457
 
415
- describe "metrics api" do
416
- # copy from _spec/app_spec.rb ?
417
458
  end
418
459
 
460
+ describe "three-dim gauges api" do
461
+
462
+ before(:all) do
463
+ @redis.keys("fnordmetric-foospace*").each { |k| @redis.del(k) }
464
+ gauge_key = "fnordmetric-foospace-gauge-test3gauge-#{1.hour.to_i}-1323691200"
465
+ @redis.zadd(gauge_key, 18, "fnordyblubb")
466
+ @redis.zadd(gauge_key, 23, "uberfoo")
467
+ @redis.set(gauge_key+"-count", 41)
468
+ end
469
+
470
+ it "should return the right answer for: /metric/:name?at=timestamp" do
471
+ get "/foospace/gauge/test3gauge?at=1323691205"
472
+ JSON.parse(last_response.body)["count"].to_i.should == 41
473
+ JSON.parse(last_response.body)["values"].length.should == 2
474
+ JSON.parse(last_response.body)["values"][0].should == ["uberfoo", "23"]
475
+ JSON.parse(last_response.body)["values"][1].should == ["fnordyblubb", "18"]
476
+ end
477
+
478
+ end
419
479
 
420
480
  end
@@ -153,6 +153,28 @@ describe FnordMetric::GaugeModifiers do
153
153
 
154
154
  end
155
155
 
156
+ describe "increment an average-gauge" do
157
+
158
+ it "should increment_unique a non-progressive gauge" do
159
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_917-10"
160
+ @redis.hset(gauge_key, "695280200", "54")
161
+ @redis.set(gauge_key+"-695280200-value-count", 5)
162
+ create_gauge_context({
163
+ :key => "mygauge_917",
164
+ :average => true,
165
+ :tick => 10
166
+ }, proc{
167
+ incr(:mygauge_917, 30)
168
+ }).tap do |context|
169
+ event = { :_time => @now, :_session_key => "mysesskey" }
170
+ context.call(event, @redis_wrap)
171
+ end
172
+ @redis.hget(gauge_key, "695280200").should == "84"
173
+ @redis.get(gauge_key+"-695280200-value-count").should == "6"
174
+ end
175
+
176
+ end
177
+
156
178
  describe "increment uniquely by session_key" do
157
179
 
158
180
  it "should increment_unique a non-progressive gauge" do
@@ -257,8 +279,141 @@ describe FnordMetric::GaugeModifiers do
257
279
 
258
280
  end
259
281
 
260
- it "should increment a field on a three-dimensional gauge by 1"
261
- it "should increment a field on a three-dimensional gauge by 5"
282
+ describe "increment three-dimensional gagues" do
283
+
284
+ it "should increment a three-dim gauge by 1" do
285
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_434-10-695280200"
286
+ @redis.zadd(gauge_key, 12, "whoopwhoop")
287
+ create_gauge_context({
288
+ :key => "mygauge_434",
289
+ :three_dimensional => true,
290
+ :tick => 10,
291
+ }, proc{
292
+ incr_field(:mygauge_434, "whoopwhoop", 1)
293
+ }).tap do |context|
294
+ event = { :_time => @now }
295
+ context.call(event, @redis_wrap)
296
+ end
297
+ @redis.zscore(gauge_key, "whoopwhoop").should == "13"
298
+ @redis.get(gauge_key+"-count").should == "1"
299
+ end
300
+
301
+ it "should increment a three-dim gauge by 5 on an empty field" do
302
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_634-10-695280200"
303
+ @redis.set(gauge_key+"-count", 6)
304
+ create_gauge_context({
305
+ :key => "mygauge_634",
306
+ :three_dimensional => true,
307
+ :tick => 10,
308
+ }, proc{
309
+ incr_field(:mygauge_634, "whoopwhoop", 5)
310
+ }).tap do |context|
311
+ event = { :_time => @now }
312
+ context.call(event, @redis_wrap)
313
+ end
314
+ @redis.zscore(gauge_key, "whoopwhoop").should == "5"
315
+ @redis.get(gauge_key+"-count").should == "7"
316
+ end
317
+
318
+ it "should increment a three-dim gauge by event supplied field" do
319
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_634-10-695280200"
320
+ @redis.zadd(gauge_key, 11, "fnordybar")
321
+ create_gauge_context({
322
+ :key => "mygauge_634",
323
+ :three_dimensional => true,
324
+ :tick => 10,
325
+ }, proc{
326
+ incr_field(:mygauge_634, data[:myfield], 5)
327
+ }).tap do |context|
328
+ event = { :_time => @now, :myfield => "fnordybar" }
329
+ context.call(event, @redis_wrap)
330
+ end
331
+ @redis.zscore(gauge_key, "fnordybar").should == "16"
332
+ end
333
+
334
+ it "should increment_unique a three-dim gauge" do
335
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_1263-10-695280200"
336
+ @redis.zadd(gauge_key, 54, "mykey")
337
+ @redis.set(gauge_key+"-sessions-count", 5)
338
+ create_gauge_context({
339
+ :key => "mygauge_1263",
340
+ :tick => 10,
341
+ :unique => true,
342
+ :three_dimensional => true
343
+ }, proc{
344
+ incr_field(:mygauge_1263, "mykey", 30)
345
+ }).tap do |context|
346
+ event = { :_time => @now, :_session_key => "mysesskey" }
347
+ context.call(event, @redis_wrap)
348
+ end
349
+ @redis.zscore(gauge_key, "mykey").should == "84"
350
+ @redis.get(gauge_key+"-sessions-count").should == "6"
351
+ @redis.smembers(gauge_key+"-sessions").should == ["mysesskey"]
352
+ end
353
+
354
+ it "should not increment_unique a non-progressive gauge if session is known" do
355
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_1266-695280200"
356
+ @redis.zadd(gauge_key, 54, "otherkey")
357
+ @redis.set(gauge_key+"-sessions-count", 5)
358
+ @redis.sadd(gauge_key+"-sessions", "mysesskey")
359
+ create_gauge_context({
360
+ :key => "mygauge_1266",
361
+ :tick => 10,
362
+ :unique => true,
363
+ :three_dimensional => true
364
+ }, proc{
365
+ incr_field(:mygauge_1266, "otherkey", 30)
366
+ }).tap do |context|
367
+ event = { :_time => @now, :_session_key => "mysesskey" }
368
+ context.call(event, @redis_wrap)
369
+ end
370
+ @redis.zscore(gauge_key, "otherkey").should == "54"
371
+ @redis.get(gauge_key+"-sessions-count").should == "5"
372
+ @redis.smembers(gauge_key+"-sessions").should == ["mysesskey"]
373
+ end
374
+
375
+ end
376
+
377
+ describe "set value on two/three-dim gauge" do
378
+
379
+ it "should set a value on a two-dim gauge" do
380
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_5463-10"
381
+ @redis.hset(gauge_key, "695280200", "54")
382
+ @redis.set(gauge_key+"-695280200-sessions-count", 5)
383
+ @redis.hget(gauge_key, "695280200").should == "54"
384
+ create_gauge_context({
385
+ :key => "mygauge_5463",
386
+ :tick => 10
387
+ }, proc{
388
+ set_value(:mygauge_5463, 17)
389
+ }).tap do |context|
390
+ event = { :_time => @now, :_session_key => "mysesskey" }
391
+ context.call(event, @redis_wrap)
392
+ end
393
+ @redis.hget(gauge_key, "695280200").should == "17"
394
+ end
395
+
396
+
397
+ it "should set a value on a two-dim gauge" do
398
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_1463-10-695280200"
399
+ @redis.zadd(gauge_key, 65, "asdasdkey")
400
+ @redis.zscore(gauge_key, "asdasdkey").should == "65"
401
+ create_gauge_context({
402
+ :key => "mygauge_1463",
403
+ :three_dimensional => true,
404
+ :tick => 10
405
+ }, proc{
406
+ set_field(:mygauge_1463, "asdasdkey", 23)
407
+ }).tap do |context|
408
+ event = { :_time => @now, :_session_key => "mysesskey" }
409
+ context.call(event, @redis_wrap)
410
+ end
411
+ @redis.zscore(gauge_key, "asdasdkey").should == "23"
412
+ end
413
+
414
+ end
415
+
416
+
262
417
  it "should raise an error if incr_field is called on a 2d gauge"
263
418
 
264
419
  private
@@ -12,11 +12,21 @@ describe FnordMetric::Gauge do
12
12
  @redis.keys("fnordmetric-myns*").each { |k| @redis.del(k) }
13
13
  end
14
14
 
15
- it "should remember it's own name" do
15
+ it "should remember its own name" do
16
16
  gauge = FnordMetric::Gauge.new({:key_prefix => "foo", :key => "fnordgauge"})
17
17
  gauge.name.should == "fnordgauge"
18
18
  end
19
19
 
20
+ it "should return its key as title if none specified" do
21
+ gauge = FnordMetric::Gauge.new({:key_prefix => "foo", :key => "fnordgauge"})
22
+ gauge.title.should == "fnordgauge"
23
+ end
24
+
25
+ it "should return its title as title if none specified" do
26
+ gauge = FnordMetric::Gauge.new({:key_prefix => "foo", :key => "fnordgauge", :title => "Fnord Gauge"})
27
+ gauge.title.should == "Fnord Gauge"
28
+ end
29
+
20
30
  it "should raise an error when initialize without key" do
21
31
  lambda{
22
32
  FnordMetric::Gauge.new({:key_prefix => "foo"})
@@ -41,9 +51,15 @@ describe FnordMetric::Gauge do
41
51
 
42
52
  describe "ticks" do
43
53
 
44
- it "should return the correct tick if configured"
45
- it "should return the default tick if none configured"
54
+ it "should return the correct tick if configured" do
55
+ gauge = FnordMetric::Gauge.new({:tick => 23, :key_prefix => "fnordmetrics-myns", :key => "mygauge"})
56
+ gauge.tick.should == 23
57
+ end
46
58
 
59
+ it "should return the default tick if none configured" do
60
+ gauge = FnordMetric::Gauge.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge"})
61
+ gauge.tick.should == 3600
62
+ end
47
63
 
48
64
  it "should return the correct tick_at" do
49
65
  gauge = FnordMetric::Gauge.new({:tick => 10, :key_prefix => "fnordmetrics-myns", :key => "mygauge"})
@@ -81,8 +97,30 @@ describe FnordMetric::Gauge do
81
97
  end
82
98
 
83
99
  it "should return the correct value_at per session" do
100
+ @redis.hset(@gauge_key, "695280200", "76")
84
101
  @redis.set(@gauge_key+"-695280200-sessions-count", "23")
85
- @gauge.value_at(@now, :avg_per_session => 1).should == (54.0/23.0)
102
+ _gauge = FnordMetric::Gauge.new({
103
+ :tick => 10,
104
+ :key_prefix => "fnordmetric-myns",
105
+ :key => "mygauge_966",
106
+ :unique => true,
107
+ :redis => @redis
108
+ })
109
+ _gauge.value_at(@now).should == "76"
110
+ end
111
+
112
+ it "should return the correct value_at per session with avg" do
113
+ @redis.hset(@gauge_key, "695280200", "76")
114
+ @redis.set(@gauge_key+"-695280200-sessions-count", "23")
115
+ _gauge = FnordMetric::Gauge.new({
116
+ :tick => 10,
117
+ :key_prefix => "fnordmetric-myns",
118
+ :key => "mygauge_966",
119
+ :unique => true,
120
+ :average => true,
121
+ :redis => @redis
122
+ })
123
+ _gauge.value_at(@now).should == (76.0/23.0)
86
124
  end
87
125
 
88
126
  it "should receive gauge values for multiple ticks" do
@@ -95,7 +133,33 @@ describe FnordMetric::Gauge do
95
133
  it "should receive gauge values per session for multiple ticks" do
96
134
  @redis.set(@gauge_key+"-695280200-sessions-count", "23")
97
135
  @redis.set(@gauge_key+"-695280210-sessions-count", "8")
98
- @gauge.values_at([@now, @now+8], :avg_per_session => 1).should == {
136
+ @redis.hset(@gauge_key, "695280200", "76")
137
+ @redis.hset(@gauge_key, "695280210", "56")
138
+ _gauge = FnordMetric::Gauge.new({
139
+ :tick => 10,
140
+ :key_prefix => "fnordmetric-myns",
141
+ :key => "mygauge_966",
142
+ :unique => true,
143
+ :redis => @redis
144
+ })
145
+ _gauge.values_at([@now, @now+8]).should == {
146
+ 695280200 => "76",
147
+ 695280210 => "56"
148
+ }
149
+ end
150
+
151
+ it "should receive gauge values per session for multiple ticks with avg" do
152
+ @redis.set(@gauge_key+"-695280200-sessions-count", "23")
153
+ @redis.set(@gauge_key+"-695280210-sessions-count", "8")
154
+ _gauge = FnordMetric::Gauge.new({
155
+ :tick => 10,
156
+ :key_prefix => "fnordmetric-myns",
157
+ :key => "mygauge_966",
158
+ :unique => true,
159
+ :average => true,
160
+ :redis => @redis
161
+ })
162
+ _gauge.values_at([@now, @now+8]).should == {
99
163
  695280200 => (54.0/23.0),
100
164
  695280210 => (123.0/8.0)
101
165
  }
@@ -111,18 +175,85 @@ describe FnordMetric::Gauge do
111
175
  end
112
176
 
113
177
  it "should receive gauge values for all ticks in a given range" do
114
- @gauge.values_in(@now..@now+8).should == {
178
+ @gauge.values_in(@now+10..@now+18).should == {
115
179
  695280200 => "54",
116
180
  695280210 => "123"
117
181
  }
118
- @gauge.values_in(@now..@now+6).should == {
119
- 695280200 => "54"
120
- }
121
- @gauge.values_in(@now+8..@now+10).should == {
122
- 695280210 => "123"
123
- }
124
182
  end
125
183
 
126
184
  end
127
185
 
186
+ describe "three-dim value retrival" do
187
+
188
+ before(:each) do
189
+ @gauge = FnordMetric::Gauge.new({
190
+ :tick => 10,
191
+ :key_prefix => "fnordmetric-myns",
192
+ :three_dimensional => true,
193
+ :key => "mygauge_966",
194
+ :redis => @redis
195
+ })
196
+ @redis.keys("fnordmetric-myns*").each { |k| @redis.del(k) }
197
+ @gauge_key = "fnordmetric-myns-gauge-mygauge_966-10-1323691200"
198
+ @redis.zadd(@gauge_key, 18, "fnordyblubb")
199
+ @redis.zadd(@gauge_key, 23, "uberfoo")
200
+ @redis.set(@gauge_key+"-count", 41)
201
+ end
202
+
203
+ it "should retrieve field_values at a given time" do
204
+ @gauge.field_values_at(1323691200).should be_a(Array)
205
+ @gauge.field_values_at(1323691200).length.should == 2
206
+ @gauge.field_values_at(1323691200)[0].should == ["uberfoo", "23"]
207
+ @gauge.field_values_at(1323691200)[1].should == ["fnordyblubb", "18"]
208
+ end
209
+
210
+ it "should retrieve the correct total count" do
211
+ @gauge.field_values_total(1323691200).should == 41
212
+ end
213
+
214
+ it "should retrieve max 50 fields per default" do
215
+ 70.times{ |n| @redis.zadd(@gauge_key, 23, "field#{n}") }
216
+ @gauge.field_values_at(1323691200).should be_a(Array)
217
+ @gauge.field_values_at(1323691200).length.should == 50
218
+ end
219
+
220
+ it "should retrieve more than 50 fields if requested" do
221
+ 70.times{ |n| @redis.zadd(@gauge_key, 23, "field#{n}") }
222
+ @gauge.field_values_at(1323691200, :max_fields => 60).should be_a(Array)
223
+ @gauge.field_values_at(1323691200, :max_fields => 60).length.should == 60
224
+ end
225
+
226
+ it "should retrieve all fields if requested" do
227
+ 70.times{ |n| @redis.zadd(@gauge_key, 23, "field#{n}") }
228
+ @gauge.field_values_at(1323691200, :max_fields => 0).should be_a(Array)
229
+ @gauge.field_values_at(1323691200, :max_fields => 0).length.should == 72
230
+ end
231
+
232
+ it "should call the value calculation block and return the result" do
233
+ vals = @gauge.field_values_at(1323691200){ |v| v.to_i + 123 }
234
+ vals.should be_a(Array)
235
+ vals.length.should == 2
236
+ vals[0].should == ["uberfoo", 146]
237
+ vals[1].should == ["fnordyblubb", 141]
238
+ end
239
+
240
+ it "should return the correct field_values per session with avg" do
241
+ @redis.set(@gauge_key+"-sessions-count", "3")
242
+ @gauge = FnordMetric::Gauge.new({
243
+ :tick => 10,
244
+ :key_prefix => "fnordmetric-myns",
245
+ :three_dimensional => true,
246
+ :unique => true,
247
+ :average => true,
248
+ :key => "mygauge_966",
249
+ :redis => @redis
250
+ })
251
+ vals = @gauge.field_values_at(1323691200)
252
+ vals.should be_a(Array)
253
+ vals.length.should == 2
254
+ vals[0].should == ["uberfoo", 23/3.0]
255
+ vals[1].should == ["fnordyblubb", 18/3.0]
256
+ end
257
+
258
+ end
128
259
  end