fnordmetric 0.7.5 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/V1.0-ROADMAP +97 -0
- data/doc/full_example.rb +95 -511
- data/doc/legacy_example.rb +640 -0
- data/doc/minimal_example.rb +26 -0
- data/doc/preview3.png +0 -0
- data/fnordmetric.gemspec +3 -2
- data/lib/fnordmetric/acceptors/acceptor.rb +29 -0
- data/lib/fnordmetric/{inbound_stream.rb → acceptors/tcp_acceptor.rb} +8 -5
- data/lib/fnordmetric/{inbound_datagram.rb → acceptors/udp_acceptor.rb} +9 -8
- data/lib/fnordmetric/api.rb +2 -2
- data/lib/fnordmetric/context.rb +37 -18
- data/lib/fnordmetric/defaults.rb +9 -0
- data/lib/fnordmetric/ext.rb +72 -0
- data/lib/fnordmetric/gauge.rb +37 -10
- data/lib/fnordmetric/gauge_calculations.rb +38 -16
- data/lib/fnordmetric/gauge_modifiers.rb +67 -0
- data/lib/fnordmetric/gauge_rendering.rb +40 -0
- data/lib/fnordmetric/gauge_validations.rb +15 -0
- data/lib/fnordmetric/gauges/distribution_gauge.rb +85 -0
- data/lib/fnordmetric/gauges/timeseries_gauge.rb +143 -0
- data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
- data/lib/fnordmetric/histogram.rb +57 -0
- data/lib/fnordmetric/logger.rb +42 -36
- data/lib/fnordmetric/namespace.rb +47 -23
- data/lib/fnordmetric/session.rb +6 -6
- data/lib/fnordmetric/standalone.rb +15 -35
- data/lib/fnordmetric/timeseries.rb +79 -0
- data/lib/fnordmetric/toplist.rb +61 -0
- data/lib/fnordmetric/version.rb +1 -1
- data/lib/fnordmetric/web/app.rb +122 -0
- data/lib/fnordmetric/web/app_helpers.rb +42 -0
- data/lib/fnordmetric/{dashboard.rb → web/dashboard.rb} +4 -0
- data/lib/fnordmetric/{event.rb → web/event.rb} +7 -2
- data/lib/fnordmetric/web/reactor.rb +87 -0
- data/lib/fnordmetric/web/web.rb +53 -0
- data/lib/fnordmetric/web/websocket.rb +38 -0
- data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
- data/lib/fnordmetric/{html_widget.rb → widgets/html_widget.rb} +0 -0
- data/lib/fnordmetric/widgets/numbers_widget.rb +56 -0
- data/lib/fnordmetric/{pie_widget.rb → widgets/pie_widget.rb} +0 -0
- data/lib/fnordmetric/widgets/timeseries_widget.rb +55 -0
- data/lib/fnordmetric/widgets/toplist_widget.rb +64 -0
- data/lib/fnordmetric/worker.rb +26 -25
- data/lib/fnordmetric.rb +85 -115
- data/readme.md +362 -0
- data/spec/gauge_like_shared.rb +54 -0
- data/spec/gauge_spec.rb +2 -36
- data/spec/namespace_spec.rb +25 -11
- data/spec/spec_helper.rb +4 -0
- data/spec/{inbound_stream_spec.rb → tcp_acceptor_spec.rb} +3 -3
- data/spec/timeseries_gauge_spec.rb +54 -0
- data/spec/{inbound_datagram_spec.rb → udp_acceptor_spec.rb} +3 -3
- data/web/fnordmetric.css +786 -0
- data/web/haml/app.haml +38 -0
- data/web/haml/distribution_gauge.haml +118 -0
- data/web/haml/timeseries_gauge.haml +80 -0
- data/web/haml/toplist_gauge.haml +194 -0
- data/web/img/head.png +0 -0
- data/web/img/list.png +0 -0
- data/web/img/list_active.png +0 -0
- data/web/img/list_hover.png +0 -0
- data/web/img/loader_white.gif +0 -0
- data/web/img/navbar.png +0 -0
- data/web/img/navbar_btn.png +0 -0
- data/web/img/picto_gauge.png +0 -0
- data/web/js/fnordmetric.bars_widget.js +178 -0
- data/web/js/fnordmetric.dashboard_view.js +99 -0
- data/web/js/fnordmetric.gauge_view.js +260 -0
- data/web/js/fnordmetric.html_widget.js +21 -0
- data/web/js/fnordmetric.js +255 -0
- data/web/js/fnordmetric.numbers_widget.js +121 -0
- data/web/js/fnordmetric.overview_view.js +35 -0
- data/web/js/fnordmetric.pie_widget.js +118 -0
- data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
- data/web/js/fnordmetric.session_view.js +343 -0
- data/web/js/fnordmetric.timeline_widget.js +333 -0
- data/web/js/fnordmetric.timeseries_widget.js +388 -0
- data/web/js/fnordmetric.toplist_widget.js +112 -0
- data/web/js/fnordmetric.ui.js +91 -0
- data/web/js/fnordmetric.util.js +244 -0
- data/{pub → web}/loader.gif +0 -0
- data/web/vendor/d3.v2.js +9382 -0
- data/web/vendor/font-awesome/css/font-awesome.css +239 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.svg +175 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.svgz +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
- data/web/vendor/jquery-1.6.2.min.js +18 -0
- data/web/vendor/jquery-ui.min.js +413 -0
- data/web/vendor/jquery.maskedinput.js +252 -0
- data/web/vendor/rickshaw.css +286 -0
- data/web/vendor/rickshaw.fnordmetric.js +2676 -0
- metadata +129 -79
- data/Gemfile +0 -6
- data/README.md +0 -404
- data/Rakefile +0 -6
- data/doc/version +0 -1
- data/haml/app.haml +0 -79
- data/haml/widget.haml +0 -9
- data/lib/fnordmetric/app.rb +0 -163
- data/lib/fnordmetric/average_metric.rb +0 -7
- data/lib/fnordmetric/bars_widget.rb +0 -26
- data/lib/fnordmetric/combine_metric.rb +0 -7
- data/lib/fnordmetric/count_metric.rb +0 -13
- data/lib/fnordmetric/funnel_widget.rb +0 -2
- data/lib/fnordmetric/metric.rb +0 -80
- data/lib/fnordmetric/metric_api.rb +0 -37
- data/lib/fnordmetric/numbers_widget.rb +0 -26
- data/lib/fnordmetric/report.rb +0 -29
- data/lib/fnordmetric/sum_metric.rb +0 -13
- data/lib/fnordmetric/timeline_widget.rb +0 -30
- data/lib/fnordmetric/toplist_widget.rb +0 -25
- data/pub/fnordmetric.css +0 -145
- data/pub/fnordmetric.js +0 -1179
- data/pub/vendor/highcharts.js +0 -170
- data/pub/vendor/jquery-1.6.1.min.js +0 -18
data/readme.md
ADDED
@@ -0,0 +1,362 @@
|
|
1
|
+
FnordMetric
|
2
|
+
===========
|
3
|
+
|
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!
|
7
|
+
|
8
|
+
[ ![Build status - Travis-ci](https://secure.travis-ci.org/paulasmuth/fnordmetric.png) ](http://travis-ci.org/paulasmuth/fnordmetric)
|
9
|
+
|
10
|
+
|
11
|
+
[ ![Screenshot](https://github.com/paulasmuth/fnordmetric/raw/v1.0-alpha/doc/preview3.png) ](http://github.com/paulasmuth/fnordmetric)
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
Getting Started
|
16
|
+
---------------
|
17
|
+
|
18
|
+
Simple Example: this will listen for json-events with `type=unicorn_seen`
|
19
|
+
and render a timeline-plot showing the number of received events per hour.
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require "fnordmetric"
|
23
|
+
|
24
|
+
FnordMetric.namespace :myapp do
|
25
|
+
|
26
|
+
# timeline+plot and punchcard
|
27
|
+
timeseries_gauge :unicorns_seen_per_hour,
|
28
|
+
:resolution => 5.minutes,
|
29
|
+
:title => "Unicorns seenper Hour",
|
30
|
+
:punchcard => true
|
31
|
+
|
32
|
+
# on every event like { _type: 'unicorn_seen' }
|
33
|
+
event(:unicorn_seen) do
|
34
|
+
# increment the unicorns_seen_per_hour gauge by 1
|
35
|
+
incr :unicorns_seen_per_hour
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
FnordMetric.standalone
|
41
|
+
```
|
42
|
+
|
43
|
+
This is the easiest way to submit an event:
|
44
|
+
|
45
|
+
echo '{"_type": "unicorn_seen"}' | nc localhost 1337
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
Installation
|
50
|
+
------------
|
51
|
+
|
52
|
+
gem install fnordmetric
|
53
|
+
|
54
|
+
or in your Gemfile:
|
55
|
+
|
56
|
+
gem 'fnordmetric', '>= 0.9.6'
|
57
|
+
|
58
|
+
|
59
|
+
Documentation
|
60
|
+
-------------
|
61
|
+
|
62
|
+
Check out the docs in [the wiki](http://github.com/paulasmuth/fnordmetric/wiki) or have a look at `doc/full_example.rb`. There are also a few blogs/howtos:
|
63
|
+
|
64
|
+
+ [Blog: Monitor your Python App With FnordMetric](http://stephenholiday.com/articles/2012/monitor-your-python-app-with-fnordmetric/)
|
65
|
+
+ [Blog: FnordMetric and C (Blog/Howto)](http://johnmurray.io/log/2012/01/19/FnordMetrics-and-C%23.md)
|
66
|
+
+ [Blog: FnordMetric HowTo (russian)](http://www.pvsm.ru/ruby/2723)
|
67
|
+
|
68
|
+
|
69
|
+
### More Resources
|
70
|
+
|
71
|
+
+ [PHP API for FnordMetric (github.com/leemachin/fnordmetric-php-api)](https://github.com/leemachin/fnordmetric-php-api)
|
72
|
+
+ [Python API for FnordMetric (github.com/sholiday/pyfnordmetric)](https://github.com/sholiday/pyfnordmetric)
|
73
|
+
+ [Another Ruby API for FnordMetric](https://github.com/savonarola/fnordmetric-client)
|
74
|
+
+ [Beanstalk Monitoring with FnordMetric](https://github.com/sholiday/fnordstalk)
|
75
|
+
+ [The "FnordMetric" google group](http://groups.google.com/group/fnordmetric)
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
Full Example
|
80
|
+
------------
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
require "fnordmetric"
|
84
|
+
|
85
|
+
FnordMetric.namespace :myapp do
|
86
|
+
|
87
|
+
hide_overview
|
88
|
+
hide_active_users
|
89
|
+
|
90
|
+
|
91
|
+
# NEW DSL (v1.0 upwards)
|
92
|
+
|
93
|
+
timeseries_gauge :number_of_signups,
|
94
|
+
:group => "My Group",
|
95
|
+
:title => "Number of Signups",
|
96
|
+
:key_nouns => ["Singup", "Signups"],
|
97
|
+
:series => [:via_twitter, :via_facebook],
|
98
|
+
:resolution => 2.minutes
|
99
|
+
|
100
|
+
|
101
|
+
distribution_gauge :user_age_distribution,
|
102
|
+
:title => "User Age Distribution",
|
103
|
+
:value_ranges => [(10..16), (16..20), (20..24), (24..28), (28..32), (32..36), (40..44), (44..48),
|
104
|
+
(48..52), (52..56), (60..64), (64..68), (68..72), (72..76), (70..74), (74..78)],
|
105
|
+
:value_scale => 1,
|
106
|
+
:resolution => 2.minutes
|
107
|
+
|
108
|
+
|
109
|
+
toplist_gauge :popular_keywords,
|
110
|
+
:title => "Popular Keywords",
|
111
|
+
:resolution => 2.minutes
|
112
|
+
|
113
|
+
|
114
|
+
event :search do
|
115
|
+
observe :popular_keywords, data[:keyword]
|
116
|
+
end
|
117
|
+
|
118
|
+
event :signup do
|
119
|
+
if data[:referrer] == "facebook"
|
120
|
+
incr :number_of_signups, :via_facebook, 1
|
121
|
+
elsif data[:referrer] == "twitter"
|
122
|
+
incr :number_of_signups, :via_twitter, 1
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
# OLD DSL (will be supported forever, allows finer-grained control)
|
128
|
+
|
129
|
+
gauge :events_per_hour, :tick => 1.hour
|
130
|
+
gauge :events_per_second, :tick => 1.second
|
131
|
+
gauge :events_per_minute, :tick => 1.minute
|
132
|
+
|
133
|
+
event :"*" do
|
134
|
+
incr :events_per_hour
|
135
|
+
incr :events_per_minute
|
136
|
+
incr :events_per_second
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
gauge :pageviews_daily_unique, :tick => 1.day.to_i, :unique => true, :title => "Unique Visits (Daily)"
|
141
|
+
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 (Month)"
|
143
|
+
|
144
|
+
gauge :messages_sent, :tick => 1.day.to_i, :title => "Messages (sent)"
|
145
|
+
gauge :messages_read, :tick => 1.day.to_i, :title => "Messages (read)"
|
146
|
+
gauge :winks_sent, :tick => 1.day.to_i, :title => "Winks sent"
|
147
|
+
|
148
|
+
gauge :pageviews_per_url_daily,
|
149
|
+
:tick => 1.day.to_i,
|
150
|
+
:title => "Daily Pageviews per URL",
|
151
|
+
:three_dimensional => true
|
152
|
+
|
153
|
+
gauge :pageviews_per_url_monthly,
|
154
|
+
:tick => 30.days.to_i,
|
155
|
+
:title => "Monthly Pageviews per URL",
|
156
|
+
:three_dimensional => true
|
157
|
+
|
158
|
+
event :_pageview do
|
159
|
+
incr :pageviews_daily_unique
|
160
|
+
incr :pageviews_hourly_unique
|
161
|
+
incr :pageviews_monthly_unique
|
162
|
+
incr_field :pageviews_per_url_daily, data[:url]
|
163
|
+
incr_field :pageviews_per_url_monthly, data[:url]
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
widget 'TechStats', {
|
168
|
+
:title => "Events per Minute",
|
169
|
+
:type => :timeline,
|
170
|
+
:width => 100,
|
171
|
+
:gauges => :events_per_minute,
|
172
|
+
:include_current => true,
|
173
|
+
:autoupdate => 30
|
174
|
+
}
|
175
|
+
|
176
|
+
widget 'TechStats', {
|
177
|
+
:title => "Events per Hour",
|
178
|
+
:type => :timeline,
|
179
|
+
:width => 50,
|
180
|
+
:gauges => :events_per_hour,
|
181
|
+
:include_current => true,
|
182
|
+
:autoupdate => 30
|
183
|
+
}
|
184
|
+
|
185
|
+
|
186
|
+
widget 'TechStats', {
|
187
|
+
:title => "Events/Second",
|
188
|
+
:type => :timeline,
|
189
|
+
:width => 50,
|
190
|
+
:gauges => :events_per_second,
|
191
|
+
:include_current => true,
|
192
|
+
:plot_style => :areaspline,
|
193
|
+
:autoupdate => 1
|
194
|
+
}
|
195
|
+
|
196
|
+
widget 'TechStats', {
|
197
|
+
:title => "Events Numbers",
|
198
|
+
:type => :numbers,
|
199
|
+
:width => 100,
|
200
|
+
:gauges => [:events_per_second, :events_per_minute, :events_per_hour],
|
201
|
+
:offsets => [1,3,5,10],
|
202
|
+
:autoupdate => 1
|
203
|
+
}
|
204
|
+
|
205
|
+
|
206
|
+
gauge :age_distribution_female_monthly,
|
207
|
+
:tick => 1.month.to_i,
|
208
|
+
:three_dimensional => true,
|
209
|
+
:title => "Age Distribution (female) monthly"
|
210
|
+
|
211
|
+
gauge :age_distribution_male_monthly,
|
212
|
+
:tick => 1.month.to_i,
|
213
|
+
:three_dimensional => true,
|
214
|
+
:title => "Age Distribution (male) monthly"
|
215
|
+
|
216
|
+
gauge :age_distribution_female_daily,
|
217
|
+
:tick => 1.day.to_i,
|
218
|
+
:three_dimensional => true,
|
219
|
+
:title => "Age Distribution (female) daily"
|
220
|
+
|
221
|
+
gauge :age_distribution_male_daily,
|
222
|
+
:tick => 1.day.to_i,
|
223
|
+
:three_dimensional => true,
|
224
|
+
:title => "Age Distribution (male) daily"
|
225
|
+
|
226
|
+
|
227
|
+
widget 'Demography', {
|
228
|
+
:title => "Age Distribution: Female Users (Monthly)",
|
229
|
+
:type => :bars,
|
230
|
+
:width => 50,
|
231
|
+
:autoupdate => 5,
|
232
|
+
:order_by => :field,
|
233
|
+
:gauges => [ :age_distribution_female_monthly ]
|
234
|
+
}
|
235
|
+
|
236
|
+
widget 'Demography', {
|
237
|
+
:title => "Age Distribution: Male Users (Monthly)",
|
238
|
+
:type => :bars,
|
239
|
+
:width => 50,
|
240
|
+
:autoupdate => 5,
|
241
|
+
:order_by => :field,
|
242
|
+
:gauges => [ :age_distribution_male_monthly ]
|
243
|
+
}
|
244
|
+
|
245
|
+
|
246
|
+
widget 'Demography', {
|
247
|
+
:title => "Age Distribution: Female Users",
|
248
|
+
:type => :toplist,
|
249
|
+
:width => 50,
|
250
|
+
:autoupdate => 5,
|
251
|
+
:gauges => [ :age_distribution_female_monthly, :age_distribution_female_daily ]
|
252
|
+
}
|
253
|
+
|
254
|
+
widget 'Demography', {
|
255
|
+
:title => "Age Distribution: Male Users",
|
256
|
+
:type => :toplist,
|
257
|
+
:width => 50,
|
258
|
+
:autoupdate => 5,
|
259
|
+
:gauges => [ :age_distribution_male_monthly, :age_distribution_male_daily ]
|
260
|
+
}
|
261
|
+
|
262
|
+
event "user_demography" do
|
263
|
+
if data[:gender] == "female"
|
264
|
+
incr_field(:age_distribution_female_monthly, data[:age], 1)
|
265
|
+
incr_field(:age_distribution_female_daily, data[:age], 1)
|
266
|
+
end
|
267
|
+
if data[:gender] == "male"
|
268
|
+
incr_field(:age_distribution_male_monthly, data[:age], 1)
|
269
|
+
incr_field(:age_distribution_male_daily, data[:age], 1)
|
270
|
+
end
|
271
|
+
observe :user_age_distribution, data[:age]
|
272
|
+
end
|
273
|
+
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
FnordMetric.options = {
|
278
|
+
:event_queue_ttl => 10, # all data that isn't processed within 10s is discarded to prevent memory overruns
|
279
|
+
:event_data_ttl => 10,
|
280
|
+
:session_data_ttl => 1, # we don't care about session data for now
|
281
|
+
:redis_prefix => "fnordmetric"
|
282
|
+
}
|
283
|
+
|
284
|
+
def start_example_data_generator
|
285
|
+
|
286
|
+
api = FnordMetric::API.new
|
287
|
+
Thread.new do
|
288
|
+
loop do
|
289
|
+
api.event(:_type => :signup, :referrer => (rand(3) == 1 ? :twitter : :facebook))
|
290
|
+
api.event(:_type => :search, :keyword => (%w(Donau Dampf Schiff Fahrts Kaptitaens Muetzen Staender).shuffle[0..2] * ""))
|
291
|
+
api.event(:_type => :user_demography, :age => rand(15..85), :gender => (rand(2)==1 ? :female : :male) )
|
292
|
+
sleep (rand(10)/10.to_f)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
start_example_data_generator
|
299
|
+
|
300
|
+
FnordMetric::Web.new(:port => 4242)
|
301
|
+
FnordMetric::Acceptor.new(:protocol => :tcp, :port => 2323)
|
302
|
+
FnordMetric::Worker.new
|
303
|
+
FnordMetric.run
|
304
|
+
```
|
305
|
+
|
306
|
+
|
307
|
+
|
308
|
+
|
309
|
+
Contributors
|
310
|
+
------------
|
311
|
+
|
312
|
+
http://github.com/paulasmuth/fnordmetric/graphs/contributors
|
313
|
+
|
314
|
+
(One patch or more)
|
315
|
+
|
316
|
+
+ Simon Menke (http://github.com/fd)
|
317
|
+
+ Bruno Michel (http://github.com/nono)
|
318
|
+
+ Marco Borromeo (http://github.com/mborromeo)
|
319
|
+
+ Leo Lou (http://github.com/l4u)
|
320
|
+
+ Andy Lindeman (http://github.com/alindeman)
|
321
|
+
+ Jurriaan Pruis (http://github.com/jurriaan)
|
322
|
+
+ Kacper Bielecki (http://github.com/kazjote)
|
323
|
+
+ John Murray (http://github.com/JohnMurray)
|
324
|
+
+ Lars Gierth (http://github.com/lgierth)
|
325
|
+
+ Ross Kaffenberger (http://github.com/rossta)
|
326
|
+
+ Kunal Modi (http://github.com/kunalmodi)
|
327
|
+
+ Michael Fairchild (http://github.com/fairchild)
|
328
|
+
+ James Cox (http://github.com/imajes)
|
329
|
+
+ Pieter Noordhuis (http://github.com/pietern)
|
330
|
+
|
331
|
+
To contribute, please fork this repository, make your changes and run the
|
332
|
+
specs, commit them to your github repository and send me a pull request.
|
333
|
+
Need help, head on over to our [Google Groups][1] page to discuss any ideas
|
334
|
+
that you might have.
|
335
|
+
|
336
|
+
|
337
|
+
License
|
338
|
+
-------
|
339
|
+
|
340
|
+
Copyright (c) 2011 Paul Asmuth
|
341
|
+
|
342
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
343
|
+
a copy of this software and associated documentation files (the
|
344
|
+
"Software"), to use, copy and modify copies of the Software, subject
|
345
|
+
to the following conditions:
|
346
|
+
|
347
|
+
The above copyright notice and this permission notice shall be
|
348
|
+
included in all copies or substantial portions of the Software.
|
349
|
+
|
350
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
351
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
352
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
353
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
354
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
355
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
356
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
357
|
+
|
358
|
+
|
359
|
+
[1]: http://groups.google.com/group/fnordmetric
|
360
|
+
[2]: http://www.screenr.com/KiJs
|
361
|
+
[3]: https://secure.travis-ci.org/paulasmuth/fnordmetric.png
|
362
|
+
[4]: http://travis-ci.org/paulasmuth/fnordmetric
|
@@ -0,0 +1,54 @@
|
|
1
|
+
share_examples_for FnordMetric::GaugeLike do
|
2
|
+
|
3
|
+
it "should remember its own name" do
|
4
|
+
gauge = @gauge_klass.new({:key_prefix => "foo", :key => "fnordgauge", :ticks => [1.hour], :series => [:fu]})
|
5
|
+
gauge.name.should == "fnordgauge"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should return its key as title if none specified" do
|
9
|
+
gauge = @gauge_klass.new({:key_prefix => "foo", :key => "fnordgauge", :ticks => [1.hour], :series => [:fu]})
|
10
|
+
gauge.title.should == "fnordgauge"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return its title as title if none specified" do
|
14
|
+
gauge = @gauge_klass.new({:key_prefix => "foo", :key => "fnordgauge", :ticks => [1.hour], :title => "Fnord Gauge", :series => [:fu]})
|
15
|
+
gauge.title.should == "Fnord Gauge"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise an error when initialize without key" do
|
19
|
+
lambda{
|
20
|
+
@gauge_klass.new({:key_prefix => "foo", :ticks => [1.hour], :series => [:fu]})
|
21
|
+
}.should raise_error(key_error_klass)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise an error when initialize without key_prefix" do
|
25
|
+
lambda{
|
26
|
+
@gauge_klass.new({:key => "foo", :ticks => [1.hour], :series => [:fu]})
|
27
|
+
}.should raise_error(key_error_klass)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should generate the correct key without append" do
|
31
|
+
gauge = @gauge_klass.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge", :tick => 23, :ticks => [1.hour], :series => [ :fnord ]})
|
32
|
+
if [@gauge_klass, @gauge_klass.superclass].include?(FnordMetric::MultiGauge)
|
33
|
+
gauge.key.should == "fnordmetrics-myns-multigauge-mygauge"
|
34
|
+
else
|
35
|
+
gauge.key.should == "fnordmetrics-myns-gauge-mygauge-23"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should generate the correct key with append" do
|
40
|
+
gauge = @gauge_klass.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge", :tick => 23, :ticks => [1.hour], :series => [ :fnord ]})
|
41
|
+
if [@gauge_klass, @gauge_klass.superclass].include?(FnordMetric::MultiGauge)
|
42
|
+
gauge.key(:fnord).should == "fnordmetrics-myns-multigauge-mygauge-fnord"
|
43
|
+
else
|
44
|
+
gauge.key(:fnord).should == "fnordmetrics-myns-gauge-mygauge-23-fnord"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should add redis" do
|
49
|
+
gauge = @gauge_klass.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge", :tick => 23, :ticks => [1.hour], :series => [ :fnord ]})
|
50
|
+
gauge.add_redis("FNORD")
|
51
|
+
gauge.instance_variable_get(:"@opts")[:redis].should == "FNORD"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/spec/gauge_spec.rb
CHANGED
@@ -6,48 +6,14 @@ describe FnordMetric::Gauge do
|
|
6
6
|
@now = Time.utc(1992,01,13,5,23,23).to_i
|
7
7
|
@redis = Redis.new
|
8
8
|
@redis_wrap = RedisWrap.new(@redis, false)
|
9
|
+
@gauge_klass = FnordMetric::Gauge
|
9
10
|
end
|
10
11
|
|
11
12
|
before(:each) do
|
12
13
|
@redis.keys("fnordmetric-myns*").each { |k| @redis.del(k) }
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
gauge = FnordMetric::Gauge.new({:key_prefix => "foo", :key => "fnordgauge"})
|
17
|
-
gauge.name.should == "fnordgauge"
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should return its key as title if none specified" do
|
21
|
-
gauge = FnordMetric::Gauge.new({:key_prefix => "foo", :key => "fnordgauge"})
|
22
|
-
gauge.title.should == "fnordgauge"
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should return its title as title if none specified" do
|
26
|
-
gauge = FnordMetric::Gauge.new({:key_prefix => "foo", :key => "fnordgauge", :title => "Fnord Gauge"})
|
27
|
-
gauge.title.should == "Fnord Gauge"
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should raise an error when initialize without key" do
|
31
|
-
lambda{
|
32
|
-
FnordMetric::Gauge.new({:key_prefix => "foo"})
|
33
|
-
}.should raise_error(key_error_klass)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should raise an error when initialize without key_prefix" do
|
37
|
-
lambda{
|
38
|
-
FnordMetric::Gauge.new({:key => "foo"})
|
39
|
-
}.should raise_error(key_error_klass)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should generate the correct key without append" do
|
43
|
-
gauge = FnordMetric::Gauge.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge", :tick => 23})
|
44
|
-
gauge.key.should == "fnordmetrics-myns-gauge-mygauge-23"
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should generate the correct key with append" do
|
48
|
-
gauge = FnordMetric::Gauge.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge", :tick => 23})
|
49
|
-
gauge.key(:fnord).should == "fnordmetrics-myns-gauge-mygauge-23-fnord"
|
50
|
-
end
|
16
|
+
it_should_behave_like FnordMetric::GaugeLike
|
51
17
|
|
52
18
|
describe "ticks" do
|
53
19
|
|
data/spec/namespace_spec.rb
CHANGED
@@ -2,7 +2,6 @@ require ::File.expand_path('../spec_helper.rb', __FILE__)
|
|
2
2
|
|
3
3
|
describe FnordMetric::Namespace do
|
4
4
|
|
5
|
-
|
6
5
|
before(:all) do
|
7
6
|
@redis = Redis.new
|
8
7
|
@redis_wrap = RedisWrap.new(@redis)
|
@@ -10,13 +9,12 @@ describe FnordMetric::Namespace do
|
|
10
9
|
|
11
10
|
before(:each) do
|
12
11
|
@redis.keys("fnordmetric-myns*").each { |k| @redis.del(k) }
|
12
|
+
@namespace = FnordMetric::Namespace.new(:myns_213, :redis_prefix => "fnordmetric")
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
it "should generate the correct redis prefix"
|
16
16
|
|
17
|
-
|
18
|
-
@namespace = FnordMetric::Namespace.new(:myns_213, :redis_prefix => "fnordmetric")
|
19
|
-
end
|
17
|
+
describe "instance methods" do
|
20
18
|
|
21
19
|
it "should create a new dashboard if a widget is added" do
|
22
20
|
@namespace.widget("MyFooDash", nil)
|
@@ -33,18 +31,34 @@ describe FnordMetric::Namespace do
|
|
33
31
|
|
34
32
|
end
|
35
33
|
|
34
|
+
describe "registering gauges" do
|
36
35
|
|
37
|
-
|
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
|
38
40
|
|
39
|
-
|
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
|
41
46
|
|
42
|
-
|
47
|
+
it "should register a multi gauge" do
|
48
|
+
@namespace.numeric_gauge(:multigauge, {:fnord => 23, :ticks => [1.hour], :series => ["fnord"]})
|
49
|
+
@namespace.gauges[:multigauge].should be_a(FnordMetric::NumericGauge)
|
50
|
+
end
|
43
51
|
|
44
|
-
|
45
|
-
@namespace
|
52
|
+
it "should register a multi gauge and pass options" do
|
53
|
+
@namespace.numeric_gauge(:multigauge2, {:fnord => 42, :ticks => [1.hour], :series => ["fnord"]})
|
54
|
+
@namespace.gauges[:multigauge2].instance_variable_get(:@opts).should include({:fnord => 42})
|
55
|
+
@namespace.gauges[:multigauge2].instance_variable_get(:@opts).should include({:key => :multigauge2})
|
46
56
|
end
|
47
57
|
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "registering event handlers" do
|
61
|
+
|
48
62
|
it "should register an event handler" do
|
49
63
|
@namespace.handlers.length.should == 0
|
50
64
|
@namespace.event(:foobar){}
|
data/spec/spec_helper.rb
CHANGED
@@ -13,6 +13,10 @@ require "fnordmetric"
|
|
13
13
|
require "eventmachine"
|
14
14
|
require 'em-hiredis'
|
15
15
|
|
16
|
+
$: << ::File.expand_path('../../spec', __FILE__)
|
17
|
+
module FnordMetric::GaugeLike; end
|
18
|
+
require "gauge_like_shared"
|
19
|
+
|
16
20
|
def EM.defer; yield; end
|
17
21
|
def EM.next_tick; yield; end
|
18
22
|
|
@@ -1,16 +1,16 @@
|
|
1
1
|
require ::File.expand_path('../spec_helper.rb', __FILE__)
|
2
2
|
|
3
|
-
describe FnordMetric::
|
3
|
+
describe FnordMetric::TCPAcceptor do
|
4
4
|
|
5
5
|
before(:all) do
|
6
6
|
@redis = Redis.new
|
7
7
|
@redis_wrap = RedisWrap.new(@redis)
|
8
|
-
FnordMetric::
|
8
|
+
FnordMetric::TCPAcceptor.options(
|
9
9
|
:redis_url => "redis://localhost:6379",
|
10
10
|
:redis_prefix => "fnordmetric-test",
|
11
11
|
:event_queue_ttl => 120
|
12
12
|
)
|
13
|
-
@inbound_stream = FnordMetric::
|
13
|
+
@inbound_stream = FnordMetric::TCPAcceptor.new(nil)
|
14
14
|
end
|
15
15
|
|
16
16
|
describe "pushing new events" do
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require ::File.expand_path('../spec_helper.rb', __FILE__)
|
2
|
+
|
3
|
+
describe FnordMetric::TimeseriesGauge 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::TimeseriesGauge
|
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 "option validation" do
|
19
|
+
|
20
|
+
it "should raise when initialized with non-unique series tokens" do
|
21
|
+
lambda{
|
22
|
+
FnordMetric::TimeseriesGauge.new(
|
23
|
+
:series => [:fnord, :fnord],
|
24
|
+
:ticks => [1.hour],
|
25
|
+
:key => 123,
|
26
|
+
:key_prefix => 123
|
27
|
+
)
|
28
|
+
}.should raise_exception
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should raise when initialized without series tokens key" do
|
32
|
+
lambda{
|
33
|
+
FnordMetric::TimeseriesGauge.new(
|
34
|
+
:key => 123,
|
35
|
+
:ticks => [1.hour],
|
36
|
+
:key_prefix => 123
|
37
|
+
)
|
38
|
+
}.should raise_exception
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should raise when initialized with emtpy series tokens" do
|
42
|
+
lambda{
|
43
|
+
FnordMetric::TimeseriesGauge.new(
|
44
|
+
:series => [],
|
45
|
+
:key => 123,
|
46
|
+
:ticks => [1.hour],
|
47
|
+
:key_prefix => 123
|
48
|
+
)
|
49
|
+
}.should raise_exception
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require ::File.expand_path('../spec_helper.rb', __FILE__)
|
2
2
|
|
3
|
-
describe FnordMetric::
|
3
|
+
describe FnordMetric::UDPAcceptor do
|
4
4
|
|
5
|
-
let(:inbound_datagram) { FnordMetric::
|
5
|
+
let(:inbound_datagram) { FnordMetric::UDPAcceptor.new(nil) }
|
6
6
|
|
7
7
|
before(:all) do
|
8
8
|
@redis = Redis.new
|
9
9
|
@redis_wrap = RedisWrap.new(@redis)
|
10
|
-
FnordMetric::
|
10
|
+
FnordMetric::UDPAcceptor.opts = {
|
11
11
|
:redis_url => "redis://localhost:6379",
|
12
12
|
:redis_prefix => "fnordmetric-test",
|
13
13
|
:event_queue_ttl => 120
|