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 DELETED
@@ -1,404 +0,0 @@
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
- [SCREENCAST][2]: the FnordMetric-instance we use to track our social dating app.
11
-
12
- ----
13
-
14
- FnordMetric keeps track of your data and draws nice timeline plots.
15
-
16
- [ ![Nice timeline plots][5] ][6]
17
-
18
- FnordMetric gives you a live dashboard, that shows who is using your app in
19
- realtime. You can select a single user and follow them step by step.
20
-
21
- [ ![Live dashboard][7] ][8]
22
-
23
-
24
- Getting Started
25
- ---------------
26
-
27
- Copy `doc/full_example.rb` (that's the configuration from the screenshots
28
- and screencast) or the simple example from below to `my_stats_app.rb`.
29
-
30
- Simple Example: this will listen for json-events with `type=unicorn_seen`
31
- and render a timeline-plot showing the number of received events per hour.
32
-
33
- ```ruby
34
- require "fnordmetric"
35
-
36
- FnordMetric.namespace :myapp do
37
-
38
- # numeric (delta) gauge, 1-hour tick
39
- gauge :unicorns_seen_per_hour,
40
- :tick => 1.hour.to_i,
41
- :title => "Unicorns seenper Hour"
42
-
43
- # on every event like { _type: 'unicorn_seen' }
44
- event(:unicorn_seen) do
45
- # increment the unicorns_seen_per_hour gauge by 1
46
- incr :unicorns_seen_per_hour
47
- end
48
-
49
- # draw a timeline showing the gauges value, auto-refresh every 2s
50
- widget 'Overview', {
51
- :title => "Unicorn-Sightings per Hour",
52
- :type => :timeline,
53
- :gauges => :unicorns_seen_per_hour,
54
- :include_current => true,
55
- :autoupdate => 2
56
- }
57
-
58
- end
59
-
60
- FnordMetric.standalone
61
- ```
62
-
63
- Start the app (requires ruby >= 1.9.2):
64
-
65
- $ ruby my_stats_app.rb run
66
-
67
- Log all incoming events:
68
-
69
- $ ruby my_stats_app.rb log DUMP_FILE=/tmp/foo.json
70
-
71
- This is the easiest way to submit an event:
72
-
73
- echo "{\"_type\": \"unicorn_seen\"}" | nc localhost 1337
74
-
75
-
76
- Installation
77
- ------------
78
-
79
- gem install fnordmetric
80
-
81
- or in your Gemfile:
82
-
83
- gem 'fnordmetric', '>= 0.6.3'
84
-
85
-
86
- Documentation
87
- -------------
88
-
89
- ### Sending Events ###
90
-
91
- The slow way: HTTP-Post the json event to the fnordmetric webinterface.
92
-
93
- POST http://localhost:2323/events _type=unicorn_seen
94
-
95
- curl -X POST -d "_type=unicorn_seen" http://localhost:4242/events
96
-
97
- The easy way: Stream one ore more newline-seperated json encoded events
98
- through a tcp connection.
99
-
100
- echo "\{\"_type\": \"unicorn_seen\"\}\n" | nc localhost 2323
101
-
102
- The fast way: Add your event directly to the redis-based queue.
103
-
104
- ```ruby
105
- uuid = (8**32).to_s(36)
106
- event = { :_type => "unicorn_seen" }.to_json
107
-
108
- redis.set("fnordmetric-event-#{uuid}", event)
109
- redis.expire("fnordmetric-event-#{uuid}", 60)
110
- redis.lpush("fnordmetric-queue", uuid)
111
- ```
112
-
113
- The Ruby way: Using the API.
114
-
115
- ```ruby
116
- api = FnordMetric::API.new({})
117
- api.event({:_type => "unicorn_seen"})
118
- ```
119
-
120
- ----
121
-
122
- ### Special Events ###
123
-
124
- ```js
125
- // track a pageview
126
- { "_type": "_pageview", "url": "/blob/my_super_seo_article", "_session": "mysessiontoken" }
127
-
128
- // set the user name
129
- { "_type": "_set_name", "name": "Tingle Tangle Bob", "_session": "mysessiontoken" }
130
-
131
- // set the user picture
132
- { "_type": "_set_picture", "url": "http://myhost/123.jpg", "_session": "mysessiontoken" }
133
- ```
134
-
135
- ----
136
-
137
- ### Assigning Events to a Namespace ###
138
-
139
- ```js
140
- { "_type": "unicorn_seen", "_namespace": "myapp" }
141
- ```
142
-
143
- ### Event Handlers ###
144
-
145
- Call these methods from the event-handler block
146
-
147
- incr(gauge_name, value=1):
148
- Increment the given (two-dimensional) gauge by value
149
- at the tick specified by event-time
150
-
151
- incr_field(gauge_name, field_name, value=1):
152
- Increment the given field on a three-dimensional gauge
153
- by value at the tick specified by event-time
154
-
155
- set_value(gauge_name, value)
156
- Set the given (two-dimensional) to value at the tick
157
- specified by event-time (overwrite existing value)
158
-
159
- set_field(gauge_name, field_name, value)
160
- Set the given field on a three-dimensional gauge to
161
- value at the tick specified by event-time (overwrite
162
- existing value)
163
-
164
- ----
165
-
166
- ### Options: Widgets ###
167
-
168
- + `[autoupdate]` auto-refresh the timeline every n secs (0 turns autoupdate off)
169
-
170
- TimelineWidget
171
-
172
- + `[plot_style]` one of: line, areaspline
173
- + `[include_current]` show the current tick?
174
- + `[ticks]` number of ticks to show (defaults to 24/30)
175
-
176
- BarsWidget
177
-
178
- + `[plot_style]` one of: vertical, horizontal
179
- + `[order_by]`: order bars/columns by: value, field
180
-
181
-
182
- ----
183
-
184
-
185
- Resources
186
- ----------
187
-
188
- + [PHP API for FnordMetric (github.com/leemachin/fnordmetric-php-api)](https://github.com/leemachin/fnordmetric-php-api)
189
- + [Python API for FnordMetric (github.com/sholiday/pyfnordmetric)](https://github.com/sholiday/pyfnordmetric)
190
- + [FnordMetric and C (Blog/Howto)](http://johnmurray.io/log/2012/01/19/FnordMetrics-and-C%23.md)
191
- + [FnordMetric HowTo in russian](http://www.pvsm.ru/ruby/2723)
192
- + [The "fnordmetric" google group](http://groups.google.com/group/fnordmetric)
193
-
194
-
195
- Examples
196
- --------
197
-
198
- + doc/full_example.rb
199
-
200
-
201
- ## Full Example ##
202
-
203
- ```ruby
204
- require "fnordmetric"
205
-
206
- FnordMetric.namespace :myapp do
207
-
208
- # Set a custom namespace title, if you want one
209
- # set_title "Emails sent"
210
-
211
- # Hide the "Active Users" tab, if you want
212
- # hide_active_users
213
-
214
- # numeric (delta) gauge, 1-hour tick
215
- gauge :messages_sent,
216
- :tick => 1.hour.to_i,
217
- :title => "Messages (sent) per Hour"
218
-
219
- # numeric (delta) gauge, 1-hour tick
220
- gauge :messages_read,
221
- :tick => 1.hour.to_i,
222
- :title => "Messages (read) per Hour"
223
-
224
- # numeric (progressive) gauge, 1-hour tick
225
- gauge :events_total,
226
- :tick => 1.day.to_i,
227
- :progressive => true,
228
- :title => "Events (total)"
229
-
230
- # numeric (delta) gauge, increments uniquely by session_key
231
- gauge :pageviews_daily_unique,
232
- :tick => 1.day.to_i,
233
- :unique => true,
234
- :title => "Unique Visits (Daily)"
235
-
236
- # numeric (delta) gauge, increments uniquely by session_key, returns average
237
- gauge :avg_age_per_session,
238
- :tick => 1.day.to_i,
239
- :unique => true,
240
- :average => true,
241
- :title => "Avg. User Age"
242
-
243
- # three-dimensional (delta) gauge (time->key->value)
244
- gauge :pageviews_per_url_daily,
245
- :tick => 1.day.to_i,
246
- :title => "Daily Pageviews per URL",
247
- :three_dimensional => true
248
-
249
-
250
- # on every event like { "_type": "message_sent" }
251
- event(:message_sent) do
252
- # increment the messages_sent gauge by 1
253
- incr :messages_sent
254
- end
255
-
256
- # on every event like { "_type": "message_read" }
257
- event(:message_read) do
258
- # increment the messages_read gauge by 1
259
- incr :messages_read
260
- end
261
-
262
- # on _every_ event
263
- event :"*" do
264
- # increment the events_total gauge by 1
265
- incr :events_total
266
- end
267
-
268
- # on every event like
269
- # { "_type": "_pageview", "_session": "sbz7jset", "url": "/page2" }
270
- event :_pageview do
271
- # increment the daily_uniques gauge by 1 if session_key hasn't been seen
272
- # in this tick yet
273
- incr :pageviews_daily_unique
274
- # increment the pageviews_per_url_daily gauge by 1 where key = 'page2'
275
- incr_field :pageviews_per_url_daily, data[:url]
276
- end
277
-
278
- # on every event like { "_type": "_my_set_age", "my_age_field": "23" }
279
- event(:my_set_age) do
280
- # add the value of my_set_age to the avg_age_per_session gauge if session_key
281
- # hasn't been seen in this tick yet
282
- incr :avg_age_per_session, data[:my_age_field]
283
- end
284
-
285
- # draw a timeline showing the pageviews_daily_unique, auto-refresh every 30s
286
- widget 'Overview', {
287
- :title => "Unique Visits per Day",
288
- :type => :timeline,
289
- :width => 70,
290
- :gauges => :pageviews_daily_unique,
291
- :include_current => true,
292
- :autoupdate => 30
293
- }
294
-
295
- # draw the values of the messages_sent and messages_read gauge at the current
296
- # tick, three ticks ago, and the sum of the last 10 ticks, auto-refresh every
297
- # 20s
298
- widget 'Overview', {
299
- :title => "Messages Sent / Read",
300
- :type => :numbers,
301
- :width => 30,
302
- :autoupdate => 20,
303
- :offsets => [0,3,"10s"],
304
- :gauges => [ :messages_sent, :messages_read ]
305
- }
306
-
307
- # draw a list of the most visited urls (url, visits + percentage),
308
- # auto-refresh every 20s
309
- widget 'Overview', {
310
- :title => "Top Pages",
311
- :type => :toplist,
312
- :autoupdate => 20,
313
- :gauges => [ :pageviews_per_url_daily ]
314
- }
315
-
316
- end
317
-
318
- FnordMetric.server_configuration = {
319
- :redis_url => "redis://localhost:6379",
320
- :redis_prefix => "fnordmetric",
321
- :inbound_stream => ["0.0.0.0", "1339"],
322
- :start_worker => true,
323
- :print_stats => 3,
324
-
325
- # events that aren't processed after 2 min get dropped
326
- :event_queue_ttl => 120,
327
-
328
- # event data is kept for one month
329
- :event_data_ttl => 3600*24*30,
330
-
331
- # session data is kept for one month
332
- :session_data_ttl => 3600*24*30
333
- }
334
-
335
- FnordMetric.standalone
336
- ```
337
-
338
- Contributors
339
- ------------
340
-
341
- + Simon Menke (http://github.com/fd)
342
- + Bruno Michel (http://github.com/nono)
343
- + Marco Borromeo (http://github.com/mborromeo)
344
- + Leo Lou (http://github.com/l4u)
345
- + Andy Lindeman (http://github.com/alindeman)
346
- + Jurriaan Pruis (http://github.com/jurriaan)
347
- + Kacper Bielecki (http://github.com/kazjote)
348
- + John Murray (http://github.com/JohnMurray)
349
- + Lars Gierth (http://github.com/lgierth)
350
- + Ross Kaffenberger (http://github.com/rossta)
351
- + Kunal Modi (http://github.com/kunalmodi)
352
-
353
- To contribute, please fork this repository, make your changes and run the
354
- specs, commit them to your github repository and send me a pull request.
355
- Need help, head on over to our [Google Groups][1] page to discuss any ideas
356
- that you might have.
357
-
358
-
359
- License
360
- -------
361
-
362
- Copyright (c) 2011 Paul Asmuth
363
-
364
- Permission is hereby granted, free of charge, to any person obtaining
365
- a copy of this software and associated documentation files (the
366
- "Software"), to use, copy and modify copies of the Software, subject
367
- to the following conditions:
368
-
369
- The above copyright notice and this permission notice shall be
370
- included in all copies or substantial portions of the Software.
371
-
372
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
373
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
374
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
375
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
376
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
377
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
378
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
379
-
380
-
381
- Todos
382
- -----
383
-
384
- + readme: user_data (_session), import/log/_time, data expiration
385
- + combine/calculation gauges via opts_gauge({}, &block) (+calculate ctr)
386
- + timeline_widget: 'compare mode': compare gauge to yesterday
387
- + numbers_widget: handle decreasing vals
388
- + opt_event options: :increment => gauge_name
389
- + prune the namespace-sessions-timline (remove event_ids older than x)
390
- + prune the namespace-event-types-list (trim to max items)
391
- + the funnel-widget
392
- + timelinewidget + numberswidget => should use redis hmget
393
- + get multiple metrics in a single http get
394
-
395
-
396
-
397
- [1]: http://groups.google.com/group/fnordmetric
398
- [2]: http://www.screenr.com/KiJs
399
- [3]: https://secure.travis-ci.org/paulasmuth/fnordmetric.png
400
- [4]: http://travis-ci.org/paulasmuth/fnordmetric
401
- [5]: https://raw.github.com/paulasmuth/fnordmetric/master/doc/preview1.png
402
- [6]: https://raw.github.com/paulasmuth/fnordmetric/master/doc/preview1.png
403
- [7]: https://raw.github.com/paulasmuth/fnordmetric/master/doc/preview2.png
404
- [8]: https://raw.github.com/paulasmuth/fnordmetric/master/doc/preview2.png
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require 'rspec'
2
- require 'rspec/core/rake_task'
3
- desc "Run all examples"
4
- task RSpec::Core::RakeTask.new('spec')
5
-
6
- task :default => "spec"
data/doc/version DELETED
@@ -1 +0,0 @@
1
- 0.5.2
data/haml/app.haml DELETED
@@ -1,79 +0,0 @@
1
- !!!
2
- %html
3
-
4
- %head
5
- %title=current_namespace.title
6
-
7
- %script(type="text/javascript" src="#{path_prefix}/vendor/jquery-1.6.1.min.js")
8
- %script(type="text/javascript" src="#{path_prefix}/vendor/highcharts.js")
9
-
10
- %script(type="text/javascript" src="#{path_prefix}/fnordmetric.js")
11
- %link(type="text/css" rel="stylesheet" href="#{path_prefix}/fnordmetric.css")
12
-
13
- :javascript
14
- FnordMetric.p = '#{path_prefix}';
15
-
16
- %body
17
- .topbar{:class => namespaces.count > 1 ? 'shown' : 'hidden'}
18
- %ul
19
- -namespaces.each do |key,namespace|
20
- %li{:class => namespace.token == current_namespace.token ? 'active' : nil}
21
- %a{:href=> "#{path_prefix}/#{namespace.token}"}=h namespace.title
22
-
23
- #wrap
24
- #tabs
25
- %ul
26
- - if current_namespace.active_users_available
27
- %li.active.sessions
28
- .picto.piechart
29
- Active Users
30
-
31
- -current_namespace.dashboards.each do |key,dashboard|
32
- %li.dashboard{:rel => dashboard.token}
33
- .picto.piechart
34
- =h dashboard.title
35
-
36
- #viewport
37
- .viewport_inner.clearfix
38
-
39
-
40
- :javascript
41
- $(document).ready(function(){
42
-
43
- FnordMetric.init('#{current_namespace.token}', $('.viewport_inner'));
44
-
45
- $('#tabs li.dashboard').click(function(){
46
- FnordMetric.renderDashboard($(this).attr('rel'));
47
- window.location.hash = $(this).attr('rel');
48
- });
49
-
50
- $('#tabs li.sessions').click(function(){
51
- FnordMetric.renderSessionView();
52
- window.location.hash = '';
53
- });
54
-
55
- $('#tabs li').click(function(){
56
- $(this).addClass('active').siblings().removeClass('active');
57
- });
58
-
59
- function resizeViewport(){
60
- var viewport_width = window.innerWidth-220
61
- $('#viewport').width(viewport_width);
62
- FnordMetric.resizeView();
63
- }
64
-
65
- resizeViewport();
66
- $(window).resize(resizeViewport);
67
-
68
- if(!#{current_namespace.active_users_available.to_s}) {
69
- $('#tabs li:first').trigger('click');
70
- }
71
-
72
- if(window.location.hash){
73
- $('#tabs li.dashboard[rel="'+window.location.hash.slice(1)+'"]').trigger('click');
74
- }
75
-
76
- });
77
-
78
-
79
-
data/haml/widget.haml DELETED
@@ -1,9 +0,0 @@
1
- !!!
2
- %html
3
-
4
- %head
5
- %script(type="text/javascript" src="/fnordmetric/fnordmetric.js")
6
-
7
- %body
8
- =@widget.render
9
-
@@ -1,163 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class FnordMetric::App < Sinatra::Base
4
-
5
- @@sessions = Hash.new
6
- @@public_files = {
7
- "fnordmetric.css" => "text/css",
8
- "fnordmetric.js" => "application/x-javascript",
9
- "vendor/jquery-1.6.1.min.js" => "application/x-javascript",
10
- "vendor/highcharts.js" => "application/x-javascript"
11
- }
12
-
13
- if RUBY_VERSION =~ /1.9.\d/
14
- Encoding.default_external = Encoding::UTF_8
15
- end
16
-
17
- enable :session
18
-
19
- set :haml, :format => :html5
20
- set :views, ::File.expand_path('../../../haml', __FILE__)
21
-
22
- def initialize(namespaces, opts)
23
- @namespaces = {}
24
- @redis = Redis.connect(:url => opts[:redis_url])
25
- @opts = opts
26
- namespaces.each do |key, block|
27
- @namespaces[key] = FnordMetric::Namespace.new(key, opts.clone)
28
- @namespaces[key].instance_eval(&block)
29
- @namespaces[key].ready!(@redis.clone)
30
- end
31
- super(nil)
32
- end
33
-
34
- helpers do
35
- include Rack::Utils
36
- alias_method :h, :escape_html
37
-
38
- def path_prefix
39
- request.env["SCRIPT_NAME"]
40
- end
41
-
42
- def namespaces
43
- @namespaces
44
- end
45
-
46
- def current_namespace
47
- @namespaces[@namespaces.keys.detect{ |k|
48
- k.to_s == params[:namespace]
49
- }.try(:intern)]
50
- end
51
-
52
- end
53
-
54
- if ENV['RACK_ENV'] == "test"
55
- set :raise_errors, true
56
- end
57
-
58
- get '/' do
59
- redirect "#{path_prefix}/#{@namespaces.keys.first}"
60
- end
61
-
62
- get '/:namespace' do
63
- pass unless current_namespace
64
- haml :app
65
- end
66
-
67
- get '/favicon.ico' do
68
- ""
69
- end
70
-
71
- get '/:namespace/gauge/:name' do
72
-
73
- gauge = current_namespace.gauges.fetch(params[:name].intern)
74
-
75
- data = if gauge.three_dimensional?
76
- _t = (params[:at] || Time.now).to_i
77
- { :count => gauge.field_values_total(_t), :values => gauge.field_values_at(_t) }
78
- elsif params[:at] && params[:at] =~ /^[0-9]+$/
79
- { (_t = gauge.tick_at(params[:at].to_i)) => gauge.value_at(_t) }
80
- elsif params[:at] && params[:at] =~ /^([0-9]+)-([0-9]+)$/
81
- _range = params[:at].split("-").map(&:to_i)
82
- _values = gauge.values_in(_range.first.._range.last)
83
- params[:sum] ? { :sum => _values.values.compact.map(&:to_i).sum } : _values
84
- else
85
- { (_t = gauge.tick_at(Time.now.to_i-gauge.tick)) => gauge.value_at(_t) }
86
- end
87
-
88
- data.to_json
89
- end
90
-
91
- get '/:namespace/sessions' do
92
-
93
- sessions = current_namespace.sessions(:all, :limit => 100).map do |session|
94
- session.fetch_data!
95
- session.to_json
96
- end
97
-
98
- { :sessions => sessions }.to_json
99
- end
100
-
101
- get '/:namespace/events' do
102
-
103
- events = if params[:type]
104
- current_namespace.events(:by_type, :type => params[:type])
105
- elsif params[:session_key]
106
- current_namespace.events(:by_session_key, :session_key => params[:session_key])
107
- else
108
- find_opts = { :limit => 100 }
109
- find_opts.merge!(:since => params[:since].to_i+1) if params[:since]
110
- current_namespace.events(:all, find_opts)
111
- end
112
-
113
- { :events => events.map(&:to_json) }.to_json
114
- end
115
-
116
- get '/:namespace/event_types' do
117
- types_key = current_namespace.key_prefix("type-")
118
- keys = @redis.keys("#{types_key}*").map{ |k| k.gsub(types_key,'') }
119
-
120
- { :types => keys }.to_json
121
- end
122
-
123
- get '/:namespace/dashboard/:dashboard' do
124
- dashboard = current_namespace.dashboards.fetch(params[:dashboard])
125
-
126
- dashboard.to_json
127
- end
128
-
129
- post '/events' do
130
- halt 400, 'please specify the event_type (_type)' unless params["_type"]
131
- track_event((8**32).to_s(36), parse_params(params))
132
- end
133
-
134
- @@public_files.each do |public_file, public_file_type|
135
- get "/#{public_file}" do
136
- content_type(public_file_type)
137
- ::File.open(::File.expand_path("../../../pub/#{public_file}", __FILE__)).read
138
- end
139
- end
140
- private
141
-
142
- def parse_params(hash)
143
- hash.tap do |h|
144
- h.keys.each{ |k| h[k] = parse_param(h[k]) }
145
- end
146
- end
147
-
148
- def parse_param(object)
149
- return object unless object.is_a?(String)
150
- return object.to_f if object.match(/^[0-9]+[,\.][0-9]+$/)
151
- return object.to_i if object.match(/^[0-9]+$/)
152
- object
153
- end
154
-
155
- def track_event(event_id, event_data)
156
- @redis.hincrby "#{@opts[:redis_prefix]}-stats", "events_received", 1
157
- @redis.set "#{@opts[:redis_prefix]}-event-#{event_id}", event_data.to_json
158
- @redis.lpush "#{@opts[:redis_prefix]}-queue", event_id
159
- @redis.expire "#{@opts[:redis_prefix]}-event-#{event_id}", @opts[:event_queue_ttl]
160
- end
161
-
162
- end
163
-
@@ -1,7 +0,0 @@
1
- class FnordMetric::AverageMetric < FnordMetric::Metric
2
-
3
- def value_at(time_or_range)
4
- 5.23 #fixme
5
- end
6
-
7
- end
@@ -1,26 +0,0 @@
1
- class FnordMetric::BarsWidget < FnordMetric::Widget
2
-
3
- def data
4
- super.merge(
5
- :gauges => gauges.map(&:name),
6
- :gauge_titles => gauge_titles,
7
- :autoupdate => (@opts[:autoupdate] || 60),
8
- :order_by => (@opts[:order_by] || 'value'),
9
- :plot_style => (@opts[:plot_style] || 'vertical'),
10
- :tick => tick
11
- )
12
- end
13
-
14
- def gauge_titles
15
- {}.tap do |_hash|
16
- gauges.each do |gauge|
17
- _hash.merge!(gauge.name => gauge.title)
18
- end
19
- end
20
- end
21
-
22
- def has_tick?
23
- false
24
- end
25
-
26
- end
@@ -1,7 +0,0 @@
1
- class FnordMetric::CombineMetric < FnordMetric::Metric
2
-
3
- def value_at(time_or_range)
4
- @options[:combine].call(time_or_range)
5
- end
6
-
7
- end