fnordmetric 0.7.5 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/doc/V1.0-ROADMAP +97 -0
  2. data/doc/full_example.rb +95 -511
  3. data/doc/legacy_example.rb +640 -0
  4. data/doc/minimal_example.rb +26 -0
  5. data/doc/preview3.png +0 -0
  6. data/fnordmetric.gemspec +3 -2
  7. data/lib/fnordmetric/acceptors/acceptor.rb +29 -0
  8. data/lib/fnordmetric/{inbound_stream.rb → acceptors/tcp_acceptor.rb} +8 -5
  9. data/lib/fnordmetric/{inbound_datagram.rb → acceptors/udp_acceptor.rb} +9 -8
  10. data/lib/fnordmetric/api.rb +2 -2
  11. data/lib/fnordmetric/context.rb +37 -18
  12. data/lib/fnordmetric/defaults.rb +9 -0
  13. data/lib/fnordmetric/ext.rb +72 -0
  14. data/lib/fnordmetric/gauge.rb +37 -10
  15. data/lib/fnordmetric/gauge_calculations.rb +38 -16
  16. data/lib/fnordmetric/gauge_modifiers.rb +67 -0
  17. data/lib/fnordmetric/gauge_rendering.rb +40 -0
  18. data/lib/fnordmetric/gauge_validations.rb +15 -0
  19. data/lib/fnordmetric/gauges/distribution_gauge.rb +85 -0
  20. data/lib/fnordmetric/gauges/timeseries_gauge.rb +143 -0
  21. data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
  22. data/lib/fnordmetric/histogram.rb +57 -0
  23. data/lib/fnordmetric/logger.rb +42 -36
  24. data/lib/fnordmetric/namespace.rb +47 -23
  25. data/lib/fnordmetric/session.rb +6 -6
  26. data/lib/fnordmetric/standalone.rb +15 -35
  27. data/lib/fnordmetric/timeseries.rb +79 -0
  28. data/lib/fnordmetric/toplist.rb +61 -0
  29. data/lib/fnordmetric/version.rb +1 -1
  30. data/lib/fnordmetric/web/app.rb +122 -0
  31. data/lib/fnordmetric/web/app_helpers.rb +42 -0
  32. data/lib/fnordmetric/{dashboard.rb → web/dashboard.rb} +4 -0
  33. data/lib/fnordmetric/{event.rb → web/event.rb} +7 -2
  34. data/lib/fnordmetric/web/reactor.rb +87 -0
  35. data/lib/fnordmetric/web/web.rb +53 -0
  36. data/lib/fnordmetric/web/websocket.rb +38 -0
  37. data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
  38. data/lib/fnordmetric/{html_widget.rb → widgets/html_widget.rb} +0 -0
  39. data/lib/fnordmetric/widgets/numbers_widget.rb +56 -0
  40. data/lib/fnordmetric/{pie_widget.rb → widgets/pie_widget.rb} +0 -0
  41. data/lib/fnordmetric/widgets/timeseries_widget.rb +55 -0
  42. data/lib/fnordmetric/widgets/toplist_widget.rb +64 -0
  43. data/lib/fnordmetric/worker.rb +26 -25
  44. data/lib/fnordmetric.rb +85 -115
  45. data/readme.md +362 -0
  46. data/spec/gauge_like_shared.rb +54 -0
  47. data/spec/gauge_spec.rb +2 -36
  48. data/spec/namespace_spec.rb +25 -11
  49. data/spec/spec_helper.rb +4 -0
  50. data/spec/{inbound_stream_spec.rb → tcp_acceptor_spec.rb} +3 -3
  51. data/spec/timeseries_gauge_spec.rb +54 -0
  52. data/spec/{inbound_datagram_spec.rb → udp_acceptor_spec.rb} +3 -3
  53. data/web/fnordmetric.css +786 -0
  54. data/web/haml/app.haml +38 -0
  55. data/web/haml/distribution_gauge.haml +118 -0
  56. data/web/haml/timeseries_gauge.haml +80 -0
  57. data/web/haml/toplist_gauge.haml +194 -0
  58. data/web/img/head.png +0 -0
  59. data/web/img/list.png +0 -0
  60. data/web/img/list_active.png +0 -0
  61. data/web/img/list_hover.png +0 -0
  62. data/web/img/loader_white.gif +0 -0
  63. data/web/img/navbar.png +0 -0
  64. data/web/img/navbar_btn.png +0 -0
  65. data/web/img/picto_gauge.png +0 -0
  66. data/web/js/fnordmetric.bars_widget.js +178 -0
  67. data/web/js/fnordmetric.dashboard_view.js +99 -0
  68. data/web/js/fnordmetric.gauge_view.js +260 -0
  69. data/web/js/fnordmetric.html_widget.js +21 -0
  70. data/web/js/fnordmetric.js +255 -0
  71. data/web/js/fnordmetric.numbers_widget.js +121 -0
  72. data/web/js/fnordmetric.overview_view.js +35 -0
  73. data/web/js/fnordmetric.pie_widget.js +118 -0
  74. data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
  75. data/web/js/fnordmetric.session_view.js +343 -0
  76. data/web/js/fnordmetric.timeline_widget.js +333 -0
  77. data/web/js/fnordmetric.timeseries_widget.js +388 -0
  78. data/web/js/fnordmetric.toplist_widget.js +112 -0
  79. data/web/js/fnordmetric.ui.js +91 -0
  80. data/web/js/fnordmetric.util.js +244 -0
  81. data/{pub → web}/loader.gif +0 -0
  82. data/web/vendor/d3.v2.js +9382 -0
  83. data/web/vendor/font-awesome/css/font-awesome.css +239 -0
  84. data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
  85. data/web/vendor/font-awesome/font/fontawesome-webfont.svg +175 -0
  86. data/web/vendor/font-awesome/font/fontawesome-webfont.svgz +0 -0
  87. data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
  88. data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
  89. data/web/vendor/jquery-1.6.2.min.js +18 -0
  90. data/web/vendor/jquery-ui.min.js +413 -0
  91. data/web/vendor/jquery.maskedinput.js +252 -0
  92. data/web/vendor/rickshaw.css +286 -0
  93. data/web/vendor/rickshaw.fnordmetric.js +2676 -0
  94. metadata +129 -79
  95. data/Gemfile +0 -6
  96. data/README.md +0 -404
  97. data/Rakefile +0 -6
  98. data/doc/version +0 -1
  99. data/haml/app.haml +0 -79
  100. data/haml/widget.haml +0 -9
  101. data/lib/fnordmetric/app.rb +0 -163
  102. data/lib/fnordmetric/average_metric.rb +0 -7
  103. data/lib/fnordmetric/bars_widget.rb +0 -26
  104. data/lib/fnordmetric/combine_metric.rb +0 -7
  105. data/lib/fnordmetric/count_metric.rb +0 -13
  106. data/lib/fnordmetric/funnel_widget.rb +0 -2
  107. data/lib/fnordmetric/metric.rb +0 -80
  108. data/lib/fnordmetric/metric_api.rb +0 -37
  109. data/lib/fnordmetric/numbers_widget.rb +0 -26
  110. data/lib/fnordmetric/report.rb +0 -29
  111. data/lib/fnordmetric/sum_metric.rb +0 -13
  112. data/lib/fnordmetric/timeline_widget.rb +0 -30
  113. data/lib/fnordmetric/toplist_widget.rb +0 -25
  114. data/pub/fnordmetric.css +0 -145
  115. data/pub/fnordmetric.js +0 -1179
  116. data/pub/vendor/highcharts.js +0 -170
  117. 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
- it "should remember its own name" do
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
 
@@ -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
- describe "instance methods" do
15
+ it "should generate the correct redis prefix"
16
16
 
17
- before(:each) do
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
- it "should generate the correct redis prefix"
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
- it "should register a gauge"
40
- it "should register a gauge and pass options"
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
- describe "registering event handlers" do
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
- before(:each) do
45
- @namespace = FnordMetric::Namespace.new(:myns_213, :redis_prefix => "fnordmetric")
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::InboundStream do
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::InboundStream.options(
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::InboundStream.new(nil)
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::InboundDatagram do
3
+ describe FnordMetric::UDPAcceptor do
4
4
 
5
- let(:inbound_datagram) { FnordMetric::InboundDatagram.new(nil) }
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::InboundDatagram.opts = {
10
+ FnordMetric::UDPAcceptor.opts = {
11
11
  :redis_url => "redis://localhost:6379",
12
12
  :redis_prefix => "fnordmetric-test",
13
13
  :event_queue_ttl => 120