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,121 @@
1
+ FnordMetric.widgets.numbersWidget = function(){
2
+
3
+ var max_per_row = 8;
4
+ var opts;
5
+
6
+ function render(_opts){
7
+
8
+ opts = _opts;
9
+
10
+ opts.elem.append(
11
+ $('<div class="headbar small"></div>').html(opts.title)
12
+ ).css({
13
+ 'marginBottom': 20,
14
+ 'overflow': 'hidden'
15
+ });
16
+
17
+ if(!opts.series_titles){
18
+ opts.series_titles = {};
19
+ }
20
+
21
+ for(k in opts.series){
22
+
23
+ if (!opts.series_titles[opts.series[k]]){
24
+ opts.series_titles[opts.series[k]] = opts.series[k];
25
+ }
26
+
27
+ var container = $('<div></div>')
28
+ .addClass('numbers_container')
29
+ .attr('rel', opts.series[k])
30
+ .append($('<div class="title">').html(opts.series_titles[opts.series[k]]));
31
+
32
+ opts.elem.append(container);
33
+ }
34
+
35
+ if(opts.autoupdate){
36
+ var secs = parseInt(opts.autoupdate);
37
+ if(secs > 0){
38
+
39
+ var autoupdate_interval = window.setInterval(function(){
40
+ requestValues();
41
+ }, secs*1000);
42
+
43
+ $('body').bind('fm_dashboard_close', function(){
44
+ window.clearInterval(autoupdate_interval);
45
+ });
46
+ }
47
+ }
48
+
49
+ requestValues();
50
+ }
51
+
52
+ function resize(){
53
+ $('.numbers_container', opts.elem).each(function(i, e){
54
+ var num_numbers = $('.number', e).length;
55
+ if(num_numbers > max_per_row){ num_numbers = max_per_row; }
56
+ $(e).css('width', (num_numbers * 95)+'px');
57
+ });
58
+ }
59
+
60
+ function requestValues(){
61
+ for(k in opts.series){
62
+ FnordMetric.publish({
63
+ "namespace": FnordMetric.currentNamespace,
64
+ "type": "widget_request",
65
+ "klass": "NumbersWidget",
66
+ "channel": opts.channel,
67
+ "cmd": "values_for",
68
+ "gauge": opts.series[k],
69
+ "offsets": opts.offsets,
70
+ "widget_key": opts.widget_key
71
+ })
72
+ }
73
+ }
74
+
75
+ function renderValues(series, values){
76
+ for(vkey in values){
77
+ if(!values[vkey].desc){ values[vkey].desc = vkey; }
78
+
79
+ var celem = $('.numbers_container[rel="'+series+'"]', opts.elem)
80
+ var velem = $('.number[rel="'+vkey+'"]', celem);
81
+ var vdesc = FnordMetric.util.evilFormat(values[vkey].desc);
82
+
83
+ if (velem.length == 0){
84
+ velem = $('<div></div>')
85
+ .addClass('number')
86
+ .attr('rel', vkey)
87
+ .append($('<span class="desc">').html(vdesc))
88
+ .append($('<span class="value">').html(0))
89
+ celem.append(velem);
90
+ }
91
+
92
+ if(!!opts.dont_animate){
93
+ velem.attr('data', values[vkey].value)
94
+ $('.value', velem).html(FnordMetric.util.formatGaugeValue(vkey, values[vkey].value));
95
+ } else {
96
+ velem.attr('data', values[vkey].value)
97
+ }
98
+ }
99
+
100
+ resize();
101
+
102
+ if(!opts.dont_animate){
103
+ FnordMetric.util.updateNumbers($(opts.elem), 4);
104
+ }
105
+ }
106
+
107
+ function announce(ev){
108
+ if(ev.widget_key == opts.widget_key){
109
+ if((ev.class == "widget_response") && (ev.cmd == "values_for")){
110
+ renderValues(ev.series, ev.values)
111
+ }
112
+ }
113
+ }
114
+
115
+
116
+ return {
117
+ render: render,
118
+ announce: announce
119
+ };
120
+
121
+ };
@@ -0,0 +1,35 @@
1
+ FnordMetric.views.overviewView = function(){
2
+ var widgets = [];
3
+ var viewport = null;
4
+
5
+ function load(_viewport){
6
+ viewport = _viewport.html('');
7
+
8
+ viewport.append('<div class="navbar"></div>');
9
+ viewport.append('<h1>Application Overview</h1>');
10
+ viewport.append('<h3>Welcome to FnordMetric :)</h3>');
11
+
12
+ // $.ajax({
13
+ // url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/dashboard/'+dashboard_name,
14
+ // success: function(resp, status){
15
+ // var conf = JSON.parse(resp);
16
+ // renderWidgets(conf.widgets);
17
+ // }
18
+ // });
19
+ };
20
+
21
+ function resize(){
22
+ // here be dragons
23
+ }
24
+
25
+ function close(){
26
+ // here be dragons
27
+ }
28
+
29
+ return {
30
+ load: load,
31
+ resize: resize,
32
+ close: close
33
+ };
34
+
35
+ };
@@ -0,0 +1,118 @@
1
+ FnordMetric.widgets.pieWidget = function(){
2
+
3
+ function render(opts){
4
+
5
+ return drawLayout();
6
+
7
+ var widget_uid = FnordMetric.util.getNextWidgetUID();
8
+ var chart=false;
9
+
10
+ function redraw(first_time, silent){
11
+ if(!silent){ $(opts.elem).css('opacity', 0.5); }
12
+ var gauge_values = {};
13
+ var gauges_left = opts.gauges.length;
14
+ var at = parseInt(new Date().getTime()/1000);
15
+ $(opts.gauges).each(function(i,gauge){
16
+ $.ajax({
17
+ url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/gauge/'+gauge+'?at='+at,
18
+ success: function(_resp){
19
+ var resp = JSON.parse(_resp);
20
+ gauges_left -= 1;
21
+ for(_tk in resp){
22
+ gauge_values[gauge] = parseInt(resp[_tk]||0);
23
+ }
24
+ if(gauges_left==0){
25
+ redrawChart(first_time, gauge_values);
26
+ }
27
+ }
28
+ });
29
+ });
30
+ }
31
+
32
+ function redrawChart(first_time, gauge_values){
33
+
34
+ var series_data = [];
35
+
36
+ for(_gkey in gauge_values){
37
+ series_data.push([
38
+ opts.gauge_titles[_gkey],
39
+ gauge_values[_gkey]
40
+ ]);
41
+ }
42
+
43
+ /*chart = new Highcharts.Chart({
44
+ chart: {
45
+ renderTo: 'container-'+widget_uid,
46
+ defaultSeriesType: 'pie',
47
+ height: 270,
48
+ spacingTop: 5,
49
+ spacingBottom: 30
50
+ },
51
+ credits: {
52
+ enabled: false
53
+ },
54
+ title: { text: '' },
55
+ legend: {
56
+ layout: 'horizontal',
57
+ align: 'top',
58
+ verticalAlign: 'top',
59
+ margin: 25,
60
+ borderWidth: 0
61
+ },
62
+ tooltip: {
63
+ formatter: function() {
64
+ return '<b>'+ this.point.name +'</b>: '+ this.y + ' (' + this.percentage.toFixed(1) + '%)';
65
+ }
66
+ },
67
+ plotOptions: {
68
+ pie: {
69
+ animation: first_time,
70
+ dataLabels: {
71
+ formatter: function() {
72
+ return '<b>'+ this.point.name +'</b><br />'+ this.percentage.toFixed(1) +' %';
73
+ }
74
+ }
75
+ }
76
+ },
77
+ series: [
78
+ {
79
+ name: opts.title,
80
+ data: series_data
81
+ }
82
+ ]
83
+ });*/
84
+
85
+ //chart.redraw();
86
+ $(opts.elem).css('opacity', 1);
87
+ }
88
+
89
+ function drawLayout(){
90
+ $(opts.elem).append( $('<div></div>').attr('class', 'headbar small').append(
91
+ $('<span></span>').html(opts.title)
92
+ ) ).append(
93
+ $('<div></div>').attr('id', 'container-'+widget_uid).css({
94
+ height: 270
95
+ })
96
+ );
97
+ }
98
+
99
+ drawLayout();
100
+ redraw(true);
101
+
102
+ if(opts.autoupdate){
103
+ var autoupdate_interval = window.setInterval(function(){
104
+ redraw(false, true);
105
+ }, opts.autoupdate*1000);
106
+
107
+ $('body').bind('fm_dashboard_close', function(){
108
+ window.clearInterval(autoupdate_interval);
109
+ });
110
+ }
111
+
112
+ }
113
+
114
+ return {
115
+ render: render
116
+ };
117
+
118
+ };
@@ -0,0 +1,175 @@
1
+ FnordMetric.widgets.realtimeValueWidget = function(){
2
+
3
+ var xpadding = 20;
4
+ var ypadding = 10;
5
+ var bmargin = 6;
6
+ var bwidth = 5;
7
+ var bcolor = '#06C';
8
+ var zero_height = 5;
9
+
10
+
11
+ var widget_uid = FnordMetric.util.getNextWidgetUID();
12
+ var width, height, canvas, opts, max;
13
+ var bars = [];
14
+ var tick = false;
15
+ var next_values = [];
16
+ var next_value_interval = false;
17
+
18
+
19
+ function render(_opts){
20
+ opts = _opts;
21
+
22
+ drawLayout();
23
+
24
+ width = opts.elem.width() - (xpadding * 2) - 15 - 250;
25
+ height = opts.height || 210;
26
+ //xtick = width / (xticks - 1);
27
+
28
+ canvas = d3.select('#container-'+widget_uid)
29
+ .append("svg:svg")
30
+ .attr("width", width+(2*xpadding))
31
+ .attr("height", height);
32
+
33
+ canvas.selectAll("*").remove();
34
+
35
+ changeTick(opts.ticks[0]);
36
+ }
37
+
38
+ function changeTick(_tick){
39
+ tick = _tick;
40
+ canvas.selectAll('.valuebar').remove();
41
+ next_values = [];
42
+ max = 1;
43
+
44
+ for(var n=parseInt(width / bmargin); n > 0; n--){
45
+ drawValue(0, n-1);
46
+ }
47
+ }
48
+
49
+ function nextValue(value){
50
+ if (value > max){
51
+ var old_max = max;
52
+ max = value * 1.2;
53
+ canvas.selectAll('.valuebar').each(function(){
54
+ var theight = parseInt($(this).attr('height'))*(old_max/max);
55
+ if(theight < zero_height){ theight = zero_height; }
56
+ $(this).attr("y", height-(ypadding*2)-theight)
57
+ $(this).attr("height", theight);
58
+ });
59
+ }
60
+
61
+ drawValue(value);
62
+
63
+ canvas.selectAll('.valuebar').each(function(){
64
+ var new_x = parseInt($(this).attr('x'))-bmargin;
65
+ if(new_x < 5){ new_x = 5; }
66
+ $(this).attr("x", new_x);
67
+ });
68
+
69
+ pruneValues();
70
+ next_value_interval = false;
71
+ nextValueAsync();
72
+ }
73
+
74
+ function nextValueAsync(value){
75
+ if(value != undefined){
76
+ next_values.unshift(value);
77
+ $('.big_number .value', opts.elem).html(FnordMetric.util.formatValue(value));
78
+ }
79
+ if(next_values.length > 0){
80
+ if(!next_value_interval){
81
+ next_value_interval = window.setInterval(function(){
82
+ var _v = next_values.pop();
83
+ if(_v != undefined){ nextValue(_v); }
84
+ }, 20);
85
+ }
86
+ }
87
+ }
88
+
89
+ function pruneValues(){
90
+ while(bars.length > (width / bmargin)){
91
+ bars.pop().remove();
92
+ }
93
+ }
94
+
95
+ function drawValue(value, offset){
96
+ if(!offset){ offset = 0; }
97
+ if(!value){ value = 0; }
98
+
99
+ if(value > 0){
100
+ var theight = (height-(ypadding*4)) * (value/max);
101
+ var fillc = bcolor;
102
+ } else {
103
+ var theight = zero_height;
104
+ var fillc = '#ddd';
105
+ }
106
+
107
+ if(theight < zero_height){
108
+ theight = zero_height;
109
+ }
110
+
111
+ bars.unshift(canvas
112
+ .append("svg:rect")
113
+ .attr("class", "valuebar")
114
+ .attr("x", width+xpadding-(offset*bmargin))
115
+ .attr("y", height-(ypadding*2)-theight)
116
+ .attr("fill", fillc)
117
+ .attr("width", bwidth)
118
+ .attr("height", theight));
119
+
120
+ }
121
+
122
+ function announce(evt){
123
+ if((evt._class == "widget_push") && (evt.cmd == "value")){
124
+ if(evt.values[tick]){
125
+ nextValueAsync(parseFloat(evt.values[tick]));
126
+ } else {
127
+ nextValueAsync(0);
128
+ }
129
+ }
130
+ }
131
+
132
+ function drawLayout(){
133
+ if(!opts.no_headbar){
134
+ $(opts.elem).append( $('<div></div>').attr('class', 'headbar').append(
135
+ $('<h2></h2>').html(opts.title)
136
+ ));
137
+ }
138
+
139
+ $(opts.elem).append(
140
+ $('<div></div>').attr('id', 'container-'+widget_uid).css({
141
+ height: opts.height + 6,
142
+ marginBottom: 20,
143
+ overflow: 'hidden'
144
+ }).append(
145
+ $('<div></div>')
146
+ .addClass('big_number number')
147
+ .attr('data-current', 0)
148
+ .attr('data', 0)
149
+ .append($('<span class="desc">').html(opts.desc))
150
+ .append($('<span class="value">'))
151
+ )
152
+ );
153
+
154
+ if(opts.ticks){
155
+ $('.headbar', opts.elem).append('<div class="tick_btns btn_group" style="margin-right:17px;"></div>');
156
+ for(__tick in opts.ticks){
157
+ var _tick = opts.ticks[__tick];
158
+ $('.tick_btns', opts.elem).append(
159
+ $('<div></div>').attr('class', 'button tick').append($('<span></span>')
160
+ .html(FnordMetric.util.formatTimeRange(_tick)))
161
+ .attr('data-tick', _tick)
162
+ .click(function(){
163
+ changeTick($(this).attr('data-tick'));
164
+ })
165
+ );
166
+ }
167
+ }
168
+ }
169
+
170
+ return {
171
+ render: render,
172
+ announce: announce
173
+ }
174
+
175
+ };