fnordmetric 0.3.2 → 0.5.0

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 (59) hide show
  1. data/Gemfile +6 -0
  2. data/Gemfile.lock +21 -0
  3. data/Procfile +1 -2
  4. data/VERSION +1 -1
  5. data/_spec/app_spec.rb +178 -0
  6. data/{spec → _spec}/cache_spec.rb +0 -0
  7. data/{spec → _spec}/combine_metric_spec.rb +0 -0
  8. data/{spec → _spec}/core_spec.rb +0 -0
  9. data/{spec → _spec}/count_metric_spec.rb +0 -0
  10. data/_spec/dashboard_spec.rb +67 -0
  11. data/_spec/event_spec.rb +46 -0
  12. data/{spec → _spec}/metric_spec.rb +0 -0
  13. data/{spec → _spec}/report_spec.rb +0 -0
  14. data/{spec → _spec}/sum_metric_spec.rb +0 -0
  15. data/_spec/widget_spec.rb +107 -0
  16. data/doc/import_dump.rb +26 -0
  17. data/em_runner.rb +33 -0
  18. data/fnordmetric.gemspec +59 -20
  19. data/haml/app.haml +26 -12
  20. data/lib/fnordmetric.rb +150 -15
  21. data/lib/fnordmetric/app.rb +70 -11
  22. data/lib/fnordmetric/cache.rb +4 -4
  23. data/lib/fnordmetric/context.rb +65 -0
  24. data/lib/fnordmetric/dashboard.rb +16 -12
  25. data/lib/fnordmetric/event.rb +65 -15
  26. data/lib/fnordmetric/gauge.rb +46 -0
  27. data/lib/fnordmetric/gauge_calculations.rb +43 -0
  28. data/lib/fnordmetric/gauge_modifiers.rb +43 -0
  29. data/lib/fnordmetric/inbound_stream.rb +66 -0
  30. data/lib/fnordmetric/logger.rb +38 -0
  31. data/lib/fnordmetric/namespace.rb +120 -0
  32. data/lib/fnordmetric/numbers_widget.rb +29 -11
  33. data/lib/fnordmetric/session.rb +131 -0
  34. data/lib/fnordmetric/standalone.rb +31 -0
  35. data/lib/fnordmetric/timeline_widget.rb +29 -9
  36. data/lib/fnordmetric/widget.rb +50 -45
  37. data/lib/fnordmetric/worker.rb +80 -0
  38. data/pub/fnordmetric/fnordmetric.css +76 -9
  39. data/pub/fnordmetric/fnordmetric.js +541 -42
  40. data/pub/raphael-min.js +8 -0
  41. data/pub/raphael-utils.js +221 -0
  42. data/readme.rdoc +172 -27
  43. data/server.rb +22 -0
  44. data/spec/app_spec.rb +359 -117
  45. data/spec/context_spec.rb +42 -0
  46. data/spec/dashboard_spec.rb +7 -47
  47. data/spec/event_spec.rb +114 -33
  48. data/spec/gauge_modifiers_spec.rb +276 -0
  49. data/spec/gauge_spec.rb +128 -0
  50. data/spec/namespace_spec.rb +104 -0
  51. data/spec/session_spec.rb +231 -0
  52. data/spec/spec_helper.rb +27 -4
  53. data/spec/widget_spec.rb +81 -75
  54. data/spec/worker_spec.rb +37 -0
  55. data/test_stream.sh +187 -0
  56. data/ulm_stats.rb +198 -0
  57. metadata +114 -35
  58. data/lib/fnordmetric/core.rb +0 -66
  59. data/lib/fnordmetric/engine.rb +0 -3
@@ -0,0 +1,42 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::Context do
4
+
5
+ before(:all) do
6
+ @redis = Redis.new
7
+ @redis_wrap = RedisWrap.new(@redis)
8
+ end
9
+
10
+ before(:each) do
11
+ @redis.keys("fnordmetrictest*").each { |k| @redis.del(k) }
12
+ end
13
+
14
+ it "should fetch a gauge by key"
15
+ it "should fetch a gauge by gauge"
16
+ it "should raise an error if unable to fetch a gauge"
17
+
18
+ it "should expose the current session_key" do
19
+ ns = FnordMetric::Namespace.new(
20
+ :myns_253,
21
+ :redis_prefix => "fnordmetrictest"
22
+ )
23
+ ns.opt_event(:fnordbar, {}) do
24
+ session_key.should == "145d3f6dee1a770e3a3c550b3993dc81"
25
+ end
26
+ ns.ready!(@redis_wrap).announce(
27
+ :_eid => "35r2423",
28
+ :_time => Time.now.to_i,
29
+ :_type => "fnordbar",
30
+ :_session => "sess213"
31
+ )
32
+ end
33
+
34
+ it "should instance-eval the handler on call" do
35
+ Thread.current["fnord_123"] = false
36
+ my_block = proc{ Thread.current["fnord_123"] = "35r25" }
37
+ context = FnordMetric::Context.new({}, my_block)
38
+ context.call({}, nil)
39
+ Thread.current["fnord_123"].should == "35r25"
40
+ end
41
+
42
+ end
@@ -3,12 +3,10 @@ require ::File.expand_path('../spec_helper.rb', __FILE__)
3
3
  describe FnordMetric::Dashboard do
4
4
 
5
5
  before(:each) do
6
- FnordMetric::Event.destroy_all
7
- FnordMetric.reset_metrics
8
6
  end
9
7
 
10
8
  it "should remember it's title" do
11
- dashboard = FnordMetric::Dashboard.new(:title => 'My Foobar Dashboard'){ |dash| }
9
+ dashboard = FnordMetric::Dashboard.new(:title => 'My Foobar Dashboard')
12
10
  dashboard.title.should == 'My Foobar Dashboard'
13
11
  end
14
12
 
@@ -18,50 +16,12 @@ describe FnordMetric::Dashboard do
18
16
  end
19
17
 
20
18
  it "should add a widget" do
21
- dashboard = FnordMetric::Dashboard.new(:title => 'My!F00bar-.Dash_board'){ |dash| }
22
- FnordMetric.metric(:my_metric, :sum => :my_field)
23
- widget = FnordMetric.widget(:my_widget, :metrics => :my_metric, :title => "My Widget", :type => :timeline)
24
- dashboard.add_widget(widget)
25
- dashboard.widgets.first.should == widget
26
- end
27
-
28
- it "should add a widget by name" do
29
- dashboard = FnordMetric::Dashboard.new(:title => 'My!F00bar-.Dash_board'){ |dash| }
30
- FnordMetric.metric(:my_metric, :sum => :my_field)
31
- widget = FnordMetric.widget(:my_widget, :metrics => :my_metric, :title => "My Widget", :type => :timeline)
32
- dashboard.add_widget(:my_widget)
33
- dashboard.widgets.first.should == widget
34
- end
35
-
36
- it "should add the report on init (and to all widgets)" do
37
- FnordMetric.metric(:my_metric, :sum => :my_field)
38
- report = FnordMetric.report(:range => (4.days.ago..Time.now))
39
- dashboard = FnordMetric::Dashboard.new(:title => 'My Foobar Dashboard', :report => report){ |dash|
40
- dash.add_widget FnordMetric.widget(:my_widget, :metrics => :my_metric, :title => "My Widget", :type => :timeline)
41
- }
42
- dashboard.report.should == report
43
- dashboard.widgets.last.report.should == report
44
- end
45
-
46
- it "should add the report after init (and to all widgets)" do
47
- FnordMetric.metric(:my_metric, :sum => :my_field)
48
- report = FnordMetric.report(:range => (4.days.ago..Time.now))
49
- dashboard = FnordMetric::Dashboard.new(:title => 'My Foobar Dashboard'){ |dash|
50
- dash.add_widget FnordMetric.widget(:my_widget, :metrics => :my_metric, :title => "My Widget", :type => :timeline)
51
- }
52
- dashboard.report.should == nil
53
- dashboard.add_report(report)
54
- dashboard.report.should == report
55
- dashboard.widgets.last.report.should == report
56
- end
57
-
58
- it "should call the config block" do
59
- block_called = false
60
- FnordMetric::Dashboard.new(:title => 'My Dashboard') do |dash|
61
- block_called = true
62
- dash.should be_a(FnordMetric::Dashboard)
63
- end
64
- block_called.should be_true
19
+ pending("fix this")
20
+ #dashboard = FnordMetric::Dashboard.new(:title => 'My!F00bar-.Dash_board'){ |dash| }
21
+ #FnordMetric.metric(:my_metric, :sum => :my_field)
22
+ #idget = FnordMetric.widget(:my_widget, :metrics => :my_metric, :title => "My Widget", :type => :timeline)
23
+ #dashboard.add_widget(widget)
24
+ #dashboard.widgets.first.should == widget
65
25
  end
66
26
 
67
27
  end
data/spec/event_spec.rb CHANGED
@@ -1,46 +1,127 @@
1
1
  require ::File.expand_path('../spec_helper.rb', __FILE__)
2
2
 
3
- include FnordMetric
3
+ describe FnordMetric::Event do
4
4
 
5
- describe "event" do
5
+ include FnordMetric
6
6
 
7
- before(:each) do
8
- Event.destroy_all
9
- end
7
+ before(:all) do
8
+ @now = Time.utc(1992,01,13,5,23,23).to_i
9
+ @redis = Redis.new
10
+ @redis_wrap = RedisWrap.new(@redis)
10
11
 
11
- it "should track an event" do
12
- event = Event.track!('_referral', :foobar => "fnord")
13
- Event.last[:type].should == "_referral"
14
- Event.last[:foobar].should == "fnord"
15
- end
12
+ @namespace = "fnordmetric-test-ns123"
13
+ @timeline = "#{@namespace}-timeline"
16
14
 
17
- it "should track an event via the proxy method" do
18
- FnordMetric.track('blubb', :foo => "bar")
19
- FnordMetric::Event.last.foo.should == "bar"
15
+ @opts = {
16
+ :namespace_prefix => "#{@namespace}",
17
+ :redis_prefix => "fnordmetric-test",
18
+ :redis => @redis
19
+ }
20
20
  end
21
21
 
22
- it "should access info like a 'ostruct' object" do
23
- event = Event.track!('_referral', :foobar => "fnord")
24
- Event.last.type.should == "_referral"
25
- Event.last.foobar.should == "fnord"
26
- end
22
+ describe "finding events" do
27
23
 
28
- it "should insert a data point in the past" do
29
- my_time = 23.minutes.ago
30
- event = Event.track!('_referral', :foobar => "fnord", :time => my_time)
31
- Event.last[:type].should == "_referral"
32
- Event.last[:foobar].should == "fnord"
33
- Event.last[:time].should == my_time.to_i
34
- end
24
+ before(:each) do
25
+ @redis.keys("fnordmetric-test-*").each { |k| @redis.del(k) }
26
+ end
35
27
 
36
- it "should save integer data" do
37
- event = Event.track!('_test', :num => 23)
38
- Event.last.num.should == 23
39
- end
28
+ it "should find all events" do
29
+ create_event("242342", {:_type => "foo", :_time => @now})
30
+ create_event("453484", {:_type => "foo", :_time => @now})
31
+ Event.all(@opts).length.should == 2
32
+ end
33
+
34
+ it "should find all events and return event objects" do
35
+ create_event("434454", {:_type => "foo", :_time => @now})
36
+ Event.all(@opts).first.should be_a(FnordMetric::Event)
37
+ end
38
+
39
+ it "should find all events and returnevent objects with time" do
40
+ create_event("352234", {:_type => "Fn0rd", :blah => :blubb, :_time => @now})
41
+ events = Event.all(@opts)
42
+ events.first.time.to_i.should == @now
43
+ end
44
+
45
+ it "should find an event and return a event object" do
46
+ create_event("756753", {:_type => "Fn0rd", :_time => @now})
47
+ event = Event.find("756753", @opts)
48
+ event.should be_a(FnordMetric::Event)
49
+ event.type.should == "Fn0rd"
50
+ end
51
+
52
+ it "should find an event and return a event object with data" do
53
+ create_event("53454", {:_type => "Fn0rd", :blah => :blubb, :_time => @now})
54
+ event = Event.find("53454", @opts)
55
+ event.data(:blah).should == "blubb"
56
+ end
57
+
58
+ it "should find an event and return a event object with id" do
59
+ create_event("5262435", {:_type => "Fn0rd", :blah => :blubb, :_time => @now})
60
+ event = Event.find("5262435", @opts)
61
+ event.id.should == "5262435"
62
+ end
63
+
64
+ it "should find all in the correct order" do
65
+ create_event("5645642", {:_type => "foo", :_time => @now-17})
66
+ create_event("2342366", {:_type => "foo", :_time => @now-23})
67
+ create_event("3452345", {:_type => "foo", :_time => @now-42})
68
+ create_event("6345345", {:_type => "foo", :_time => @now-5})
69
+ Event.all(@opts).length.should == 4
70
+ Event.all(@opts)[0].id.should == "6345345"
71
+ Event.all(@opts)[1].id.should == "5645642"
72
+ Event.all(@opts)[2].id.should == "2342366"
73
+ Event.all(@opts)[3].id.should == "3452345"
74
+ end
75
+
76
+ it "should find all events since a given time, including that exact time" do
77
+ create_event("3452345", {:_type => "foo", :_time => @now-42})
78
+ create_event("2342366", {:_type => "foo", :_time => @now-23})
79
+ create_event("5645642", {:_type => "foo", :_time => @now-17})
80
+ create_event("6345345", {:_type => "foo", :_time => @now-5})
81
+ Event.all(@opts).length.should == 4
82
+ Event.all(@opts.merge(:since => @now-42)).length.should == 4
83
+ Event.all(@opts.merge(:since => @now-23)).length.should == 3
84
+ Event.all(@opts.merge(:since => @now-22)).length.should == 2
85
+ Event.all(@opts.merge(:since => @now-17)).length.should == 2
86
+ Event.all(@opts.merge(:since => @now-16)).length.should == 1
87
+ Event.all(@opts.merge(:since => @now-5)).length.should == 1
88
+ end
89
+
90
+ it "should find a maximum number of events" do
91
+ create_event("3452345", {:_type => "foo", :_time => @now-42})
92
+ create_event("2342366", {:_type => "foo", :_time => @now-23})
93
+ create_event("5645642", {:_type => "foo", :_time => @now-17})
94
+ create_event("6345345", {:_type => "foo", :_time => @now-5})
95
+ Event.all(@opts).length.should == 4
96
+ Event.all(@opts.merge(:limit => 2)).length.should == 2
97
+ Event.all(@opts.merge(:limit => 2)).first.id.should == "6345345"
98
+ Event.all(@opts.merge(:limit => 2)).last.id.should == "5645642"
99
+ end
100
+
101
+ it "should find all events by type" do
102
+ namespace = Namespace.new(:ns123, :redis_prefix => "fnordmetric-test")
103
+ namespace.ready!(@redis_wrap).announce(
104
+ :_type => "fn0rd",
105
+ :_time => @now
106
+ )
107
+ namespace.ready!(@redis_wrap).announce(
108
+ :_type => "f00bar",
109
+ :_time => @now
110
+ )
111
+ namespace.ready!(@redis_wrap).announce(
112
+ :_type => "fn0rd",
113
+ :_time => @now
114
+ )
115
+ Event.by_type('fn0rd', @opts).length.should == 2
116
+ Event.by_type('f00bar', @opts).length.should == 1
117
+ end
118
+
119
+ def create_event(event_id, event_data)
120
+ @redis_wrap.zadd(@timeline, event_data.delete(:_time), event_id)
121
+ @redis.set("fnordmetric-test-event-#{event_id}", event_data.to_json)
122
+ end
40
123
 
41
- it "should save float data" do
42
- event = Event.track!('_test', :num => 42.5)
43
- Event.last.num.should == 42.5
44
124
  end
45
-
125
+
126
+
46
127
  end
@@ -0,0 +1,276 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::GaugeModifiers do
4
+
5
+ before(:all) do
6
+ @now = Time.utc(1992,01,13,5,23,23).to_i
7
+ @redis = Redis.new
8
+ @redis_wrap = RedisWrap.new(@redis)
9
+ end
10
+
11
+ before(:each) do
12
+ @redis.keys("fnordmetrics-myns*").each { |k| @redis.del(k) }
13
+ end
14
+
15
+ describe "increment non-progressive gauges" do
16
+
17
+ it "should increment a non-progressive gauge by 1" do
18
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_234-10"
19
+ @redis.hset(gauge_key, "695280200", "12")
20
+ create_gauge_context({
21
+ :key => "mygauge_234",
22
+ :tick => 10,
23
+ }, proc{
24
+ incr(:mygauge_234, 1)
25
+ }).tap do |context|
26
+ event = { :_time => @now }
27
+ context.call(event, @redis_wrap)
28
+ end
29
+ @redis.hget(gauge_key, "695280200").should == "13"
30
+ end
31
+
32
+ it "should increment a non-progressive gauge by 5" do
33
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_224-10"
34
+ @redis.hset(gauge_key, "695280200", "18")
35
+ create_gauge_context({
36
+ :key => "mygauge_224",
37
+ :tick => 10,
38
+ }, proc{
39
+ incr(:mygauge_224, 5)
40
+ }).tap do |context|
41
+ event = { :_time => @now }
42
+ context.call(event, @redis_wrap)
43
+ end
44
+ @redis.hget(gauge_key, "695280200").should == "23"
45
+ end
46
+
47
+ it "should increment a non-progressive gauge by event_value" do
48
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_253-10"
49
+ @redis.hset(gauge_key, "695280200", "11")
50
+ create_gauge_context({
51
+ :key => "mygauge_253",
52
+ :tick => 10,
53
+ }, proc{
54
+ incr(:mygauge_253, data[:myval].to_i)
55
+ }).tap do |context|
56
+ event = { :_time => @now, :myval => "25" }
57
+ context.call(event, @redis_wrap)
58
+ end
59
+ @redis.hget(gauge_key, "695280200").should == "36"
60
+ end
61
+
62
+ end
63
+
64
+
65
+ describe "increment progressive gauges" do
66
+
67
+ it "should increment a progressive gauge by 1" do
68
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_123-10"
69
+ @redis.hset(gauge_key, "695280200", "23")
70
+ @redis.set(gauge_key+"-head", "23")
71
+ create_gauge_context({
72
+ :key => "mygauge_123",
73
+ :tick => 10,
74
+ :progressive => true
75
+ }, proc{
76
+ incr(:mygauge_123, 1)
77
+ }).tap do |context|
78
+ event = { :_time => @now }
79
+ context.call(event, @redis_wrap)
80
+ end
81
+ @redis.hget(gauge_key, "695280200").should == "24"
82
+ @redis.get(gauge_key+"-head").should == "24"
83
+ end
84
+
85
+ it "should increment a progressive gauge by 5" do
86
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_125-10"
87
+ @redis.hset(gauge_key, "695280200", "22")
88
+ @redis.set(gauge_key+"-head", "22")
89
+ create_gauge_context({
90
+ :key => "mygauge_125",
91
+ :tick => 10,
92
+ :progressive => true
93
+ }, proc{
94
+ incr(:mygauge_125, 5)
95
+ }).tap do |context|
96
+ event = { :_time => @now }
97
+ context.call(event, @redis_wrap)
98
+ end
99
+ @redis.hget(gauge_key, "695280200").should == "27"
100
+ @redis.get(gauge_key+"-head").should == "27"
101
+ end
102
+
103
+ it "should increment a progressive gauge by 1 and copy head" do
104
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_128-10"
105
+ @redis.hdel(gauge_key, "695280200")
106
+ @redis.set(gauge_key+"-head", "17")
107
+ create_gauge_context({
108
+ :key => "mygauge_128",
109
+ :tick => 10,
110
+ :progressive => true
111
+ }, proc{
112
+ incr(:mygauge_128, 3)
113
+ }).tap do |context|
114
+ event = { :_time => @now }
115
+ context.call(event, @redis_wrap)
116
+ end
117
+ @redis.hget(gauge_key, "695280200").should == "20"
118
+ @redis.get(gauge_key+"-head").should == "20"
119
+ end
120
+
121
+ it "should increment a progressive gauge by 5 and copy head" do
122
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_121-10"
123
+ @redis.hdel(gauge_key, "695280200")
124
+ @redis.set(gauge_key+"-head", "19")
125
+ create_gauge_context({
126
+ :key => "mygauge_121",
127
+ :tick => 10,
128
+ :progressive => true
129
+ }, proc{
130
+ incr(:mygauge_121, 6)
131
+ }).tap do |context|
132
+ event = { :_time => @now }
133
+ context.call(event, @redis_wrap)
134
+ end
135
+ @redis.hget(gauge_key, "695280200").should == "25"
136
+ @redis.get(gauge_key+"-head").should == "25"
137
+ end
138
+
139
+ it "should raise an error if incr is called on a 3d gauge" do
140
+ create_gauge_context({
141
+ :key => "mygauge_167",
142
+ :tick => 10,
143
+ :three_dimensional => true
144
+ }, proc{
145
+ incr(:mygauge_167, 1)
146
+ }).tap do |context|
147
+ event = { :_time => @now }
148
+ lambda{
149
+ context.call(event, @redis_wrap)
150
+ }.should raise_error(RuntimeError)
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+ describe "increment uniquely by session_key" do
157
+
158
+ it "should increment_unique a non-progressive gauge" do
159
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_963-10"
160
+ @redis.hset(gauge_key, "695280200", "54")
161
+ @redis.set(gauge_key+"-695280200-sessions-count", 5)
162
+ create_gauge_context({
163
+ :key => "mygauge_963",
164
+ :unique => true,
165
+ :tick => 10
166
+ }, proc{
167
+ incr(:mygauge_963, 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-sessions-count").should == "6"
174
+ @redis.smembers(gauge_key+"-695280200-sessions").should == ["mysesskey"]
175
+ end
176
+
177
+ it "should not increment_unique a non-progressive gauge if session is known" do
178
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_966"
179
+ @redis.hset(gauge_key, "695280200", "54")
180
+ @redis.set(gauge_key+"-695280200-sessions-count", 5)
181
+ @redis.sadd(gauge_key+"-695280200-sessions", "mysesskey")
182
+ create_gauge_context({
183
+ :key => "mygauge_966",
184
+ :unique => true,
185
+ :tick => 10
186
+ }, proc{
187
+ incr(:mygauge_966, 30)
188
+ }).tap do |context|
189
+ event = { :_time => @now, :_session_key => "mysesskey" }
190
+ context.call(event, @redis_wrap)
191
+ end
192
+ @redis.hget(gauge_key, "695280200").should == "54"
193
+ @redis.get(gauge_key+"-695280200-sessions-count").should == "5"
194
+ @redis.smembers(gauge_key+"-695280200-sessions").should == ["mysesskey"]
195
+ end
196
+
197
+ it "should not increment_unique a non-progressive gauge w/o session" do
198
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_966"
199
+ @redis.hset(gauge_key, "695280200", "54")
200
+ @redis.set(gauge_key+"-695280200-sessions-count", 5)
201
+ create_gauge_context({
202
+ :key => "mygauge_966",
203
+ :unique => true,
204
+ :tick => 10
205
+ }, proc{
206
+ incr(:mygauge_966, 30)
207
+ }).tap do |context|
208
+ event = { :_time => @now }
209
+ context.call(event, @redis_wrap)
210
+ end
211
+ @redis.hget(gauge_key, "695280200").should == "54"
212
+ @redis.get(gauge_key+"-695280200-sessions-count").should == "5"
213
+ @redis.smembers(gauge_key+"-695280200-sessions").should == []
214
+ end
215
+
216
+
217
+ it "should increment_unique a non-progressive gauge" do
218
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_963-10"
219
+ @redis.hset(gauge_key, "695280200", "54")
220
+ @redis.set(gauge_key+"-progressive-sessions-count", 5)
221
+ create_gauge_context({
222
+ :key => "mygauge_963",
223
+ :tick => 10,
224
+ :unique => true,
225
+ :progressive => true
226
+ }, proc{
227
+ incr(:mygauge_963, 30)
228
+ }).tap do |context|
229
+ event = { :_time => @now, :_session_key => "mysesskey" }
230
+ context.call(event, @redis_wrap)
231
+ end
232
+ @redis.hget(gauge_key, "695280200").should == "84"
233
+ @redis.get(gauge_key+"-progressive-sessions-count").should == "6"
234
+ @redis.smembers(gauge_key+"-progressive-sessions").should == ["mysesskey"]
235
+ end
236
+
237
+ it "should not increment_unique a non-progressive gauge if session is known" do
238
+ gauge_key = "fnordmetrics-myns-gauge-mygauge_966"
239
+ @redis.hset(gauge_key, "695280200", "54")
240
+ @redis.set(gauge_key+"-progressive-sessions-count", 5)
241
+ @redis.sadd(gauge_key+"-progressive-sessions", "mysesskey")
242
+ create_gauge_context({
243
+ :key => "mygauge_966",
244
+ :tick => 10,
245
+ :unique => true,
246
+ :progressive => true
247
+ }, proc{
248
+ incr(:mygauge_966, 30)
249
+ }).tap do |context|
250
+ event = { :_time => @now, :_session_key => "mysesskey" }
251
+ context.call(event, @redis_wrap)
252
+ end
253
+ @redis.hget(gauge_key, "695280200").should == "54"
254
+ @redis.get(gauge_key+"-progressive-sessions-count").should == "5"
255
+ @redis.smembers(gauge_key+"-progressive-sessions").should == ["mysesskey"]
256
+ end
257
+
258
+ end
259
+
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"
262
+ it "should raise an error if incr_field is called on a 2d gauge"
263
+
264
+ private
265
+
266
+ def create_gauge_context(opts, block)
267
+ gauge = FnordMetric::Gauge.new({
268
+ :key_prefix => "fnordmetrics-myns"
269
+ }.merge(opts))
270
+ FnordMetric::Context.new({
271
+ :gauges => { opts[:key].intern => gauge }
272
+ }, block)
273
+ end
274
+
275
+
276
+ end