bp-fnordmetric 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/Gemfile +6 -0
  2. data/Rakefile +6 -0
  3. data/fnordmetric.gemspec +41 -0
  4. data/lib/fnordmetric.rb +149 -0
  5. data/lib/fnordmetric/acceptors/acceptor.rb +42 -0
  6. data/lib/fnordmetric/acceptors/amqp_acceptor.rb +56 -0
  7. data/lib/fnordmetric/acceptors/fyrehose_acceptor.rb +43 -0
  8. data/lib/fnordmetric/acceptors/stomp_acceptor.rb +71 -0
  9. data/lib/fnordmetric/acceptors/tcp_acceptor.rb +58 -0
  10. data/lib/fnordmetric/acceptors/udp_acceptor.rb +37 -0
  11. data/lib/fnordmetric/api.rb +46 -0
  12. data/lib/fnordmetric/cache.rb +20 -0
  13. data/lib/fnordmetric/context.rb +96 -0
  14. data/lib/fnordmetric/defaults.rb +22 -0
  15. data/lib/fnordmetric/enterprise/compatibility_handler.rb +42 -0
  16. data/lib/fnordmetric/ext.rb +75 -0
  17. data/lib/fnordmetric/gauge.rb +98 -0
  18. data/lib/fnordmetric/gauge_calculations.rb +106 -0
  19. data/lib/fnordmetric/gauge_modifiers.rb +144 -0
  20. data/lib/fnordmetric/gauge_rendering.rb +40 -0
  21. data/lib/fnordmetric/gauge_validations.rb +15 -0
  22. data/lib/fnordmetric/gauges/distribution_gauge.rb +87 -0
  23. data/lib/fnordmetric/gauges/server_health_gauge.rb +13 -0
  24. data/lib/fnordmetric/gauges/timeseries_gauge.rb +138 -0
  25. data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
  26. data/lib/fnordmetric/histogram.rb +64 -0
  27. data/lib/fnordmetric/logger.rb +63 -0
  28. data/lib/fnordmetric/namespace.rb +208 -0
  29. data/lib/fnordmetric/session.rb +139 -0
  30. data/lib/fnordmetric/standalone.rb +20 -0
  31. data/lib/fnordmetric/timeseries.rb +79 -0
  32. data/lib/fnordmetric/toplist.rb +61 -0
  33. data/lib/fnordmetric/udp_client.rb +22 -0
  34. data/lib/fnordmetric/util.rb +25 -0
  35. data/lib/fnordmetric/version.rb +3 -0
  36. data/lib/fnordmetric/web/app.rb +63 -0
  37. data/lib/fnordmetric/web/app_helpers.rb +42 -0
  38. data/lib/fnordmetric/web/dashboard.rb +40 -0
  39. data/lib/fnordmetric/web/event.rb +99 -0
  40. data/lib/fnordmetric/web/reactor.rb +127 -0
  41. data/lib/fnordmetric/web/web.rb +59 -0
  42. data/lib/fnordmetric/web/websocket.rb +41 -0
  43. data/lib/fnordmetric/widget.rb +82 -0
  44. data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
  45. data/lib/fnordmetric/widgets/html_widget.rb +28 -0
  46. data/lib/fnordmetric/widgets/numbers_widget.rb +80 -0
  47. data/lib/fnordmetric/widgets/pie_widget.rb +23 -0
  48. data/lib/fnordmetric/widgets/timeseries_widget.rb +65 -0
  49. data/lib/fnordmetric/widgets/toplist_widget.rb +68 -0
  50. data/lib/fnordmetric/worker.rb +89 -0
  51. data/lib/fnordmetric/zero_config_gauge.rb +138 -0
  52. data/run_specs.sh +11 -0
  53. data/spec/api_spec.rb +49 -0
  54. data/spec/context_spec.rb +42 -0
  55. data/spec/dashboard_spec.rb +38 -0
  56. data/spec/event_spec.rb +170 -0
  57. data/spec/ext_spec.rb +14 -0
  58. data/spec/fnordmetric_spec.rb +56 -0
  59. data/spec/gauge_like_shared.rb +56 -0
  60. data/spec/gauge_modifiers_spec.rb +583 -0
  61. data/spec/gauge_spec.rb +230 -0
  62. data/spec/namespace_spec.rb +114 -0
  63. data/spec/session_spec.rb +231 -0
  64. data/spec/spec_helper.rb +49 -0
  65. data/spec/tcp_acceptor_spec.rb +35 -0
  66. data/spec/timeseries_gauge_spec.rb +56 -0
  67. data/spec/udp_acceptor_spec.rb +35 -0
  68. data/spec/util_spec.rb +46 -0
  69. data/spec/widget_spec.rb +113 -0
  70. data/spec/worker_spec.rb +40 -0
  71. data/web/.gitignore +4 -0
  72. data/web/build.sh +34 -0
  73. data/web/css/fnordmetric.core.css +868 -0
  74. data/web/haml/app.haml +20 -0
  75. data/web/haml/distribution_gauge.haml +118 -0
  76. data/web/haml/timeseries_gauge.haml +80 -0
  77. data/web/haml/toplist_gauge.haml +194 -0
  78. data/web/img/head.png +0 -0
  79. data/web/img/list.png +0 -0
  80. data/web/img/list_active.png +0 -0
  81. data/web/img/list_hover.png +0 -0
  82. data/web/img/loader.gif +0 -0
  83. data/web/img/loader_white.gif +0 -0
  84. data/web/img/navbar.png +0 -0
  85. data/web/img/navbar_btn.png +0 -0
  86. data/web/img/picto_gauge.png +0 -0
  87. data/web/js/fnordmetric.bars_widget.js +178 -0
  88. data/web/js/fnordmetric.dashboard_view.js +99 -0
  89. data/web/js/fnordmetric.gauge_explorer.js +173 -0
  90. data/web/js/fnordmetric.gauge_view.js +260 -0
  91. data/web/js/fnordmetric.html_widget.js +21 -0
  92. data/web/js/fnordmetric.js +315 -0
  93. data/web/js/fnordmetric.numbers_widget.js +122 -0
  94. data/web/js/fnordmetric.overview_view.js +35 -0
  95. data/web/js/fnordmetric.pie_widget.js +118 -0
  96. data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
  97. data/web/js/fnordmetric.session_view.js +342 -0
  98. data/web/js/fnordmetric.timeline_widget.js +333 -0
  99. data/web/js/fnordmetric.timeseries_widget.js +405 -0
  100. data/web/js/fnordmetric.toplist_widget.js +119 -0
  101. data/web/js/fnordmetric.ui.js +91 -0
  102. data/web/js/fnordmetric.util.js +248 -0
  103. data/web/vendor/font-awesome/css/font-awesome-ie7.min.css +22 -0
  104. data/web/vendor/font-awesome/css/font-awesome.css +540 -0
  105. data/web/vendor/font-awesome/css/font-awesome.min.css +33 -0
  106. data/web/vendor/font-awesome/font/FontAwesome.otf +0 -0
  107. data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
  108. data/web/vendor/font-awesome/font/fontawesome-webfont.svg +284 -0
  109. data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
  110. data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
  111. data/web/vendor/jquery-1.6.2.min.js +18 -0
  112. data/web/vendor/jquery-ui.min.js +6 -0
  113. data/web/vendor/jquery.combobox.js +129 -0
  114. data/web/vendor/jquery.maskedinput.js +252 -0
  115. metadata +438 -0
@@ -0,0 +1,230 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::Gauge 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, false)
9
+ @gauge_klass = FnordMetric::Gauge
10
+ end
11
+
12
+ before(:each) do
13
+ @redis.keys("fnordmetric-myns*").each { |k| @redis.del(k) }
14
+ end
15
+
16
+ it_should_behave_like FnordMetric::GaugeLike
17
+
18
+ describe "ticks" do
19
+
20
+ it "should return the correct tick if configured" do
21
+ gauge = FnordMetric::Gauge.new({:tick => 23, :key_prefix => "fnordmetrics-myns", :key => "mygauge"})
22
+ gauge.tick.should == 23
23
+ end
24
+
25
+ it "should return the correct tick if configured with flush_interval" do
26
+ gauge = FnordMetric::Gauge.new({:flush_interval => 42, :key_prefix => "fnordmetrics-myns", :key => "mygauge"})
27
+ gauge.tick.should == 42
28
+ end
29
+
30
+ it "should return the default tick if none configured" do
31
+ gauge = FnordMetric::Gauge.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge"})
32
+ gauge.tick.should == FnordMetric.options[:default_flush_interval]
33
+ end
34
+
35
+ it "should return the correct tick_at" do
36
+ gauge = FnordMetric::Gauge.new({:tick => 10, :key_prefix => "fnordmetrics-myns", :key => "mygauge"})
37
+ gauge.tick_at(@now).should == 695280200
38
+ gauge.tick_at(@now+6).should == 695280200
39
+ gauge.tick_at(@now+8).should == 695280210
40
+ end
41
+
42
+ end
43
+
44
+ describe "value retrival" do
45
+
46
+ before(:each) do
47
+ @gauge_key = "fnordmetric-myns-gauge-mygauge_966-10"
48
+ @redis.hset(@gauge_key, "695280200", "54")
49
+ @redis.hset(@gauge_key, "695280210", "123")
50
+ @gauge = FnordMetric::Gauge.new({
51
+ :tick => 10,
52
+ :key_prefix => "fnordmetric-myns",
53
+ :key => "mygauge_966",
54
+ :redis => @redis
55
+ })
56
+ end
57
+
58
+ it "should retrieve a gauge value at a given time" do
59
+ @gauge.value_at(@now).should == "54"
60
+ @gauge.value_at(@now+6).should == "54"
61
+ @gauge.value_at(@now+8).should == "123"
62
+ end
63
+
64
+ it "should retrieve a gauge value at the current tick"
65
+
66
+ it "should call the value calculation block and return the result" do
67
+ @gauge.value_at(@now){ |v, t| v.to_i + 123 }.should == 177
68
+ end
69
+
70
+ it "should return the correct value_at per session" do
71
+ @redis.hset(@gauge_key, "695280200", "76")
72
+ @redis.set(@gauge_key+"-695280200-sessions-count", "23")
73
+ _gauge = FnordMetric::Gauge.new({
74
+ :tick => 10,
75
+ :key_prefix => "fnordmetric-myns",
76
+ :key => "mygauge_966",
77
+ :unique => true,
78
+ :redis => @redis
79
+ })
80
+ _gauge.value_at(@now).should == "76"
81
+ end
82
+
83
+ it "should return the correct value_at per session with avg" do
84
+ @redis.hset(@gauge_key, "695280200", "76")
85
+ @redis.set(@gauge_key+"-695280200-sessions-count", "23")
86
+ _gauge = FnordMetric::Gauge.new({
87
+ :tick => 10,
88
+ :key_prefix => "fnordmetric-myns",
89
+ :key => "mygauge_966",
90
+ :unique => true,
91
+ :average => true,
92
+ :redis => @redis
93
+ })
94
+ _gauge.value_at(@now).should == (76.0/23.0)
95
+ end
96
+
97
+ it "should receive gauge values for multiple ticks" do
98
+ @gauge.values_at([@now, @now+8]).should == {
99
+ 695280200 => "54",
100
+ 695280210 => "123"
101
+ }
102
+ end
103
+
104
+ it "should receive gauge values per session for multiple ticks" do
105
+ @redis.set(@gauge_key+"-695280200-sessions-count", "23")
106
+ @redis.set(@gauge_key+"-695280210-sessions-count", "8")
107
+ @redis.hset(@gauge_key, "695280200", "76")
108
+ @redis.hset(@gauge_key, "695280210", "56")
109
+ _gauge = FnordMetric::Gauge.new({
110
+ :tick => 10,
111
+ :key_prefix => "fnordmetric-myns",
112
+ :key => "mygauge_966",
113
+ :unique => true,
114
+ :redis => @redis
115
+ })
116
+ _gauge.values_at([@now, @now+8]).should == {
117
+ 695280200 => "76",
118
+ 695280210 => "56"
119
+ }
120
+ end
121
+
122
+ it "should receive gauge values per session for multiple ticks with avg" do
123
+ @redis.set(@gauge_key+"-695280200-sessions-count", "23")
124
+ @redis.set(@gauge_key+"-695280210-sessions-count", "8")
125
+ _gauge = FnordMetric::Gauge.new({
126
+ :tick => 10,
127
+ :key_prefix => "fnordmetric-myns",
128
+ :key => "mygauge_966",
129
+ :unique => true,
130
+ :average => true,
131
+ :redis => @redis
132
+ })
133
+ _gauge.values_at([@now, @now+8]).should == {
134
+ 695280200 => (54.0/23.0),
135
+ 695280210 => (123.0/8.0)
136
+ }
137
+ end
138
+
139
+ it "should receive gauge values with custom calculation for multiple ticks" do
140
+ @gauge.values_at([@now, @now+8]){ |val, time|
141
+ val.to_i + 30
142
+ }.should == {
143
+ 695280200 => 84,
144
+ 695280210 => 153
145
+ }
146
+ end
147
+
148
+ it "should receive gauge values for all ticks in a given range" do
149
+ @gauge.values_in(@now+10..@now+18).should == {
150
+ 695280200 => "54",
151
+ 695280210 => "123"
152
+ }
153
+ end
154
+
155
+ end
156
+
157
+ describe "three-dim value retrival" do
158
+
159
+ before(:each) do
160
+ @gauge = FnordMetric::Gauge.new({
161
+ :tick => 10,
162
+ :key_prefix => "fnordmetric-myns",
163
+ :three_dimensional => true,
164
+ :key => "mygauge_966",
165
+ :redis => @redis
166
+ })
167
+ @redis.keys("fnordmetric-myns*").each { |k| @redis.del(k) }
168
+ @gauge_key = "fnordmetric-myns-gauge-mygauge_966-10-1323691200"
169
+ @redis.zadd(@gauge_key, 18, "fnordyblubb")
170
+ @redis.zadd(@gauge_key, 23, "uberfoo")
171
+ @redis.set(@gauge_key+"-count", 41)
172
+ end
173
+
174
+ it "should retrieve field_values at a given time" do
175
+ @gauge.field_values_at(1323691200).should be_a(Array)
176
+ @gauge.field_values_at(1323691200).length.should == 2
177
+ @gauge.field_values_at(1323691200)[0].should == ["uberfoo", "23"]
178
+ @gauge.field_values_at(1323691200)[1].should == ["fnordyblubb", "18"]
179
+ end
180
+
181
+ it "should retrieve the correct total count" do
182
+ @gauge.field_values_total(1323691200).should == 41
183
+ end
184
+
185
+ it "should retrieve max 50 fields per default" do
186
+ 70.times{ |n| @redis.zadd(@gauge_key, 23, "field#{n}") }
187
+ @gauge.field_values_at(1323691200).should be_a(Array)
188
+ @gauge.field_values_at(1323691200).length.should == 50
189
+ end
190
+
191
+ it "should retrieve more than 50 fields if requested" do
192
+ 70.times{ |n| @redis.zadd(@gauge_key, 23, "field#{n}") }
193
+ @gauge.field_values_at(1323691200, :max_fields => 60).should be_a(Array)
194
+ @gauge.field_values_at(1323691200, :max_fields => 60).length.should == 60
195
+ end
196
+
197
+ it "should retrieve all fields if requested" do
198
+ 70.times{ |n| @redis.zadd(@gauge_key, 23, "field#{n}") }
199
+ @gauge.field_values_at(1323691200, :max_fields => 0).should be_a(Array)
200
+ @gauge.field_values_at(1323691200, :max_fields => 0).length.should == 72
201
+ end
202
+
203
+ it "should call the value calculation block and return the result" do
204
+ vals = @gauge.field_values_at(1323691200){ |v, t| v.to_i + 123 }
205
+ vals.should be_a(Array)
206
+ vals.length.should == 2
207
+ vals[0].should == ["uberfoo", 146]
208
+ vals[1].should == ["fnordyblubb", 141]
209
+ end
210
+
211
+ it "should return the correct field_values per session with avg" do
212
+ @redis.set(@gauge_key+"-sessions-count", "3")
213
+ @gauge = FnordMetric::Gauge.new({
214
+ :tick => 10,
215
+ :key_prefix => "fnordmetric-myns",
216
+ :three_dimensional => true,
217
+ :unique => true,
218
+ :average => true,
219
+ :key => "mygauge_966",
220
+ :redis => @redis
221
+ })
222
+ vals = @gauge.field_values_at(1323691200)
223
+ vals.should be_a(Array)
224
+ vals.length.should == 2
225
+ vals[0].should == ["uberfoo", 23/3.0]
226
+ vals[1].should == ["fnordyblubb", 18/3.0]
227
+ end
228
+
229
+ end
230
+ end
@@ -0,0 +1,114 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::Namespace 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("fnordmetric-myns*").each { |k| @redis.del(k) }
12
+ @namespace = FnordMetric::Namespace.new(:myns_213, :redis_prefix => "fnordmetric")
13
+ end
14
+
15
+ it "should generate the correct redis prefix"
16
+
17
+ describe "instance methods" do
18
+
19
+ it "should create a new dashboard if a widget is added" do
20
+ @namespace.widget("MyFooDash", nil)
21
+ @namespace.dashboards.keys.should == ["MyFooDash"]
22
+ end
23
+
24
+ it "should create a new dashboard if the dashboard-title contains whitespaces" do
25
+ @namespace.widget("My Dash", nil)
26
+ @namespace.dashboards.keys.should == ["MyDash"]
27
+ end
28
+
29
+ it "should create a new dashboard if a widget is added and add the widget"
30
+ it "should add widget to an existing dashboard"
31
+
32
+ end
33
+
34
+ describe "registering gauges" do
35
+
36
+ it "should register a simple gauge" do
37
+ @namespace.gauge(:fugauge, {:fnord => 23})
38
+ @namespace.gauges[:fugauge].should be_a(FnordMetric::Gauge)
39
+ end
40
+
41
+ it "should register a simple gauge and pass options" do
42
+ @namespace.gauge(:fugauge2, {:fnord => 23})
43
+ @namespace.gauges[:fugauge2].instance_variable_get(:@opts).should include({:fnord => 23})
44
+ @namespace.gauges[:fugauge2].instance_variable_get(:@opts).should include({:key => :fugauge2})
45
+ end
46
+
47
+ it "should register a multi gauge" do
48
+ pending "fixme"
49
+ @namespace.numeric_gauge(:multigauge, {:fnord => 23, :ticks => [1.hour], :series => ["fnord"]})
50
+ @namespace.gauges[:multigauge].should be_a(FnordMetric::NumericGauge)
51
+ end
52
+
53
+ it "should register a multi gauge and pass options" do
54
+ pending "fixme"
55
+ @namespace.numeric_gauge(:multigauge2, {:fnord => 42, :ticks => [1.hour], :series => ["fnord"]})
56
+ @namespace.gauges[:multigauge2].instance_variable_get(:@opts).should include({:fnord => 42})
57
+ @namespace.gauges[:multigauge2].instance_variable_get(:@opts).should include({:key => :multigauge2})
58
+ end
59
+
60
+ end
61
+
62
+ describe "registering event handlers" do
63
+
64
+ it "should register an event handler" do
65
+ @namespace.handlers.length.should == 0
66
+ @namespace.event(:foobar){}
67
+ @namespace.event(:fnordbar){}
68
+ @namespace.handlers["foobar"].length.should == 1
69
+ @namespace.handlers["fnordbar"].length.should == 1
70
+ @namespace.handlers.length.should == 2
71
+ end
72
+
73
+ it "should register an event handler and create a context"
74
+ it "should register an event handler and pass options"
75
+ it "should register an event handler and pass gauges"
76
+ it "should announce an event to the correct handler"
77
+ it "should announce an event to multiple handlers"
78
+ it "should announce an event to the wildcard handler"
79
+ end
80
+
81
+ it "should create a new session on announce if _session is set" do
82
+ FnordMetric::Session.should_receive(:create).and_return(SessionMock.new)
83
+ FnordMetric::Namespace.new(
84
+ :myns_213,
85
+ :redis_prefix => "fnordmetric"
86
+ ).ready!(@redis_wrap, @redis).announce(
87
+ :_time => Time.now.to_i,
88
+ :_type => "foobar",
89
+ :_session => "sess213"
90
+ )
91
+ end
92
+
93
+ it "should add the event to the namespace-event-type-list" do
94
+ FnordMetric::Namespace.new(
95
+ :myns_215,
96
+ :redis_prefix => "fnordmetric"
97
+ ).ready!(@redis_wrap, @redis).announce(
98
+ :_eid => "35r2423",
99
+ :_time => Time.now.to_i,
100
+ :_type => "fnordbar",
101
+ :_session => "sess213"
102
+ )
103
+ event_ids = @redis.lrange("fnordmetric-myns_215-type-fnordbar", 0, -1)
104
+ event_ids.length.should == 1
105
+ event_ids.first.should == "35r2423"
106
+ end
107
+
108
+ class SessionMock
109
+ def session_key
110
+ "asdasd"
111
+ end
112
+ end
113
+
114
+ end
@@ -0,0 +1,231 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::Session do
4
+
5
+ include FnordMetric
6
+
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)
11
+
12
+ @namespace = "fnordmetric-ns123"
13
+ @sessions = "#{@namespace}-session"
14
+ end
15
+
16
+ describe "creating sessions" do
17
+
18
+ before(:all) do
19
+ @event = { :_session => "sess123", :_time => @now, :_eid => "34089749" }
20
+ @md5_key = Digest::MD5.hexdigest("sess123")
21
+
22
+ @redis.del("#{@namespace}-session")
23
+ @redis.del("#{@namespace}-session-#{@md5_key}-events")
24
+ @redis.del("#{@namespace}-session-#{@md5_key}-data")
25
+ end
26
+
27
+ it "should add a new session on intialize" do
28
+ FnordMetric::Session.create(
29
+ :namespace_prefix => @namespace,
30
+ :event => @event,
31
+ :session_data_ttl => 10,
32
+ :redis => @redis_wrap
33
+ )
34
+ @redis.zcard(@sessions).should == 1
35
+ end
36
+
37
+ it "should add a new session on intialize and hash the session token" do
38
+ FnordMetric::Session.create(
39
+ :namespace_prefix => @namespace,
40
+ :event => @event,
41
+ :session_data_ttl => 10,
42
+ :redis => @redis_wrap
43
+ )
44
+ @redis.zrange(@sessions, 0, -1).should == [ @md5_key]
45
+ end
46
+
47
+ it "should add a new session on intialize and set the timestamp as score" do
48
+ FnordMetric::Session.create(
49
+ :namespace_prefix => @namespace,
50
+ :event => @event,
51
+ :session_data_ttl => 10,
52
+ :redis => @redis_wrap
53
+ )
54
+ @redis.zscore(@sessions, @md5_key).to_i.should == @now
55
+ end
56
+
57
+ it "should update the timestamp on a existing session" do
58
+ @redis.zadd(@sessions, @now-10, @md5_key)
59
+ @redis.zscore(@sessions, @md5_key).to_i.should == @now-10
60
+ FnordMetric::Session.create(
61
+ :namespace_prefix => @namespace,
62
+ :event => @event,
63
+ :session_data_ttl => 10,
64
+ :redis => @redis_wrap
65
+ )
66
+ @redis.zscore(@sessions, @md5_key).to_i.should == @now
67
+ end
68
+
69
+ it "should add the event_id to the session-event set on a new session" do
70
+ FnordMetric::Session.create(
71
+ :namespace_prefix => @namespace,
72
+ :event => @event,
73
+ :session_data_ttl => 10,
74
+ :redis => @redis_wrap
75
+ )
76
+ events_key = "#{@namespace}-session-#{@md5_key}-events"
77
+ @redis.zrange(events_key, 0, -1).first.should == @event[:_eid]
78
+ end
79
+
80
+ it "should store a name in the session data" do
81
+ event_data = @event.merge(
82
+ :_type => "_set_name",
83
+ :name => "Horst Mayer"
84
+ )
85
+ FnordMetric::Session.create(
86
+ :namespace_prefix => @namespace,
87
+ :event => event_data,
88
+ :session_data_ttl => 10,
89
+ :redis => @redis_wrap
90
+ )
91
+ data_key = "#{@namespace}-session-#{@md5_key}-data"
92
+ @redis.hget(data_key, "_name").should == "Horst Mayer"
93
+ end
94
+
95
+ it "should store a picture in the session data" do
96
+ event_data = @event.merge(
97
+ :_type => "_set_picture",
98
+ :url => "http://myhost/mypic.jpg"
99
+ )
100
+ FnordMetric::Session.create(
101
+ :namespace_prefix => @namespace,
102
+ :event => event_data,
103
+ :session_data_ttl => 10,
104
+ :redis => @redis_wrap
105
+ )
106
+ data_key = "#{@namespace}-session-#{@md5_key}-data"
107
+ @redis.hget(data_key, "_picture").should == "http://myhost/mypic.jpg"
108
+ end
109
+
110
+ it "should store arbitrary data in the session data" do
111
+ event_data = @event.merge(
112
+ :_type => "_set_data",
113
+ :fnord => "blubb",
114
+ :foobar => "123"
115
+ )
116
+ FnordMetric::Session.create(
117
+ :namespace_prefix => @namespace,
118
+ :event => event_data,
119
+ :session_data_ttl => 10,
120
+ :redis => @redis_wrap
121
+ )
122
+ data_key = "#{@namespace}-session-#{@md5_key}-data"
123
+ @redis.hget(data_key, "fnord").should == "blubb"
124
+ @redis.hget(data_key, "foobar").should == "123"
125
+ end
126
+
127
+ it "not store special attributes in the session" do
128
+ event_data = @event.merge(
129
+ :_type => "_set_data",
130
+ :fnord => "blubb",
131
+ :foobar => "123"
132
+ )
133
+ FnordMetric::Session.create(
134
+ :namespace_prefix => @namespace,
135
+ :event => event_data,
136
+ :session_data_ttl => 10,
137
+ :redis => @redis_wrap
138
+ )
139
+ data_key = "#{@namespace}-session-#{@md5_key}-data"
140
+ @redis.hget(data_key, "_time").should be_nil
141
+ @redis.hget(data_key, "_eid").should be_nil
142
+ end
143
+
144
+ end
145
+
146
+ describe "Finding Sessions" do
147
+
148
+ before(:each) do
149
+ @redis.del("#{@namespace}-session")
150
+ @redis.keys("#{@namespace}-session-*").each { |k| @redis.del(k) }
151
+
152
+ @opts = {
153
+ :redis_prefix => "#{@namespace}-session",
154
+ :namespace_prefix => "#{@namespace}",
155
+ :redis => @redis
156
+ }
157
+ end
158
+
159
+ it "should find all sessions" do
160
+ create_session("sess533", @now, {})
161
+ create_session("sess343", @now, {})
162
+ FnordMetric::Session.all(@opts).length.should == 2
163
+ end
164
+
165
+ it "should find all sessions and return session objects" do
166
+ create_session("sess523", @now, {})
167
+ FnordMetric::Session.all(@opts).first.should be_a(FnordMetric::Session)
168
+ end
169
+
170
+ it "should find a session and return a session object" do
171
+ create_session("sess223", @now, {})
172
+ sess = FnordMetric::Session.find(Digest::MD5.hexdigest("sess223"), @opts)
173
+ sess.should be_a(FnordMetric::Session)
174
+ sess.session_key.should == Digest::MD5.hexdigest("sess223")
175
+ end
176
+
177
+ it "should find a sessions and return a session object with data" do
178
+ create_session("sess123", @now, { :fnord => "blubb" })
179
+ sess = FnordMetric::Session.find(Digest::MD5.hexdigest("sess123"), @opts)
180
+ sess.fetch_data!
181
+ sess.data(:fnord).should == "blubb"
182
+ end
183
+
184
+ it "should not include special attributes in data" do
185
+ event_data = { :_name => "Horst Mayer", :_picture => "http://myhost/mypic.jpg" }
186
+ create_session("sess173", @now, event_data)
187
+ sess = FnordMetric::Session.find(Digest::MD5.hexdigest("sess173"), @opts)
188
+ sess.fetch_data!
189
+ sess.data(:_name).should == nil
190
+ sess.data(:_picture).should == nil
191
+ end
192
+
193
+ it "should find a session and return a session object with picture" do
194
+ event_data = { :_name => "Horst Mayer", :_picture => "http://myhost/mypic.jpg" }
195
+ create_session("sess163", @now, event_data)
196
+ sess = FnordMetric::Session.find(Digest::MD5.hexdigest("sess163"), @opts)
197
+ sess.fetch_data!
198
+ sess.picture.should == "http://myhost/mypic.jpg"
199
+ end
200
+
201
+ it "should find a session and return a session object with name" do
202
+ event_data = { :_name => "Horst Mayer", :_picture => "http://myhost/mypic.jpg" }
203
+ create_session("sess143", @now, event_data)
204
+ sess = FnordMetric::Session.find(Digest::MD5.hexdigest("sess143"), @opts)
205
+ sess.fetch_data!
206
+ sess.name.should == "Horst Mayer"
207
+ end
208
+
209
+ it "should find a session and return a session object with event_ids" do
210
+ sesshash = create_session("sess923", @now, {})
211
+ @redis_wrap.zadd("#{@namespace}-session-#{sesshash}-events", @now, "shmoo")
212
+ @redis_wrap.zadd("#{@namespace}-session-#{sesshash}-events", @now, "fnord")
213
+ sess = FnordMetric::Session.find(sesshash, @opts)
214
+ sess.fetch_event_ids!
215
+ sess.event_ids.should include("shmoo")
216
+ sess.event_ids.should include("fnord")
217
+ end
218
+
219
+ def create_session(sesskey, sesstime, sessdata)
220
+ Digest::MD5.hexdigest(sesskey).tap do |sesshash|
221
+ @redis_wrap.zadd("#{@namespace}-session", sesstime, sesshash)
222
+ sessdata.each do |k,v|
223
+ @redis_wrap.hset("#{@namespace}-session-#{sesshash}-data", k, v)
224
+ end
225
+ end
226
+ end
227
+
228
+ end
229
+
230
+
231
+ end