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
@@ -0,0 +1,640 @@
1
+ $: << ::File.expand_path("../../../fnordmetric/lib/", __FILE__)
2
+ require "fnordmetric"
3
+
4
+ FnordMetric.namespace :ulm do
5
+
6
+ gauge :skip_votes, :tick => 1.day.to_i, :title => "Skip-Votes"
7
+ gauge :yes_votes, :tick => 1.day.to_i, :title => "Yes-Votes"
8
+ gauge :maybe_votes, :tick => 1.day.to_i, :title => "Maybe-Votes"
9
+
10
+ gauge :pageviews_daily_unique, :tick => 1.day.to_i, :unique => true, :title => "Unique Visits (Daily)"
11
+ gauge :pageviews_hourly_unique, :tick => 1.hour.to_i, :unique => true, :title => "Unique Visits (Hourly)"
12
+ gauge :pageviews_monthly_unique, :tick => 40.days.to_i, :unique => true, :title => "Unique Visits (Month)"
13
+
14
+ gauge :messages_sent, :tick => 1.day.to_i, :title => "Messages (sent)"
15
+ gauge :messages_read, :tick => 1.day.to_i, :title => "Messages (read)"
16
+ gauge :winks_sent, :tick => 1.day.to_i, :title => "Winks sent"
17
+
18
+ gauge :pageviews_per_url_daily,
19
+ :tick => 1.day.to_i,
20
+ :title => "Daily Pageviews per URL",
21
+ :three_dimensional => true
22
+
23
+ gauge :pageviews_per_url_monthly,
24
+ :tick => 30.days.to_i,
25
+ :title => "Monthly Pageviews per URL",
26
+ :three_dimensional => true
27
+
28
+ event :_pageview do
29
+ incr :pageviews_daily_unique
30
+ incr :pageviews_hourly_unique
31
+ incr :pageviews_monthly_unique
32
+ incr_field :pageviews_per_url_daily, data[:url]
33
+ incr_field :pageviews_per_url_monthly, data[:url]
34
+ end
35
+
36
+ event(:action_wink){ incr :winks_sent }
37
+ event(:wink_sent){ incr :winks_sent }
38
+ event(:message_sent){ incr :messages_sent }
39
+ event(:message_read){ incr :messages_read }
40
+
41
+ event(:skip_vote){ incr :skip_votes }
42
+ event(:action_skip){ incr :skip_votes }
43
+ event(:yes_vote){ incr :yes_votes }
44
+ event(:action_yes){ incr :yes_votes }
45
+ event(:maybe_vote){ incr :maybe_votes }
46
+ event(:action_maybe){ incr :maybe_votes }
47
+
48
+
49
+ gauge :mails_sent, :tick => 1.day.to_i, :title => "Mails (sent)"
50
+ gauge :mails_clicked, :tick => 1.day.to_i, :title => "Mails (clicked)"
51
+
52
+ event(:mail_sent){ incr :mails_sent }
53
+ event(:mail_clicked){ incr :mails_clicked }
54
+
55
+
56
+ gauge :app_requests_sent, :tick => 1.day.to_i, :title => "App-Requests (sent)"
57
+ gauge :app_requests_clicked, :tick => 1.day.to_i, :title => "App-Requests (clicked)"
58
+
59
+ gauge :app_invites_sent, :tick => 1.day.to_i, :title => "App-Invites (sent)"
60
+ gauge :app_invites_clicked, :tick => 1.day.to_i, :title => "App-Invites (clicked)"
61
+
62
+ event(:app_request_sent){ incr :app_requests_sent }
63
+ event(:app_request_click){ incr :app_requests_clicked }
64
+
65
+ event(:app_invite_sent){ incr :app_invites_sent }
66
+ event(:app_invite_click){ incr :app_invites_clicked }
67
+
68
+ gauge :rockyou1_ppis, :tick => 1.day.to_i, :title => "RockYou (12/11): Paid Installs"
69
+ gauge :rockyou1_requests, :tick => 1.day.to_i, :title => "RockYou (12/11): Invites sent"
70
+ gauge :rockyou1_refs, :tick => 1.day.to_i, :title => "RockYou (12/11): Ref. Installs"
71
+
72
+
73
+
74
+
75
+ widget 'Overview', {
76
+ :title => "Unique Visits per Day",
77
+ :type => :timeline,
78
+ :width => 67,
79
+ :gauges => :pageviews_daily_unique,
80
+ :include_current => true,
81
+ :autoupdate => 30
82
+ }
83
+
84
+ widget 'Overview', {
85
+ :title => "Unique Visits per Hour",
86
+ :type => :timeline,
87
+ :width => 33,
88
+ :gauges => :pageviews_hourly_unique,
89
+ :include_current => true,
90
+ :autoupdate => 30
91
+ }
92
+
93
+ widget 'Overview', {
94
+ :title => "ULM Key Metrics",
95
+ :type => :numbers,
96
+ :width => 100,
97
+ :autoupdate => 30,
98
+ :gauges => [
99
+ :pageviews_daily_unique, :pageviews_monthly_unique, :app_requests_sent, :app_requests_clicked, :mails_sent, :mails_clicked,
100
+ :app_invites_sent, :app_invites_clicked
101
+ ]
102
+ }
103
+
104
+ widget 'Overview', {
105
+ :title => "User-Activity",
106
+ :type => :timeline,
107
+ :width => 67,
108
+ :autoupdate => 30,
109
+ :gauges => [:skip_votes, :yes_votes, :maybe_votes]
110
+ }
111
+
112
+ widget 'Overview', {
113
+ :title => "Top Pages",
114
+ :type => :toplist,
115
+ :autoupdate => 30,
116
+ :width => 33,
117
+ :gauges => [ :pageviews_per_url_daily, :pageviews_per_url_monthly ]
118
+ }
119
+
120
+
121
+ widget 'Overview', {
122
+ :title => "ULM User Metrics",
123
+ :type => :numbers,
124
+ :width => 67,
125
+ :autoupdate => 30,
126
+ :gauges => [
127
+ :skip_votes, :yes_votes,
128
+ :maybe_votes, :winks_sent, :messages_sent, :messages_read,
129
+ ]
130
+ }
131
+
132
+ widget 'Overview', {
133
+ :title => "RockYou Campaign (12/11) Metrics",
134
+ :type => :numbers,
135
+ :width => 33,
136
+ :autoupdate => 30,
137
+ :gauges => [ :rockyou1_ppis, :rockyou1_refs, :rockyou1_requests ]
138
+ }
139
+
140
+
141
+ # user activity
142
+
143
+ widget 'UserActivity', {
144
+ :title => "Yes/No/Skip-Votes",
145
+ :type => :timeline,
146
+ :gauges => [:skip_votes, :yes_votes, :maybe_votes]
147
+ }
148
+
149
+ widget 'UserActivity', {
150
+ :title => "Yes/No/Skip Numbers",
151
+ :type => :numbers,
152
+ :gauges => [:skip_votes, :yes_votes, :maybe_votes]
153
+ }
154
+
155
+
156
+ widget 'UserActivity', {
157
+ :title => "Messages sent/read",
158
+ :type => :timeline,
159
+ :gauges => [:messages_sent, :messages_read, :winks_sent]
160
+ }
161
+
162
+ widget 'UserActivity', {
163
+ :title => "Messages sent+read/Winks Numbers",
164
+ :type => :numbers,
165
+ :gauges => [:messages_sent, :messages_read, :winks_sent]
166
+ }
167
+
168
+
169
+ widget 'TrafficChannels', {
170
+ :title => "Mails sent/read",
171
+ :type => :timeline,
172
+ :gauges => [:mails_sent, :mails_clicked]
173
+ }
174
+
175
+ widget 'TrafficChannels', {
176
+ :title => "Mail sent/read Numbers",
177
+ :type => :numbers,
178
+ :gauges => [:mails_sent, :mails_clicked]
179
+ }
180
+
181
+ widget 'TrafficChannels', {
182
+ :title => "App-Requests sent/clicked",
183
+ :type => :timeline,
184
+ :gauges => [:app_requests_sent, :app_requests_clicked]
185
+ }
186
+
187
+ widget 'TrafficChannels', {
188
+ :title => "App-Requests sent/clicked Numbers",
189
+ :type => :numbers,
190
+ :gauges => [:app_requests_sent, :app_requests_clicked]
191
+ }
192
+
193
+ widget 'TrafficChannels', {
194
+ :title => "App-Invites sent/clicked",
195
+ :type => :timeline,
196
+ :gauges => [:app_invites_sent, :app_invites_clicked]
197
+ }
198
+
199
+ widget 'TrafficChannels', {
200
+ :title => "App-Invites sent/clicked Numbers",
201
+ :type => :numbers,
202
+ :gauges => [:app_invites_sent, :app_invites_clicked]
203
+ }
204
+
205
+ gauge :wall_posts_sent, :tick => 1.day.to_i
206
+ gauge :wall_posts_clicked, :tick => 1.day.to_i
207
+
208
+ event(:wallpost_sent){ incr :wall_posts_sent }
209
+ event(:wallpost_click){ incr :wall_posts_clicked }
210
+
211
+ widget 'TrafficChannels', {
212
+ :title => "Wall-Posts sent/clicked",
213
+ :type => :timeline,
214
+ :gauges => [:wall_posts_sent, :wall_posts_clicked]
215
+ }
216
+
217
+ widget 'TrafficChannels', {
218
+ :title => "Wall-Posts sent/clicked Numbers",
219
+ :type => :numbers,
220
+ :gauges => [:wall_posts_sent, :wall_posts_clicked]
221
+ }
222
+
223
+
224
+
225
+ event :campaign_install do
226
+ if %w(ry201112a ry201112b).include?(data[:campaign_key])
227
+ incr :rockyou1_ppis
228
+ end
229
+ if %w(ry201112_ref).include?(data[:campaign_key])
230
+ incr :rockyou1_refs
231
+ end
232
+ end
233
+
234
+ event :app_request_sent do
235
+ if %w(ry201112a ry201112b ry201112_ref).include?(data[:campaign_key])
236
+ incr :rockyou1_requests
237
+ end
238
+ end
239
+
240
+ widget 'Campaigns', {
241
+ :title => "RockYou (1) - PPI vs. Requests vs. Refs",
242
+ :gauges => [:rockyou1_requests, :rockyou1_ppis, :rockyou1_refs],
243
+ :type => :timeline
244
+ }
245
+
246
+ widget 'Campaigns', {
247
+ :title => "RockYou (1) - Installs via PPI",
248
+ :type => :timeline,
249
+ :gauges => [:rockyou1_ppis]
250
+ }
251
+
252
+ widget 'Campaigns', {
253
+ :title => "RockYou (1) - Installs via Referral",
254
+ :gauges => [:rockyou1_refs],
255
+ :type => :timeline
256
+ }
257
+
258
+ widget 'Campaigns', {
259
+ :title => "RockYou (1) - AppRequests sent",
260
+ :gauges => [:rockyou1_requests],
261
+ :type => :timeline
262
+ }
263
+
264
+
265
+
266
+ gauge :abtest_sidebar_btn_totals,
267
+ :tick => 36000.days.to_i,
268
+ :title => "(A/B) sidebar_btn: Totals",
269
+ :three_dimensional => true
270
+
271
+ gauge :abtest_sidebar_btn_daily,
272
+ :tick => 1.day.to_i,
273
+ :title => "(A/B) sidebar_btn: Daily",
274
+ :three_dimensional => true
275
+
276
+ gauge :abtest_sidebar_btn_leute_treffen,
277
+ :tick => 1.day.to_i,
278
+ :title => "leute_treffen"
279
+
280
+ gauge :abtest_sidebar_btn_jetzt_losflirten,
281
+ :tick => 1.day.to_i,
282
+ :title => "jetzt_losflirten"
283
+
284
+ gauge :abtest_sidebar_btn_dates_finden,
285
+ :tick => 1.day.to_i,
286
+ :title => "dates_finden"
287
+
288
+ gauge :abtest_sidebar_btn_leute_treffen_monthly,
289
+ :tick => 1.month.to_i,
290
+ :title => "leute_treffen"
291
+
292
+ gauge :abtest_sidebar_btn_jetzt_losflirten_monthly,
293
+ :tick => 1.month.to_i,
294
+ :title => "jetzt_losflirten"
295
+
296
+ gauge :abtest_sidebar_btn_dates_finden_monthly,
297
+ :tick => 1.month.to_i,
298
+ :title => "dates_finden"
299
+
300
+
301
+ event :abtest_sidebar_btn_click do
302
+ incr :abtest_sidebar_btn_leute_treffen if data[:variant] == "leute_treffen"
303
+ incr :abtest_sidebar_btn_jetzt_losflirten if data[:variant] == "jetzt_losflirten"
304
+ incr :abtest_sidebar_btn_dates_finden if data[:variant] == "dates_finden"
305
+ incr :abtest_sidebar_btn_leute_treffen_monthly if data[:variant] == "leute_treffen"
306
+ incr :abtest_sidebar_btn_jetzt_losflirten_monthly if data[:variant] == "jetzt_losflirten"
307
+ incr :abtest_sidebar_btn_dates_finden_monthly if data[:variant] == "dates_finden"
308
+ incr_field :abtest_sidebar_btn_totals, data[:variant]
309
+ incr_field :abtest_sidebar_btn_daily, data[:variant]
310
+ end
311
+
312
+
313
+ widget 'ABTests', {
314
+ :title => "Sidebar-Button (A/B): Daily Clicks per Variant",
315
+ :type => :timeline,
316
+ :autoupdate => 5,
317
+ :width => 67,
318
+ :gauges => [
319
+ :abtest_sidebar_btn_leute_treffen,
320
+ :abtest_sidebar_btn_jetzt_losflirten,
321
+ :abtest_sidebar_btn_dates_finden
322
+ ]
323
+ }
324
+
325
+ widget 'ABTests', {
326
+ :title => "Top Pages",
327
+ :type => :toplist,
328
+ :autoupdate => 5,
329
+ :width => 33,
330
+ :gauges => [ :abtest_sidebar_btn_totals, :abtest_sidebar_btn_daily ]
331
+ }
332
+
333
+
334
+ widget 'ABTests', {
335
+ :title => "Sidebar-Button (A/B): Daily Clicks per Variant (Numbers)",
336
+ :type => :numbers,
337
+ :autoupdate => 5,
338
+ :width => 67,
339
+ :gauges => [
340
+ :abtest_sidebar_btn_leute_treffen,
341
+ :abtest_sidebar_btn_jetzt_losflirten,
342
+ :abtest_sidebar_btn_dates_finden
343
+ ]
344
+ }
345
+
346
+ widget 'ABTests', {
347
+ :title => "Sidebar-Button (A/B): Monthly Clicks per Variant",
348
+ :type => :pie,
349
+ :autoupdate => 5,
350
+ :width => 33,
351
+ :gauges => [
352
+ :abtest_sidebar_btn_leute_treffen_monthly,
353
+ :abtest_sidebar_btn_jetzt_losflirten_monthly,
354
+ :abtest_sidebar_btn_dates_finden_monthly
355
+ ]
356
+ }
357
+
358
+
359
+ gauge :age_distribution_female_monthly,
360
+ :tick => 1.month.to_i,
361
+ :three_dimensional => true,
362
+ :unique => true,
363
+ :title => "Age Distribution (female) monthly"
364
+
365
+ gauge :age_distribution_male_monthly,
366
+ :tick => 1.month.to_i,
367
+ :three_dimensional => true,
368
+ :unique => true,
369
+ :title => "Age Distribution (male) monthly"
370
+
371
+ gauge :age_distribution_female_daily,
372
+ :tick => 1.day.to_i,
373
+ :three_dimensional => true,
374
+ :unique => true,
375
+ :title => "Age Distribution (female) daily"
376
+
377
+ gauge :age_distribution_male_daily,
378
+ :tick => 1.day.to_i,
379
+ :three_dimensional => true,
380
+ :unique => true,
381
+ :title => "Age Distribution (male) daily"
382
+
383
+
384
+ widget 'Demography', {
385
+ :title => "Age Distribution: Female Users (Monthly)",
386
+ :type => :bars,
387
+ :width => 50,
388
+ :autoupdate => 5,
389
+ :order_by => :field,
390
+ :gauges => [ :age_distribution_female_monthly ]
391
+ }
392
+
393
+ widget 'Demography', {
394
+ :title => "Age Distribution: Male Users (Monthly)",
395
+ :type => :bars,
396
+ :width => 50,
397
+ :autoupdate => 5,
398
+ :order_by => :field,
399
+ :gauges => [ :age_distribution_male_monthly ]
400
+ }
401
+
402
+
403
+ widget 'Demography', {
404
+ :title => "Age Distribution: Female Users",
405
+ :type => :toplist,
406
+ :width => 50,
407
+ :autoupdate => 5,
408
+ :gauges => [ :age_distribution_female_monthly, :age_distribution_female_daily ]
409
+ }
410
+
411
+ widget 'Demography', {
412
+ :title => "Age Distribution: Male Users",
413
+ :type => :toplist,
414
+ :width => 50,
415
+ :autoupdate => 5,
416
+ :gauges => [ :age_distribution_male_monthly, :age_distribution_male_daily ]
417
+ }
418
+
419
+ event "user_demography" do
420
+ if data[:gender] == "female"
421
+ incr_field(:age_distribution_female_monthly, data[:age], 1)
422
+ incr_field(:age_distribution_female_daily, data[:age], 1)
423
+ end
424
+ if data[:gender] == "male"
425
+ incr_field(:age_distribution_male_monthly, data[:age], 1)
426
+ incr_field(:age_distribution_male_daily, data[:age], 1)
427
+ end
428
+ end
429
+
430
+
431
+ gauge :competitors_badoo_mau,
432
+ :tick => 1.day.to_i,
433
+ :title => "Badoo (MAU)"
434
+
435
+ gauge :competitors_badoo_dau,
436
+ :tick => 1.day.to_i,
437
+ :title => "Badoo (DAU)"
438
+
439
+ gauge :competitors_zoosk_mau,
440
+ :tick => 1.day.to_i,
441
+ :title => "zoosk (MAU)"
442
+
443
+ gauge :competitors_zoosk_dau,
444
+ :tick => 1.day.to_i,
445
+ :title => "zoosk (DAU)"
446
+
447
+ gauge :competitors_areyouinterested_mau,
448
+ :tick => 1.day.to_i,
449
+ :title => "areyouinterested (MAU)"
450
+
451
+ gauge :competitors_areyouinterested_dau,
452
+ :tick => 1.day.to_i,
453
+ :title => "areyouinterested (DAU)"
454
+
455
+ gauge :competitors_onetwolike_mau,
456
+ :tick => 1.day.to_i,
457
+ :title => "onetwolike (MAU)"
458
+
459
+ gauge :competitors_onetwolike_dau,
460
+ :tick => 1.day.to_i,
461
+ :title => "onetwolike (DAU)"
462
+
463
+ gauge :competitors_kizzle_mau,
464
+ :tick => 1.day.to_i,
465
+ :title => "kizzle (MAU)"
466
+
467
+ gauge :competitors_kizzle_dau,
468
+ :tick => 1.day.to_i,
469
+ :title => "kizzle (DAU)"
470
+
471
+ event :competition_data do
472
+ set_value(:competitors_badoo_mau, data[:badoo_mau]) if data[:badoo_mau]
473
+ set_value(:competitors_badoo_dau, data[:badoo_dau]) if data[:badoo_dau]
474
+ set_value(:competitors_areyouinterested_mau, data[:areyouinterested_mau]) if data[:areyouinterested_mau]
475
+ set_value(:competitors_areyouinterested_dau, data[:areyouinterested_dau]) if data[:areyouinterested_dau]
476
+ set_value(:competitors_zoosk_mau, data[:zoosk_mau]) if data[:zoosk_mau]
477
+ set_value(:competitors_zoosk_dau, data[:zoosk_dau]) if data[:zoosk_dau]
478
+ set_value(:competitors_onetwolike_mau, data[:onetwolike_mau]) if data[:onetwolike_mau]
479
+ set_value(:competitors_onetwolike_dau, data[:onetwolike_dau]) if data[:onetwolike_dau]
480
+ set_value(:competitors_kizzle_mau, data[:kizzle_mau]) if data[:kizzle_mau]
481
+ set_value(:competitors_kizzle_dau, data[:kizzle_dau]) if data[:kizzle_dau]
482
+ end
483
+
484
+ widget "Competition", {
485
+ :title => "Competition: Badoo",
486
+ :type => :timeline,
487
+ :ticks => 90,
488
+ :gauges => [:competitors_badoo_mau, :competitors_badoo_dau]
489
+ }
490
+
491
+ widget "Competition", {
492
+ :title => "Competition: Badoo (Numbers)",
493
+ :type => :numbers,
494
+ :offsets => [10, 30, 90],
495
+ :gauges => [:competitors_badoo_mau, :competitors_badoo_dau]
496
+ }
497
+
498
+ widget "Competition", {
499
+ :title => "Competition: zoosk",
500
+ :type => :timeline,
501
+ :ticks => 90,
502
+ :gauges => [:competitors_zoosk_mau, :competitors_zoosk_dau]
503
+ }
504
+
505
+ widget "Competition", {
506
+ :title => "Competition: zoosk (Numbers)",
507
+ :type => :numbers,
508
+ :offsets => [10, 30, 90],
509
+ :gauges => [:competitors_zoosk_mau, :competitors_zoosk_dau]
510
+ }
511
+
512
+ widget "Competition", {
513
+ :title => "Competition: onetwolike",
514
+ :type => :timeline,
515
+ :ticks => 90,
516
+ :gauges => [:competitors_onetwolike_mau, :competitors_onetwolike_dau]
517
+ }
518
+
519
+ widget "Competition", {
520
+ :title => "Competition: onetwolike (Numbers)",
521
+ :type => :numbers,
522
+ :offsets => [10, 30, 90],
523
+ :gauges => [:competitors_onetwolike_mau, :competitors_onetwolike_dau]
524
+ }
525
+
526
+ widget "Competition", {
527
+ :title => "Competition: kizzle",
528
+ :type => :timeline,
529
+ :ticks => 90,
530
+ :gauges => [:competitors_kizzle_mau, :competitors_kizzle_dau]
531
+ }
532
+
533
+ widget "Competition", {
534
+ :title => "Competition: kizzle (Numbers)",
535
+ :type => :numbers,
536
+ :offsets => [10, 30, 90],
537
+ :gauges => [:competitors_kizzle_mau, :competitors_kizzle_dau]
538
+ }
539
+
540
+ widget "Competition", {
541
+ :title => "Competition: areyouinterested",
542
+ :type => :timeline,
543
+ :ticks => 90,
544
+ :gauges => [:competitors_areyouinterested_mau, :competitors_areyouinterested_dau]
545
+ }
546
+
547
+ widget "Competition", {
548
+ :title => "Competition: areyouinterested (Numbers)",
549
+ :type => :numbers,
550
+ :offsets => [10, 30, 90],
551
+ :gauges => [:competitors_areyouinterested_mau, :competitors_areyouinterested_dau]
552
+ }
553
+
554
+
555
+
556
+ gauge :events_per_minute, :tick => 60
557
+ gauge :events_per_hour, :tick => 1.hour.to_i
558
+ gauge :events_per_second, :tick => 1
559
+ gauge :votes_per_second, :tick => 1
560
+
561
+ event :"*" do
562
+ incr :events_per_minute
563
+ incr :events_per_hour
564
+ incr :events_per_second
565
+ end
566
+
567
+
568
+ event(:skip_vote){ incr :votes_per_second }
569
+ event(:action_skip){ incr :votes_per_second }
570
+ event(:yes_vote){ incr :votes_per_second }
571
+ event(:action_yes){ incr :votes_per_second }
572
+ event(:maybe_vote){ incr :votes_per_second }
573
+ event(:action_maybe){ incr :votes_per_second }
574
+
575
+
576
+ widget 'TechStats', {
577
+ :title => "Events per Minute",
578
+ :type => :timeline,
579
+ :width => 50,
580
+ :gauges => :events_per_minute,
581
+ :include_current => true,
582
+ :autoupdate => 30
583
+ }
584
+
585
+ widget 'TechStats', {
586
+ :title => "Events per Hour",
587
+ :type => :timeline,
588
+ :width => 50,
589
+ :gauges => :events_per_hour,
590
+ :include_current => true,
591
+ :autoupdate => 30
592
+ }
593
+
594
+
595
+ widget 'TechStats', {
596
+ :title => "Events/Second",
597
+ :type => :timeline,
598
+ :width => 50,
599
+ :gauges => :events_per_second,
600
+ :include_current => true,
601
+ :plot_style => :areaspline,
602
+ :autoupdate => 1
603
+ }
604
+
605
+
606
+ widget 'TechStats', {
607
+ :title => "Votes/Second",
608
+ :type => :timeline,
609
+ :width => 50,
610
+ :gauges => :votes_per_second,
611
+ :include_current => true,
612
+ :plot_style => :areaspline,
613
+ :autoupdate => 1
614
+ }
615
+
616
+ end
617
+
618
+ FnordMetric.server_configuration = {
619
+ :redis_url => "redis://localhost:6379",
620
+ :redis_prefix => "fnordmetric",
621
+ :inbound_stream => ["0.0.0.0", "1337"],
622
+ :web_interface => ["0.0.0.0", "4242"],
623
+ :start_worker => true,
624
+ :print_stats => 3,
625
+
626
+ # events that aren't processed after 2 min get dropped
627
+ :event_queue_ttl => 120,
628
+
629
+ # event data is kept for one month
630
+ :event_data_ttl => 3600*24*30,
631
+
632
+ # session data is kept for one month
633
+ :session_data_ttl => 3600*24*30
634
+ }
635
+
636
+ #task :setup do
637
+ # @fm_opts = {:web_interface => ["0.0.0.0", "2323"]} if ENV['DEV']
638
+ #end
639
+
640
+ FnordMetric.standalone
@@ -0,0 +1,26 @@
1
+ $: << ::File.expand_path("../../../fnordmetric/lib/", __FILE__)
2
+ require "fnordmetric"
3
+
4
+ FnordMetric.namespace :fn do
5
+
6
+ timeseries_gauge :unicorns_seen,
7
+ :tick => 30.seconds,
8
+ :calculate => :average,
9
+ :series => [:num_unicorns]
10
+
11
+
12
+ event :unicorn_seen do
13
+ incr :unicorns_seen, :num_unicorns, rand(5)
14
+ end
15
+
16
+ end
17
+
18
+ Thread.new do
19
+ api = FnordMetric::API.new
20
+ loop do
21
+ api.event(:_type => :unicorn_seen)
22
+ sleep rand(10)/10.to_f
23
+ end
24
+ end
25
+
26
+ FnordMetric.standalone
data/doc/preview3.png ADDED
Binary file
data/fnordmetric.gemspec CHANGED
@@ -18,14 +18,15 @@ Gem::Specification.new do |s|
18
18
  s.add_dependency "sinatra", ">= 1.2.6"
19
19
  s.add_dependency "redis", ">= 2.2.2"
20
20
  s.add_dependency "eventmachine"
21
- s.add_dependency "em-hiredis"
21
+ s.add_dependency "websocket-rack", "0.4.0"
22
+ s.add_dependency "em-hiredis", "0.1.1"
22
23
  s.add_dependency "json"
23
24
  s.add_dependency "i18n"
24
25
  s.add_dependency "haml"
25
26
  s.add_dependency "rack"
26
27
  s.add_dependency "rack-test"
27
28
  s.add_dependency "yajl-ruby"
28
- s.add_dependency "thin"
29
+ s.add_dependency "thin", "~> 1.3.0"
29
30
  s.add_dependency "activesupport"
30
31
 
31
32
  s.add_development_dependency "delorean"
@@ -0,0 +1,29 @@
1
+ class FnordMetric::Acceptor
2
+
3
+ def initialize(opts)
4
+ @opts = opts
5
+
6
+ FnordMetric.register(self)
7
+ end
8
+
9
+ def initialized
10
+ inbound_class = if @opts[:protocol] == :udp
11
+ FnordMetric::UDPAcceptor
12
+ else
13
+ FnordMetric::TCPAcceptor
14
+ end
15
+
16
+ @opts[:listen] = [
17
+ @opts[:host] || "0.0.0.0",
18
+ @opts[:port] || 2323
19
+ ]
20
+
21
+ begin
22
+ inbound_stream = inbound_class.start(@opts)
23
+ FnordMetric.log "listening on #{@opts[:protocol]}://#{@opts[:listen][0..1].join(":")}"
24
+ #rescue
25
+ # FnordMetric.log "cant start #{inbound_class.name}. port in use?"
26
+ end
27
+ end
28
+
29
+ end