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,99 @@
1
+ FnordMetric.views.dashboardView = (function(dashboard_name){
2
+ var widgets = [];
3
+ var widget_objs = {};
4
+ var viewport = null;
5
+
6
+ function load(_viewport){
7
+ viewport = _viewport.html('');
8
+ viewport.append('<div class="navbar"></div>');
9
+ viewport.append('<div class="dashboard_view"></div>');
10
+
11
+ FnordMetric.ui.navbar($('.navbar', viewport), {
12
+ breadcrumb: [
13
+ ["Dashboard", "/group/fnord"],
14
+ [dashboard_name, "/dashboard/"+dashboard_name]
15
+ ],
16
+ buttons: [
17
+ ["<i class='icon-refresh'></i>Refresh", function(){ load(viewport); }]
18
+ ]
19
+ });
20
+
21
+ $.ajax({
22
+ url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/dashboard/'+dashboard_name,
23
+ success: function(resp, status){
24
+ var conf = JSON.parse(resp);
25
+ renderWidgets(conf.widgets);
26
+ }
27
+ });
28
+ };
29
+
30
+ function renderWidgets(_widgets){
31
+ for(wkey in _widgets){
32
+ var widget = _widgets[wkey];
33
+ widget["elem"] = $('<div class="widget"></div>');
34
+ widgets[wkey] = widget;
35
+ $('.dashboard_view', viewport).append(widget.elem);
36
+ resizeWidget(wkey);
37
+ renderWidget(wkey);
38
+ };
39
+ resize();
40
+ };
41
+
42
+ function renderWidget(wkey, _w){
43
+ var widget = widgets[wkey];
44
+ if(!widget["widget_key"]){ widget["widget_key"] = wkey; }
45
+ /* argh... */
46
+ if(widget.klass=='TimelineWidget'){ _w = FnordMetric.widgets.timeseriesWidget(); }
47
+ if(widget.klass=='NumbersWidget'){ _w = FnordMetric.widgets.numbersWidget(); }
48
+
49
+ if(widget.klass=='ToplistWidget'){ _w = FnordMetric.widgets.toplistWidget(); }
50
+
51
+ if(widget.klass=='BarsWidget'){ _w = FnordMetric.widgets.barsWidget(); }
52
+ if(widget.klass=='PieWidget'){ _w = FnordMetric.widgets.pieWidget(); }
53
+ if(widget.klass=="HtmlWidget") { _w = FnordMetric.widgets.htmlWidget(); }
54
+
55
+ if(_w){
56
+ _w.render(widget);
57
+ widget_objs[wkey] = _w;
58
+ }
59
+ }
60
+
61
+ function resizeWidget(wkey){
62
+ var widget = widgets[wkey];
63
+ var wwperc = widgets[wkey].width;
64
+ if(!wwperc){ wwperc = 100; }
65
+ var wwidth = viewport.width() * (wwperc/100.0);
66
+ if(wwperc==100){
67
+ widgets[wkey].elem.addClass('full_width');
68
+ } else { wwidth -= 1; }
69
+ widget.elem.width(wwidth);
70
+ }
71
+
72
+ function resize(){
73
+ for(wkey in widgets){
74
+ resizeWidget(wkey);
75
+ };
76
+ };
77
+
78
+ function close(){
79
+ $('body').trigger('fm_dashboard_close');
80
+ };
81
+
82
+ function announce(evt){
83
+ if((evt.class == "widget_response") || (evt.class == "widget_push")){
84
+ for(wkey in widget_objs){
85
+ if(widget_objs[wkey].announce){
86
+ widget_objs[wkey].announce(evt)
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ return {
93
+ load: load,
94
+ resize: resize,
95
+ announce: announce,
96
+ close: close
97
+ };
98
+
99
+ });
@@ -0,0 +1,260 @@
1
+ FnordMetric.views.gaugeView = (function(gauge_name){
2
+ var widgets = [];
3
+ var widget_objs = {};
4
+ var viewport = null;
5
+ var tabs = [];
6
+ var conf = {};
7
+ var tick;
8
+
9
+ var start_timestamp, end_timestamp;
10
+
11
+ function load(_viewport){
12
+ viewport = _viewport;
13
+ viewport.html('');
14
+ viewport.append('<div class="navbar"></div>');
15
+ viewport.append($('<div class="gauge_viewport"></div>'));
16
+
17
+ conf.title = gauge_name;
18
+ tick = FnordMetric.gauges[gauge_name].tick
19
+ ctick = Math.max(3600, tick);
20
+
21
+ FnordMetric.ui.navbar($('.navbar', viewport), {
22
+ breadcrumb: [
23
+ ["Fnord", "/group/fnord"],
24
+ [conf.title, "/gauge/"+gauge_name]
25
+ ],
26
+ buttons: [
27
+ ["<i class='icon-refresh'></i>Refresh", function(){ load(viewport); }]
28
+ ],
29
+ datepicker: true
30
+ });
31
+
32
+ var now = parseInt((new Date()).getTime() / 1000);
33
+
34
+ start_timestamp = atTick((now-(ctick*24)));
35
+ end_timestamp = atTick(now);
36
+
37
+ updateDatepicker();
38
+ load_interval();
39
+ }
40
+
41
+ function atTick(t){
42
+ return (Math.ceil(t / ctick) * ctick);
43
+ }
44
+
45
+ function close(){
46
+
47
+ }
48
+
49
+ function resize(){
50
+
51
+ }
52
+
53
+ function updateDatepicker(){
54
+ $(".navbar .datepicker .date", viewport).html(
55
+ FnordMetric.util.dateFormat(start_timestamp) +
56
+ '&nbsp;&dash;&nbsp;' +
57
+ FnordMetric.util.dateFormat(end_timestamp)
58
+ ).parent().click(function(){
59
+ open_interval_modal();
60
+ });
61
+ }
62
+
63
+ function announce(evt){
64
+ if ((evt.gauge != gauge_name) ||
65
+ (evt.type != "render_response") ||
66
+ (!evt.payload)){ return true; }
67
+
68
+ if(evt.payload.html){
69
+ $('.gauge_viewport', viewport)
70
+ .html(evt.payload.html);
71
+ }
72
+
73
+ if(evt.payload.exec){
74
+ eval(evt.payload.exec);
75
+ }
76
+
77
+ FnordMetric.resizeView();
78
+ }
79
+
80
+ function interval_modal_done(modal){
81
+ var _sdate = $('.start_date', modal).val().match('([0-9]{2})\.([0-9]{2})\.([0-9]{4})')
82
+ var _stime = $('.start_time', modal).val().match('([0-9]{2}):([0-9]{2})')
83
+ var _edate = $('.end_date', modal).val().match('([0-9]{2})\.([0-9]{2})\.([0-9]{4})')
84
+ var _etime = $('.end_time', modal).val().match('([0-9]{2}):([0-9]{2})')
85
+
86
+ if (_sdate && _stime && _edate && _etime){
87
+ var sd = new Date();
88
+ var ed = new Date();
89
+ sd.setHours(parseInt(_stime[1]), parseInt(_stime[2]), 0);
90
+ sd.setFullYear(parseInt(_sdate[3]), parseInt(_sdate[2])-1, parseInt(_sdate[1]));
91
+ ed.setHours(parseInt(_etime[1]), parseInt(_etime[2]), 0);
92
+ ed.setFullYear(parseInt(_edate[3]), parseInt(_edate[2])-1, parseInt(_edate[1]));
93
+
94
+ if (sd && ed && (ed.getTime() > sd.getTime())) {
95
+ start_timestamp = parseInt(sd.getTime() / 1000);
96
+ end_timestamp = parseInt(ed.getTime() / 1000);
97
+
98
+ load_interval();
99
+ FnordMetric.ui.close_modal('body');
100
+ }
101
+
102
+ }
103
+ }
104
+
105
+ function open_interval_modal(){
106
+ var modal = $('<div>');
107
+
108
+ var interval_list = $('<ul>');
109
+ var now = parseInt((new Date()).getTime() / 1000);
110
+
111
+ var enter_catcher = function(e){
112
+ if (e.which == 13) interval_modal_done(modal);
113
+ }
114
+
115
+ var offset_opener = function(e){
116
+ var now = parseInt((new Date()).getTime() / 1000);
117
+
118
+ if($(this).attr('data-offset-off')){
119
+ now -= eval($(this).attr('data-offset-off'));
120
+ }
121
+
122
+ var off = eval($(this).attr('data-offset'));
123
+
124
+ if (off > ctick) {
125
+ start_timestamp = atTick((now-(off)));
126
+ end_timestamp = atTick(now);
127
+ } else {
128
+ start_timestamp = now-off;
129
+ end_timestamp = now;
130
+ }
131
+
132
+ load_interval();
133
+ FnordMetric.ui.close_modal('body');
134
+ }
135
+
136
+ modal.append(
137
+ $('<div>')
138
+ .css({
139
+ background: '#f2f2f2',
140
+ borderBottom: "1px solid #ddd",
141
+ padding: '12px 20px 10px 20px'
142
+ })
143
+ .append('<a class="button dark" style="height:30px; float:right; margin:1px; line-height:30px;">OK</a>')
144
+ .append('<input class="input ropen start_date" style="width:100px;" placeholder="DD.MM.YYYY" />')
145
+ .append('<input class="input lopen start_time" style="width:50px;" placeholder="HH:MM" />')
146
+ .append('<span style="margin:0 15px; color:#999;">&mdash;</span>')
147
+ .append('<input class="input ropen end_date" style="width:100px;" placeholder="DD.MM.YYYY" />')
148
+ .append('<input type="text" class="input lopen end_time" style="width:50px;" placeholder="HH:MM" />')
149
+ ).append($('<div style="padding:15px 20px;" class="offset_links ui_fancylinks">'));
150
+
151
+ if (tick < 300){
152
+ $('.offset_links', modal)
153
+ .append('<b>Just now</b>')
154
+ .append('<a data-offset="5*60">Last 5 Minutes</a> ')
155
+ .append('<a data-offset="10*60">Last 10 Minutes</a> ')
156
+ .append('<a data-offset="15*60">Last 15 Minutes</a> ')
157
+ .append('<a data-offset="30*60">Last 30 Minutes</a> ')
158
+ .append('<a data-offset="45*60">Last 45 Minutes</a><br /><br />');
159
+ }
160
+
161
+ if (tick < 4000){
162
+ $('.offset_links', modal)
163
+ .append('<b>Hourly</b>')
164
+ .append('<a data-offset="3600">Last Hour</a> ')
165
+ .append('<a data-offset="3600*3">Last 3 Hours</a> ')
166
+ .append('<a data-offset="3600*6">Last 6 Hours</a> ')
167
+ .append('<a data-offset="3600*12">Last 12 Hours</a> ')
168
+ .append('<a data-offset="3600*18">Last 18 Hours</a><br /><br />');
169
+ }
170
+
171
+ $('.offset_links', modal)
172
+ .append('<b>Daily</b>')
173
+ .append('<a data-offset="3600*24">Today</a>, ')
174
+ .append('<a data-offset="3600*24" data-offset-off="3600*24">Yesterday</a> ')
175
+ .append('<a data-offset="3600*3*24">Last 3 Days</a> ')
176
+ .append('<a data-offset="3600*7*24">Last 7 Days</a> ')
177
+ .append('<a data-offset="3600*7*24*14">Last 14 Days</a> ')
178
+ .append('<a data-offset="3600*7*24*30">Last 30 Days</a> ');
179
+
180
+ $('.offset_links a', modal)
181
+ .click(offset_opener);
182
+
183
+ $.mask.definitions['~']='[0-5]';
184
+ $.mask.definitions['%']='[0-2]';
185
+ $.mask.definitions['$']='[0-2]';
186
+ $.mask.definitions['#']='[0-3]';
187
+
188
+ $('.button', modal)
189
+ .click(function(){ interval_modal_done(modal) });
190
+
191
+ $('.start_date', modal)
192
+ .mask("#9.$9.2099")
193
+ .keypress(enter_catcher)
194
+ .val(FnordMetric.util.dateFormat(start_timestamp).split(" ")[0]);
195
+
196
+ $('.start_time', modal)
197
+ .mask("%9:~9")
198
+ .keypress(enter_catcher)
199
+ .val(FnordMetric.util.dateFormat(start_timestamp).split(" ")[1]);
200
+
201
+ $('.end_date', modal)
202
+ .mask("#9.$9.2099")
203
+ .keypress(enter_catcher)
204
+ .val(FnordMetric.util.dateFormat(end_timestamp).split(" ")[0]);
205
+
206
+ $('.end_time', modal)
207
+ .mask("%9:~9")
208
+ .keypress(enter_catcher)
209
+ .val(FnordMetric.util.dateFormat(end_timestamp).split(" ")[1]);
210
+
211
+
212
+ /*for(n=0; n < 10; n++){
213
+ var interval = now;
214
+ now -= 3600;
215
+ interval += "-" + now;
216
+ interval_list.append(
217
+ $('<li>')
218
+ .html($('<a href="#">')
219
+ .html(interval)
220
+ .attr('data', interval)
221
+ .click(function(){
222
+ select_interval($(this).attr('data'))
223
+ }))
224
+ );
225
+ }*/
226
+
227
+ FnordMetric.ui.modal({
228
+ height: 280,
229
+ max_width: 570,
230
+ content: modal
231
+ });
232
+ }
233
+
234
+ function select_interval(inter){
235
+ start_timestamp = parseInt(inter.split("-")[0]);
236
+ end_timestamp = parseInt(inter.split("-")[1]);
237
+ updateDatepicker();
238
+ load_interval();
239
+ FnordMetric.ui.close_modal(this);
240
+ }
241
+
242
+ function load_interval(){
243
+ $('.gauge_viewport', viewport)
244
+ .html("");
245
+
246
+ FnordMetric.publish({
247
+ "gauge": gauge_name,
248
+ "type": "render_request",
249
+ "interval": start_timestamp + "-" + end_timestamp
250
+ })
251
+ }
252
+
253
+ return {
254
+ load: load,
255
+ resize: resize,
256
+ announce: announce,
257
+ close: close
258
+ };
259
+
260
+ });
@@ -0,0 +1,21 @@
1
+ FnordMetric.widgets.htmlWidget = function(){
2
+ function render(opts){
3
+
4
+ opts.elem.append(
5
+ $('<div class="headbar small"></div>').html(opts.title)
6
+ ).css({
7
+ 'marginBottom': 20,
8
+ 'overflow': 'hidden'
9
+ });
10
+
11
+ var container = $('<div></div>')
12
+ .addClass('html_container')
13
+ .html(opts.html);
14
+
15
+ opts.elem.append(container);
16
+ }
17
+
18
+ return {
19
+ render: render
20
+ };
21
+ }
@@ -0,0 +1,255 @@
1
+ var FnordMetric = (function(){
2
+
3
+ var canvasElem = false;
4
+ var currentView = false;
5
+ var currentNamespace = false;
6
+ var gauges = {};
7
+ var socket, conf;
8
+
9
+ var navigatedViaHash = false;
10
+
11
+ function renderDashboard(_dash){
12
+ loadView(FnordMetric.views.dashboardView(_dash));
13
+ }
14
+
15
+ function renderGauge(_gauge){
16
+ loadView(FnordMetric.views.gaugeView(_gauge));
17
+ }
18
+
19
+ function renderSidebarGroup(grname){
20
+ var ul = $("<ul>")
21
+ .attr('data-group', grname);
22
+
23
+ $('#sidebar')
24
+ .append('<div class="ul_head">' + grname + '</div>')
25
+ .append(ul);
26
+
27
+ return ul;
28
+ }
29
+
30
+ function renderSidebar(){
31
+ var prev_active = false;
32
+
33
+ if($('#sidebar li.active').length > 0){
34
+ prev_active = $('#sidebar li.active:first').attr('data-token');
35
+ }
36
+
37
+ $('#sidebar')
38
+ .html('');
39
+
40
+ /*if(!conf.hide_overview){
41
+ renderSidebarGroup('Overview')
42
+ .append($('<li class="overview">')
43
+ .append('<span class="picto piechart">')
44
+ .append($('<a href="#" class="title">').html('App Overview')));
45
+ }*/
46
+
47
+ if(!conf.hide_active_users){
48
+ renderSidebarGroup('Overview')
49
+ .append($('<li class="overview">')
50
+ .append($('<a href="#" class="title">').html('Active Users'))
51
+ .click(function(){ renderSessionView(); }));
52
+ }
53
+
54
+ for(gkey in gauges){
55
+ if(!gauges[gkey].group){ gauges[gkey].group = 'Gauges'; }
56
+ if(!gauges[gkey].title){ gauges[gkey].title = gkey; }
57
+
58
+ var ul = $('#sidebar ul[data-group="' + gauges[gkey].group + '"]');
59
+ if(ul.length == 0){ ul = renderSidebarGroup(gauges[gkey].group); }
60
+
61
+ ul.append($('<li class="gauge">')
62
+ .attr('data-token', gkey)
63
+ .attr('data-view', gauges[gkey].view_type)
64
+ .append('<i class="icon-folder-close">')
65
+ .append($('<a href="#" class="title">').html(gauges[gkey].title)));
66
+ }
67
+
68
+ $('#sidebar li').click(sidebarClick);
69
+
70
+ if(prev_active){
71
+ $('#sidebar li[data-token="'+prev_active+'"]').addClass('active');
72
+ }
73
+ }
74
+
75
+ function sidebarClick(){
76
+ $('#sidebar li').removeClass('active');
77
+ $(this).addClass('active');
78
+
79
+ if($(this).attr('data-view') == "dashboard"){
80
+ FnordMetric.renderDashboard($(this).attr('data-token'));
81
+ window.location.hash = 'dashboard/' + $(this).attr('data-token');
82
+ } else if($(this).attr('data-view') == "gauge"){
83
+ FnordMetric.renderGauge($(this).attr('data-token'));
84
+ window.location.hash = 'gauge/' + $(this).attr('data-token');
85
+ }
86
+
87
+ $(this).addClass('active');
88
+
89
+ return false;
90
+ }
91
+
92
+ function addGauge(msg){
93
+ if(!gauges[msg.gauge_key]){
94
+ gauges[msg.gauge_key] = {
95
+ "view_type": msg.view,
96
+ "title": msg.title,
97
+ "tick": msg.tick,
98
+ "group": msg.group
99
+ };
100
+
101
+ renderSidebar();
102
+
103
+ if(!currentView && (window.location.hash.length < 2)){
104
+ sidebarClick.apply($('#sidebar li:first'));
105
+ } else if(!navigatedViaHash){
106
+ navigateViaHash();
107
+ }
108
+ }
109
+ }
110
+
111
+ function renderSessionView(){
112
+ window.location.hash = 'active_users';
113
+ loadView(FnordMetric.views.sessionView());
114
+ }
115
+
116
+ function renderOverviewView(){
117
+ loadView(FnordMetric.views.overviewView());
118
+ }
119
+
120
+ function loadView(_view){
121
+ FnordMetric.ui.close_modal('body');
122
+ if(currentView){ currentView.close(); }
123
+ canvasElem.html('loading!');
124
+ currentView = _view;
125
+ currentView.load(canvasElem);
126
+ resizeView();
127
+ };
128
+
129
+ function resizeView(){
130
+ var viewport_width = window.innerWidth - 220;
131
+ if(viewport_width < 780){ viewport_width=780; }
132
+ $('#viewport').width(viewport_width);
133
+ $('.navbar').width(viewport_width);
134
+ FnordMetric.ui.resizable('.viewport_inner');
135
+ if(currentView){
136
+ currentView.resize(
137
+ canvasElem.innerWidth(),
138
+ canvasElem.innerHeight()
139
+ );
140
+ }
141
+ $('.resize_full_height').height(window.innerHeight-40);
142
+ $('#viewport .viewport_inner').css('minHeight', window.innerHeight-2);
143
+ $('.resize_min_full_height').css('minHeight', window.innerHeight-2);
144
+ $(".resize_listener").trigger('fm_resize');
145
+ };
146
+
147
+
148
+ function init(_conf){
149
+ conf = _conf;
150
+ this.currentNamespace = _conf.token;
151
+
152
+ if(conf.title){ $('title').html(conf.title); }
153
+
154
+ canvasElem = $("<div class='viewport_inner'>");
155
+ canvasElem.addClass('clearfix');
156
+
157
+ var _wrap_elem = $("<div id='wrap'>")
158
+ .append($("<div id='sidebar'>"))
159
+ .append($("<div id='viewport'>").append(canvasElem));
160
+
161
+ connect();
162
+
163
+ $('#app').html(_wrap_elem);
164
+ $(window).resize(resizeView);
165
+ resizeView();
166
+ };
167
+
168
+ function connect(){
169
+ socket = new WebSocket("ws://" + document.location.host + '/stream');
170
+ socket.onmessage = socketMessage;
171
+ socket.onclose = socketClose;
172
+ socket.onopen = socketOpen;
173
+ }
174
+
175
+ function publish(obj){
176
+ if(!obj.namespace){
177
+ obj.namespace = FnordMetric.currentNamespace;
178
+ }
179
+ socket.send(JSON.stringify(obj));
180
+ }
181
+
182
+ function socketMessage(raw){
183
+ var evt = JSON.parse(raw.data);
184
+
185
+ if((evt.type == "discover_response")){
186
+ addGauge(evt);
187
+ } else {
188
+ if(currentView){ currentView.announce(evt); }
189
+ }
190
+ }
191
+
192
+ function socketOpen(){
193
+ console.log("connected...");
194
+ publish({"type": "discover_request"});
195
+ $('.flash_msg_over').fadeOut(function(){ $(this).remove(); });
196
+ }
197
+
198
+ function socketClose(){
199
+ console.log("socket closed");
200
+
201
+ if($('.flash_msg_over').length == 0){
202
+ $(viewport)
203
+ .append($("<div class='flash_msg_over'>")
204
+ .append($("<div class='inner'>")
205
+ .append('<h1>Oopsiedaisy, lost the connection...</h1>')
206
+ .append('<h2>Reconnecting to server...</h2>')
207
+ .append('<div class="loader_white">')));
208
+
209
+ window.setTimeout(function(){
210
+ $('.flash_msg_over').addClass('visible');
211
+ }, 20);
212
+ }
213
+
214
+ window.setTimeout(connect, 1000);
215
+ }
216
+
217
+ function navigateViaHash(){
218
+ if (window.location.hash){
219
+ var elem = null;
220
+ if (!!window.location.hash.match(/^#dashboard\/[a-zA-Z_0-9-]+$/)) {
221
+ elem = $('#sidebar li.gauge[data-token="'+window.location.hash.slice(11)+'"]');
222
+ } else if (!!window.location.hash.match(/^#gauge\/[a-zA-Z_0-9-]+$/)){
223
+ elem = $('#sidebar li.gauge[data-token="'+window.location.hash.slice(7)+'"]');
224
+ } else if(window.location.hash == "#active_users") {
225
+ navigatedViaHash = true;
226
+ renderSessionView();
227
+ }
228
+
229
+ if (elem && (elem.length > 0)) {
230
+ navigatedViaHash = true;
231
+ elem.click();
232
+ }
233
+ }
234
+ }
235
+
236
+ return {
237
+ renderDashboard: renderDashboard,
238
+ renderGauge: renderGauge,
239
+ renderSessionView: renderSessionView,
240
+ renderOverviewView: renderOverviewView,
241
+ resizeView: resizeView,
242
+ init: init,
243
+ publish: publish,
244
+ p: '',
245
+ socket: socket,
246
+ currentNamespace: null,
247
+ currentWidgetUID: 23,
248
+ ui: {},
249
+ views: {},
250
+ widgets: {},
251
+ util: {},
252
+ gauges: gauges
253
+ };
254
+
255
+ })();