fnordmetric 1.0.0 → 1.0.1
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.
- 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
|
[  ](http://travis-ci.org/paulasmuth/fnordmetric)
|
9
9
|
|
10
|
-
|
11
10
|
[  ](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
|