fnordmetric 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/fnordmetric.gemspec +1 -2
- data/lib/fnordmetric.rb +1 -4
- data/lib/fnordmetric/namespace.rb +7 -3
- data/lib/fnordmetric/version.rb +1 -1
- data/lib/fnordmetric/web/app.rb +3 -3
- data/readme.md +12 -10
- data/spec/spec_helper.rb +4 -1
- data/web/fnordmetric.css +1 -1
- data/web/haml/app.haml +1 -1
- metadata +34 -47
- data/spec/app_spec.rb +0 -486
data/fnordmetric.gemspec
CHANGED
@@ -13,8 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.summary = %q{FnordMetric is a Ruby Event-Tracking gem on steroids}
|
14
14
|
s.description = %q{FnordMetric is a Ruby Event-Tracking gem on steroids}
|
15
15
|
s.licenses = ["MIT"]
|
16
|
-
|
17
|
-
s.add_dependency "bson_ext", ">= 1.4.0"
|
16
|
+
|
18
17
|
s.add_dependency "sinatra", ">= 1.2.6"
|
19
18
|
s.add_dependency "redis", ">= 2.2.2"
|
20
19
|
s.add_dependency "eventmachine"
|
data/lib/fnordmetric.rb
CHANGED
@@ -47,10 +47,7 @@ module FnordMetric
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def self.mk_redis
|
50
|
-
|
51
|
-
redis_opts = { :host => host }
|
52
|
-
redis_opts.merge!(:port => port) if port
|
53
|
-
Redis.new(redis_opts)
|
50
|
+
Redis.new(:url => options[:redis_url])
|
54
51
|
end
|
55
52
|
|
56
53
|
def self.default_options(opts = {})
|
@@ -2,7 +2,7 @@ class FnordMetric::Namespace
|
|
2
2
|
|
3
3
|
attr_reader :handlers, :gauges, :opts, :key, :dashboards, :flags
|
4
4
|
|
5
|
-
@@opts = [:event, :gauge, :widget, :set_title, :hide_active_users, :hide_overview]
|
5
|
+
@@opts = [:event, :gauge, :widget, :set_title, :hide_active_users, :hide_overview, :dashboard]
|
6
6
|
@@multi_gauges = [:timeseries_gauge, :toplist_gauge, :distribution_gauge]
|
7
7
|
|
8
8
|
def initialize(key, opts)
|
@@ -79,9 +79,9 @@ class FnordMetric::Namespace
|
|
79
79
|
@active_users_available
|
80
80
|
end
|
81
81
|
|
82
|
-
def dashboards(name=nil)
|
82
|
+
def dashboards(name=nil, opts = {})
|
83
83
|
return @dashboards unless name
|
84
|
-
dash = FnordMetric::Dashboard.new(:title => name)
|
84
|
+
dash = FnordMetric::Dashboard.new(opts.merge(:title => name))
|
85
85
|
@dashboards[dash.token.to_s] ||= dash
|
86
86
|
end
|
87
87
|
|
@@ -138,6 +138,10 @@ class FnordMetric::Namespace
|
|
138
138
|
dashboards(dashboard).add_widget(widget)
|
139
139
|
end
|
140
140
|
|
141
|
+
def opt_dashboard(dashboard, opts)
|
142
|
+
dashboards(dashboard, opts)
|
143
|
+
end
|
144
|
+
|
141
145
|
def build_widget(opts)
|
142
146
|
_gauges = [opts[:gauges]].flatten.map{ |g| @gauges.fetch(g) }
|
143
147
|
widget_klass = "FnordMetric::#{opts.fetch(:type).to_s.capitalize}Widget"
|
data/lib/fnordmetric/version.rb
CHANGED
data/lib/fnordmetric/web/app.rb
CHANGED
@@ -22,11 +22,11 @@ class FnordMetric::App < Sinatra::Base
|
|
22
22
|
include FnordMetric::AppHelpers
|
23
23
|
end
|
24
24
|
|
25
|
-
def initialize(opts)
|
26
|
-
@opts = opts
|
25
|
+
def initialize(opts = {})
|
26
|
+
@opts = FnordMetric.default_options(opts)
|
27
27
|
|
28
28
|
@namespaces = FnordMetric.namespaces
|
29
|
-
@redis = Redis.connect(:url => opts[:redis_url])
|
29
|
+
@redis = Redis.connect(:url => @opts[:redis_url])
|
30
30
|
|
31
31
|
super(nil)
|
32
32
|
end
|
data/readme.md
CHANGED
@@ -2,12 +2,11 @@ FnordMetric
|
|
2
2
|
===========
|
3
3
|
|
4
4
|
FnordMetric is a highly configurable (and pretty fast) realtime app/event
|
5
|
-
tracking thing based on ruby eventmachine and redis. You define your own
|
6
|
-
plotting and counting functions as ruby blocks!
|
5
|
+
tracking thing based on [ruby eventmachine](http://rubyeventmachine.com/) and [redis](http://redis.io/). You define your own
|
6
|
+
plotting and counting functions as ruby blocks! [See it in action! (RailsCasts)](http://railscasts.com/episodes/378-fnordmetric)
|
7
7
|
|
8
8
|
[ ![Build status - Travis-ci](https://secure.travis-ci.org/paulasmuth/fnordmetric.png) ](http://travis-ci.org/paulasmuth/fnordmetric)
|
9
9
|
|
10
|
-
|
11
10
|
[ ![Screenshot](https://github.com/paulasmuth/fnordmetric/raw/v1.0-alpha/doc/preview3.png) ](http://github.com/paulasmuth/fnordmetric)
|
12
11
|
|
13
12
|
|
@@ -26,8 +25,9 @@ FnordMetric.namespace :myapp do
|
|
26
25
|
# timeline+plot and punchcard
|
27
26
|
timeseries_gauge :unicorns_seen_per_hour,
|
28
27
|
:resolution => 5.minutes,
|
29
|
-
:title => "Unicorns
|
30
|
-
:punchcard => true
|
28
|
+
:title => "Unicorns seen per Hour",
|
29
|
+
:punchcard => true,
|
30
|
+
:series => [:num_unicorns]
|
31
31
|
|
32
32
|
# on every event like { _type: 'unicorn_seen' }
|
33
33
|
event(:unicorn_seen) do
|
@@ -64,11 +64,13 @@ Check out the docs in [the wiki](http://github.com/paulasmuth/fnordmetric/wiki)
|
|
64
64
|
+ [Blog: Monitor your Python App With FnordMetric](http://stephenholiday.com/articles/2012/monitor-your-python-app-with-fnordmetric/)
|
65
65
|
+ [Blog: FnordMetric and C (Blog/Howto)](http://johnmurray.io/log/2012/01/19/FnordMetrics-and-C%23.md)
|
66
66
|
+ [Blog: FnordMetric HowTo (russian)](http://www.pvsm.ru/ruby/2723)
|
67
|
+
+ [RailsCast: FnordMetric (378)](http://railscasts.com/episodes/378-fnordmetric)
|
67
68
|
|
68
69
|
|
69
70
|
### More Resources
|
70
71
|
|
71
|
-
+ [PHP API for FnordMetric (github.com/leemachin/fnordmetric-php-api)](https://github.com/leemachin/fnordmetric-php-api)
|
72
|
+
+ [PHP API for FnordMetric (use TCP) (github.com/leemachin/fnordmetric-php-api)](https://github.com/leemachin/fnordmetric-php-api)
|
73
|
+
+ [PHP API for FnordMetric directly into Redis (github.com/votintsev/fnordmetric-php-redis)](https://github.com/votintsev/fnordmetric-php-redis)
|
72
74
|
+ [Python API for FnordMetric (github.com/sholiday/pyfnordmetric)](https://github.com/sholiday/pyfnordmetric)
|
73
75
|
+ [Another Ruby API for FnordMetric](https://github.com/savonarola/fnordmetric-client)
|
74
76
|
+ [Beanstalk Monitoring with FnordMetric](https://github.com/sholiday/fnordstalk)
|
@@ -93,7 +95,7 @@ FnordMetric.namespace :myapp do
|
|
93
95
|
timeseries_gauge :number_of_signups,
|
94
96
|
:group => "My Group",
|
95
97
|
:title => "Number of Signups",
|
96
|
-
:key_nouns => ["
|
98
|
+
:key_nouns => ["Signup", "Signups"],
|
97
99
|
:series => [:via_twitter, :via_facebook],
|
98
100
|
:resolution => 2.minutes
|
99
101
|
|
@@ -139,7 +141,7 @@ FnordMetric.namespace :myapp do
|
|
139
141
|
|
140
142
|
gauge :pageviews_daily_unique, :tick => 1.day.to_i, :unique => true, :title => "Unique Visits (Daily)"
|
141
143
|
gauge :pageviews_hourly_unique, :tick => 1.hour.to_i, :unique => true, :title => "Unique Visits (Hourly)"
|
142
|
-
gauge :pageviews_monthly_unique, :tick => 40.days.to_i, :unique => true, :title => "Unique Visits (
|
144
|
+
gauge :pageviews_monthly_unique, :tick => 40.days.to_i, :unique => true, :title => "Unique Visits (Monthly)"
|
143
145
|
|
144
146
|
gauge :messages_sent, :tick => 1.day.to_i, :title => "Messages (sent)"
|
145
147
|
gauge :messages_read, :tick => 1.day.to_i, :title => "Messages (read)"
|
@@ -184,7 +186,7 @@ FnordMetric.namespace :myapp do
|
|
184
186
|
|
185
187
|
|
186
188
|
widget 'TechStats', {
|
187
|
-
:title => "Events
|
189
|
+
:title => "Events per Second",
|
188
190
|
:type => :timeline,
|
189
191
|
:width => 50,
|
190
192
|
:gauges => :events_per_second,
|
@@ -288,7 +290,7 @@ def start_example_data_generator
|
|
288
290
|
loop do
|
289
291
|
api.event(:_type => :signup, :referrer => (rand(3) == 1 ? :twitter : :facebook))
|
290
292
|
api.event(:_type => :search, :keyword => (%w(Donau Dampf Schiff Fahrts Kaptitaens Muetzen Staender).shuffle[0..2] * ""))
|
291
|
-
api.event(:_type => :user_demography, :age =>
|
293
|
+
api.event(:_type => :user_demography, :age => [*15..85].sample, :gender => (rand(2)==1 ? :female : :male) )
|
292
294
|
sleep (rand(10)/10.to_f)
|
293
295
|
end
|
294
296
|
end
|
data/spec/spec_helper.rb
CHANGED
data/web/fnordmetric.css
CHANGED
data/web/haml/app.haml
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
%script{:src => "/js/fnordmetric.pie_widget.js", :type => "text/javascript"}
|
17
17
|
%script{:src => "/js/fnordmetric.toplist_widget.js", :type => "text/javascript"}
|
18
18
|
%script{:src => "/js/fnordmetric.html_widget.js", :type => "text/javascript"}
|
19
|
-
%script{:src => "/js/fnordmetric.
|
19
|
+
%script{:src => "/js/fnordmetric.realtime_timeline_widget.js", :type => "text/javascript"}
|
20
20
|
%script{:src => "/js/fnordmetric.timeseries_widget.js", :type => "text/javascript"}
|
21
21
|
%script{:src => "/js/fnordmetric.overview_view.js", :type => "text/javascript"}
|
22
22
|
%script{:src => "/js/fnordmetric.gauge_view.js", :type => "text/javascript"}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fnordmetric
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: bson_ext
|
16
|
-
requirement: &20343380 !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 1.4.0
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: *20343380
|
25
14
|
- !ruby/object:Gem::Dependency
|
26
15
|
name: sinatra
|
27
|
-
requirement: &
|
16
|
+
requirement: &21192660 !ruby/object:Gem::Requirement
|
28
17
|
none: false
|
29
18
|
requirements:
|
30
19
|
- - ! '>='
|
@@ -32,10 +21,10 @@ dependencies:
|
|
32
21
|
version: 1.2.6
|
33
22
|
type: :runtime
|
34
23
|
prerelease: false
|
35
|
-
version_requirements: *
|
24
|
+
version_requirements: *21192660
|
36
25
|
- !ruby/object:Gem::Dependency
|
37
26
|
name: redis
|
38
|
-
requirement: &
|
27
|
+
requirement: &21190360 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
29
|
requirements:
|
41
30
|
- - ! '>='
|
@@ -43,10 +32,10 @@ dependencies:
|
|
43
32
|
version: 2.2.2
|
44
33
|
type: :runtime
|
45
34
|
prerelease: false
|
46
|
-
version_requirements: *
|
35
|
+
version_requirements: *21190360
|
47
36
|
- !ruby/object:Gem::Dependency
|
48
37
|
name: eventmachine
|
49
|
-
requirement: &
|
38
|
+
requirement: &21188420 !ruby/object:Gem::Requirement
|
50
39
|
none: false
|
51
40
|
requirements:
|
52
41
|
- - ! '>='
|
@@ -54,10 +43,10 @@ dependencies:
|
|
54
43
|
version: '0'
|
55
44
|
type: :runtime
|
56
45
|
prerelease: false
|
57
|
-
version_requirements: *
|
46
|
+
version_requirements: *21188420
|
58
47
|
- !ruby/object:Gem::Dependency
|
59
48
|
name: websocket-rack
|
60
|
-
requirement: &
|
49
|
+
requirement: &21185340 !ruby/object:Gem::Requirement
|
61
50
|
none: false
|
62
51
|
requirements:
|
63
52
|
- - =
|
@@ -65,10 +54,10 @@ dependencies:
|
|
65
54
|
version: 0.4.0
|
66
55
|
type: :runtime
|
67
56
|
prerelease: false
|
68
|
-
version_requirements: *
|
57
|
+
version_requirements: *21185340
|
69
58
|
- !ruby/object:Gem::Dependency
|
70
59
|
name: em-hiredis
|
71
|
-
requirement: &
|
60
|
+
requirement: &21196680 !ruby/object:Gem::Requirement
|
72
61
|
none: false
|
73
62
|
requirements:
|
74
63
|
- - =
|
@@ -76,10 +65,10 @@ dependencies:
|
|
76
65
|
version: 0.1.1
|
77
66
|
type: :runtime
|
78
67
|
prerelease: false
|
79
|
-
version_requirements: *
|
68
|
+
version_requirements: *21196680
|
80
69
|
- !ruby/object:Gem::Dependency
|
81
70
|
name: json
|
82
|
-
requirement: &
|
71
|
+
requirement: &21195740 !ruby/object:Gem::Requirement
|
83
72
|
none: false
|
84
73
|
requirements:
|
85
74
|
- - ! '>='
|
@@ -87,10 +76,10 @@ dependencies:
|
|
87
76
|
version: '0'
|
88
77
|
type: :runtime
|
89
78
|
prerelease: false
|
90
|
-
version_requirements: *
|
79
|
+
version_requirements: *21195740
|
91
80
|
- !ruby/object:Gem::Dependency
|
92
81
|
name: i18n
|
93
|
-
requirement: &
|
82
|
+
requirement: &21193800 !ruby/object:Gem::Requirement
|
94
83
|
none: false
|
95
84
|
requirements:
|
96
85
|
- - ! '>='
|
@@ -98,10 +87,10 @@ dependencies:
|
|
98
87
|
version: '0'
|
99
88
|
type: :runtime
|
100
89
|
prerelease: false
|
101
|
-
version_requirements: *
|
90
|
+
version_requirements: *21193800
|
102
91
|
- !ruby/object:Gem::Dependency
|
103
92
|
name: haml
|
104
|
-
requirement: &
|
93
|
+
requirement: &21208740 !ruby/object:Gem::Requirement
|
105
94
|
none: false
|
106
95
|
requirements:
|
107
96
|
- - ! '>='
|
@@ -109,10 +98,10 @@ dependencies:
|
|
109
98
|
version: '0'
|
110
99
|
type: :runtime
|
111
100
|
prerelease: false
|
112
|
-
version_requirements: *
|
101
|
+
version_requirements: *21208740
|
113
102
|
- !ruby/object:Gem::Dependency
|
114
103
|
name: rack
|
115
|
-
requirement: &
|
104
|
+
requirement: &21207680 !ruby/object:Gem::Requirement
|
116
105
|
none: false
|
117
106
|
requirements:
|
118
107
|
- - ! '>='
|
@@ -120,10 +109,10 @@ dependencies:
|
|
120
109
|
version: '0'
|
121
110
|
type: :runtime
|
122
111
|
prerelease: false
|
123
|
-
version_requirements: *
|
112
|
+
version_requirements: *21207680
|
124
113
|
- !ruby/object:Gem::Dependency
|
125
114
|
name: rack-test
|
126
|
-
requirement: &
|
115
|
+
requirement: &21205940 !ruby/object:Gem::Requirement
|
127
116
|
none: false
|
128
117
|
requirements:
|
129
118
|
- - ! '>='
|
@@ -131,10 +120,10 @@ dependencies:
|
|
131
120
|
version: '0'
|
132
121
|
type: :runtime
|
133
122
|
prerelease: false
|
134
|
-
version_requirements: *
|
123
|
+
version_requirements: *21205940
|
135
124
|
- !ruby/object:Gem::Dependency
|
136
125
|
name: yajl-ruby
|
137
|
-
requirement: &
|
126
|
+
requirement: &21217620 !ruby/object:Gem::Requirement
|
138
127
|
none: false
|
139
128
|
requirements:
|
140
129
|
- - ! '>='
|
@@ -142,10 +131,10 @@ dependencies:
|
|
142
131
|
version: '0'
|
143
132
|
type: :runtime
|
144
133
|
prerelease: false
|
145
|
-
version_requirements: *
|
134
|
+
version_requirements: *21217620
|
146
135
|
- !ruby/object:Gem::Dependency
|
147
136
|
name: thin
|
148
|
-
requirement: &
|
137
|
+
requirement: &21216440 !ruby/object:Gem::Requirement
|
149
138
|
none: false
|
150
139
|
requirements:
|
151
140
|
- - ~>
|
@@ -153,10 +142,10 @@ dependencies:
|
|
153
142
|
version: 1.3.0
|
154
143
|
type: :runtime
|
155
144
|
prerelease: false
|
156
|
-
version_requirements: *
|
145
|
+
version_requirements: *21216440
|
157
146
|
- !ruby/object:Gem::Dependency
|
158
147
|
name: activesupport
|
159
|
-
requirement: &
|
148
|
+
requirement: &21215840 !ruby/object:Gem::Requirement
|
160
149
|
none: false
|
161
150
|
requirements:
|
162
151
|
- - ! '>='
|
@@ -164,10 +153,10 @@ dependencies:
|
|
164
153
|
version: '0'
|
165
154
|
type: :runtime
|
166
155
|
prerelease: false
|
167
|
-
version_requirements: *
|
156
|
+
version_requirements: *21215840
|
168
157
|
- !ruby/object:Gem::Dependency
|
169
158
|
name: delorean
|
170
|
-
requirement: &
|
159
|
+
requirement: &21215020 !ruby/object:Gem::Requirement
|
171
160
|
none: false
|
172
161
|
requirements:
|
173
162
|
- - ! '>='
|
@@ -175,10 +164,10 @@ dependencies:
|
|
175
164
|
version: '0'
|
176
165
|
type: :development
|
177
166
|
prerelease: false
|
178
|
-
version_requirements: *
|
167
|
+
version_requirements: *21215020
|
179
168
|
- !ruby/object:Gem::Dependency
|
180
169
|
name: rspec
|
181
|
-
requirement: &
|
170
|
+
requirement: &21214160 !ruby/object:Gem::Requirement
|
182
171
|
none: false
|
183
172
|
requirements:
|
184
173
|
- - ~>
|
@@ -186,10 +175,10 @@ dependencies:
|
|
186
175
|
version: 2.8.0
|
187
176
|
type: :development
|
188
177
|
prerelease: false
|
189
|
-
version_requirements: *
|
178
|
+
version_requirements: *21214160
|
190
179
|
- !ruby/object:Gem::Dependency
|
191
180
|
name: shoulda
|
192
|
-
requirement: &
|
181
|
+
requirement: &21213400 !ruby/object:Gem::Requirement
|
193
182
|
none: false
|
194
183
|
requirements:
|
195
184
|
- - ! '>='
|
@@ -197,7 +186,7 @@ dependencies:
|
|
197
186
|
version: '0'
|
198
187
|
type: :development
|
199
188
|
prerelease: false
|
200
|
-
version_requirements: *
|
189
|
+
version_requirements: *21213400
|
201
190
|
description: FnordMetric is a Ruby Event-Tracking gem on steroids
|
202
191
|
email:
|
203
192
|
- paul@paulasmuth.com
|
@@ -258,7 +247,6 @@ files:
|
|
258
247
|
- lib/fnordmetric/worker.rb
|
259
248
|
- readme.md
|
260
249
|
- spec/api_spec.rb
|
261
|
-
- spec/app_spec.rb
|
262
250
|
- spec/context_spec.rb
|
263
251
|
- spec/dashboard_spec.rb
|
264
252
|
- spec/event_spec.rb
|
@@ -343,7 +331,6 @@ specification_version: 3
|
|
343
331
|
summary: FnordMetric is a Ruby Event-Tracking gem on steroids
|
344
332
|
test_files:
|
345
333
|
- spec/api_spec.rb
|
346
|
-
- spec/app_spec.rb
|
347
334
|
- spec/context_spec.rb
|
348
335
|
- spec/dashboard_spec.rb
|
349
336
|
- spec/event_spec.rb
|
data/spec/app_spec.rb
DELETED
@@ -1,486 +0,0 @@
|
|
1
|
-
require ::File.expand_path('../spec_helper.rb', __FILE__)
|
2
|
-
|
3
|
-
include Rack::Test::Methods
|
4
|
-
include FnordMetric
|
5
|
-
|
6
|
-
=begin
|
7
|
-
describe "app" do
|
8
|
-
|
9
|
-
before(:all) do
|
10
|
-
redis = Redis.new
|
11
|
-
@redis = RedisWrap.new(redis, false)
|
12
|
-
@opts = {
|
13
|
-
:redis_prefix => "fnordmetric",
|
14
|
-
:session_data_ttl => 120,
|
15
|
-
}
|
16
|
-
@now = Time.utc(1992,01,13,5,23,23).to_i
|
17
|
-
@namespace = Namespace.new(:foospace, @opts)
|
18
|
-
@redis_wrap = RedisWrap.new(@redis)
|
19
|
-
end
|
20
|
-
|
21
|
-
def app
|
22
|
-
@app ||= FnordMetric::App.new({
|
23
|
-
:foospace => proc{
|
24
|
-
widget 'Blubb', nil
|
25
|
-
|
26
|
-
gauge :testgauge, :tick => 1.hour.to_i, :progressive => true
|
27
|
-
gauge :test3gauge, :tick => 1.hour.to_i, :three_dimensional => true
|
28
|
-
|
29
|
-
}
|
30
|
-
}, @opts)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should redirect to the first namespace" do
|
34
|
-
get "/"
|
35
|
-
last_response.status.should == 302
|
36
|
-
last_response.location.should == "http://example.org/foospace"
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should render the namespace" do
|
40
|
-
get "/foospace"
|
41
|
-
last_response.status.should == 200
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should render the dashboards" do
|
45
|
-
@app ||= FnordMetric::App.new({
|
46
|
-
:foospace => proc{
|
47
|
-
widget 'Blubb', nil
|
48
|
-
}
|
49
|
-
}, @opts)
|
50
|
-
get "/foospace"
|
51
|
-
last_response.status.should == 200
|
52
|
-
last_response.body.should include("Blubb")
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should render the dashboards" do
|
56
|
-
@app ||= FnordMetric::App.new({
|
57
|
-
:foospace => proc{
|
58
|
-
widget 'Blubb', nil
|
59
|
-
widget 'Fnord', nil
|
60
|
-
}
|
61
|
-
}, @opts)
|
62
|
-
get "/foospace"
|
63
|
-
last_response.status.should == 200
|
64
|
-
last_response.body.should include("Blubb")
|
65
|
-
last_response.body.should include("Fnord")
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "sessions api" do
|
69
|
-
|
70
|
-
before(:each) do
|
71
|
-
@redis.keys("fnordmetric-foospace*").each { |k| @redis.del(k) }
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should render a list of all active sessions" do
|
75
|
-
@namespace.ready!(@redis_wrap).announce(
|
76
|
-
:_time => Time.now.to_i,
|
77
|
-
:_type => "foobar",
|
78
|
-
:_session => "sess213"
|
79
|
-
)
|
80
|
-
get "/foospace/sessions"
|
81
|
-
JSON.parse(last_response.body).should have_key("sessions")
|
82
|
-
JSON.parse(last_response.body)["sessions"].length.should == 1
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should render a list of all active sessions with timestamps" do
|
86
|
-
@namespace.ready!(@redis_wrap).announce(
|
87
|
-
:_time => @now-5,
|
88
|
-
:_type => "foobar",
|
89
|
-
:_session => "sess213"
|
90
|
-
)
|
91
|
-
get "/foospace/sessions"
|
92
|
-
sess = JSON.parse(last_response.body)["sessions"].first
|
93
|
-
sess["_updated_at"].should == (@now-5).to_s
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should render a list of all active sessions with usernames" do
|
97
|
-
@namespace.ready!(@redis_wrap).announce(
|
98
|
-
:_time => @now,
|
99
|
-
:_type => "_set_name",
|
100
|
-
:_session => "sess213",
|
101
|
-
:name => "Hans Peter"
|
102
|
-
)
|
103
|
-
get "/foospace/sessions"
|
104
|
-
sess = JSON.parse(last_response.body)["sessions"].first
|
105
|
-
sess["_name"].should == "Hans Peter"
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should render a list of all active sessions with user pictures" do
|
109
|
-
@namespace.ready!(@redis_wrap).announce(
|
110
|
-
:_time => @now,
|
111
|
-
:_type => "_set_picture",
|
112
|
-
:_session => "sess213",
|
113
|
-
:url => "http://myhost.com/mypic.jpg"
|
114
|
-
)
|
115
|
-
get "/foospace/sessions"
|
116
|
-
sess = JSON.parse(last_response.body)["sessions"].first
|
117
|
-
sess["_picture"].should == "http://myhost.com/mypic.jpg"
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should render a list of all active sessions with hashed keys" do
|
121
|
-
@namespace.ready!(@redis_wrap).announce(
|
122
|
-
:_time => @now-5,
|
123
|
-
:_type => "foobar",
|
124
|
-
:_session => "sess133"
|
125
|
-
)
|
126
|
-
get "/foospace/sessions"
|
127
|
-
sess = JSON.parse(last_response.body)["sessions"].first
|
128
|
-
sess["session_key"].should == Digest::MD5.hexdigest("sess133")
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should not render more than 100 sessions at once" do
|
132
|
-
123.times do |n|
|
133
|
-
@namespace.ready!(@redis_wrap).announce(
|
134
|
-
:_time => Time.now.to_i,
|
135
|
-
:_type => "foobar",
|
136
|
-
:_session => "sess213-#{n}"
|
137
|
-
)
|
138
|
-
end
|
139
|
-
get "/foospace/sessions"
|
140
|
-
JSON.parse(last_response.body).should have_key("sessions")
|
141
|
-
JSON.parse(last_response.body)["sessions"].length.should == 100
|
142
|
-
end
|
143
|
-
|
144
|
-
it "should render sessions ordered by last_updated_at" do
|
145
|
-
context = @namespace.ready!(@redis_wrap)
|
146
|
-
context.announce(
|
147
|
-
:_time => Time.now.to_i,
|
148
|
-
:_type => "foobar",
|
149
|
-
:_session => "sessfoo"
|
150
|
-
)
|
151
|
-
context.announce(
|
152
|
-
:_time => Time.now.to_i-23,
|
153
|
-
:_type => "foobar",
|
154
|
-
:_session => "sessbar"
|
155
|
-
)
|
156
|
-
context.announce(
|
157
|
-
:_time => Time.now.to_i-5,
|
158
|
-
:_type => "foobar",
|
159
|
-
:_session => "sessfnord"
|
160
|
-
)
|
161
|
-
get "/foospace/sessions"
|
162
|
-
sessions = JSON.parse(last_response.body)["sessions"]
|
163
|
-
sessions.length.should == 3
|
164
|
-
sessions[0]["session_key"].should == Digest::MD5.hexdigest("sessfoo")
|
165
|
-
sessions[1]["session_key"].should == Digest::MD5.hexdigest("sessfnord")
|
166
|
-
sessions[2]["session_key"].should == Digest::MD5.hexdigest("sessbar")
|
167
|
-
end
|
168
|
-
|
169
|
-
end
|
170
|
-
|
171
|
-
describe "events api: rendering events" do
|
172
|
-
|
173
|
-
before(:each) do
|
174
|
-
@redis.keys("fnordmetric-foospace*").each { |k| @redis.del(k) }
|
175
|
-
end
|
176
|
-
|
177
|
-
it "should render a list of all events" do
|
178
|
-
@namespace.ready!(@redis_wrap).announce(
|
179
|
-
:_eid => "sdkjgh9sd8f",
|
180
|
-
:_time => Time.now.to_i,
|
181
|
-
:_type => "foobar!!!"
|
182
|
-
)
|
183
|
-
get "/foospace/events"
|
184
|
-
JSON.parse(last_response.body).should have_key("events")
|
185
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
186
|
-
end
|
187
|
-
|
188
|
-
it "should render a list of all events including event-times" do
|
189
|
-
@namespace.ready!(@redis_wrap).announce(
|
190
|
-
:_eid => "sdkjgh9sd8f",
|
191
|
-
:_time => @now-23,
|
192
|
-
:_type => "foobar!!!"
|
193
|
-
)
|
194
|
-
get "/foospace/events"
|
195
|
-
JSON.parse(last_response.body).should have_key("events")
|
196
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
197
|
-
JSON.parse(last_response.body)["events"].first["_time"].to_i.should == @now-23
|
198
|
-
end
|
199
|
-
|
200
|
-
it "should render a list of all events including event-ids" do
|
201
|
-
@namespace.ready!(@redis_wrap).announce(
|
202
|
-
:_eid => "sdkjgh9sd8f",
|
203
|
-
:_time => Time.now.to_i,
|
204
|
-
:_type => "foobar!!!"
|
205
|
-
)
|
206
|
-
get "/foospace/events"
|
207
|
-
JSON.parse(last_response.body).should have_key("events")
|
208
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
209
|
-
JSON.parse(last_response.body)["events"].first["_eid"].should == "sdkjgh9sd8f"
|
210
|
-
end
|
211
|
-
|
212
|
-
|
213
|
-
it "should render a list of all events including event-types" do
|
214
|
-
create_event("sdkjgh9sd8f", {
|
215
|
-
:_eid => "sdkjgh9sd8f",
|
216
|
-
:_time => Time.now.to_i,
|
217
|
-
:_type => "foobar!!!"
|
218
|
-
})
|
219
|
-
get "/foospace/events"
|
220
|
-
JSON.parse(last_response.body).should have_key("events")
|
221
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
222
|
-
JSON.parse(last_response.body)["events"].first["_type"].should == "foobar!!!"
|
223
|
-
end
|
224
|
-
|
225
|
-
it "should render a list of all events including _session-data" do
|
226
|
-
create_event("65785678634", {
|
227
|
-
:_eid => "65785678634",
|
228
|
-
:_time => @now-23,
|
229
|
-
:_type => "foobar!!!",
|
230
|
-
:_session => "blubb123"
|
231
|
-
})
|
232
|
-
get "/foospace/events"
|
233
|
-
JSON.parse(last_response.body).should have_key("events")
|
234
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
235
|
-
JSON.parse(last_response.body)["events"].first["_session"].should == "blubb123"
|
236
|
-
end
|
237
|
-
|
238
|
-
it "should render a list of all events including _session-data" do
|
239
|
-
create_event("4234234634", {
|
240
|
-
:_eid => "4234234634",
|
241
|
-
:_time => @now-23,
|
242
|
-
:_type => "foobar!!!",
|
243
|
-
:_session => "blubb123",
|
244
|
-
:fnord => "yeah"
|
245
|
-
})
|
246
|
-
get "/foospace/events"
|
247
|
-
JSON.parse(last_response.body).should have_key("events")
|
248
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
249
|
-
blubb123_md5 = "e5fa475b26873af5ec6c77668f9975a5"
|
250
|
-
JSON.parse(last_response.body)["events"].first["_session_key"].should == blubb123_md5
|
251
|
-
end
|
252
|
-
|
253
|
-
it "should render a list of all events in the correct chronological order" do
|
254
|
-
create_event("daasdasd", {
|
255
|
-
:_eid => "daasdasd",
|
256
|
-
:_time => @now-23,
|
257
|
-
:_type => "foobar!!!"
|
258
|
-
})
|
259
|
-
create_event("345345345", {
|
260
|
-
:_eid => "345345345",
|
261
|
-
:_time => @now-5,
|
262
|
-
:_type => "foobar!!!"
|
263
|
-
})
|
264
|
-
create_event("sdygsygsdg", {
|
265
|
-
:_eid => "sdygsygsdg",
|
266
|
-
:_time => @now-16,
|
267
|
-
:_type => "foobar!!!"
|
268
|
-
})
|
269
|
-
get "/foospace/events"
|
270
|
-
JSON.parse(last_response.body).should have_key("events")
|
271
|
-
JSON.parse(last_response.body)["events"].length.should == 3
|
272
|
-
JSON.parse(last_response.body)["events"][0]["_eid"].should == "345345345"
|
273
|
-
JSON.parse(last_response.body)["events"][1]["_eid"].should == "sdygsygsdg"
|
274
|
-
JSON.parse(last_response.body)["events"][2]["_eid"].should == "daasdasd"
|
275
|
-
end
|
276
|
-
|
277
|
-
it "should not render more than 100 events at a time" do
|
278
|
-
120.times do |n|
|
279
|
-
create_event("sdygsygsdg-#{n}", {
|
280
|
-
:_eid => "sdygsygsdg-#{n}",
|
281
|
-
:_time => @now-16,
|
282
|
-
:_type => "foobar!!!"
|
283
|
-
})
|
284
|
-
end
|
285
|
-
get "/foospace/events"
|
286
|
-
JSON.parse(last_response.body).should have_key("events")
|
287
|
-
JSON.parse(last_response.body)["events"].length.should == 100
|
288
|
-
end
|
289
|
-
|
290
|
-
it "should render all events since a time, not including events at that exact time" do
|
291
|
-
create_event("daasdasd", {
|
292
|
-
:_eid => "daasdasd",
|
293
|
-
:_time => @now-23,
|
294
|
-
:_type => "foobar!!!"
|
295
|
-
})
|
296
|
-
create_event("345345345", {
|
297
|
-
:_eid => "345345345",
|
298
|
-
:_time => @now-5,
|
299
|
-
:_type => "foobar!!!"
|
300
|
-
})
|
301
|
-
create_event("sdygsygsdg", {
|
302
|
-
:_eid => "sdygsygsdg",
|
303
|
-
:_time => @now-16,
|
304
|
-
:_type => "foobar!!!"
|
305
|
-
})
|
306
|
-
get "/foospace/events?since=#{@now-24}"
|
307
|
-
JSON.parse(last_response.body)["events"].length.should == 3
|
308
|
-
get "/foospace/events?since=#{@now-17}"
|
309
|
-
JSON.parse(last_response.body)["events"].length.should == 2
|
310
|
-
get "/foospace/events?since=#{@now-16}"
|
311
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
312
|
-
get "/foospace/events?since=#{@now-2}"
|
313
|
-
JSON.parse(last_response.body)["events"].length.should == 0
|
314
|
-
end
|
315
|
-
|
316
|
-
it "should render all events for a single event type" do
|
317
|
-
@namespace.ready!(@redis_wrap).announce(
|
318
|
-
:_type => "fn0rd",
|
319
|
-
:_time => @now,
|
320
|
-
:_eid => "124234"
|
321
|
-
)
|
322
|
-
@namespace.ready!(@redis_wrap).announce(
|
323
|
-
:_type => "f00bar",
|
324
|
-
:_time => @now,
|
325
|
-
:_eid => "12235234"
|
326
|
-
)
|
327
|
-
@namespace.ready!(@redis_wrap).announce(
|
328
|
-
:_type => "fn0rd",
|
329
|
-
:_time => @now,
|
330
|
-
:_eid => "124234234"
|
331
|
-
)
|
332
|
-
get "/foospace/events?type=fn0rd"
|
333
|
-
JSON.parse(last_response.body)["events"].length.should == 2
|
334
|
-
get "/foospace/events?type=f00bar"
|
335
|
-
JSON.parse(last_response.body)["events"].length.should == 1
|
336
|
-
end
|
337
|
-
|
338
|
-
it "should render all events for a single session key" do
|
339
|
-
@namespace.ready!(@redis_wrap).announce(
|
340
|
-
:_time => @now,
|
341
|
-
:_session => "max_session",
|
342
|
-
:_eid => "124234"
|
343
|
-
)
|
344
|
-
@namespace.ready!(@redis_wrap).announce(
|
345
|
-
:_time => @now,
|
346
|
-
:_session => "kate_session",
|
347
|
-
:_eid => "12235234"
|
348
|
-
)
|
349
|
-
@namespace.ready!(@redis_wrap).announce(
|
350
|
-
:_time => @now,
|
351
|
-
:_session => "kate_session",
|
352
|
-
:_eid => "124234234"
|
353
|
-
)
|
354
|
-
@namespace.ready!(@redis_wrap).announce(
|
355
|
-
:_time => @now,
|
356
|
-
:_eid => "124234234"
|
357
|
-
)
|
358
|
-
max_session_key = Digest::MD5.hexdigest "max_session"
|
359
|
-
kate_session_key = Digest::MD5.hexdigest "kate_session"
|
360
|
-
|
361
|
-
get "/foospace/events?session_key=#{max_session_key}"
|
362
|
-
events = JSON.parse(last_response.body)["events"]
|
363
|
-
events.length.should == 1
|
364
|
-
|
365
|
-
get "/foospace/events?session_key=#{kate_session_key}"
|
366
|
-
events = JSON.parse(last_response.body)["events"]
|
367
|
-
events.length.should == 2
|
368
|
-
end
|
369
|
-
|
370
|
-
it "should render a list of event types" do
|
371
|
-
@namespace.ready!(@redis_wrap).announce(
|
372
|
-
:_type => "fn0rd",
|
373
|
-
:_time => @now,
|
374
|
-
:_eid => "124234"
|
375
|
-
)
|
376
|
-
@namespace.ready!(@redis_wrap).announce(
|
377
|
-
:_type => "f00bar",
|
378
|
-
:_time => @now,
|
379
|
-
:_eid => "12235234"
|
380
|
-
)
|
381
|
-
@namespace.ready!(@redis_wrap).announce(
|
382
|
-
:_type => "fn0rd",
|
383
|
-
:_time => @now,
|
384
|
-
:_eid => "124234234"
|
385
|
-
)
|
386
|
-
get "/foospace/event_types"
|
387
|
-
JSON.parse(last_response.body)["types"].length.should == 2
|
388
|
-
JSON.parse(last_response.body)["types"].should include("fn0rd")
|
389
|
-
JSON.parse(last_response.body)["types"].should include("f00bar")
|
390
|
-
end
|
391
|
-
|
392
|
-
it "should render all events for a single session"
|
393
|
-
|
394
|
-
it "should render all events for a single session since a unix timestamp"
|
395
|
-
|
396
|
-
it "should render all events for a single session, but not more than 100"
|
397
|
-
|
398
|
-
def create_event(event_id, event_data)
|
399
|
-
@redis_wrap.zadd(@namespace.key_prefix(:timeline), event_data.delete(:_time), event_id)
|
400
|
-
@redis_wrap.set("fnordmetric-event-#{event_id}", event_data.to_json)
|
401
|
-
end
|
402
|
-
|
403
|
-
end
|
404
|
-
|
405
|
-
describe "events api: creating events" do
|
406
|
-
|
407
|
-
it "should track an event without auth" do
|
408
|
-
post "/events", :_type => "myevent", :fnord => "foobar"
|
409
|
-
last_response.status.should == 200
|
410
|
-
end
|
411
|
-
|
412
|
-
it "should return 400 if no type is provided" do
|
413
|
-
pending("fix this")
|
414
|
-
post "/events", :fnord => "foobar"
|
415
|
-
last_response.status.should == 400
|
416
|
-
last_response.body.should == "please specify the event_type"
|
417
|
-
end
|
418
|
-
|
419
|
-
end
|
420
|
-
|
421
|
-
describe "gauges api" do
|
422
|
-
|
423
|
-
before(:all) do
|
424
|
-
@redis.keys("fnordmetric-foospace*").each { |k| @redis.del(k) }
|
425
|
-
gauge_key = "fnordmetric-foospace-gauge-testgauge-#{1.hour.to_i}"
|
426
|
-
@redis.hset(gauge_key, 1323687600, "18")
|
427
|
-
@redis.hset(gauge_key, 1323691200, "23")
|
428
|
-
end
|
429
|
-
|
430
|
-
it "should return the right answer for: /metric/:name?at=timestamp" do
|
431
|
-
get "/foospace/gauge/testgauge?at=1323691205"
|
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" do
|
436
|
-
get "/foospace/gauge/testgauge?at=1323691200"
|
437
|
-
JSON.parse(last_response.body).first.last.to_i.should == 23
|
438
|
-
end
|
439
|
-
|
440
|
-
it "should return the right answer for: /metric/:name?at=timestamp-timstamp" do
|
441
|
-
get "/foospace/gauge/testgauge?at=1323691200-1323691205"
|
442
|
-
JSON.parse(last_response.body).first.last.to_i.should == 18
|
443
|
-
end
|
444
|
-
|
445
|
-
it "should return the right answer for: /metric/:name?at=timestamp-timstamp" do
|
446
|
-
get "/foospace/gauge/testgauge?at=1323691201-1323695205"
|
447
|
-
JSON.parse(last_response.body).keys.length
|
448
|
-
end
|
449
|
-
|
450
|
-
it "should return the right answer for: /metric/:name?at=timestamp-timstamp" do
|
451
|
-
get "/foospace/gauge/testgauge?at=1323691199-1323701201"
|
452
|
-
JSON.parse(last_response.body).keys.length.should == 4
|
453
|
-
JSON.parse(last_response.body)["1323687600"].to_i.should == 18
|
454
|
-
JSON.parse(last_response.body)["1323691200"].to_i.should == 23
|
455
|
-
end
|
456
|
-
|
457
|
-
it "should return the right answer for: /metric/:name?at=timestamp-timstamp&sum=true" do
|
458
|
-
get "/foospace/gauge/testgauge?at=1323691199-1323701201&sum=true"
|
459
|
-
JSON.parse(last_response.body).keys.length.should == 1
|
460
|
-
JSON.parse(last_response.body)["sum"].to_i.should == 18+23
|
461
|
-
end
|
462
|
-
|
463
|
-
end
|
464
|
-
|
465
|
-
describe "three-dim gauges api" do
|
466
|
-
|
467
|
-
before(:all) do
|
468
|
-
@redis.keys("fnordmetric-foospace*").each { |k| @redis.del(k) }
|
469
|
-
gauge_key = "fnordmetric-foospace-gauge-test3gauge-#{1.hour.to_i}-1323691200"
|
470
|
-
@redis.zadd(gauge_key, 18, "fnordyblubb")
|
471
|
-
@redis.zadd(gauge_key, 23, "uberfoo")
|
472
|
-
@redis.set(gauge_key+"-count", 41)
|
473
|
-
end
|
474
|
-
|
475
|
-
it "should return the right answer for: /metric/:name?at=timestamp" do
|
476
|
-
get "/foospace/gauge/test3gauge?at=1323691205"
|
477
|
-
JSON.parse(last_response.body)["count"].to_i.should == 41
|
478
|
-
JSON.parse(last_response.body)["values"].length.should == 2
|
479
|
-
JSON.parse(last_response.body)["values"][0].should == ["uberfoo", "23"]
|
480
|
-
JSON.parse(last_response.body)["values"][1].should == ["fnordyblubb", "18"]
|
481
|
-
end
|
482
|
-
|
483
|
-
end
|
484
|
-
|
485
|
-
end
|
486
|
-
=end
|