fnordmetric 0.7.5 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/V1.0-ROADMAP +97 -0
- data/doc/full_example.rb +95 -511
- data/doc/legacy_example.rb +640 -0
- data/doc/minimal_example.rb +26 -0
- data/doc/preview3.png +0 -0
- data/fnordmetric.gemspec +3 -2
- data/lib/fnordmetric/acceptors/acceptor.rb +29 -0
- data/lib/fnordmetric/{inbound_stream.rb → acceptors/tcp_acceptor.rb} +8 -5
- data/lib/fnordmetric/{inbound_datagram.rb → acceptors/udp_acceptor.rb} +9 -8
- data/lib/fnordmetric/api.rb +2 -2
- data/lib/fnordmetric/context.rb +37 -18
- data/lib/fnordmetric/defaults.rb +9 -0
- data/lib/fnordmetric/ext.rb +72 -0
- data/lib/fnordmetric/gauge.rb +37 -10
- data/lib/fnordmetric/gauge_calculations.rb +38 -16
- data/lib/fnordmetric/gauge_modifiers.rb +67 -0
- data/lib/fnordmetric/gauge_rendering.rb +40 -0
- data/lib/fnordmetric/gauge_validations.rb +15 -0
- data/lib/fnordmetric/gauges/distribution_gauge.rb +85 -0
- data/lib/fnordmetric/gauges/timeseries_gauge.rb +143 -0
- data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
- data/lib/fnordmetric/histogram.rb +57 -0
- data/lib/fnordmetric/logger.rb +42 -36
- data/lib/fnordmetric/namespace.rb +47 -23
- data/lib/fnordmetric/session.rb +6 -6
- data/lib/fnordmetric/standalone.rb +15 -35
- data/lib/fnordmetric/timeseries.rb +79 -0
- data/lib/fnordmetric/toplist.rb +61 -0
- data/lib/fnordmetric/version.rb +1 -1
- data/lib/fnordmetric/web/app.rb +122 -0
- data/lib/fnordmetric/web/app_helpers.rb +42 -0
- data/lib/fnordmetric/{dashboard.rb → web/dashboard.rb} +4 -0
- data/lib/fnordmetric/{event.rb → web/event.rb} +7 -2
- data/lib/fnordmetric/web/reactor.rb +87 -0
- data/lib/fnordmetric/web/web.rb +53 -0
- data/lib/fnordmetric/web/websocket.rb +38 -0
- data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
- data/lib/fnordmetric/{html_widget.rb → widgets/html_widget.rb} +0 -0
- data/lib/fnordmetric/widgets/numbers_widget.rb +56 -0
- data/lib/fnordmetric/{pie_widget.rb → widgets/pie_widget.rb} +0 -0
- data/lib/fnordmetric/widgets/timeseries_widget.rb +55 -0
- data/lib/fnordmetric/widgets/toplist_widget.rb +64 -0
- data/lib/fnordmetric/worker.rb +26 -25
- data/lib/fnordmetric.rb +85 -115
- data/readme.md +362 -0
- data/spec/gauge_like_shared.rb +54 -0
- data/spec/gauge_spec.rb +2 -36
- data/spec/namespace_spec.rb +25 -11
- data/spec/spec_helper.rb +4 -0
- data/spec/{inbound_stream_spec.rb → tcp_acceptor_spec.rb} +3 -3
- data/spec/timeseries_gauge_spec.rb +54 -0
- data/spec/{inbound_datagram_spec.rb → udp_acceptor_spec.rb} +3 -3
- data/web/fnordmetric.css +786 -0
- data/web/haml/app.haml +38 -0
- data/web/haml/distribution_gauge.haml +118 -0
- data/web/haml/timeseries_gauge.haml +80 -0
- data/web/haml/toplist_gauge.haml +194 -0
- data/web/img/head.png +0 -0
- data/web/img/list.png +0 -0
- data/web/img/list_active.png +0 -0
- data/web/img/list_hover.png +0 -0
- data/web/img/loader_white.gif +0 -0
- data/web/img/navbar.png +0 -0
- data/web/img/navbar_btn.png +0 -0
- data/web/img/picto_gauge.png +0 -0
- data/web/js/fnordmetric.bars_widget.js +178 -0
- data/web/js/fnordmetric.dashboard_view.js +99 -0
- data/web/js/fnordmetric.gauge_view.js +260 -0
- data/web/js/fnordmetric.html_widget.js +21 -0
- data/web/js/fnordmetric.js +255 -0
- data/web/js/fnordmetric.numbers_widget.js +121 -0
- data/web/js/fnordmetric.overview_view.js +35 -0
- data/web/js/fnordmetric.pie_widget.js +118 -0
- data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
- data/web/js/fnordmetric.session_view.js +343 -0
- data/web/js/fnordmetric.timeline_widget.js +333 -0
- data/web/js/fnordmetric.timeseries_widget.js +388 -0
- data/web/js/fnordmetric.toplist_widget.js +112 -0
- data/web/js/fnordmetric.ui.js +91 -0
- data/web/js/fnordmetric.util.js +244 -0
- data/{pub → web}/loader.gif +0 -0
- data/web/vendor/d3.v2.js +9382 -0
- data/web/vendor/font-awesome/css/font-awesome.css +239 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.svg +175 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.svgz +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
- data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
- data/web/vendor/jquery-1.6.2.min.js +18 -0
- data/web/vendor/jquery-ui.min.js +413 -0
- data/web/vendor/jquery.maskedinput.js +252 -0
- data/web/vendor/rickshaw.css +286 -0
- data/web/vendor/rickshaw.fnordmetric.js +2676 -0
- metadata +129 -79
- data/Gemfile +0 -6
- data/README.md +0 -404
- data/Rakefile +0 -6
- data/doc/version +0 -1
- data/haml/app.haml +0 -79
- data/haml/widget.haml +0 -9
- data/lib/fnordmetric/app.rb +0 -163
- data/lib/fnordmetric/average_metric.rb +0 -7
- data/lib/fnordmetric/bars_widget.rb +0 -26
- data/lib/fnordmetric/combine_metric.rb +0 -7
- data/lib/fnordmetric/count_metric.rb +0 -13
- data/lib/fnordmetric/funnel_widget.rb +0 -2
- data/lib/fnordmetric/metric.rb +0 -80
- data/lib/fnordmetric/metric_api.rb +0 -37
- data/lib/fnordmetric/numbers_widget.rb +0 -26
- data/lib/fnordmetric/report.rb +0 -29
- data/lib/fnordmetric/sum_metric.rb +0 -13
- data/lib/fnordmetric/timeline_widget.rb +0 -30
- data/lib/fnordmetric/toplist_widget.rb +0 -25
- data/pub/fnordmetric.css +0 -145
- data/pub/fnordmetric.js +0 -1179
- data/pub/vendor/highcharts.js +0 -170
- data/pub/vendor/jquery-1.6.1.min.js +0 -18
@@ -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
|
+
' ‐ ' +
|
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;">—</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
|
+
})();
|