consul-templaterb 1.9.2 → 1.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/consul/async/consul_endpoint.rb +7 -2
- data/lib/consul/async/utilities.rb +5 -0
- data/lib/consul/async/version.rb +1 -1
- data/samples/consul-ui/common/header.html.erb +1 -0
- data/samples/consul-ui/images/favicon.png +0 -0
- data/samples/consul-ui/js/service.js +1 -1
- data/samples/consul-ui/js/timeline.js +1 -1
- data/samples/consul-ui/js/utils.js +9 -2
- data/samples/consul-ui/ringbuffer.rb +107 -0
- data/samples/consul-ui/timeline.json.erb +4 -30
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5782528a3540e33076a9db4244d558f9e62d846b68f7aa57cb625dbc2cca7415
|
|
4
|
+
data.tar.gz: c3d33c3bb5f760f1b0108807213e8d59aceca92cce6eccb67c32ff759010ece8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 02cb21ad2703bfd0a847181c4b4d0b5bd4a96503130e949db99498461dee4e1744e35b406a056ddcd2023eacc6aac3463e51b33685748a8733dd02fa57852efd
|
|
7
|
+
data.tar.gz: 19015ff464cdeb7ee09b04471d78562b415b02878349c2d9c5bd96acac758276759efdff2132000558b96d3003ac473d29369c47090189fc29cf16178918e3d6
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## (UNRELEASED)
|
|
4
4
|
|
|
5
|
+
## 1.9.3 (January 9, 2019)
|
|
6
|
+
|
|
7
|
+
IMPROVEMENTS:
|
|
8
|
+
|
|
9
|
+
* Perform some randomization on retries, so in case of massive errors,
|
|
10
|
+
system will likely re-open all connections at the same time.
|
|
11
|
+
* consul-timeline more optimize ringbuffer for larger history
|
|
12
|
+
* UI improvements (tooltips for services/checks)
|
|
13
|
+
|
|
5
14
|
## 1.9.2 (January 4, 2019)
|
|
6
15
|
|
|
7
16
|
IMPROVEMENTS:
|
|
@@ -137,7 +137,7 @@ module Consul
|
|
|
137
137
|
"[#{stats.body_bytes_human.ljust(8)}][#{stats.bytes_per_sec_human.ljust(9)}]"\
|
|
138
138
|
" #{path.ljust(48)} idx:#{result.x_consul_index}, next in #{result.retry_in} s"
|
|
139
139
|
end
|
|
140
|
-
on_error { |http| STDERR.puts "[ERROR]: #{path}: #{http.error}" }
|
|
140
|
+
on_error { |http| STDERR.puts "[ERROR]: #{path}: #{http.error.inspect}" }
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
def on_response(&block)
|
|
@@ -185,8 +185,12 @@ module Consul
|
|
|
185
185
|
http.response_header['X-Consul-Index']
|
|
186
186
|
end
|
|
187
187
|
|
|
188
|
+
def _compute_retry_in(retry_in)
|
|
189
|
+
retry_in / 2 + Consul::Async::Utilities.random.rand(retry_in)
|
|
190
|
+
end
|
|
191
|
+
|
|
188
192
|
def _handle_error(http, consul_index)
|
|
189
|
-
retry_in = [600, conf.retry_duration + 2**@consecutive_errors].min
|
|
193
|
+
retry_in = _compute_retry_in([600, conf.retry_duration + 2**@consecutive_errors].min)
|
|
190
194
|
STDERR.puts "[ERROR][#{path}] X-Consul-Index:#{consul_index} - #{http.error} - Retry in #{retry_in}s #{stats.body_bytes_human}"
|
|
191
195
|
@consecutive_errors += 1
|
|
192
196
|
http_result = HttpResponse.new(http)
|
|
@@ -227,6 +231,7 @@ module Consul
|
|
|
227
231
|
else
|
|
228
232
|
retry_in = modified ? conf.min_duration : conf.retry_on_non_diff
|
|
229
233
|
end
|
|
234
|
+
retry_in = _compute_retry_in(retry_in)
|
|
230
235
|
retry_in = 0.1 if retry_in < 0.1
|
|
231
236
|
unless @stopping
|
|
232
237
|
EventMachine.add_timer(retry_in) do
|
data/lib/consul/async/version.rb
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
<meta name="description" content="Display Consul information"/>
|
|
32
32
|
<meta name="author" content="Criteo"/>
|
|
33
33
|
<title><%= param('title', 'Consul Real Time information') %></title>
|
|
34
|
+
<link rel="icon" type="image/png" href="images/favicon.png" sizes="32x32" />
|
|
34
35
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
|
|
35
36
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.11/css/all.css" integrity="sha384-p2jx59pefphTFIpeqCcISO9MdVfIm4pNnsL08A6v5vaQc4owkQqxMV8kg4Yvhaw/" crossorigin="anonymous">
|
|
36
37
|
<link rel="stylesheet" href="css/style.css">
|
|
Binary file
|
|
@@ -251,7 +251,7 @@ class ConsulService {
|
|
|
251
251
|
serviceHtml.appendChild(tagsGenerator(instance.tags));
|
|
252
252
|
serviceHtml.appendChild(serviceMetaGenerator(instance.sMeta));
|
|
253
253
|
serviceHtml.appendChild(connectGenerator(instance))
|
|
254
|
-
serviceHtml.appendChild(checksStatusGenerator(instance
|
|
254
|
+
serviceHtml.appendChild(checksStatusGenerator(instance));
|
|
255
255
|
serviceHtml.setAttribute('status', state);
|
|
256
256
|
$("#instances-list").append(serviceHtml);
|
|
257
257
|
}
|
|
@@ -457,7 +457,7 @@ class ServiceTimeline {
|
|
|
457
457
|
var checkName = document.createElement('div');
|
|
458
458
|
checkName.setAttribute('class', 'lookup checkName');
|
|
459
459
|
checkName.setAttribute('data-toggle', 'tooltip');
|
|
460
|
-
checkName.setAttribute('title', c['id']+'\n\n' + c.output);
|
|
460
|
+
checkName.setAttribute('title', 'ID: ' + c['id'] + '\nName: ' + c['name'] + '\n\n' + c.output);
|
|
461
461
|
checkName.appendChild(document.createTextNode(c['name']));
|
|
462
462
|
checksCell.appendChild(checkName);
|
|
463
463
|
}
|
|
@@ -52,6 +52,10 @@ function serviceTitleGenerator(instance) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
var htmlTitle = document.createElement('h5');
|
|
55
|
+
htmlTitle.setAttribute('title', 'Node Name: ' + instance.name +
|
|
56
|
+
'\nAddress : ' + instance.addr +
|
|
57
|
+
'\nService ID: ' + instance.id +
|
|
58
|
+
'\nService Port : ' + instance.port);
|
|
55
59
|
|
|
56
60
|
var instanceLink = document.createElement('a');
|
|
57
61
|
instanceLink.setAttribute('class', 'instance-name');
|
|
@@ -223,14 +227,16 @@ function servicesGenerator(instanceServices) {
|
|
|
223
227
|
return services;
|
|
224
228
|
}
|
|
225
229
|
|
|
226
|
-
function checksStatusGenerator(
|
|
230
|
+
function checksStatusGenerator(instance) {
|
|
231
|
+
var instanceChecks = instance.checks;
|
|
227
232
|
var checks = document.createElement('div');
|
|
228
233
|
checks.className = 'checks';
|
|
229
234
|
checks.appendChild(document.createTextNode("Checks: "));
|
|
230
235
|
checks.appendChild(document.createElement('br'));
|
|
231
236
|
|
|
232
237
|
for (var checkKey in instanceChecks) {
|
|
233
|
-
|
|
238
|
+
var checkInstance = instanceChecks[checkKey];
|
|
239
|
+
var checkId = instance.name + '::' + checkInstance.checkid;
|
|
234
240
|
var btn = 'btn-' + toCSSClass(instanceChecks[checkKey]['status'])
|
|
235
241
|
var check = document.createElement('div');
|
|
236
242
|
|
|
@@ -240,6 +246,7 @@ function checksStatusGenerator(instanceChecks) {
|
|
|
240
246
|
btnCheck.setAttribute('data-toggle', 'collapse');
|
|
241
247
|
btnCheck.setAttribute('data-target', '#' + checkId);
|
|
242
248
|
btnCheck.setAttribute('aria-expanded', 'false');
|
|
249
|
+
btnCheck.setAttribute('title', checkInstance.checkid);
|
|
243
250
|
|
|
244
251
|
btnCheck.appendChild(document.createTextNode(instanceChecks[checkKey]['name']));
|
|
245
252
|
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module ConsulTimeline
|
|
2
|
+
class RingBufferNode
|
|
3
|
+
attr_reader :prev, :value, :next
|
|
4
|
+
attr_writer :prev, :next, :value
|
|
5
|
+
def initialize(value, p_elem, n_elem)
|
|
6
|
+
@value = value
|
|
7
|
+
@prev = p_elem
|
|
8
|
+
@next = n_elem
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Insert element before current element, return inserted Node
|
|
12
|
+
def insert_before(obj)
|
|
13
|
+
old_prev = @prev
|
|
14
|
+
@prev = RingBufferNode.new(obj, old_prev, self)
|
|
15
|
+
old_prev&.next = @prev
|
|
16
|
+
@prev
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Append element after current ince, return inserted Node
|
|
20
|
+
def append(obj)
|
|
21
|
+
old_next = @next
|
|
22
|
+
@next = RingBufferNode.new(obj, self, old_next)
|
|
23
|
+
old_next&.prev = @next
|
|
24
|
+
@next
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_s
|
|
28
|
+
"[prev=#{@prev.object_id}, next=#{@next.object_id}, value=#{@value}]"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
class SortedRingBuffer
|
|
32
|
+
include Enumerable
|
|
33
|
+
def initialize(max_size, sort_func)
|
|
34
|
+
raise "Invalid size #{max_size}" unless max_size.positive?
|
|
35
|
+
@head = RingBufferNode.new(nil, nil, nil)
|
|
36
|
+
@sort_func = sort_func
|
|
37
|
+
@tail = @head
|
|
38
|
+
@max_size = max_size
|
|
39
|
+
(max_size - 1).times do
|
|
40
|
+
@head = @head.insert_before(nil)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def push(obj)
|
|
45
|
+
return unless obj
|
|
46
|
+
cur = @tail
|
|
47
|
+
raise "No head.next found in #{@head}" unless @head.next
|
|
48
|
+
while cur && cur.value && @sort_func.call(cur.value, obj).positive?
|
|
49
|
+
cur = cur.prev
|
|
50
|
+
end
|
|
51
|
+
if cur.nil?
|
|
52
|
+
# The value we try to insert is before @head
|
|
53
|
+
# no need to do anything
|
|
54
|
+
elsif cur == @head
|
|
55
|
+
# This is the head, just update the value
|
|
56
|
+
@head.value = obj
|
|
57
|
+
else
|
|
58
|
+
@head = @head.next
|
|
59
|
+
@head.prev = nil
|
|
60
|
+
new_val = cur.append(obj)
|
|
61
|
+
@tail = new_val if @tail == cur
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def each
|
|
66
|
+
return enum_for(:each) unless block_given? # Sparkling magic!
|
|
67
|
+
cur = @head
|
|
68
|
+
until cur.nil?
|
|
69
|
+
yield cur.value if cur.value
|
|
70
|
+
cur = cur.next
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_a
|
|
75
|
+
arr = Array.new(@max_size)
|
|
76
|
+
cur = @head
|
|
77
|
+
i = 0
|
|
78
|
+
until cur.nil?
|
|
79
|
+
if cur.value
|
|
80
|
+
arr[i] = cur.value
|
|
81
|
+
i += 1
|
|
82
|
+
end
|
|
83
|
+
cur = cur.next
|
|
84
|
+
end
|
|
85
|
+
if i != @max_size
|
|
86
|
+
arr.reject(&:nil?)
|
|
87
|
+
else
|
|
88
|
+
arr
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if ARGV.count.positive? && ARGV[0] == 'debug'
|
|
95
|
+
require 'json'
|
|
96
|
+
size = (ARGV[1] || 10).to_i
|
|
97
|
+
ringbuff = ConsulTimeline::SortedRingBuffer.new(size, ->(a, b) { a <=> b })
|
|
98
|
+
ringbuff.push 0.5
|
|
99
|
+
puts ringbuff.to_a
|
|
100
|
+
(size * 10).times do |i|
|
|
101
|
+
ringbuff.push(2 * i + Random.rand(size / 10))
|
|
102
|
+
end
|
|
103
|
+
ringbuff.push 99_999_999_999_999
|
|
104
|
+
arr = ringbuff.to_a
|
|
105
|
+
raise "OOPS wrong size := #{arr.count} instead of #{size}" unless arr.count == size
|
|
106
|
+
STDOUT.puts JSON.generate(arr)
|
|
107
|
+
end
|
|
@@ -55,33 +55,7 @@ old_state = if @previous_state
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
unless @events
|
|
58
|
-
|
|
59
|
-
attr_reader :max_size
|
|
60
|
-
|
|
61
|
-
def initialize(max_size:, enum: nil)
|
|
62
|
-
@max_size = max_size
|
|
63
|
-
warn "Ringbuffer initialized with #{max_size}"
|
|
64
|
-
enum&.each { |e| self << e }
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def <<(element)
|
|
68
|
-
return unless element
|
|
69
|
-
if size >= @max_size
|
|
70
|
-
shift
|
|
71
|
-
end
|
|
72
|
-
previous_e = last
|
|
73
|
-
after = []
|
|
74
|
-
while !previous_e.nil? && (previous_e['idx'] > element['idx'])
|
|
75
|
-
after.insert(0, pop)
|
|
76
|
-
previous_e = last
|
|
77
|
-
end
|
|
78
|
-
push(element)
|
|
79
|
-
after.each do |x|
|
|
80
|
-
push(x)
|
|
81
|
-
end
|
|
82
|
-
self
|
|
83
|
-
end
|
|
84
|
-
end
|
|
58
|
+
load File.expand_path(File.join(File.dirname(template_info['source']), 'ringbuffer.rb'))
|
|
85
59
|
|
|
86
60
|
def diff(old, new_e)
|
|
87
61
|
diff = OpenStruct.new
|
|
@@ -92,7 +66,7 @@ unless @events
|
|
|
92
66
|
diff
|
|
93
67
|
end
|
|
94
68
|
|
|
95
|
-
@events =
|
|
69
|
+
@events = ::ConsulTimeline::SortedRingBuffer.new((ENV['CONSUL_TIMELINE_BUFFER'] || 10000).to_i, lambda {|a, b| a['idx'] <=> b['idx'] })
|
|
96
70
|
end
|
|
97
71
|
@new_events = []
|
|
98
72
|
|
|
@@ -209,7 +183,7 @@ sorted_events = @new_events.sort do |a, b|
|
|
|
209
183
|
end
|
|
210
184
|
res
|
|
211
185
|
end
|
|
212
|
-
sorted_events.each { |e| @events
|
|
186
|
+
sorted_events.each { |e| @events.push e }
|
|
213
187
|
@new_events.clear
|
|
214
188
|
|
|
215
189
|
# We save the previous state only when we have a complete state once
|
|
@@ -217,4 +191,4 @@ if template_info['was_rendered_once']
|
|
|
217
191
|
warn "First full rendering completed at #{@current_time} !" unless @previous_state
|
|
218
192
|
@previous_state = cur_state
|
|
219
193
|
end
|
|
220
|
-
%><%= JSON.generate(@events) %>
|
|
194
|
+
%><%= JSON.generate(@events.to_a) %>
|
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.9.
|
|
4
|
+
version: 1.9.3
|
|
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: 2019-01-
|
|
11
|
+
date: 2019-01-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: em-http-request
|
|
@@ -184,11 +184,13 @@ files:
|
|
|
184
184
|
- samples/consul-ui/consul_nodes.json.erb
|
|
185
185
|
- samples/consul-ui/consul_services.json.erb
|
|
186
186
|
- samples/consul-ui/css/style.css
|
|
187
|
+
- samples/consul-ui/images/favicon.png
|
|
187
188
|
- samples/consul-ui/js/keys.js
|
|
188
189
|
- samples/consul-ui/js/nodes.js
|
|
189
190
|
- samples/consul-ui/js/service.js
|
|
190
191
|
- samples/consul-ui/js/timeline.js
|
|
191
192
|
- samples/consul-ui/js/utils.js
|
|
193
|
+
- samples/consul-ui/ringbuffer.rb
|
|
192
194
|
- samples/consul-ui/timeline.json.erb
|
|
193
195
|
- samples/consul-ui/vendors/highlight/atom-one-dark.css
|
|
194
196
|
- samples/consul-ui/vendors/highlight/highlight.pack.js
|