bp-fnordmetric 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/Gemfile +6 -0
  2. data/Rakefile +6 -0
  3. data/fnordmetric.gemspec +41 -0
  4. data/lib/fnordmetric.rb +149 -0
  5. data/lib/fnordmetric/acceptors/acceptor.rb +42 -0
  6. data/lib/fnordmetric/acceptors/amqp_acceptor.rb +56 -0
  7. data/lib/fnordmetric/acceptors/fyrehose_acceptor.rb +43 -0
  8. data/lib/fnordmetric/acceptors/stomp_acceptor.rb +71 -0
  9. data/lib/fnordmetric/acceptors/tcp_acceptor.rb +58 -0
  10. data/lib/fnordmetric/acceptors/udp_acceptor.rb +37 -0
  11. data/lib/fnordmetric/api.rb +46 -0
  12. data/lib/fnordmetric/cache.rb +20 -0
  13. data/lib/fnordmetric/context.rb +96 -0
  14. data/lib/fnordmetric/defaults.rb +22 -0
  15. data/lib/fnordmetric/enterprise/compatibility_handler.rb +42 -0
  16. data/lib/fnordmetric/ext.rb +75 -0
  17. data/lib/fnordmetric/gauge.rb +98 -0
  18. data/lib/fnordmetric/gauge_calculations.rb +106 -0
  19. data/lib/fnordmetric/gauge_modifiers.rb +144 -0
  20. data/lib/fnordmetric/gauge_rendering.rb +40 -0
  21. data/lib/fnordmetric/gauge_validations.rb +15 -0
  22. data/lib/fnordmetric/gauges/distribution_gauge.rb +87 -0
  23. data/lib/fnordmetric/gauges/server_health_gauge.rb +13 -0
  24. data/lib/fnordmetric/gauges/timeseries_gauge.rb +138 -0
  25. data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
  26. data/lib/fnordmetric/histogram.rb +64 -0
  27. data/lib/fnordmetric/logger.rb +63 -0
  28. data/lib/fnordmetric/namespace.rb +208 -0
  29. data/lib/fnordmetric/session.rb +139 -0
  30. data/lib/fnordmetric/standalone.rb +20 -0
  31. data/lib/fnordmetric/timeseries.rb +79 -0
  32. data/lib/fnordmetric/toplist.rb +61 -0
  33. data/lib/fnordmetric/udp_client.rb +22 -0
  34. data/lib/fnordmetric/util.rb +25 -0
  35. data/lib/fnordmetric/version.rb +3 -0
  36. data/lib/fnordmetric/web/app.rb +63 -0
  37. data/lib/fnordmetric/web/app_helpers.rb +42 -0
  38. data/lib/fnordmetric/web/dashboard.rb +40 -0
  39. data/lib/fnordmetric/web/event.rb +99 -0
  40. data/lib/fnordmetric/web/reactor.rb +127 -0
  41. data/lib/fnordmetric/web/web.rb +59 -0
  42. data/lib/fnordmetric/web/websocket.rb +41 -0
  43. data/lib/fnordmetric/widget.rb +82 -0
  44. data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
  45. data/lib/fnordmetric/widgets/html_widget.rb +28 -0
  46. data/lib/fnordmetric/widgets/numbers_widget.rb +80 -0
  47. data/lib/fnordmetric/widgets/pie_widget.rb +23 -0
  48. data/lib/fnordmetric/widgets/timeseries_widget.rb +65 -0
  49. data/lib/fnordmetric/widgets/toplist_widget.rb +68 -0
  50. data/lib/fnordmetric/worker.rb +89 -0
  51. data/lib/fnordmetric/zero_config_gauge.rb +138 -0
  52. data/run_specs.sh +11 -0
  53. data/spec/api_spec.rb +49 -0
  54. data/spec/context_spec.rb +42 -0
  55. data/spec/dashboard_spec.rb +38 -0
  56. data/spec/event_spec.rb +170 -0
  57. data/spec/ext_spec.rb +14 -0
  58. data/spec/fnordmetric_spec.rb +56 -0
  59. data/spec/gauge_like_shared.rb +56 -0
  60. data/spec/gauge_modifiers_spec.rb +583 -0
  61. data/spec/gauge_spec.rb +230 -0
  62. data/spec/namespace_spec.rb +114 -0
  63. data/spec/session_spec.rb +231 -0
  64. data/spec/spec_helper.rb +49 -0
  65. data/spec/tcp_acceptor_spec.rb +35 -0
  66. data/spec/timeseries_gauge_spec.rb +56 -0
  67. data/spec/udp_acceptor_spec.rb +35 -0
  68. data/spec/util_spec.rb +46 -0
  69. data/spec/widget_spec.rb +113 -0
  70. data/spec/worker_spec.rb +40 -0
  71. data/web/.gitignore +4 -0
  72. data/web/build.sh +34 -0
  73. data/web/css/fnordmetric.core.css +868 -0
  74. data/web/haml/app.haml +20 -0
  75. data/web/haml/distribution_gauge.haml +118 -0
  76. data/web/haml/timeseries_gauge.haml +80 -0
  77. data/web/haml/toplist_gauge.haml +194 -0
  78. data/web/img/head.png +0 -0
  79. data/web/img/list.png +0 -0
  80. data/web/img/list_active.png +0 -0
  81. data/web/img/list_hover.png +0 -0
  82. data/web/img/loader.gif +0 -0
  83. data/web/img/loader_white.gif +0 -0
  84. data/web/img/navbar.png +0 -0
  85. data/web/img/navbar_btn.png +0 -0
  86. data/web/img/picto_gauge.png +0 -0
  87. data/web/js/fnordmetric.bars_widget.js +178 -0
  88. data/web/js/fnordmetric.dashboard_view.js +99 -0
  89. data/web/js/fnordmetric.gauge_explorer.js +173 -0
  90. data/web/js/fnordmetric.gauge_view.js +260 -0
  91. data/web/js/fnordmetric.html_widget.js +21 -0
  92. data/web/js/fnordmetric.js +315 -0
  93. data/web/js/fnordmetric.numbers_widget.js +122 -0
  94. data/web/js/fnordmetric.overview_view.js +35 -0
  95. data/web/js/fnordmetric.pie_widget.js +118 -0
  96. data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
  97. data/web/js/fnordmetric.session_view.js +342 -0
  98. data/web/js/fnordmetric.timeline_widget.js +333 -0
  99. data/web/js/fnordmetric.timeseries_widget.js +405 -0
  100. data/web/js/fnordmetric.toplist_widget.js +119 -0
  101. data/web/js/fnordmetric.ui.js +91 -0
  102. data/web/js/fnordmetric.util.js +248 -0
  103. data/web/vendor/font-awesome/css/font-awesome-ie7.min.css +22 -0
  104. data/web/vendor/font-awesome/css/font-awesome.css +540 -0
  105. data/web/vendor/font-awesome/css/font-awesome.min.css +33 -0
  106. data/web/vendor/font-awesome/font/FontAwesome.otf +0 -0
  107. data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
  108. data/web/vendor/font-awesome/font/fontawesome-webfont.svg +284 -0
  109. data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
  110. data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
  111. data/web/vendor/jquery-1.6.2.min.js +18 -0
  112. data/web/vendor/jquery-ui.min.js +6 -0
  113. data/web/vendor/jquery.combobox.js +129 -0
  114. data/web/vendor/jquery.maskedinput.js +252 -0
  115. metadata +438 -0
@@ -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
+ };
@@ -0,0 +1,342 @@
1
+ FnordMetric.views.sessionView = (function(){
2
+
3
+ var listElem = $('<ul class="session_list"></ul>');
4
+ var feedInnerElem = $('<ul class="feed_inner"></ul>');
5
+ var typeListElem = $('<ul class="event_type_list"></ul>');
6
+
7
+ var filterElem = $('<div class="events_sidebar"></div>')
8
+ .append("<div class='headbar small'>Event Types</div>")
9
+ .append(typeListElem);
10
+
11
+ var feedElem = $('<div class="sessions_feed"></div>').append(feedInnerElem);
12
+ var sideElem = $('<div class="sessions_sidebar"></div>').append(listElem);
13
+
14
+ var eventsPolledUntil = false;
15
+ var eventsFilter = {uncheckedTypes: [], checkedSessions: []};
16
+ var sessionData = {};
17
+ var pollRunning = true;
18
+ var first_poll = true;
19
+
20
+ function load(elem){
21
+ eventsPolledUntil = parseInt(new Date().getTime()/10000);
22
+
23
+ elem.html('')
24
+ .append('<div class="navbar"></div>');
25
+
26
+ FnordMetric.ui.navbar($('.navbar', viewport), {
27
+ breadcrumb: [
28
+ ["Fnord", "/group/fnord"],
29
+ ["Active Users", "/active_users"]
30
+ ],
31
+ buttons: [
32
+ ["<i class='icon-refresh'></i>Refresh", function(){ }]
33
+ ]
34
+ });
35
+
36
+ elem
37
+ .append(filterElem.css('marginTop', '47px'))
38
+ .append(feedElem)
39
+ .append(sideElem);
40
+
41
+ startPoll();
42
+ loadEventTypes();
43
+ };
44
+
45
+ function resize(_width, _height){
46
+ $('.sessions_feed').width(_width-452);
47
+ };
48
+
49
+ function startPoll(){
50
+ (doSessionPoll())();
51
+ (doEventsPoll())();
52
+ FnordMetric.views.sessionView.session_poll = window.setInterval(doSessionPoll(), 1000);
53
+ };
54
+
55
+ function stopPoll(){
56
+ pollRunning = false;
57
+ window.clearInterval(FnordMetric.views.sessionView.session_poll);
58
+ }
59
+
60
+ function doSessionPoll(){
61
+ return (function(){
62
+ /*$.ajax({
63
+ url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/sessions',
64
+ success: callbackSessionPoll()
65
+ });*/
66
+ sortSessions();
67
+ });
68
+ };
69
+
70
+ function loadEventHistory(params){
71
+ feedInnerElem.html('');
72
+ /*$.ajax({
73
+ url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/events',
74
+ data: params,
75
+ success: function(_data, _status){
76
+ var data = JSON.parse(_data).events;
77
+ for(var n=data.length; n >= 0; n--){
78
+ if(data[n]){ renderEvent(data[n]); }
79
+ }
80
+ }
81
+ });*/
82
+ }
83
+
84
+ function callbackSessionPoll(){
85
+ return (function(_data, _status){
86
+ $.each(JSON.parse(_data).sessions, function(i,v){
87
+ updateSession(v);
88
+ });
89
+ sortSessions();
90
+ });
91
+ };
92
+
93
+ function loadEventTypes(data){
94
+ typeListElem.html('');
95
+ $(data).each(function(i,v){
96
+ if((v.length > 0) && (v.slice(0,5)!='_set_')){
97
+ addEventType(v,v);
98
+ }
99
+ });
100
+ };
101
+
102
+ function setCheckboxesCheckedState(types_state, sessions_state) {
103
+ $('.event_type_list .event_type input').attr('checked', types_state);
104
+ $('.session_list .session input').attr('checked', sessions_state);
105
+ }
106
+
107
+ function addEventType(type, display){
108
+ typeListElem.append(
109
+ $('<li class="event_type"></li>').append(
110
+ $('<span class="history"></span>').html('history')
111
+ .click(function(){
112
+ setCheckboxesCheckedState(true, true);
113
+ $('input', $(this).parent()).attr('checked', true);
114
+ updateEventFilter(); loadEventHistory({type: type});
115
+ })
116
+ ).append(
117
+ $('<input type="checkbox" />').attr('checked', true)
118
+ .click(function(){ updateEventFilter(); })
119
+ ).append(
120
+ $('<span></span>').html(display)
121
+ ).attr('rel', type)
122
+ );
123
+ }
124
+
125
+ function updateEventFilter(){
126
+ var _unchecked_types = [];
127
+ $('ul.event_type_list li.event_type').each(function(i,v){
128
+ if(!$('input', v).attr('checked')){
129
+ _unchecked_types.push($(v).attr('rel'));
130
+ }
131
+ });
132
+ eventsFilter.uncheckedTypes = _unchecked_types;
133
+
134
+ var _checked_sessions = [];
135
+ $('ul.session_list li.session').each(function(i,v){
136
+ if($('input', v).attr('checked')){
137
+ _checked_sessions.push($(v).data().session);
138
+ }
139
+ });
140
+ eventsFilter.checkedSessions = _checked_sessions;
141
+ }
142
+
143
+ function doEventsPoll(){
144
+ return (function(){
145
+
146
+ /*$.ajax({
147
+ url: FnordMetric.p + '/' + FnordMetric.currentNamespace+'/events?since='+eventsPolledUntil,
148
+ success: callbackEventsPoll()
149
+ });*/
150
+
151
+ FnordMetric.publish({
152
+ "type": "active_users_request",
153
+ "first_poll": first_poll,
154
+ "since": eventsPolledUntil
155
+ });
156
+
157
+ first_poll = false;
158
+
159
+ });
160
+ };
161
+
162
+ function announce(evt){
163
+ if (evt.type == "active_users_response"){
164
+ callbackEventsPoll(evt);
165
+ $(evt.sessions).each(function(){ updateSession(this); });
166
+ if(evt.types.length > 0){ loadEventTypes(evt.types); }
167
+ }
168
+ }
169
+
170
+ function callbackEventsPoll(data){
171
+ var events = data.events;
172
+ var timeout = 1000;
173
+ var maxevents = 200;
174
+ var passesFiltering = function(event_data) {
175
+ var passes_type_filtering = false;
176
+ var passes_session_filtering = false;
177
+ if(eventsFilter.uncheckedTypes.indexOf(event_data._type) == -1) {
178
+ if(parseInt(v._time)<=eventsPolledUntil) {
179
+ passes_type_filtering = true;
180
+ }
181
+ }
182
+ if(!passes_type_filtering) return false;
183
+
184
+ if(eventsFilter.checkedSessions.length == 0){
185
+ return true; // No filter set - show all events
186
+ } else {
187
+ if(event_data._session_key){
188
+ if(eventsFilter.checkedSessions.indexOf(event_data._session_key) >= 0){
189
+ return true; // Filter set and match
190
+ } else {
191
+ return false; // Filter set but no match
192
+ }
193
+ } else {
194
+ return false; // Filter set but event is not associated with session
195
+ }
196
+ }
197
+ }
198
+
199
+ if(events.length > 0){
200
+ eventsPolledUntil = parseInt(events[0]._time)-1;
201
+ }
202
+ for(var n=events.length-1; n >= 0; n--){
203
+ var v = events[n];
204
+ if(passesFiltering(v)) {
205
+ renderEvent(v);
206
+ }
207
+ };
208
+ var elems = $("p", feedInnerElem);
209
+ for(var n=maxevents; n < elems.length; n++){
210
+ $(elems[n]).remove();
211
+ }
212
+ if(pollRunning){
213
+ window.setTimeout(doEventsPoll(), timeout);
214
+ }
215
+ };
216
+
217
+ function updateSession(session_data){
218
+ var session_key = session_data.session_key;
219
+ if(!sessionData[session_key]){
220
+ updateEventFilter()
221
+ }
222
+ sessionData[session_key] = session_data;
223
+ renderSession(session_data);
224
+ }
225
+
226
+ function sortSessions(){
227
+ }
228
+
229
+ function renderSession(session_data){
230
+
231
+ var session_name = session_data["_name"];
232
+ var session_time = FnordMetric.util.formatTimeSince(session_data["_updated_at"]);
233
+ var session_elem = $('li[data-session='+session_data["session_key"]+']:first');
234
+
235
+ if(session_elem.length>0){
236
+
237
+ if(session_data["_picture"] && (session_data["_picture"].length > 1)){
238
+ $('.picture img', session_elem).attr('src', session_data["_picture"])
239
+ }
240
+
241
+ if(session_name){
242
+ $('.name', session_elem).html(session_name);
243
+ }
244
+
245
+ $('.time', session_elem).html(session_time);
246
+
247
+ } else {
248
+
249
+ var session_picture = $('<img width="25" />');
250
+
251
+ if(!session_name){
252
+ session_name = session_data["session_key"].substr(0,15)
253
+ };
254
+
255
+ if(session_data["_picture"]){
256
+ session_picture.attr('src', session_data["_picture"]);
257
+ };
258
+
259
+ listElem.append(
260
+ $('<li class="session"></li>').append(
261
+ $('<div class="picture"></div>').html(session_picture)
262
+ ).append(
263
+ $('<span class="name"></span>').html(session_name)
264
+ ).append(
265
+ $('<span class="time"></span>').html(session_time)
266
+ ).append(
267
+ $('<span class="history"></span>').html('history')
268
+ .click(function(){
269
+ setCheckboxesCheckedState(true, false);
270
+ updateEventFilter();
271
+ loadEventHistory({session_key: session_data["session_key"]});
272
+ })
273
+ ).attr('data-session', session_data["session_key"])
274
+ );
275
+
276
+ }
277
+ };
278
+
279
+ function renderEvent(event_data){
280
+ var event_time = $('<span class="time"></span>');
281
+ var event_message = $('<span class="message"></span>');
282
+ var event_props = $('<span class="properties"></span>');
283
+ var event_picture = $('<div class="picture"></picture>');
284
+
285
+ var event_type = event_data._type;
286
+
287
+ if(!event_type){ return true; }
288
+
289
+ if(event_data._message){
290
+ event_message.html(event_data._message);
291
+ } else if(event_type=="_pageview"){
292
+ event_message.html("Pageview: " + event_data.url);
293
+ } else if(event_type.substr(0,5) == '_set_'){
294
+ return true; /* dont render */
295
+ } else {
296
+ event_message.html(event_type);
297
+ }
298
+
299
+ event_time.html(FnordMetric.util.formatTimeOfDay(event_data._time));
300
+
301
+ if(event_data._session_key && event_data._session_key.length > 0){
302
+ var __session_key = event_data._session_key;
303
+ var load_usersession = (function(){
304
+ loadEventHistory({session_key: __session_key});
305
+ });
306
+ if(session_data=sessionData[event_data._session_key]){
307
+ if(session_data._name){
308
+ event_props.append(
309
+ $('<strong></strong>').html(session_data._name).css({
310
+ 'cursor': 'pointer'
311
+ }).click(load_usersession)
312
+ );
313
+ }
314
+ if(session_data._picture){
315
+ event_picture.append(
316
+ $('<img width="40" />').attr('src', session_data._picture)
317
+ ).click(load_usersession);
318
+ }
319
+ }
320
+ }
321
+
322
+ feedInnerElem.prepend(
323
+ $('<li class="feed_event"></li>')
324
+ .append(event_time)
325
+ .append(event_picture)
326
+ .append(event_message)
327
+ .append(event_props)
328
+ );
329
+ }
330
+
331
+ function close(){
332
+ stopPoll();
333
+ };
334
+
335
+ return {
336
+ load: load,
337
+ resize: resize,
338
+ announce: announce,
339
+ close: close
340
+ };
341
+
342
+ });