consul-templaterb 1.8.4 → 1.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/consul/async/consul_template.rb +1 -0
- data/lib/consul/async/version.rb +1 -1
- data/samples/consul-ui/consul-timeline-ui.html.erb +7 -3
- data/samples/consul-ui/js/timeline.js +46 -10
- data/samples/consul-ui/js/utils.js +6 -0
- data/samples/consul-ui/timeline.json.erb +14 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d17ec48b3c3611a4e49e13ef9daaeeb44f3f6cc02768ccdcd579e64c2af1a7ec
|
4
|
+
data.tar.gz: 59300692c12bacfa4e232679fc7568437ebf9fd3ca977161f702b2f1f4666b76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3356add5c81df85061ed0810ea6775252044e771ca10cce3cec5a60fc22c9e1f2cd5e60707d90c4e939b061baa3c8c97155ffe7e3fa41b16a195730f3ebbd98
|
7
|
+
data.tar.gz: 6f6b3a75a175d7314f8f7b8878c161d283500011beb7b4e21ae9c1a410d326a15ca7d83e135ed4a0a13705995053940036689a6b4cb4f2d249494881013466b1
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
## (UNRELEASED)
|
4
4
|
|
5
|
+
## 1.8.5 (December 18, 2018)
|
6
|
+
|
7
|
+
OPTIMIZATIONS:
|
8
|
+
|
9
|
+
* Use less memory on the client side for consul-timeline
|
10
|
+
* Properly handle multiple instances of JSON file behinf a LB
|
11
|
+
|
5
12
|
## 1.8.3 / 1.8.4 (December 18, 2018)
|
6
13
|
|
7
14
|
OPTIMIZATIONS:
|
@@ -185,6 +185,7 @@ module Consul
|
|
185
185
|
template_info: tpl_info
|
186
186
|
}
|
187
187
|
result = ERB.new(tpl, nil, @trim_mode).result(binding)
|
188
|
+
raise "Result is not a string :='#{result}' for #{tpl_file_path}" unless result.is_a?(String)
|
188
189
|
@context = old_value
|
189
190
|
result
|
190
191
|
rescue StandardError => e
|
data/lib/consul/async/version.rb
CHANGED
@@ -11,13 +11,17 @@
|
|
11
11
|
</div>
|
12
12
|
<div id="service-wrapper" >
|
13
13
|
<ul id="service-list" class="list-group">
|
14
|
-
<li onfocus="serviceTimeline.selectService(this)" onclick="serviceTimeline.selectService(this)" value="" class="serviceListItem list-group-item list-group-item-actionn" id="anyService"><div class="statuses float-right"><span id="allServicesCount" class="lookup badge badge-pill badge-secondary">loading…</span></div><div class="service-name">All</div></li>
|
14
|
+
<li onfocus="serviceTimeline.selectService(this)" onclick="serviceTimeline.selectService(this, true)" value="" class="serviceListItem list-group-item list-group-item-actionn" id="anyService"><div class="statuses float-right"><span id="allServicesCount" class="lookup badge badge-pill badge-secondary">loading…</span></div><div class="service-name">All</div></li>
|
15
15
|
</ul>
|
16
16
|
</div>
|
17
17
|
</div>
|
18
18
|
<div class="col-10 col-m-9">
|
19
|
-
<div id="autorefresh"
|
20
|
-
|
19
|
+
<div id="autorefresh">
|
20
|
+
<input id="autorefresh-check" type="checkbox" checked><label for="autorefresh-check">Autorefresh</label><br/>
|
21
|
+
<label for="autorefresh-check">Max Rows:</label>
|
22
|
+
<input id="maxRows" style="width: 5em;" type="number" min="100" max="<%= (ENV['CONSUL_TIMELINE_BUFFER'] || 10000) %>" step="100" value="5000"/>
|
23
|
+
</div>
|
24
|
+
<h2 class="text-center" id="service-title" style="clear:both"></h2>
|
21
25
|
<div class="row mb-2">
|
22
26
|
<div class="input-group float-left col-12">
|
23
27
|
<input id="instance-filter" type="search" placeholder="filter events" class="form-control" />
|
@@ -135,7 +135,7 @@ class ServiceTimeline {
|
|
135
135
|
setInterval(sT.reloadDataFromJSON, 10000);
|
136
136
|
}, 150);
|
137
137
|
} else {
|
138
|
-
this.
|
138
|
+
this.performFiltering($('#instance-filter')[0].value);
|
139
139
|
}
|
140
140
|
}
|
141
141
|
|
@@ -182,17 +182,20 @@ class ServiceTimeline {
|
|
182
182
|
}
|
183
183
|
console.log("Filtering on service", serviceTimeline.serviceInstanceFilter, " with ", matcher, "filterValue:=", filterValue);
|
184
184
|
var isCorrectService = function(){ return true; };
|
185
|
+
if (serviceTimeline.serviceInstanceFilter == 'All') {
|
186
|
+
serviceTimeline.serviceInstanceFilter = '';
|
187
|
+
}
|
185
188
|
if (serviceTimeline.serviceInstanceFilter == ''){
|
186
189
|
var stylesheet = document.getElementById('serviceCol');
|
187
190
|
var txt = '';
|
188
|
-
if (filterValue) {
|
191
|
+
if (filterValue != '') {
|
189
192
|
txt+='tr.filtered { display: none; }';
|
190
193
|
}
|
191
194
|
stylesheet.textContent = txt;
|
192
195
|
} else {
|
193
196
|
var stylesheet = document.getElementById('serviceCol');
|
194
197
|
var txt = '.serviceCol';
|
195
|
-
if (filterValue) {
|
198
|
+
if (filterValue != '') {
|
196
199
|
txt+=',tr.filtered'
|
197
200
|
}
|
198
201
|
for (var i in this.presentServices) {
|
@@ -203,7 +206,7 @@ class ServiceTimeline {
|
|
203
206
|
stylesheet.textContent = txt + ' { display: none; }';
|
204
207
|
isCorrectService = function(ui) { return ui.hasClass('srv-' + serviceTimeline.serviceInstanceFilter) };
|
205
208
|
}
|
206
|
-
if (filterValue) {
|
209
|
+
if (filterValue != '') {
|
207
210
|
$("#all-events > tbody").children('tr').each(function (){
|
208
211
|
var ui = $(this);
|
209
212
|
var shouldShow = isCorrectService(ui) && ui.children('.lookup').is(function (){
|
@@ -226,6 +229,7 @@ class ServiceTimeline {
|
|
226
229
|
var filterValue = $('#instance-filter')[0].value;
|
227
230
|
if (this.refreshTimeout) {
|
228
231
|
clearTimeout(this.refreshTimeout);
|
232
|
+
this.refreshTimeout = null;
|
229
233
|
}
|
230
234
|
this.refreshTimeout = window.setTimeout(function(){
|
231
235
|
serviceTimeline.performFiltering(filterValue);
|
@@ -238,7 +242,6 @@ class ServiceTimeline {
|
|
238
242
|
this.selectedService = source.closest('li');
|
239
243
|
$(this.selectedService).addClass('active');
|
240
244
|
if (serviceName == 'All') {
|
241
|
-
serviceName = '';
|
242
245
|
$("#service-title").html('');
|
243
246
|
} else {
|
244
247
|
var titleText = '<a href="consul-services-ui.html?service=' + serviceName + '">'+serviceName+'</a>';
|
@@ -246,7 +249,7 @@ class ServiceTimeline {
|
|
246
249
|
}
|
247
250
|
serviceTimeline.serviceInstanceFilter = serviceName;
|
248
251
|
if (updateUrl) {
|
249
|
-
serviceTimeline.updateURL(serviceName
|
252
|
+
serviceTimeline.updateURL(serviceName);
|
250
253
|
}
|
251
254
|
this.doFilter();
|
252
255
|
}
|
@@ -283,6 +286,7 @@ class ServiceTimeline {
|
|
283
286
|
}
|
284
287
|
|
285
288
|
displayEvents(firstReload) {
|
289
|
+
var maxRows = document.getElementById("maxRows").value;
|
286
290
|
//$("#service-title").html(service['name']);
|
287
291
|
var tableBody = $('#all-events > tbody');
|
288
292
|
var startIndex = 0;
|
@@ -290,19 +294,37 @@ class ServiceTimeline {
|
|
290
294
|
tableBody.html("");
|
291
295
|
} else {
|
292
296
|
// We first try to find new entries...
|
293
|
-
var
|
297
|
+
var lastDisplayedIndex = indexOfTimelineEvent(this.lastEntryLoaded);
|
298
|
+
var newestIndexInNewDocument = "000";
|
299
|
+
if (this.data.length > 0) {
|
300
|
+
newestIndexInNewDocument = indexOfTimelineEvent(this.data[this.data.length - 1]);
|
301
|
+
}
|
302
|
+
if (lastDisplayedIndex >= newestIndexInNewDocument) {
|
303
|
+
// Might happen when behind a VIP
|
304
|
+
console.log("Skip reload, index: ", lastDisplayedIndex, ", new is ", newestIndexInNewDocument);
|
305
|
+
return;
|
306
|
+
} else {
|
307
|
+
console.log("Index ", lastDisplayedIndex, " -> ", newestIndexInNewDocument);
|
308
|
+
}
|
294
309
|
for (var i = 0 ; i < this.data.length; i++) {
|
295
310
|
var e = this.data[i];
|
296
|
-
if (
|
311
|
+
if (lastDisplayedIndex < indexOfTimelineEvent(e)) {
|
297
312
|
startIndex = i + 1;
|
298
313
|
console.log('Resuming at ', startIndex, " with ", e);
|
299
314
|
break;
|
300
315
|
}
|
301
316
|
}
|
302
317
|
}
|
303
|
-
var
|
318
|
+
var frag = document.createDocumentFragment();
|
304
319
|
var filter = "";
|
305
320
|
var lastEntryFound = null;
|
321
|
+
if (this.data.length > maxRows) {
|
322
|
+
var remaining = this.data.length - startIndex;
|
323
|
+
if (startIndex < remaining) {
|
324
|
+
startIndex = this.data.length - maxRows;
|
325
|
+
console.log('Skip first ', startIndex, " entries on ", this.data.length, " lines...");
|
326
|
+
}
|
327
|
+
}
|
306
328
|
for (var i = startIndex ; i < this.data.length; i++) {
|
307
329
|
var e = this.data[i];
|
308
330
|
lastEntryFound = e;
|
@@ -391,8 +413,22 @@ class ServiceTimeline {
|
|
391
413
|
}
|
392
414
|
this.buildCell(row, 'td', 'ipercents', this.createBadge(percent + " %", clazz));
|
393
415
|
}
|
394
|
-
|
416
|
+
frag.prepend(row);
|
395
417
|
}
|
418
|
+
var tbody = tableBody[0];
|
419
|
+
tbody.prepend(frag);
|
396
420
|
this.lastEntryLoaded = lastEntryFound;
|
421
|
+
console.log("Last entry loaded: ", indexOfTimelineEvent(this.lastEntryLoaded));
|
422
|
+
var i = 0;
|
423
|
+
|
424
|
+
var tbody = tableBody.children('tr').each (function() {
|
425
|
+
i++;
|
426
|
+
if (i > maxRows) {
|
427
|
+
$(this).remove()
|
428
|
+
}
|
429
|
+
});
|
430
|
+
if (i > maxRows) {
|
431
|
+
console.log("Removed ", maxRows - i, " lines.")
|
432
|
+
}
|
397
433
|
}
|
398
434
|
}
|
@@ -20,6 +20,12 @@ function formatDate(date) {
|
|
20
20
|
return padDateUnit(date.getMonth()+1) + "/" + padDateUnit(date.getDate()) + " " + padDateUnit(date.getHours()) + ':' + padDateUnit(date.getMinutes()) + ':' + padDateUnit(date.getSeconds());
|
21
21
|
}
|
22
22
|
|
23
|
+
function indexOfTimelineEvent(e) {
|
24
|
+
if (e == null) {
|
25
|
+
return 'k/0000000000/0000/0000';
|
26
|
+
}
|
27
|
+
return 'k/' + e.idx.toString().padStart(10, '0') + '/' + e.service + '/' + e.instance;
|
28
|
+
}
|
23
29
|
|
24
30
|
function nodeState(checks) {
|
25
31
|
status='passing';
|
@@ -77,6 +77,7 @@ def diff(old, new)
|
|
77
77
|
end
|
78
78
|
|
79
79
|
@events = RingBuffer.new(max_size: (ENV['CONSUL_TIMELINE_BUFFER'] || 10000).to_i) unless @events
|
80
|
+
@new_events = []
|
80
81
|
|
81
82
|
def log_event(line)
|
82
83
|
puts "#{Time.now.to_i} #{line}" if ENV['DEBUG_TIMELINE']
|
@@ -84,7 +85,7 @@ end
|
|
84
85
|
|
85
86
|
def store_event(service: service_name, instance: nil, old_state: nil, new_state: nil, instance_info: nil, checks: [])
|
86
87
|
STDERR.puts "empty instance_info for #{service} ; #{instance} ; #{new_state}" unless instance_info
|
87
|
-
@
|
88
|
+
@new_events << { 'service' => service, 'instance' => instance, 'idx' => instance_info['idx'], 'old_state' => old_state, 'new_state' => new_state,
|
88
89
|
'ts' => @current_time, 'instance_info' => instance_info }.tap do |ev|
|
89
90
|
ev['checks'] = checks if checks
|
90
91
|
ev['stats'] = if instance_info
|
@@ -176,10 +177,20 @@ end
|
|
176
177
|
checks: checks)
|
177
178
|
end
|
178
179
|
end
|
180
|
+
sorted_events = @new_events.sort do |a, b|
|
181
|
+
res = 0
|
182
|
+
%w[idx service instance].each do |f|
|
183
|
+
res = a[f] <=> b[f]
|
184
|
+
break if res != 0
|
185
|
+
end
|
186
|
+
res
|
187
|
+
end
|
188
|
+
sorted_events.each { |e| @events << e }
|
189
|
+
@new_events.clear
|
190
|
+
|
179
191
|
# We save the previous state only when we have a complete state once
|
180
192
|
if template_info['was_rendered_once']
|
181
193
|
warn "First full rendering completed at #{@current_time} !" unless @previous_state
|
182
194
|
@previous_state = cur_state
|
183
195
|
end
|
184
|
-
|
185
|
-
%><%= JSON.generate(@events)%>
|
196
|
+
%><%= JSON.generate(@events) %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: consul-templaterb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SRE Core Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|