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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29433f0be694b9d9358498c00ac3f4c0cf2112fdabd86801d94c2afe899243f9
4
- data.tar.gz: df4dcdd2a3862122ffb122e3abaad2da1691366fd672c4a111b703586161ad37
3
+ metadata.gz: ed586b6f530661c89df4f8f31dd1f4960742b1fcfd9ea2aed2af44da9f059c05
4
+ data.tar.gz: d0eb5d09751bd5a8eafac6bf67febce94601ceae65f03ede0f576627f1d179ef
5
5
  SHA512:
6
- metadata.gz: b20f9e3549f5a886da874cf48b567a264269573c8fdb0204c0d6e3627adc68297411a55de04fa9ec9e8946e5141b8a7dce548d90448d843792b29b8df533d680
7
- data.tar.gz: 06722bbfaf0149c3fb3ee5b071de9950fb950ebaa53167926ad8f7d24f0bb86ea43a07e0d08f4809d19e15d7607e6d4c3a5bb6ea5365c0dd3905c403b3b1d664
6
+ metadata.gz: 865873980923a237af55f5809eb8a9ebb484279897c5dd3f37c6b7a8a19a780ed1bde203a566883f921fb14c4dc8c3e750abdf10807f86546c47d681da7a9483
7
+ data.tar.gz: 96dfd1d681f5760897609a6ec69b66fde406745ee4fb718d94e8faa566f97581637e08bd57fc91dc520be109221d426da0e9c6d327480e04fc8f0ae5b5dafdbc
data/.travis.yml CHANGED
@@ -1,6 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.3
4
+ - 2.4
5
+ - 2.5
4
6
  deploy:
5
7
  provider: rubygems
6
8
  api_key:
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`,
@@ -1,5 +1,5 @@
1
1
  module Consul
2
2
  module Async
3
- VERSION = '1.5.4'.freeze
3
+ VERSION = '1.5.5'.freeze
4
4
  end
5
5
  end
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] = res
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, stats|
65
- stats.each_pair do |state_name, state_count|
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
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-26 00:00:00.000000000 Z
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