fluent-plugin-prometheus 1.7.1 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32e8a803f1394e445d273b41ec9bde5f238f4193956c431a0866c93b2a2a0426
4
- data.tar.gz: 281024e977c3aee02030691ffb7cd86361b759dae259bb8103934db7e195f751
3
+ metadata.gz: 6be199d6eb3693d4fe35be96961c05475a667ce8a7fe4b344fb6c5f7c269e820
4
+ data.tar.gz: 3cb81f50d84773da036d7bafadfa41c05928a7fb062310eeea0eea6546382900
5
5
  SHA512:
6
- metadata.gz: 6e784fec1bca9a2ea8f725b5970ed5f08069b6d457ae11b23e1c22017d188046cab4718573c67a94b230acff1583ac12d6378a372a3713f311470c2b9a5818e3
7
- data.tar.gz: 805673a26e562f4607cefbbf256c12e3557317e115a88096357ddde30f6d5f8dea67835e580100c6bfb5aa9abfb542d0f5b0bff9374b6d4b48046034fea5527a
6
+ metadata.gz: fc05d9f8283546700cc401c771d5444470e806fd4193cc47f661e01fd91bcd402ac2b0aa7fd52f2fa92ff5811f76d19aca378e3ae9919b93de27bca8e0300581
7
+ data.tar.gz: e614db8e23a6dad5a0d416b224e49ca1895b641b4b0d41933954d709080344f90cb79bc51869533d0efc43e93422dd401e4b547fa85ea316fa1f13457236933f
@@ -0,0 +1,15 @@
1
+ Release 1.8.2 - 2020/07/17
2
+
3
+ * in_prometheus_output_monitor/in_prometheus_tail_monitor: Support USR2 reload
4
+
5
+ Release 1.8.1 - 2020/07/06
6
+
7
+ * Fix aggregate bug with async-http
8
+
9
+ Release 1.8.0 - 2020/04/17
10
+
11
+ * Use http_server helper
12
+ * Require fluentd v1.9.1 or later
13
+
14
+
15
+ For older releases, see commits on github repository.
data/README.md CHANGED
@@ -8,9 +8,13 @@ A fluent plugin that instruments metrics from records and exposes them via web i
8
8
 
9
9
  | fluent-plugin-prometheus | fluentd | ruby |
10
10
  |--------------------------|------------|--------|
11
- | 1.x.y | >= v0.14.8 | >= 2.1 |
11
+ | 1.x.y | >= v1.9.1 | >= 2.4 |
12
+ | 1.[0-7].y | >= v0.14.8 | >= 2.1 |
12
13
  | 0.x.y | >= v0.12.0 | >= 1.9 |
13
14
 
15
+ Since v1.8.0, fluent-plugin-prometheus uses [http_server helper](https://docs.fluentd.org/plugin-helper-overview/api-plugin-helper-http_server) to launch HTTP server.
16
+ If you want to handle lots of connections, install `async-http` gem.
17
+
14
18
  ## Installation
15
19
 
16
20
  Add this line to your application's Gemfile:
@@ -63,6 +67,19 @@ More configuration parameters:
63
67
  When using multiple workers, each worker binds to port + `fluent_worker_id`.
64
68
  To scrape metrics from all workers at once, you can access http://localhost:24231/aggregated_metrics.
65
69
 
70
+ #### TLS setting
71
+
72
+ Use `<trasnport tls>`. See [transport config article](https://docs.fluentd.org/configuration/transport-section) for more details.
73
+
74
+ ```
75
+ <source>
76
+ @type prometheus
77
+ <transport tls>
78
+ # TLS parameters...
79
+ </transport
80
+ </source>
81
+ ```
82
+
66
83
  ### prometheus_monitor input plugin
67
84
 
68
85
  This plugin collects internal metrics in Fluentd. The metrics are similar to/part of [monitor_agent](https://docs.fluentd.org/input/monitor_agent).
@@ -71,7 +88,7 @@ This plugin collects internal metrics in Fluentd. The metrics are similar to/par
71
88
  #### Exposed metrics
72
89
 
73
90
  - `fluentd_status_buffer_queue_length`
74
- - `fluentd_status_buffer_total_queued_size`
91
+ - `fluentd_status_buffer_total_bytes`
75
92
  - `fluentd_status_retry_count`
76
93
  - `fluentd_status_buffer_newest_timekey` from fluentd v1.4.2
77
94
  - `fluentd_status_buffer_oldest_timekey` from fluentd v1.4.2
@@ -107,7 +124,7 @@ Metrics for output
107
124
  - `fluentd_output_status_emit_records`
108
125
  - `fluentd_output_status_write_count`
109
126
  - `fluentd_output_status_rollback_count`
110
- - `fluentd_output_status_flush_time_count` from fluentd v1.6.0
127
+ - `fluentd_output_status_flush_time_count` in milliseconds from fluentd v1.6.0
111
128
  - `fluentd_output_status_slow_flush_count` from fluentd v1.6.0
112
129
 
113
130
  Metrics for buffer
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "fluent-plugin-prometheus"
3
- spec.version = "1.7.1"
3
+ spec.version = "1.8.2"
4
4
  spec.authors = ["Masahiro Sano"]
5
5
  spec.email = ["sabottenda@gmail.com"]
6
6
  spec.summary = %q{A fluent plugin that collects metrics and exposes for Prometheus.}
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
14
  spec.require_paths = ["lib"]
15
15
 
16
- spec.add_dependency "fluentd", ">= 0.14.20", "< 2"
16
+ spec.add_dependency "fluentd", ">= 1.9.1", "< 2"
17
17
  spec.add_dependency "prometheus-client", "< 0.10"
18
18
  spec.add_development_dependency "bundler"
19
19
  spec.add_development_dependency "rake"
@@ -2,13 +2,13 @@ require 'fluent/plugin/input'
2
2
  require 'fluent/plugin/prometheus'
3
3
  require 'fluent/plugin/prometheus_metrics'
4
4
  require 'net/http'
5
- require 'webrick'
5
+ require 'openssl'
6
6
 
7
7
  module Fluent::Plugin
8
8
  class PrometheusInput < Fluent::Plugin::Input
9
9
  Fluent::Plugin.register_input('prometheus', self)
10
10
 
11
- helpers :thread
11
+ helpers :thread, :http_server
12
12
 
13
13
  config_param :bind, :string, default: '0.0.0.0'
14
14
  config_param :port, :integer, default: 24231
@@ -17,30 +17,25 @@ module Fluent::Plugin
17
17
 
18
18
  desc 'Enable ssl configuration for the server'
19
19
  config_section :ssl, required: false, multi: false do
20
- config_param :enable, :bool, default: false
20
+ config_param :enable, :bool, default: false, deprecated: 'Use <transport tls> section'
21
21
 
22
22
  desc 'Path to the ssl certificate in PEM format. Read from file and added to conf as "SSLCertificate"'
23
- config_param :certificate_path, :string, default: nil
23
+ config_param :certificate_path, :string, default: nil, deprecated: 'Use cert_path in <transport tls> section'
24
24
 
25
25
  desc 'Path to the ssl private key in PEM format. Read from file and added to conf as "SSLPrivateKey"'
26
- config_param :private_key_path, :string, default: nil
26
+ config_param :private_key_path, :string, default: nil, deprecated: 'Use private_key_path in <transport tls> section'
27
27
 
28
28
  desc 'Path to CA in PEM format. Read from file and added to conf as "SSLCACertificateFile"'
29
- config_param :ca_path, :string, default: nil
29
+ config_param :ca_path, :string, default: nil, deprecated: 'Use ca_path in <transport tls> section'
30
30
 
31
31
  desc 'Additional ssl conf for the server. Ref: https://github.com/ruby/webrick/blob/master/lib/webrick/ssl.rb'
32
- config_param :extra_conf, :hash, default: {:SSLCertName => [['CN','nobody'],['DC','example']]}, symbolize_keys: true
32
+ config_param :extra_conf, :hash, default: nil, symbolize_keys: true, deprecated: 'See http helper config'
33
33
  end
34
34
 
35
- attr_reader :registry
36
-
37
- attr_reader :num_workers
38
- attr_reader :base_port
39
- attr_reader :metrics_path
40
-
41
35
  def initialize
42
36
  super
43
37
  @registry = ::Prometheus::Client.registry
38
+ @secure = nil
44
39
  end
45
40
 
46
41
  def configure(conf)
@@ -55,6 +50,7 @@ module Fluent::Plugin
55
50
  nil
56
51
  end
57
52
  @num_workers = sysconf && sysconf.workers ? sysconf.workers : 1
53
+ @secure = @transport_config.protocol == :tls || (@ssl && @ssl['enable'])
58
54
 
59
55
  @base_port = @port
60
56
  @port += fluentd_worker_id
@@ -66,7 +62,71 @@ module Fluent::Plugin
66
62
 
67
63
  def start
68
64
  super
69
- log.debug "listening prometheus http server on http://#{@bind}:#{@port}/#{@metrics_path} for worker#{fluentd_worker_id}"
65
+
66
+ scheme = @secure ? 'https' : 'http'
67
+ log.debug "listening prometheus http server on #{scheme}:://#{@bind}:#{@port}/#{@metrics_path} for worker#{fluentd_worker_id}"
68
+
69
+ proto = @secure ? :tls : :tcp
70
+
71
+ if @ssl && @ssl['enable'] && @ssl['extra_conf']
72
+ start_webrick
73
+ return
74
+ end
75
+
76
+ begin
77
+ require 'async'
78
+ require 'fluent/plugin/in_prometheus/async_wrapper'
79
+ extend AsyncWrapper
80
+ rescue LoadError => _
81
+ # ignore
82
+ end
83
+
84
+ tls_opt = if @ssl && @ssl['enable']
85
+ ssl_config = {}
86
+
87
+ if (@ssl['certificate_path'] && @ssl['private_key_path'].nil?) || (@ssl['certificate_path'].nil? && @ssl['private_key_path'])
88
+ raise Fluent::ConfigError.new('both certificate_path and private_key_path must be defined')
89
+ end
90
+
91
+ if @ssl['certificate_path']
92
+ ssl_config['cert_path'] = @ssl['certificate_path']
93
+ end
94
+
95
+ if @ssl['private_key_path']
96
+ ssl_config['private_key_path'] = @ssl['private_key_path']
97
+ end
98
+
99
+ if @ssl['ca_path']
100
+ ssl_config['ca_path'] = @ssl['ca_path']
101
+ # Only ca_path is insecure in fluentd
102
+ # https://github.com/fluent/fluentd/blob/2236ad45197ba336fd9faf56f442252c8b226f25/lib/fluent/plugin_helper/cert_option.rb#L68
103
+ ssl_config['insecure'] = true
104
+ end
105
+
106
+ ssl_config
107
+ end
108
+
109
+ http_server_create_http_server(:in_prometheus_server, addr: @bind, port: @port, logger: log, proto: proto, tls_opts: tls_opt) do |server|
110
+ server.get(@metrics_path) { |_req| all_metrics }
111
+ server.get(@aggregated_metrics_path) { |_req| all_workers_metrics }
112
+ end
113
+ end
114
+
115
+ def shutdown
116
+ if @webrick_server
117
+ @webrick_server.shutdown
118
+ @webrick_server = nil
119
+ end
120
+ super
121
+ end
122
+
123
+ private
124
+
125
+ # For compatiblity because http helper can't support extra_conf option
126
+ def start_webrick
127
+ require 'webrick/https'
128
+ require 'webrick'
129
+
70
130
  config = {
71
131
  BindAddress: @bind,
72
132
  Port: @port,
@@ -74,90 +134,96 @@ module Fluent::Plugin
74
134
  Logger: WEBrick::Log.new(STDERR, WEBrick::Log::FATAL),
75
135
  AccessLog: [],
76
136
  }
77
- unless @ssl.nil? || !@ssl['enable']
78
- require 'webrick/https'
79
- require 'openssl'
80
- if (@ssl['certificate_path'] && @ssl['private_key_path'].nil?) || (@ssl['certificate_path'].nil? && @ssl['private_key_path'])
81
- raise RuntimeError.new("certificate_path and private_key_path most both be defined")
82
- end
83
- ssl_config = {
84
- SSLEnable: true
85
- }
86
- if @ssl['certificate_path']
87
- cert = OpenSSL::X509::Certificate.new(File.read(@ssl['certificate_path']))
88
- ssl_config[:SSLCertificate] = cert
89
- end
90
- if @ssl['private_key_path']
91
- key = OpenSSL::PKey::RSA.new(File.read(@ssl['private_key_path']))
92
- ssl_config[:SSLPrivateKey] = key
93
- end
94
- ssl_config[:SSLCACertificateFile] = @ssl['ca_path'] if @ssl['ca_path']
95
- ssl_config = ssl_config.merge(@ssl['extra_conf'])
96
- config = ssl_config.merge(config)
137
+ if (@ssl['certificate_path'] && @ssl['private_key_path'].nil?) || (@ssl['certificate_path'].nil? && @ssl['private_key_path'])
138
+ raise RuntimeError.new("certificate_path and private_key_path most both be defined")
139
+ end
140
+
141
+ ssl_config = {
142
+ SSLEnable: true,
143
+ SSLCertName: [['CN', 'nobody'], ['DC', 'example']]
144
+ }
145
+
146
+ if @ssl['certificate_path']
147
+ cert = OpenSSL::X509::Certificate.new(File.read(@ssl['certificate_path']))
148
+ ssl_config[:SSLCertificate] = cert
97
149
  end
150
+
151
+ if @ssl['private_key_path']
152
+ key = OpenSSL::PKey.read(@ssl['private_key_path'])
153
+ ssl_config[:SSLPrivateKey] = key
154
+ end
155
+
156
+ ssl_config[:SSLCACertificateFile] = @ssl['ca_path'] if @ssl['ca_path']
157
+ ssl_config = ssl_config.merge(@ssl['extra_conf']) if @ssl['extra_conf']
158
+ config = ssl_config.merge(config)
159
+
98
160
  @log.on_debug do
99
161
  @log.debug("WEBrick conf: #{config}")
100
162
  end
101
163
 
102
- @server = WEBrick::HTTPServer.new(config)
103
- @server.mount(@metrics_path, MonitorServlet, self)
104
- @server.mount(@aggregated_metrics_path, MonitorServletAll, self)
105
- thread_create(:in_prometheus) do
106
- @server.start
164
+ @webrick_server = WEBrick::HTTPServer.new(config)
165
+ @webrick_server.mount_proc(@metrics_path) do |_req, res|
166
+ status, header, body = all_metrics
167
+ res.status = status
168
+ res['Content-Type'] = header['Content-Type']
169
+ res.body = body
170
+ res
107
171
  end
108
- end
109
172
 
110
- def shutdown
111
- if @server
112
- @server.shutdown
113
- @server = nil
173
+ @webrick_server.mount_proc(@aggregated_metrics_path) do |_req, res|
174
+ status, header, body = all_workers_metrics
175
+ res.status = status
176
+ res['Content-Type'] = header['Content-Type']
177
+ res.body = body
178
+ res
179
+ end
180
+
181
+ thread_create(:in_prometheus_webrick) do
182
+ @webrick_server.start
114
183
  end
115
- super
116
184
  end
117
185
 
118
- class MonitorServlet < WEBrick::HTTPServlet::AbstractServlet
119
- def initialize(server, prometheus)
120
- @prometheus = prometheus
186
+ def all_metrics
187
+ [200, { 'Content-Type' => ::Prometheus::Client::Formats::Text::CONTENT_TYPE }, ::Prometheus::Client::Formats::Text.marshal(@registry)]
188
+ rescue => e
189
+ [500, { 'Content-Type' => 'text/plain' }, e.to_s]
190
+ end
191
+
192
+ def all_workers_metrics
193
+ full_result = PromMetricsAggregator.new
194
+
195
+ send_request_to_each_worker do |resp|
196
+ if resp.code.to_s == '200'
197
+ full_result.add_metrics(resp.body)
198
+ end
121
199
  end
122
200
 
123
- def do_GET(req, res)
124
- res.status = 200
125
- res['Content-Type'] = ::Prometheus::Client::Formats::Text::CONTENT_TYPE
126
- res.body = ::Prometheus::Client::Formats::Text.marshal(@prometheus.registry)
127
- rescue
128
- res.status = 500
129
- res['Content-Type'] = 'text/plain'
130
- res.body = $!.to_s
201
+ [200, { 'Content-Type' => ::Prometheus::Client::Formats::Text::CONTENT_TYPE }, full_result.get_metrics]
202
+ rescue => e
203
+ [500, { 'Content-Type' => 'text/plain' }, e.to_s]
204
+ end
205
+
206
+ def send_request_to_each_worker
207
+ bind = (@bind == '0.0.0.0') ? '127.0.0.1' : @bind
208
+ [*(@base_port...(@base_port + @num_workers))].each do |worker_port|
209
+ do_request(host: bind, port: worker_port, secure: @secure) do |http|
210
+ yield(http.get(@metrics_path))
211
+ end
131
212
  end
132
213
  end
133
214
 
134
- class MonitorServletAll < WEBrick::HTTPServlet::AbstractServlet
135
- def initialize(server, prometheus)
136
- @prometheus = prometheus
215
+ # might be replaced by AsyncWrapper if async gem is installed
216
+ def do_request(host:, port:, secure:)
217
+ http = Net::HTTP.new(host, port)
218
+
219
+ if secure
220
+ http.use_ssl = true
221
+ # target is our child process. so it's secure.
222
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
137
223
  end
138
224
 
139
- def do_GET(req, res)
140
- res.status = 200
141
- res['Content-Type'] = ::Prometheus::Client::Formats::Text::CONTENT_TYPE
142
-
143
- full_result = PromMetricsAggregator.new
144
- fluent_server_ip = @prometheus.bind == '0.0.0.0' ? '127.0.0.1' : @prometheus.bind
145
- current_worker = 0
146
- while current_worker < @prometheus.num_workers
147
- Net::HTTP.start(fluent_server_ip, @prometheus.base_port + current_worker) do |http|
148
- req = Net::HTTP::Get.new(@prometheus.metrics_path)
149
- result = http.request(req)
150
- if result.is_a?(Net::HTTPSuccess)
151
- full_result.add_metrics(result.body)
152
- end
153
- end
154
- current_worker += 1
155
- end
156
- res.body = full_result.get_metrics
157
- rescue
158
- res.status = 500
159
- res['Content-Type'] = 'text/plain'
160
- res.body = $!.to_s
225
+ http.start do
226
+ yield(http)
161
227
  end
162
228
  end
163
229
  end
@@ -0,0 +1,46 @@
1
+ require 'async'
2
+
3
+ module Fluent::Plugin
4
+ class PrometheusInput
5
+ module AsyncWrapper
6
+ def do_request(host:, port:, secure:)
7
+ endpoint =
8
+ if secure
9
+ context = OpenSSL::SSL::SSLContext.new
10
+ context.verify_mode = OpenSSL::SSL::VERIFY_NONE
11
+ Async::HTTP::Endpoint.parse("https://#{host}:#{port}", ssl_context: context)
12
+ else
13
+ Async::HTTP::Endpoint.parse("http://#{host}:#{port}")
14
+ end
15
+
16
+ client = Async::HTTP::Client.new(endpoint)
17
+ yield(AsyncHttpWrapper.new(client))
18
+ end
19
+
20
+ Response = Struct.new(:code, :body, :headers)
21
+
22
+ class AsyncHttpWrapper
23
+ def initialize(http)
24
+ @http = http
25
+ end
26
+
27
+ def get(path)
28
+ error = nil
29
+ response = Async::Task.current.async {
30
+ begin
31
+ @http.get(path)
32
+ rescue => e # Async::Reactor rescue all error. handle it by itself
33
+ error = e
34
+ end
35
+ }.wait
36
+
37
+ if error
38
+ raise error
39
+ end
40
+
41
+ Response.new(response.status.to_s, response.body.read, response.headers)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,9 +1,9 @@
1
- require 'fluent/input'
1
+ require 'fluent/plugin/input'
2
2
  require 'fluent/plugin/in_monitor_agent'
3
3
  require 'fluent/plugin/prometheus'
4
4
 
5
5
  module Fluent::Plugin
6
- class PrometheusOutputMonitorInput < Fluent::Input
6
+ class PrometheusOutputMonitorInput < Fluent::Plugin::Input
7
7
  Fluent::Plugin.register_input('prometheus_output_monitor', self)
8
8
  include Fluent::Plugin::PrometheusLabelParser
9
9
 
@@ -44,7 +44,7 @@ module Fluent::Plugin
44
44
  super
45
45
  hostname = Socket.gethostname
46
46
  expander_builder = Fluent::Plugin::Prometheus.placeholder_expander(log)
47
- expander = expander_builder.buidl({ 'hostname' => hostname, 'worker_id' => fluentd_worker_id })
47
+ expander = expander_builder.build({ 'hostname' => hostname, 'worker_id' => fluentd_worker_id })
48
48
  @base_labels = parse_labels_elements(conf)
49
49
  @base_labels.each do |key, value|
50
50
  unless value.is_a?(String)
@@ -53,12 +53,7 @@ module Fluent::Plugin
53
53
  @base_labels[key] = expander.expand(value)
54
54
  end
55
55
 
56
- if defined?(Fluent::Plugin) && defined?(Fluent::Plugin::MonitorAgentInput)
57
- # from v0.14.6
58
- @monitor_agent = Fluent::Plugin::MonitorAgentInput.new
59
- else
60
- @monitor_agent = Fluent::MonitorAgentInput.new
61
- end
56
+ @monitor_agent = Fluent::Plugin::MonitorAgentInput.new
62
57
  end
63
58
 
64
59
  def start
@@ -66,57 +61,57 @@ module Fluent::Plugin
66
61
 
67
62
  @metrics = {
68
63
  # Buffer metrics
69
- buffer_total_queued_size: @registry.gauge(
64
+ buffer_total_queued_size: get_gauge(
70
65
  :fluentd_output_status_buffer_total_bytes,
71
66
  'Current total size of stage and queue buffers.'),
72
- buffer_stage_length: @registry.gauge(
67
+ buffer_stage_length: get_gauge(
73
68
  :fluentd_output_status_buffer_stage_length,
74
69
  'Current length of stage buffers.'),
75
- buffer_stage_byte_size: @registry.gauge(
70
+ buffer_stage_byte_size: get_gauge(
76
71
  :fluentd_output_status_buffer_stage_byte_size,
77
72
  'Current total size of stage buffers.'),
78
- buffer_queue_length: @registry.gauge(
73
+ buffer_queue_length: get_gauge(
79
74
  :fluentd_output_status_buffer_queue_length,
80
75
  'Current length of queue buffers.'),
81
- buffer_queue_byte_size: @registry.gauge(
76
+ buffer_queue_byte_size: get_gauge(
82
77
  :fluentd_output_status_queue_byte_size,
83
78
  'Current total size of queue buffers.'),
84
- buffer_available_buffer_space_ratios: @registry.gauge(
79
+ buffer_available_buffer_space_ratios: get_gauge(
85
80
  :fluentd_output_status_buffer_available_space_ratio,
86
81
  'Ratio of available space in buffer.'),
87
- buffer_newest_timekey: @registry.gauge(
82
+ buffer_newest_timekey: get_gauge(
88
83
  :fluentd_output_status_buffer_newest_timekey,
89
84
  'Newest timekey in buffer.'),
90
- buffer_oldest_timekey: @registry.gauge(
85
+ buffer_oldest_timekey: get_gauge(
91
86
  :fluentd_output_status_buffer_oldest_timekey,
92
87
  'Oldest timekey in buffer.'),
93
88
 
94
89
  # Output metrics
95
- retry_counts: @registry.gauge(
90
+ retry_counts: get_gauge(
96
91
  :fluentd_output_status_retry_count,
97
92
  'Current retry counts.'),
98
- num_errors: @registry.gauge(
93
+ num_errors: get_gauge(
99
94
  :fluentd_output_status_num_errors,
100
95
  'Current number of errors.'),
101
- emit_count: @registry.gauge(
96
+ emit_count: get_gauge(
102
97
  :fluentd_output_status_emit_count,
103
98
  'Current emit counts.'),
104
- emit_records: @registry.gauge(
99
+ emit_records: get_gauge(
105
100
  :fluentd_output_status_emit_records,
106
101
  'Current emit records.'),
107
- write_count: @registry.gauge(
102
+ write_count: get_gauge(
108
103
  :fluentd_output_status_write_count,
109
104
  'Current write counts.'),
110
- rollback_count: @registry.gauge(
105
+ rollback_count: get_gauge(
111
106
  :fluentd_output_status_rollback_count,
112
107
  'Current rollback counts.'),
113
- flush_time_count: @registry.gauge(
108
+ flush_time_count: get_gauge(
114
109
  :fluentd_output_status_flush_time_count,
115
110
  'Total flush time.'),
116
- slow_flush_count: @registry.gauge(
111
+ slow_flush_count: get_gauge(
117
112
  :fluentd_output_status_slow_flush_count,
118
113
  'Current slow flush counts.'),
119
- retry_wait: @registry.gauge(
114
+ retry_wait: get_gauge(
120
115
  :fluentd_output_status_retry_wait,
121
116
  'Current retry wait'),
122
117
  }
@@ -198,5 +193,13 @@ module Fluent::Plugin
198
193
  type: plugin_info["type"],
199
194
  )
200
195
  end
196
+
197
+ def get_gauge(name, docstring)
198
+ if @registry.exist?(name)
199
+ @registry.get(name)
200
+ else
201
+ @registry.gauge(name, docstring)
202
+ end
203
+ end
201
204
  end
202
205
  end
@@ -29,7 +29,7 @@ module Fluent::Plugin
29
29
  super
30
30
  hostname = Socket.gethostname
31
31
  expander_builder = Fluent::Plugin::Prometheus.placeholder_expander(log)
32
- expander = expander_builder.prepare_placeholders({ 'hostname' => hostname, 'worker_id' => fluentd_worker_id })
32
+ expander = expander_builder.build({ 'hostname' => hostname, 'worker_id' => fluentd_worker_id })
33
33
  @base_labels = parse_labels_elements(conf)
34
34
  @base_labels.each do |key, value|
35
35
  unless value.is_a?(String)
@@ -38,22 +38,17 @@ module Fluent::Plugin
38
38
  @base_labels[key] = expander.expand(value)
39
39
  end
40
40
 
41
- if defined?(Fluent::Plugin) && defined?(Fluent::Plugin::MonitorAgentInput)
42
- # from v0.14.6
43
- @monitor_agent = Fluent::Plugin::MonitorAgentInput.new
44
- else
45
- @monitor_agent = Fluent::MonitorAgentInput.new
46
- end
41
+ @monitor_agent = Fluent::Plugin::MonitorAgentInput.new
47
42
  end
48
43
 
49
44
  def start
50
45
  super
51
46
 
52
47
  @metrics = {
53
- position: @registry.gauge(
48
+ position: get_gauge(
54
49
  :fluentd_tail_file_position,
55
50
  'Current position of file.'),
56
- inode: @registry.gauge(
51
+ inode: get_gauge(
57
52
  :fluentd_tail_file_inode,
58
53
  'Current inode of file.'),
59
54
  }
@@ -91,5 +86,13 @@ module Fluent::Plugin
91
86
  path: path,
92
87
  )
93
88
  end
89
+
90
+ def get_gauge(name, docstring)
91
+ if @registry.exist?(name)
92
+ @registry.get(name)
93
+ else
94
+ @registry.gauge(name, docstring)
95
+ end
96
+ end
94
97
  end
95
98
  end
@@ -6,11 +6,11 @@ require 'net/http'
6
6
 
7
7
  describe Fluent::Plugin::PrometheusInput do
8
8
  CONFIG = %[
9
- type prometheus
9
+ @type prometheus
10
10
  ]
11
11
 
12
12
  LOCAL_CONFIG = %[
13
- type prometheus
13
+ @type prometheus
14
14
  bind 127.0.0.1
15
15
  ]
16
16
 
@@ -47,6 +47,130 @@ describe Fluent::Plugin::PrometheusInput do
47
47
  end
48
48
  end
49
49
 
50
+ describe '#start' do
51
+ context 'with transport section' do
52
+ let(:config) do
53
+ %[
54
+ @type prometheus
55
+ bind 127.0.0.1
56
+ <transport tls>
57
+ insecure true
58
+ </transport>
59
+ ]
60
+ end
61
+
62
+ it 'returns 200' do
63
+ driver.run(timeout: 1) do
64
+ Net::HTTP.start('127.0.0.1', port, verify_mode: OpenSSL::SSL::VERIFY_NONE, use_ssl: true) do |http|
65
+ req = Net::HTTP::Get.new('/metrics')
66
+ res = http.request(req)
67
+ expect(res.code).to eq('200')
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'old parameters are given' do
74
+ context 'when extra_conf is used' do
75
+ let(:config) do
76
+ %[
77
+ @type prometheus
78
+ bind 127.0.0.1
79
+ <ssl>
80
+ enable true
81
+ extra_conf { "SSLCertName": [["CN", "nobody"], ["DC", "example"]] }
82
+ </ssl>
83
+ ]
84
+ end
85
+
86
+ it 'uses webrick' do
87
+ expect(driver.instance).to receive(:start_webrick).once
88
+ driver.run(timeout: 1)
89
+ end
90
+
91
+ it 'returns 200' do
92
+ driver.run(timeout: 1) do
93
+ Net::HTTP.start('127.0.0.1', port, verify_mode: OpenSSL::SSL::VERIFY_NONE, use_ssl: true) do |http|
94
+ req = Net::HTTP::Get.new('/metrics')
95
+ res = http.request(req)
96
+ expect(res.code).to eq('200')
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ context 'cert_path and private_key_path combination' do
103
+ let(:config) do
104
+ %[
105
+ @type prometheus
106
+ bind 127.0.0.1
107
+ <ssl>
108
+ enable true
109
+ certificate_path path
110
+ private_key_path path1
111
+ </ssl>
112
+ ]
113
+ end
114
+
115
+ it 'converts them into new transport section' do
116
+ expect(driver.instance).to receive(:http_server_create_http_server).with(
117
+ :in_prometheus_server,
118
+ addr: anything,
119
+ logger: anything,
120
+ port: anything,
121
+ proto: :tls,
122
+ tls_opts: { 'cert_path' => 'path', 'private_key_path' => 'path1' }
123
+ ).once
124
+
125
+ driver.run(timeout: 1)
126
+ end
127
+ end
128
+
129
+ context 'insecure and ca_path' do
130
+ let(:config) do
131
+ %[
132
+ @type prometheus
133
+ bind 127.0.0.1
134
+ <ssl>
135
+ enable true
136
+ ca_path path
137
+ </ssl>
138
+ ]
139
+ end
140
+
141
+ it 'converts them into new transport section' do
142
+ expect(driver.instance).to receive(:http_server_create_http_server).with(
143
+ :in_prometheus_server,
144
+ addr: anything,
145
+ logger: anything,
146
+ port: anything,
147
+ proto: :tls,
148
+ tls_opts: { 'ca_path' => 'path', 'insecure' => true }
149
+ ).once
150
+
151
+ driver.run(timeout: 1)
152
+ end
153
+ end
154
+
155
+ context 'when only private_key_path is geven' do
156
+ let(:config) do
157
+ %[
158
+ @type prometheus
159
+ bind 127.0.0.1
160
+ <ssl>
161
+ enable true
162
+ private_key_path path
163
+ </ssl>
164
+ ]
165
+ end
166
+
167
+ it 'raises ConfigError' do
168
+ expect { driver.run(timeout: 1) }.to raise_error(Fluent::ConfigError, 'both certificate_path and private_key_path must be defined')
169
+ end
170
+ end
171
+ end
172
+ end
173
+
50
174
  describe '#run' do
51
175
  context '/metrics' do
52
176
  let(:config) { LOCAL_CONFIG }
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'fluent/plugin/in_prometheus_tail_monitor'
3
+ require 'fluent/test/driver/input'
4
+
5
+ describe Fluent::Plugin::PrometheusTailMonitorInput do
6
+ MONITOR_CONFIG = %[
7
+ @type prometheus_tail_monitor
8
+ <labels>
9
+ host ${hostname}
10
+ foo bar
11
+ </labels>
12
+ ]
13
+
14
+ INVALID_MONITOR_CONFIG = %[
15
+ @type prometheus_tail_monitor
16
+
17
+ <labels>
18
+ host ${hostname}
19
+ foo bar
20
+ invalid_use1 $.foo.bar
21
+ invalid_use2 $[0][1]
22
+ </labels>
23
+ ]
24
+
25
+ let(:config) { MONITOR_CONFIG }
26
+ let(:driver) { Fluent::Test::Driver::Input.new(Fluent::Plugin::PrometheusTailMonitorInput).configure(config) }
27
+
28
+ describe '#configure' do
29
+ describe 'valid' do
30
+ it 'does not raise error' do
31
+ expect { driver }.not_to raise_error
32
+ end
33
+ end
34
+
35
+ describe 'invalid' do
36
+ let(:config) { INVALID_MONITOR_CONFIG }
37
+ it 'expect raise error' do
38
+ expect { driver }.to raise_error
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,6 +1,6 @@
1
1
 
2
2
  BASE_CONFIG = %[
3
- type prometheus
3
+ @type prometheus
4
4
  ]
5
5
 
6
6
  SIMPLE_CONFIG = BASE_CONFIG + %[
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-prometheus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masahiro Sano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-13 00:00:00.000000000 Z
11
+ date: 2020-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.14.20
19
+ version: 1.9.1
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '2'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 0.14.20
29
+ version: 1.9.1
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '2'
@@ -110,6 +110,7 @@ files:
110
110
  - ".gitignore"
111
111
  - ".rspec"
112
112
  - ".travis.yml"
113
+ - ChangeLog
113
114
  - Gemfile
114
115
  - LICENSE
115
116
  - README.md
@@ -117,6 +118,7 @@ files:
117
118
  - fluent-plugin-prometheus.gemspec
118
119
  - lib/fluent/plugin/filter_prometheus.rb
119
120
  - lib/fluent/plugin/in_prometheus.rb
121
+ - lib/fluent/plugin/in_prometheus/async_wrapper.rb
120
122
  - lib/fluent/plugin/in_prometheus_monitor.rb
121
123
  - lib/fluent/plugin/in_prometheus_output_monitor.rb
122
124
  - lib/fluent/plugin/in_prometheus_tail_monitor.rb
@@ -131,6 +133,7 @@ files:
131
133
  - spec/fluent/plugin/filter_prometheus_spec.rb
132
134
  - spec/fluent/plugin/in_prometheus_monitor_spec.rb
133
135
  - spec/fluent/plugin/in_prometheus_spec.rb
136
+ - spec/fluent/plugin/in_prometheus_tail_monitor_spec.rb
134
137
  - spec/fluent/plugin/out_prometheus_spec.rb
135
138
  - spec/fluent/plugin/prometheus/placeholder_expander_spec.rb
136
139
  - spec/fluent/plugin/prometheus_metrics_spec.rb
@@ -163,6 +166,7 @@ test_files:
163
166
  - spec/fluent/plugin/filter_prometheus_spec.rb
164
167
  - spec/fluent/plugin/in_prometheus_monitor_spec.rb
165
168
  - spec/fluent/plugin/in_prometheus_spec.rb
169
+ - spec/fluent/plugin/in_prometheus_tail_monitor_spec.rb
166
170
  - spec/fluent/plugin/out_prometheus_spec.rb
167
171
  - spec/fluent/plugin/prometheus/placeholder_expander_spec.rb
168
172
  - spec/fluent/plugin/prometheus_metrics_spec.rb