riemann-dash 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f4c289eed32e6170e10dbe98f328ad9eef4be086
4
+ data.tar.gz: 72850ab6107b78532fe7c786aa42d27ec3e3e765
5
+ SHA512:
6
+ metadata.gz: 58bfdfb8cbaff5681efc68a5c3836c47e849b17b9ff80e1895f9e19b31c9364690ae942afee15bde2b8107eec2d2de7326554dd048f4c6165441d897447f79fd
7
+ data.tar.gz: 04db465f234ea5d5e55003d719e8c2026393e6da7a5556b4c0acbff432be56a778102f3177c43546b4d6ad72956b3695e37563936d31759969545d9325d27c11
@@ -1,6 +1,9 @@
1
1
  var format = (function() {
2
2
 
3
3
  var formatFloat = function(number, precision, commas) {
4
+ if (number == null) {
5
+ return null;
6
+ }
4
7
  precision = precision || 2;
5
8
  var base = Math.pow(10, precision);
6
9
  var val = Math.round(number * base) / base;
@@ -14,7 +14,7 @@ var subs = (function() {
14
14
 
15
15
  // Switch to turn on/off event processing
16
16
  var active = true;
17
-
17
+
18
18
  // Error queue for notification
19
19
  var errorQueue = [];
20
20
 
@@ -34,6 +34,7 @@ var subs = (function() {
34
34
 
35
35
  // Closes a subscription and deletes it from the subscription manager.
36
36
  var unsubscribe = function(sub) {
37
+ clock.unsubscribe(sub.clockSub);
37
38
  delete subs[sub.id];
38
39
  return sub.close();
39
40
  }
@@ -48,12 +49,30 @@ var subs = (function() {
48
49
  return sub.open();
49
50
  }
50
51
 
52
+ // Emit an expired event if oldest item from prioqueue is in the past.
53
+ var expire = function(sub, now) {
54
+ prioqueue = subs[sub.id].prioqueue;
55
+ if (prioqueue) {
56
+ bottom = prioqueue.bottomPriority();
57
+ if (bottom) {
58
+ expiry = new Date(bottom);
59
+ if (expiry < now) {
60
+ expired = prioqueue.shift();
61
+ expired.state = 'expired';
62
+ sub.f(expired);
63
+ }
64
+ }
65
+ }
66
+ }
67
+
51
68
  var Subscription = Backbone.Model.extend({
52
69
 
53
70
  initialize: function(id, query, f) {
54
71
  this.id = id;
55
72
  this.query = query;
56
73
  this.f = f;
74
+ this.prioqueue = new PriorityQueue();
75
+ this.clockSub = false;
57
76
  },
58
77
 
59
78
  isOpen: function() {
@@ -109,6 +128,12 @@ var subs = (function() {
109
128
  var event = JSON.parse(e.data);
110
129
  event.time = Date.parse(event.time);
111
130
  clock.advance(event.time);
131
+ if (event.ttl > 0) { // only expired events have no TTL
132
+ this.prioqueue.update(
133
+ {host: event.host, service: event.service},
134
+ event.time + (event.ttl * 1000) // convert TTL to ms
135
+ );
136
+ }
112
137
  this.f(event);
113
138
  }
114
139
  var t2 = Date.now();
@@ -134,6 +159,11 @@ var subs = (function() {
134
159
  var subscribe = function(query, f) {
135
160
  var sub = new Subscription(newId(), query, f).open();
136
161
  subs[sub.id] = sub;
162
+
163
+ sub.clockSub = clock.subscribe(function(now) {
164
+ expire(sub, now);
165
+ });
166
+
137
167
  return sub;
138
168
  }
139
169
 
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Object to be appended in the priority queue.
3
+ *
4
+ * @class
5
+ * @param mixed v
6
+ * @param integer p
7
+ * @author Augusto Pascutti
8
+ */
9
+ var QueueItem = function(v, p) {
10
+ this.value = v;
11
+ this.priority = p;
12
+ };
13
+
14
+ /**
15
+ * Priority queue class.
16
+ *
17
+ * @class
18
+ * @param Function[optional] c Compare function to be used
19
+ * @param integer[optional] m Max number of elements to hold
20
+ * @author Augusto Pascutti
21
+ */
22
+ var PriorityQueue = function(c, m) { this.init(c, m) };
23
+ PriorityQueue.prototype = {
24
+ _queue: [],
25
+ _compare: undefined,
26
+ _size: 0,
27
+
28
+ /**
29
+ * Priority queue class constructor.
30
+ *
31
+ * @class
32
+ * @param Function[optional] compare_function Compare function to be used
33
+ * @param integer[optional] maximum_size Max number of elements to hold
34
+ */
35
+ init: function(compare_function, maximum_size) {
36
+ this._compare = compare_function || undefined;
37
+ this._size = maximum_size || 0 ;
38
+ this.reset();
39
+ },
40
+
41
+ /**
42
+ * Pushes something to the priority queue.
43
+ *
44
+ * @param mixed value
45
+ * @param integer priority
46
+ * @return void
47
+ */
48
+ push: function(value, priority) {
49
+ this._queue.push(new QueueItem(value, priority));
50
+ this._queue.sort(this.compare());
51
+ this._maitain();
52
+ },
53
+
54
+
55
+ /**
56
+ * Update priority of something in the queue. Will silently add it if it
57
+ * doesn't already exist.
58
+ *
59
+ * @param mixed value
60
+ * @param integer priority
61
+ * @return void
62
+ */
63
+ update: function(value, priority) {
64
+ known = false;
65
+ idx = 0;
66
+
67
+ this._queue.forEach(function() {
68
+ if (JSON.stringify(this._queue[idx].value) === JSON.stringify(value)) {
69
+ this._queue[idx].priority = priority;
70
+ known = true;
71
+ return;
72
+ }
73
+ idx++;
74
+ }, this);
75
+
76
+ if (!known) {
77
+ this._queue.push(new QueueItem(value, priority));
78
+ }
79
+ this._queue.sort(this.compare());
80
+ this._maitain();
81
+ },
82
+
83
+ /**
84
+ * Removes the most important item and return its value.
85
+ *
86
+ * @return mixed
87
+ */
88
+ pop: function() {
89
+ item = this._queue.shift();
90
+ this._maitain();
91
+ return (item) ? item.value : undefined;
92
+ },
93
+
94
+ /**
95
+ * Returns most important item value from this queue, without removing it.
96
+ *
97
+ * @return mixed
98
+ */
99
+ top: function() {
100
+ item = this._queue[0];
101
+ return (item) ? item.value : undefined;
102
+ },
103
+
104
+ /**
105
+ * Returns most important item priority from this queue, without removing it.
106
+ *
107
+ * @return mixed
108
+ */
109
+ topPriority: function() {
110
+ item = this._queue[0];
111
+ return (item) ? item.priority : undefined;
112
+ },
113
+
114
+ /**
115
+ * Removes the less important item and return its value.
116
+ *
117
+ * @return mixed
118
+ */
119
+ shift: function() {
120
+ item = this._queue.pop();
121
+ this._maitain();
122
+ return (item) ? item.value : undefined;
123
+ },
124
+
125
+ /**
126
+ * Returns the less important item value, without removing it.
127
+ *
128
+ * @return mixed
129
+ */
130
+ bottom: function() {
131
+ idx = this.length-1;
132
+ item = this._queue[idx];
133
+ return (item) ? item.value : undefined;
134
+ },
135
+
136
+ /**
137
+ * Returns the less important item priority, without removing it.
138
+ *
139
+ * @return mixed
140
+ */
141
+ bottomPriority: function() {
142
+ idx = this.length-1;
143
+ item = this._queue[idx];
144
+ return (item) ? item.priority : undefined;
145
+ },
146
+
147
+ /**
148
+ * Returns the ordered queue as an Array.
149
+ *
150
+ * @return Array
151
+ */
152
+ getArray: function() {
153
+ return this._queue || new Array();
154
+ },
155
+
156
+ /**
157
+ * Resets the queue.
158
+ *
159
+ * @return void
160
+ */
161
+ reset: function() {
162
+ this._queue = [];
163
+ this._maitain();
164
+ },
165
+
166
+ /**
167
+ * Returns the compare function.
168
+ * If no compare function is set, defines a default one.
169
+ *
170
+ * @return Function
171
+ */
172
+ compare: function() {
173
+ if (!this._compare) {
174
+ this._compare = function(a,b) {
175
+ return b.priority - a.priority;
176
+ };
177
+ }
178
+ return this._compare;
179
+ },
180
+
181
+ /**
182
+ * Defines a fixed size to the queue.
183
+ * Zero for no limit and any other number to set it as the highest number
184
+ * of items allowed in this queue.
185
+ *
186
+ * @param integer i
187
+ * @return void
188
+ */
189
+ size: function(i) {
190
+ this._size = i;
191
+ },
192
+
193
+ /**
194
+ * Keeps the size of the queue by removing the less important item of it and length
195
+ * information atribute.
196
+ *
197
+ * @return void
198
+ */
199
+ _maitain: function() {
200
+ this.length = this._queue.length;
201
+ if ( this._size == 0 ) return;
202
+ while (this._size < this.length) {
203
+ this.shift();
204
+ }
205
+ },
206
+ };
@@ -32,6 +32,7 @@
32
32
 
33
33
  // Create local copies of slurred functions
34
34
  this.reflowGraph = util.slur(200, this.reflowGraph);
35
+ this.setGraphData = util.slur(1000, this.setGraphData);
35
36
 
36
37
  // This view can be clicked to focus on it.
37
38
  this.clickFocusable = true;
@@ -48,7 +49,8 @@
48
49
 
49
50
  this.clockSub = clock.subscribe(function(t) {
50
51
  self.trimData(t);
51
- self.setupGraph(t);
52
+ self.updateTime(t);
53
+ // self.setupGraph(t);
52
54
  });
53
55
 
54
56
  // Subscribe to our query
@@ -69,7 +71,10 @@
69
71
  FlotView.prototype.setupGraph = function(t) {
70
72
  if (this.container.width() === 0 ||
71
73
  this.container.height() === 0) {
72
- this.graph = null;
74
+ if (this.graph != null) {
75
+ this.graph.shutdown();
76
+ this.graph = null;
77
+ }
73
78
  return;
74
79
  }
75
80
 
@@ -99,6 +104,20 @@
99
104
  });
100
105
  };
101
106
 
107
+ // Called as the clock advances to new times.
108
+ FlotView.prototype.updateTime = function(t) {
109
+ if (this.graph == null) {
110
+ this.setupGraph(t);
111
+ return;
112
+ }
113
+
114
+ var axis = this.graph.getOptions().xaxes[0];
115
+ axis.min = t - this.timeRange;
116
+ axis.max = t;
117
+ this.graph.setupGrid();
118
+ this.graph.draw();
119
+ }
120
+
102
121
  // Re-order the data list and series index to be in sorted order by label.
103
122
  FlotView.prototype.resortSeries = function() {
104
123
  // Shorten labels
@@ -177,7 +196,11 @@
177
196
  series.push([event.time, event.metric]);
178
197
  }
179
198
 
180
- // Update graph data
199
+ this.setGraphData();
200
+ };
201
+
202
+ // Tells the Flot graph to use our current dataset.
203
+ FlotView.prototype.setGraphData = function() {
181
204
  if (this.graph) {
182
205
  this.graph.setData(this.data);
183
206
  }
@@ -162,12 +162,15 @@
162
162
  e.td.attr('class', "state box " + event.state);
163
163
 
164
164
  // Description
165
- e.td.attr('title', event.host + ' ' + event.service + "\n" +
166
- event.state + ' at ' + new Date(event.time).toString() + "\n\n" +
167
- event.description);
165
+ e.td.attr('title', event.host + ' ' + event.service + "\n" + event.state +
166
+ "\nreceived at " + new Date(event.time).toString() +
167
+ "\nexpiring at " + new Date(event.time + event.ttl * 1000).toString() +
168
+ (event.description ? ("\n\n" + event.description) : ""));
168
169
 
169
170
  // Metric
170
- e.metric.text(format.float(event.metric));
171
+ if (event.metric != undefined) {
172
+ e.metric.text(format.float(event.metric));
173
+ }
171
174
 
172
175
  // Bar chart
173
176
  if (event.metric === 0) {
@@ -354,7 +357,9 @@
354
357
  Grid.prototype.remove = function(e) {
355
358
  var row_key = this.row_fn(e);
356
359
  var col_key = this.col_fn(e);
357
- delete this.events[row_key][col_key];
360
+ if (this.events[row_key] && this.events[row_key][col_key]) {
361
+ delete this.events[row_key][col_key];
362
+ }
358
363
 
359
364
  // Wipe element cache
360
365
  if (this.elCache[row_key]) {
@@ -385,7 +390,11 @@
385
390
 
386
391
  // Accept an event.
387
392
  Grid.prototype.update = function(e) {
388
- this.add(e);
393
+ if (e.state === "expired") {
394
+ this.remove(e);
395
+ } else {
396
+ this.add(e);
397
+ }
389
398
  };
390
399
 
391
400
  Grid.prototype.reflow = function() {
@@ -10,6 +10,7 @@
10
10
  "<p>To save your changes to the server, press s. You can refresh the page, or press r to reload.</p>" +
11
11
  "<p>Make views bigger and smaller with the +/- keys. Pageup selects the parent of the current view. To delete a view, use the delete key.</p>" +
12
12
  "<p>Switch between workspaces with alt-1, alt-2, etc.</p>" +
13
+ "<p>View is an empty space. Title is an editable text title. Fullscreen and Balloon are top-level container views; you probably won't use them. HStack and VStack are the horizontal and vertical container views; they're implicitly created by splits, but you can create them yourself for fine control. Gauge shows a single event. Grid shows a table of events. Timeseries and Flot show metrics over time--Timeseries is deprecated; Flot will probably replace it.</p>" +
13
14
  "<p>My sincere apologies for layout jankiness. There are a few gross bugs and incapabilities in the current hstack/vstack system; if things get really bad, you can always edit ws/config.json on the server. The control scheme will probably change; I appreciate your ideas and patches.</p>" +
14
15
  '</div>'
15
16
  );
@@ -1,4 +1,4 @@
1
1
  module Riemann; end
2
2
  module Riemann::Dash
3
- VERSION = '0.2.6'
3
+ VERSION = '0.2.7'
4
4
  end
@@ -168,18 +168,14 @@ html,table {
168
168
  background: $green;
169
169
  color: #000;
170
170
  }
171
- .state.warning, .bar.warning {
171
+ .state.warning, .state.warn, .bar.warning, .bar.warn {
172
172
  background: $amber;
173
173
  color: #000;
174
174
  }
175
- .state.critical, .state.failure, .bar.critical, .bar.failure {
175
+ .state.critical, .state.failure, .state.err, .bar.critical, .bar.failure, .bar.err {
176
176
  background: $orange;
177
177
  color: #000;
178
178
  }
179
- .state.expired {
180
- background: $purple;
181
- color: #000;
182
- }
183
179
 
184
180
  .view .query {
185
181
  display: block;
@@ -341,6 +337,8 @@ h2 {
341
337
  }
342
338
 
343
339
  .grid {
340
+ white-space: nowrap;
341
+
344
342
  h2 {
345
343
  height: 28px;
346
344
  font-size: 24px;
@@ -376,6 +374,10 @@ h2 {
376
374
  position: absolute;
377
375
  width: 100%;
378
376
  border-spacing: 3px;
377
+
378
+ th {
379
+ text-align: right;
380
+ }
379
381
 
380
382
  thead {
381
383
  margin: 0;
@@ -386,7 +388,7 @@ h2 {
386
388
  position: relative;
387
389
  top: 3px;
388
390
  vertical-align: bottom;
389
- text-align: right;
391
+ text-align: left;
390
392
  }
391
393
  }
392
394
  }
@@ -24,6 +24,7 @@
24
24
  <script src="vendor/flot/jquery.flot.canvas.min.js"></script>
25
25
  <script src="vendor/flot/jquery.flot.time.min.js"></script>
26
26
  <script src="vendor/flot/jquery.flot.stack.min.js"></script>
27
+ <script src="vendor/PriorityQueue.js"></script>
27
28
  <script> // turn underscore templates into mustache style templates
28
29
  _.templateSettings = {
29
30
  evaluate : /\{\%([\s\S]+?)\%\}/g, // {% eval(js); %}
metadata CHANGED
@@ -1,100 +1,88 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riemann-dash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
5
- prerelease:
4
+ version: 0.2.7
6
5
  platform: ruby
7
6
  authors:
8
7
  - Kyle Kingsbury
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-10-21 00:00:00.000000000 Z
11
+ date: 2014-01-03 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: riemann-client
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 0.0.7
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 0.0.7
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: erubis
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: 2.7.0
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: 2.7.0
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: sinatra
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: 1.3.2
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: 1.3.2
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: sass
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: 3.1.14
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: 3.1.14
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: thin
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: 1.3.1
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: 1.3.1
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: multi_json
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
87
  - - '='
100
88
  - !ruby/object:Gem::Version
@@ -102,7 +90,6 @@ dependencies:
102
90
  type: :runtime
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
94
  - - '='
108
95
  - !ruby/object:Gem::Version
@@ -138,6 +125,7 @@ files:
138
125
  - lib/riemann/dash/public/subs.js
139
126
  - lib/riemann/dash/public/toolbar.js
140
127
  - lib/riemann/dash/public/util.js
128
+ - lib/riemann/dash/public/vendor/PriorityQueue.js
141
129
  - lib/riemann/dash/public/vendor/backbone.js
142
130
  - lib/riemann/dash/public/vendor/flot/jquery.colorhelpers.js
143
131
  - lib/riemann/dash/public/vendor/flot/jquery.colorhelpers.min.js
@@ -204,27 +192,26 @@ files:
204
192
  - test/test_helper.rb
205
193
  homepage: https://github.com/aphyr/riemann-dash
206
194
  licenses: []
195
+ metadata: {}
207
196
  post_install_message:
208
197
  rdoc_options: []
209
198
  require_paths:
210
199
  - lib
211
200
  required_ruby_version: !ruby/object:Gem::Requirement
212
- none: false
213
201
  requirements:
214
- - - ! '>='
202
+ - - '>='
215
203
  - !ruby/object:Gem::Version
216
204
  version: '0'
217
205
  required_rubygems_version: !ruby/object:Gem::Requirement
218
- none: false
219
206
  requirements:
220
- - - ! '>='
207
+ - - '>='
221
208
  - !ruby/object:Gem::Version
222
209
  version: '0'
223
210
  requirements: []
224
211
  rubyforge_project: riemann-dash
225
- rubygems_version: 1.8.23
212
+ rubygems_version: 2.1.11
226
213
  signing_key:
227
- specification_version: 3
214
+ specification_version: 4
228
215
  summary: HTTP dashboard for the distributed event system Riemann.
229
216
  test_files:
230
217
  - test/config_test.rb