consul-templaterb 1.5.4 → 1.5.5
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/.travis.yml +2 -0
- data/CHANGELOG.md +9 -0
- data/TemplateAPI.md +18 -1
- data/lib/consul/async/version.rb +1 -1
- data/samples/metrics.erb +24 -3
- metadata +2 -3
- data/lib/consul/async/endpoint.rb +0 -133
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed586b6f530661c89df4f8f31dd1f4960742b1fcfd9ea2aed2af44da9f059c05
|
4
|
+
data.tar.gz: d0eb5d09751bd5a8eafac6bf67febce94601ceae65f03ede0f576627f1d179ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 865873980923a237af55f5809eb8a9ebb484279897c5dd3f37c6b7a8a19a780ed1bde203a566883f921fb14c4dc8c3e750abdf10807f86546c47d681da7a9483
|
7
|
+
data.tar.gz: 96dfd1d681f5760897609a6ec69b66fde406745ee4fb718d94e8faa566f97581637e08bd57fc91dc520be109221d426da0e9c6d327480e04fc8f0ae5b5dafdbc
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## (UNRELEASED)
|
4
4
|
|
5
|
+
## 1.5.4 (September 27, 2018)
|
6
|
+
|
7
|
+
IMPROVEMENTS:
|
8
|
+
|
9
|
+
* Improved [Prometheus template](samples/metrics.erb) with many new metrics
|
10
|
+
* Documentation improvements regarding statistics and endpoints
|
11
|
+
* Code cleanups, code style, remove unused source file
|
12
|
+
* Travis build now runs rubocop and test with Ruby version from 2.3.x to 2.5.x
|
13
|
+
|
5
14
|
## 1.5.4 (September 26, 2018)
|
6
15
|
|
7
16
|
IMPROVEMENTS:
|
data/TemplateAPI.md
CHANGED
@@ -19,12 +19,29 @@ Have a look to [samples/](samples/) directory to start writing your own template
|
|
19
19
|
All objects returned by those functions described below all share the same structure:
|
20
20
|
|
21
21
|
* `.result` : handle the result
|
22
|
-
* `.endpoint` : get technical information about how data was retrieved and statistics
|
22
|
+
* `.endpoint` : get technical information about how data was retrieved and statistics.
|
23
|
+
|
24
|
+
## Accessing to statistics to monitor your cluster
|
25
|
+
|
26
|
+
All endpoints implement technical interface that allow to get information about what
|
27
|
+
is going on in your Consul Cluster.
|
28
|
+
|
29
|
+
On each object, you can access the `.endpoint` object that includes several informations about the endpoint being queried:
|
30
|
+
|
31
|
+
* `myresult.endpoint.x_consul_index` return the current index on blocking query
|
32
|
+
* `myresult.endpoint.stats` a object with interresting fields: `bytes_per_sec`,
|
33
|
+
`bytes_per_sec_human`, `successes`, `errors`, `body_bytes`. All stats details
|
34
|
+
are available in the file [lib/consul/async/stats.rb](lib/consul/async/stats.rb).
|
35
|
+
|
36
|
+
Using those statistics might be useful to trigger alerts very easily when something
|
37
|
+
is going on. Have a look to [samples/metrics.erb](samples/metrics.erb) that exposes
|
38
|
+
most of those metrics to [Prometheus](https://prometheus.io/).
|
23
39
|
|
24
40
|
## Common re-implemented functions for all objects
|
25
41
|
|
26
42
|
Most objects returned by all those functions are contained within a `.result` object. However, in order
|
27
43
|
to avoid having to write .result in all templates, some shortcuts have been added:
|
44
|
+
|
28
45
|
* `[]` allow to either access values for map-based data or arrays
|
29
46
|
* for all objects: `.each`, `sort`, `.select`, `.each_value`, `.count`, `.empty?`
|
30
47
|
* additionnaly, for map based results, the following methods are available: `.keys`, `.values`, `.each_pair`,
|
data/lib/consul/async/version.rb
CHANGED
data/samples/metrics.erb
CHANGED
@@ -41,7 +41,10 @@
|
|
41
41
|
state = compute_state(snode)[0]
|
42
42
|
res[state] += 1
|
43
43
|
end
|
44
|
-
backends[service_name] =
|
44
|
+
backends[service_name] = {
|
45
|
+
state: res,
|
46
|
+
stats: service(service_name).endpoint.stats,
|
47
|
+
}
|
45
48
|
end
|
46
49
|
end
|
47
50
|
%>
|
@@ -59,13 +62,31 @@ consul_services_count <%= service_count %>
|
|
59
62
|
|
60
63
|
# HELP consul_service_count A gauge of number instances of service with their current state
|
61
64
|
# TYPE consul_service_count gauge
|
65
|
+
# HELP consul_service_stats_requests_total A counter of requests performed by consul-templaterb, show activity on a service
|
66
|
+
# TYPE consul_service_stats_requests_total counter
|
67
|
+
# HELP consul_service_stats_requests_bytes A counter of bytes transfered from Consul Agent to consul-templaterb
|
68
|
+
# TYPE consul_service_stats_requests_bytes counter
|
69
|
+
# HELP consul_service_stats_requests_bytes_per_sec A counter of bytes transfered from Consul Agent to consul-templaterb
|
70
|
+
# TYPE consul_service_stats_requests_bytes_per_sec gauge
|
71
|
+
|
62
72
|
<%
|
63
73
|
json_backends = {}
|
64
|
-
backends.each_pair do |service_name,
|
65
|
-
|
74
|
+
backends.each_pair do |service_name, service_info|
|
75
|
+
service_info[:state].each_pair do |state_name, state_count|
|
66
76
|
%>consul_service_count{service="<%= service_name %>",state="<%= state_name %>"} <%= state_count %>
|
67
77
|
<%
|
68
78
|
end
|
79
|
+
current_stats = service_info[:stats]
|
80
|
+
%>consul_service_stats_requests_total{service="<%= service_name %>",type="success"} <%= current_stats.successes %>
|
81
|
+
<%
|
82
|
+
if current_stats.errors > 0
|
83
|
+
%>consul_service_stats_requests_total{service="<%= service_name %>",type="errors"} <%= current_stats.errors %>
|
84
|
+
<%
|
85
|
+
end
|
86
|
+
%>consul_service_stats_requests_bytes{service="<%= service_name %>"} <%= service_info[:stats].body_bytes %>
|
87
|
+
consul_service_stats_requests_bytes_per_sec{service="<%= service_name %>"} <%= service_info[:stats].bytes_per_sec %>
|
88
|
+
|
89
|
+
<%
|
69
90
|
end
|
70
91
|
%>
|
71
92
|
|
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.5.
|
4
|
+
version: 1.5.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-09-
|
11
|
+
date: 2018-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-http-request
|
@@ -165,7 +165,6 @@ files:
|
|
165
165
|
- lib/consul/async/consul_template.rb
|
166
166
|
- lib/consul/async/consul_template_engine.rb
|
167
167
|
- lib/consul/async/consul_template_render.rb
|
168
|
-
- lib/consul/async/endpoint.rb
|
169
168
|
- lib/consul/async/process_handler.rb
|
170
169
|
- lib/consul/async/stats.rb
|
171
170
|
- lib/consul/async/utilities.rb
|
@@ -1,133 +0,0 @@
|
|
1
|
-
require 'consul/async/utilities'
|
2
|
-
|
3
|
-
class Endpoint
|
4
|
-
attr_reader :conf, :path, :x_consul_index, :queue, :stats, :last_result, :enforce_json_200, :start_time, :default_value, :query_params
|
5
|
-
def initialize(conf, path, enforce_json_200 = true, query_params = {}, default_value = '[]')
|
6
|
-
@conf = conf.create(path)
|
7
|
-
@default_value = default_value
|
8
|
-
@path = path
|
9
|
-
@queue = EM::Queue.new
|
10
|
-
@s_callbacks = []
|
11
|
-
@e_callbacks = []
|
12
|
-
@enforce_json_200 = enforce_json_200
|
13
|
-
@start_time = Time.now.utc
|
14
|
-
@consecutive_errors = 0
|
15
|
-
@query_params = query_params
|
16
|
-
@stopping = false
|
17
|
-
@stats = EndPointStats.new
|
18
|
-
@last_result = ConsulResult.new(default_value, false, HttpResponse.new(nil), 0, stats, 1)
|
19
|
-
on_response { |result| @stats.on_reponse result }
|
20
|
-
on_error { |http| @stats.on_error http }
|
21
|
-
_enable_network_debug if conf.debug && conf.debug[:network]
|
22
|
-
fetch
|
23
|
-
queue << 0
|
24
|
-
end
|
25
|
-
|
26
|
-
def _enable_network_debug
|
27
|
-
on_response do |result|
|
28
|
-
state = result.x_consul_index.to_i < 1 ? '[WARN]' : '[ OK ]'
|
29
|
-
stats = result.stats
|
30
|
-
STDERR.puts "[DEBUG]#{state}#{result.modified? ? '[MODIFIED]' : '[NO DIFF]'}" \
|
31
|
-
"[s:#{stats.successes},err:#{stats.errors}]" \
|
32
|
-
"[#{stats.body_bytes_human.ljust(8)}][#{stats.bytes_per_sec_human.ljust(9)}]"\
|
33
|
-
" #{path.ljust(48)} idx:#{result.x_consul_index}, next in #{result.retry_in} s"
|
34
|
-
end
|
35
|
-
on_error { |http| STDERR.puts "[ERROR]: #{path}: #{http.error}" }
|
36
|
-
end
|
37
|
-
|
38
|
-
def on_response(&block)
|
39
|
-
@s_callbacks << block
|
40
|
-
end
|
41
|
-
|
42
|
-
def on_error(&block)
|
43
|
-
@e_callbacks << block
|
44
|
-
end
|
45
|
-
|
46
|
-
def ready?
|
47
|
-
@ready
|
48
|
-
end
|
49
|
-
|
50
|
-
def terminate
|
51
|
-
@stopping = true
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def build_request(headers = {}, query_params = {})
|
57
|
-
req = {
|
58
|
-
head: headers,
|
59
|
-
path: path,
|
60
|
-
query: query_params,
|
61
|
-
keepalive: true,
|
62
|
-
callback: method(:on_response)
|
63
|
-
}
|
64
|
-
@query_params.each_pair do |k, v|
|
65
|
-
req[:query][k] = v
|
66
|
-
end
|
67
|
-
req
|
68
|
-
end
|
69
|
-
|
70
|
-
def _handle_error(http, consul_index)
|
71
|
-
retry_in = [600, conf.retry_duration + 2**@consecutive_errors].min
|
72
|
-
STDERR.puts "[ERROR][#{path}] X-Consul-Index:#{consul_index} - #{http.error} - Retry in #{retry_in}s #{stats.body_bytes_human}"
|
73
|
-
@consecutive_errors += 1
|
74
|
-
http_result = HttpResponse.new(http)
|
75
|
-
EventMachine.add_timer(retry_in) do
|
76
|
-
yield
|
77
|
-
queue.push(consul_index)
|
78
|
-
end
|
79
|
-
@e_callbacks.each { |c| c.call(http_result) }
|
80
|
-
end
|
81
|
-
|
82
|
-
def fetch
|
83
|
-
options = {
|
84
|
-
connect_timeout: 5, # default connection setup timeout
|
85
|
-
inactivity_timeout: conf.wait_duration + 1, # default connection inactivity (post-setup) timeout
|
86
|
-
}
|
87
|
-
connection = EventMachine::HttpRequest.new(conf.base_url, options)
|
88
|
-
cb = proc do |consul_index|
|
89
|
-
http = connection.get(build_request(consul_index))
|
90
|
-
http.callback do
|
91
|
-
# Dirty hack, but contrary to other path, when key is not present, Consul returns 404
|
92
|
-
is_kv_empty = path.start_with?('/v1/kv') && http.response_header.status == 404
|
93
|
-
if !is_kv_empty && enforce_json_200 && http.response_header.status != 200 && http.response_header['Content-Type'] != 'application/json'
|
94
|
-
_handle_error(http, consul_index) { connection = EventMachine::HttpRequest.new(conf.base_url, options) }
|
95
|
-
else
|
96
|
-
n_consul_index = find_x_consul_token(http)
|
97
|
-
@consecutive_errors = 0
|
98
|
-
http_result = if is_kv_empty
|
99
|
-
HttpResponse.new(http, default_value)
|
100
|
-
else
|
101
|
-
HttpResponse.new(http)
|
102
|
-
end
|
103
|
-
new_content = http_result.response.freeze
|
104
|
-
modified = @last_result.nil? ? true : @last_result.data != new_content
|
105
|
-
if n_consul_index == consul_index || n_consul_index.nil?
|
106
|
-
retry_in = modified ? conf.missing_index_retry_time_on_diff : conf.missing_index_retry_time_on_unchanged
|
107
|
-
n_consul_index = consul_index
|
108
|
-
else
|
109
|
-
retry_in = modified ? conf.min_duration : conf.retry_on_non_diff
|
110
|
-
end
|
111
|
-
retry_in = 0.1 if retry_in < 0.1
|
112
|
-
unless @stopping
|
113
|
-
EventMachine.add_timer(retry_in) do
|
114
|
-
queue.push(n_consul_index)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
result = ConsulResult.new(new_content, modified, http_result, n_consul_index, stats, retry_in)
|
118
|
-
@last_result = result
|
119
|
-
@ready = true
|
120
|
-
@s_callbacks.each { |c| c.call(result) }
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
http.errback do
|
125
|
-
unless @stopping
|
126
|
-
_handle_error(http, consul_index) { connection = EventMachine::HttpRequest.new(conf.base_url, options) }
|
127
|
-
end
|
128
|
-
end
|
129
|
-
queue.pop(&cb)
|
130
|
-
end
|
131
|
-
queue.pop(&cb)
|
132
|
-
end
|
133
|
-
end
|