fluent-plugin-prometheus 0.5.0 → 1.0.0
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 +5 -5
- data/.travis.yml +2 -2
- data/Gemfile +3 -2
- data/README.md +18 -11
- data/fluent-plugin-prometheus.gemspec +2 -2
- data/lib/fluent/plugin/filter_prometheus.rb +7 -6
- data/lib/fluent/plugin/in_prometheus.rb +14 -61
- data/lib/fluent/plugin/in_prometheus_monitor.rb +10 -40
- data/lib/fluent/plugin/in_prometheus_output_monitor.rb +9 -39
- data/lib/fluent/plugin/in_prometheus_tail_monitor.rb +10 -40
- data/lib/fluent/plugin/out_prometheus.rb +8 -9
- data/lib/fluent/plugin/prometheus.rb +160 -166
- data/misc/fluentd_sample.conf +7 -0
- data/spec/fluent/plugin/filter_prometheus_spec.rb +8 -4
- data/spec/fluent/plugin/out_prometheus_spec.rb +7 -3
- data/spec/fluent/plugin/prometheus_spec.rb +5 -4
- data/spec/spec_helper.rb +2 -0
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b6e00809503106fad10f9d831e67091e69ed56da
|
4
|
+
data.tar.gz: 5f84aeff3ed1a79a6da4c7ea18a5332c02304baa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7658cc206cc8063ea61d83730b37db12a311f152a560c3c5d669c9f73dd9994c417b1a30810531d101c56821f4395f5d875fe5ef5cabb67e72948974186cdad9
|
7
|
+
data.tar.gz: ac72182e9fea379125a487f521d42a29bbf354d857abf3dc778daffdec8aa8bd346d444b3ab001cbcac951fde2b72c3ad208e0e2748aa9d5a14d35b34e73e1c3
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
# fluent-plugin-prometheus, a plugin for [Fluentd](https://www.fluentd.org)
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
[](https://travis-ci.org/fluent/fluent-plugin-prometheus)
|
3
|
+
[](https://travis-ci.org/fluent/fluent-plugin-prometheus)
|
6
4
|
|
7
5
|
A fluent plugin that instruments metrics from records and exposes them via web interface. Intended to be used together with a [Prometheus server](https://github.com/prometheus/prometheus).
|
8
6
|
|
7
|
+
If you are using Fluentd v0.10, you have to explicitly install [fluent-plugin-record-reformer](https://github.com/sonots/fluent-plugin-record-reformer) together. With Fluentd v0.12 or v0.14, there is no additional dependency.
|
8
|
+
|
9
|
+
## Requirements
|
10
|
+
|
11
|
+
| fluent-plugin-prometheus | fluentd | ruby |
|
12
|
+
|--------------------------|------------|--------|
|
13
|
+
| 1.x.y | >= v0.14.8 | >= 2.1 |
|
14
|
+
| 0.x.y | >= v0.12.0 | >= 1.9 |
|
15
|
+
|
9
16
|
## Installation
|
10
17
|
|
11
18
|
Add this line to your application's Gemfile:
|
@@ -72,7 +79,7 @@ With following configuration, those metrics are collected.
|
|
72
79
|
|
73
80
|
More configuration parameters:
|
74
81
|
|
75
|
-
- `<labels>`: additional labels for this metric (optional). See [Labels](#
|
82
|
+
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
76
83
|
- `interval`: interval to update monitor_agent information in seconds (default: 5)
|
77
84
|
|
78
85
|
### prometheus_output_monitor input plugin
|
@@ -106,7 +113,7 @@ With following configuration, those metrics are collected.
|
|
106
113
|
|
107
114
|
More configuration parameters:
|
108
115
|
|
109
|
-
- `<labels>`: additional labels for this metric (optional). See [Labels](#
|
116
|
+
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
110
117
|
- `interval`: interval to update monitor_agent information in seconds (default: 5)
|
111
118
|
|
112
119
|
### prometheus_tail_monitor input plugin
|
@@ -133,12 +140,12 @@ Default labels:
|
|
133
140
|
With following configuration, those metrics are collected.
|
134
141
|
|
135
142
|
<source>
|
136
|
-
@type
|
143
|
+
@type prometheus_tail_monitor
|
137
144
|
</source>
|
138
145
|
|
139
146
|
More configuration parameters:
|
140
147
|
|
141
|
-
- `<labels>`: additional labels for this metric (optional). See [Labels](#
|
148
|
+
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
142
149
|
- `interval`: interval to update monitor_agent information in seconds (default: 5)
|
143
150
|
|
144
151
|
### prometheus output/filter plugin
|
@@ -237,7 +244,7 @@ For details of each metric type, see [Prometheus documentation](http://prometheu
|
|
237
244
|
- `type`: metric type (required)
|
238
245
|
- `desc`: description of this metric (required)
|
239
246
|
- `key`: key name of record for instrumentation (**optional**)
|
240
|
-
- `<labels>`: additional labels for this metric (optional). See [Labels](#
|
247
|
+
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
241
248
|
|
242
249
|
If key is empty, the metric values is treated as 1, so the counter increments by 1 on each record regardless of contents of the record.
|
243
250
|
|
@@ -261,7 +268,7 @@ If key is empty, the metric values is treated as 1, so the counter increments by
|
|
261
268
|
- `type`: metric type (required)
|
262
269
|
- `desc`: description of metric (required)
|
263
270
|
- `key`: key name of record for instrumentation (required)
|
264
|
-
- `<labels>`: additional labels for this metric (optional). See [Labels](#
|
271
|
+
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
265
272
|
|
266
273
|
### summary type
|
267
274
|
|
@@ -283,7 +290,7 @@ If key is empty, the metric values is treated as 1, so the counter increments by
|
|
283
290
|
- `type`: metric type (required)
|
284
291
|
- `desc`: description of metric (required)
|
285
292
|
- `key`: key name of record for instrumentation (required)
|
286
|
-
- `<labels>`: additional labels for this metric (optional). See [Labels](#
|
293
|
+
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
287
294
|
|
288
295
|
### histogram type
|
289
296
|
|
@@ -307,7 +314,7 @@ If key is empty, the metric values is treated as 1, so the counter increments by
|
|
307
314
|
- `desc`: description of metric (required)
|
308
315
|
- `key`: key name of record for instrumentation (required)
|
309
316
|
- `buckets`: buckets of record for instrumentation (optional)
|
310
|
-
- `<labels>`: additional labels for this metric (optional). See [Labels](#
|
317
|
+
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
311
318
|
|
312
319
|
## Labels
|
313
320
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "fluent-plugin-prometheus"
|
3
|
-
spec.version = "0.
|
3
|
+
spec.version = "1.0.0"
|
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.
|
16
|
+
spec.add_dependency "fluentd", ">= 0.14.8", "< 2"
|
17
17
|
spec.add_dependency "prometheus-client"
|
18
18
|
spec.add_development_dependency "bundler"
|
19
19
|
spec.add_development_dependency "rake"
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'fluent/plugin/prometheus'
|
2
|
+
require 'fluent/plugin/filter'
|
2
3
|
|
3
|
-
module Fluent
|
4
|
-
class PrometheusFilter < Filter
|
5
|
-
Plugin.register_filter('prometheus', self)
|
6
|
-
include Fluent::Prometheus
|
4
|
+
module Fluent::Plugin
|
5
|
+
class PrometheusFilter < Fluent::Plugin::Filter
|
6
|
+
Fluent::Plugin.register_filter('prometheus', self)
|
7
|
+
include Fluent::Plugin::Prometheus
|
7
8
|
|
8
9
|
def initialize
|
9
10
|
super
|
@@ -12,8 +13,8 @@ module Fluent
|
|
12
13
|
|
13
14
|
def configure(conf)
|
14
15
|
super
|
15
|
-
labels = Fluent::Prometheus.parse_labels_elements(conf)
|
16
|
-
@metrics = Fluent::Prometheus.parse_metrics_elements(conf, @registry, labels)
|
16
|
+
labels = Fluent::Plugin::Prometheus.parse_labels_elements(conf)
|
17
|
+
@metrics = Fluent::Plugin::Prometheus.parse_metrics_elements(conf, @registry, labels)
|
17
18
|
end
|
18
19
|
|
19
20
|
def filter_stream(tag, es)
|
@@ -1,31 +1,16 @@
|
|
1
|
-
require 'fluent/input'
|
1
|
+
require 'fluent/plugin/input'
|
2
2
|
require 'fluent/plugin/prometheus'
|
3
3
|
require 'webrick'
|
4
4
|
|
5
|
-
module Fluent
|
6
|
-
class PrometheusInput < Input
|
7
|
-
Plugin.register_input('prometheus', self)
|
5
|
+
module Fluent::Plugin
|
6
|
+
class PrometheusInput < Fluent::Plugin::Input
|
7
|
+
Fluent::Plugin.register_input('prometheus', self)
|
8
8
|
|
9
|
-
|
10
|
-
config_param :port, :integer, :default => 24231
|
11
|
-
config_param :metrics_path, :string, :default => '/metrics'
|
9
|
+
helpers :thread
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
desc 'Path to the ssl certificate in PEM format. Read from file and added to conf as "SSLCertificate"'
|
18
|
-
config_param :certificate_path, :string, required: false, default: nil
|
19
|
-
|
20
|
-
desc 'Path to the ssl private key in PEM format. Read from file and added to conf as "SSLPrivateKey"'
|
21
|
-
config_param :private_key_path, :string, required: false, default: nil
|
22
|
-
|
23
|
-
desc 'Path to CA in PEM format. Read from file and added to conf as "SSLCACertificateFile"'
|
24
|
-
config_param :ca_path, :string, required: false, default: nil
|
25
|
-
|
26
|
-
desc 'Additional ssl conf for the server. Ref: https://github.com/ruby/webrick/blob/master/lib/webrick/ssl.rb'
|
27
|
-
config_param :extra_conf, :hash, multi: false, required: false, default: {:SSLCertName => [['CN','nobody'],['DC','example']]}, symbolize_keys: true
|
28
|
-
end
|
11
|
+
config_param :bind, :string, default: '0.0.0.0'
|
12
|
+
config_param :port, :integer, default: 24231
|
13
|
+
config_param :metrics_path, :string, default: '/metrics'
|
29
14
|
|
30
15
|
attr_reader :registry
|
31
16
|
|
@@ -34,59 +19,27 @@ module Fluent
|
|
34
19
|
@registry = ::Prometheus::Client.registry
|
35
20
|
end
|
36
21
|
|
37
|
-
def configure(conf)
|
38
|
-
super
|
39
|
-
end
|
40
|
-
|
41
22
|
def start
|
42
23
|
super
|
43
|
-
|
24
|
+
@server = WEBrick::HTTPServer.new(
|
44
25
|
BindAddress: @bind,
|
45
26
|
Port: @port,
|
46
27
|
MaxClients: 5,
|
47
28
|
Logger: WEBrick::Log.new(STDERR, WEBrick::Log::FATAL),
|
48
29
|
AccessLog: [],
|
49
|
-
|
50
|
-
unless @ssl.nil? || !@ssl['enable']
|
51
|
-
require 'webrick/https'
|
52
|
-
require 'openssl'
|
53
|
-
if (@ssl['certificate_path'] && @ssl['private_key_path'].nil?) || (@ssl['certificate_path'].nil? && @ssl['private_key_path'])
|
54
|
-
raise RuntimeError.new("certificate_path and private_key_path most both be defined")
|
55
|
-
end
|
56
|
-
ssl_config = {
|
57
|
-
SSLEnable: true
|
58
|
-
}
|
59
|
-
if @ssl['certificate_path']
|
60
|
-
cert = OpenSSL::X509::Certificate.new(File.read(@ssl['certificate_path']))
|
61
|
-
ssl_config[:SSLCertificate] = cert
|
62
|
-
end
|
63
|
-
if @ssl['private_key_path']
|
64
|
-
key = OpenSSL::PKey::RSA.new(File.read(@ssl['private_key_path']))
|
65
|
-
ssl_config[:SSLPrivateKey] = key
|
66
|
-
end
|
67
|
-
ssl_config[:SSLCACertificateFile] = @ssl['ca_path'] if @ssl['ca_path']
|
68
|
-
ssl_config = ssl_config.merge(@ssl['extra_conf'])
|
69
|
-
config = ssl_config.merge(config)
|
70
|
-
end
|
71
|
-
@log.on_debug do
|
72
|
-
@log.debug("WEBrick conf: #{config}")
|
73
|
-
end
|
74
|
-
|
75
|
-
@server = WEBrick::HTTPServer.new(config)
|
30
|
+
)
|
76
31
|
@server.mount(@metrics_path, MonitorServlet, self)
|
77
|
-
|
32
|
+
thread_create(:in_prometheus) do
|
33
|
+
@server.start
|
34
|
+
end
|
78
35
|
end
|
79
36
|
|
80
37
|
def shutdown
|
81
|
-
super
|
82
38
|
if @server
|
83
39
|
@server.shutdown
|
84
40
|
@server = nil
|
85
41
|
end
|
86
|
-
|
87
|
-
@thread.join
|
88
|
-
@thread = nil
|
89
|
-
end
|
42
|
+
super
|
90
43
|
end
|
91
44
|
|
92
45
|
class MonitorServlet < WEBrick::HTTPServlet::AbstractServlet
|
@@ -1,12 +1,14 @@
|
|
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
|
-
module Fluent
|
6
|
-
class PrometheusMonitorInput < Input
|
7
|
-
Plugin.register_input('prometheus_monitor', self)
|
5
|
+
module Fluent::Plugin
|
6
|
+
class PrometheusMonitorInput < Fluent::Plugin::Input
|
7
|
+
Fluent::Plugin.register_input('prometheus_monitor', self)
|
8
8
|
|
9
|
-
|
9
|
+
helpers :timer
|
10
|
+
|
11
|
+
config_param :interval, :time, default: 5
|
10
12
|
attr_reader :registry
|
11
13
|
|
12
14
|
def initialize
|
@@ -17,9 +19,9 @@ module Fluent
|
|
17
19
|
def configure(conf)
|
18
20
|
super
|
19
21
|
hostname = Socket.gethostname
|
20
|
-
expander = Fluent::Prometheus.placeholder_expander(log)
|
22
|
+
expander = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
21
23
|
placeholders = expander.prepare_placeholders({'hostname' => hostname})
|
22
|
-
@base_labels = Fluent::Prometheus.parse_labels_elements(conf)
|
24
|
+
@base_labels = Fluent::Plugin::Prometheus.parse_labels_elements(conf)
|
23
25
|
@base_labels.each do |key, value|
|
24
26
|
@base_labels[key] = expander.expand(value, placeholders)
|
25
27
|
end
|
@@ -48,41 +50,9 @@ module Fluent
|
|
48
50
|
}
|
49
51
|
end
|
50
52
|
|
51
|
-
class TimerWatcher < Coolio::TimerWatcher
|
52
|
-
def initialize(interval, repeat, log, &callback)
|
53
|
-
@callback = callback
|
54
|
-
@log = log
|
55
|
-
super(interval, repeat)
|
56
|
-
end
|
57
|
-
|
58
|
-
def on_timer
|
59
|
-
@callback.call
|
60
|
-
rescue
|
61
|
-
@log.error $!.to_s
|
62
|
-
@log.error_backtrace
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
53
|
def start
|
67
54
|
super
|
68
|
-
@
|
69
|
-
@timer = TimerWatcher.new(@interval, true, log, &method(:update_monitor_info))
|
70
|
-
@loop.attach(@timer)
|
71
|
-
@thread = Thread.new(&method(:run))
|
72
|
-
end
|
73
|
-
|
74
|
-
def shutdown
|
75
|
-
super
|
76
|
-
@loop.watchers.each {|w| w.detach }
|
77
|
-
@loop.stop
|
78
|
-
@thread.join
|
79
|
-
end
|
80
|
-
|
81
|
-
def run
|
82
|
-
@loop.run
|
83
|
-
rescue
|
84
|
-
log.error "unexpected error", :error=>$!.to_s
|
85
|
-
log.error_backtrace
|
55
|
+
timer_execute(:in_prometheus_monitor, @interval, &method(:update_monitor_info))
|
86
56
|
end
|
87
57
|
|
88
58
|
def update_monitor_info
|
@@ -2,11 +2,13 @@ require 'fluent/input'
|
|
2
2
|
require 'fluent/plugin/in_monitor_agent'
|
3
3
|
require 'fluent/plugin/prometheus'
|
4
4
|
|
5
|
-
module Fluent
|
6
|
-
class PrometheusOutputMonitorInput < Input
|
7
|
-
Plugin.register_input('prometheus_output_monitor', self)
|
5
|
+
module Fluent::Plugin
|
6
|
+
class PrometheusOutputMonitorInput < Fluent::Input
|
7
|
+
Fluent::Plugin.register_input('prometheus_output_monitor', self)
|
8
8
|
|
9
|
-
|
9
|
+
helpers :timer
|
10
|
+
|
11
|
+
config_param :interval, :time, default: 5
|
10
12
|
attr_reader :registry
|
11
13
|
|
12
14
|
MONITOR_IVARS = [
|
@@ -32,9 +34,9 @@ module Fluent
|
|
32
34
|
def configure(conf)
|
33
35
|
super
|
34
36
|
hostname = Socket.gethostname
|
35
|
-
expander = Fluent::Prometheus.placeholder_expander(log)
|
37
|
+
expander = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
36
38
|
placeholders = expander.prepare_placeholders({'hostname' => hostname})
|
37
|
-
@base_labels = Fluent::Prometheus.parse_labels_elements(conf)
|
39
|
+
@base_labels = Fluent::Plugin::Prometheus.parse_labels_elements(conf)
|
38
40
|
@base_labels.each do |key, value|
|
39
41
|
@base_labels[key] = expander.expand(value, placeholders)
|
40
42
|
end
|
@@ -77,41 +79,9 @@ module Fluent
|
|
77
79
|
}
|
78
80
|
end
|
79
81
|
|
80
|
-
class TimerWatcher < Coolio::TimerWatcher
|
81
|
-
def initialize(interval, repeat, log, &callback)
|
82
|
-
@callback = callback
|
83
|
-
@log = log
|
84
|
-
super(interval, repeat)
|
85
|
-
end
|
86
|
-
|
87
|
-
def on_timer
|
88
|
-
@callback.call
|
89
|
-
rescue
|
90
|
-
@log.error $!.to_s
|
91
|
-
@log.error_backtrace
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
82
|
def start
|
96
83
|
super
|
97
|
-
@
|
98
|
-
@timer = TimerWatcher.new(@interval, true, log, &method(:update_monitor_info))
|
99
|
-
@loop.attach(@timer)
|
100
|
-
@thread = Thread.new(&method(:run))
|
101
|
-
end
|
102
|
-
|
103
|
-
def shutdown
|
104
|
-
super
|
105
|
-
@loop.watchers.each {|w| w.detach }
|
106
|
-
@loop.stop
|
107
|
-
@thread.join
|
108
|
-
end
|
109
|
-
|
110
|
-
def run
|
111
|
-
@loop.run
|
112
|
-
rescue
|
113
|
-
log.error "unexpected error", :error=>$!.to_s
|
114
|
-
log.error_backtrace
|
84
|
+
timer_execute(:in_prometheus_output_monitor, @interval, &method(:update_monitor_info))
|
115
85
|
end
|
116
86
|
|
117
87
|
def update_monitor_info
|
@@ -1,12 +1,14 @@
|
|
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
|
-
module Fluent
|
6
|
-
class PrometheusTailMonitorInput < Input
|
7
|
-
Plugin.register_input('prometheus_tail_monitor', self)
|
5
|
+
module Fluent::Plugin
|
6
|
+
class PrometheusTailMonitorInput < Fluent::Plugin::Input
|
7
|
+
Fluent::Plugin.register_input('prometheus_tail_monitor', self)
|
8
8
|
|
9
|
-
|
9
|
+
helpers :timer
|
10
|
+
|
11
|
+
config_param :interval, :time, default: 5
|
10
12
|
attr_reader :registry
|
11
13
|
|
12
14
|
MONITOR_IVARS = [
|
@@ -21,9 +23,9 @@ module Fluent
|
|
21
23
|
def configure(conf)
|
22
24
|
super
|
23
25
|
hostname = Socket.gethostname
|
24
|
-
expander = Fluent::Prometheus.placeholder_expander(log)
|
26
|
+
expander = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
25
27
|
placeholders = expander.prepare_placeholders({'hostname' => hostname})
|
26
|
-
@base_labels = Fluent::Prometheus.parse_labels_elements(conf)
|
28
|
+
@base_labels = Fluent::Plugin::Prometheus.parse_labels_elements(conf)
|
27
29
|
@base_labels.each do |key, value|
|
28
30
|
@base_labels[key] = expander.expand(value, placeholders)
|
29
31
|
end
|
@@ -45,41 +47,9 @@ module Fluent
|
|
45
47
|
}
|
46
48
|
end
|
47
49
|
|
48
|
-
class TimerWatcher < Coolio::TimerWatcher
|
49
|
-
def initialize(interval, repeat, log, &callback)
|
50
|
-
@callback = callback
|
51
|
-
@log = log
|
52
|
-
super(interval, repeat)
|
53
|
-
end
|
54
|
-
|
55
|
-
def on_timer
|
56
|
-
@callback.call
|
57
|
-
rescue
|
58
|
-
@log.error $!.to_s
|
59
|
-
@log.error_backtrace
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
50
|
def start
|
64
51
|
super
|
65
|
-
@
|
66
|
-
@timer = TimerWatcher.new(@interval, true, log, &method(:update_monitor_info))
|
67
|
-
@loop.attach(@timer)
|
68
|
-
@thread = Thread.new(&method(:run))
|
69
|
-
end
|
70
|
-
|
71
|
-
def shutdown
|
72
|
-
super
|
73
|
-
@loop.watchers.each {|w| w.detach }
|
74
|
-
@loop.stop
|
75
|
-
@thread.join
|
76
|
-
end
|
77
|
-
|
78
|
-
def run
|
79
|
-
@loop.run
|
80
|
-
rescue
|
81
|
-
log.error "unexpected error", :error=>$!.to_s
|
82
|
-
log.error_backtrace
|
52
|
+
timer_execute(:in_prometheus_tail_monitor, @interval, &method(:update_monitor_info))
|
83
53
|
end
|
84
54
|
|
85
55
|
def update_monitor_info
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require 'fluent/output'
|
1
|
+
require 'fluent/plugin/output'
|
2
2
|
require 'fluent/plugin/prometheus'
|
3
3
|
|
4
|
-
module Fluent
|
5
|
-
class PrometheusOutput < Output
|
6
|
-
Plugin.register_output('prometheus', self)
|
7
|
-
include Fluent::Prometheus
|
4
|
+
module Fluent::Plugin
|
5
|
+
class PrometheusOutput < Fluent::Plugin::Output
|
6
|
+
Fluent::Plugin.register_output('prometheus', self)
|
7
|
+
include Fluent::Plugin::Prometheus
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
super
|
@@ -13,13 +13,12 @@ module Fluent
|
|
13
13
|
|
14
14
|
def configure(conf)
|
15
15
|
super
|
16
|
-
labels = Fluent::Prometheus.parse_labels_elements(conf)
|
17
|
-
@metrics = Fluent::Prometheus.parse_metrics_elements(conf, @registry, labels)
|
16
|
+
labels = Fluent::Plugin::Prometheus.parse_labels_elements(conf)
|
17
|
+
@metrics = Fluent::Plugin::Prometheus.parse_metrics_elements(conf, @registry, labels)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def process(tag, es)
|
21
21
|
instrument(tag, es, @metrics)
|
22
|
-
chain.next
|
23
22
|
end
|
24
23
|
end
|
25
24
|
end
|
@@ -1,219 +1,213 @@
|
|
1
1
|
require 'prometheus/client'
|
2
2
|
require 'prometheus/client/formats/text'
|
3
|
+
require 'fluent/plugin/filter_record_transformer'
|
3
4
|
|
4
5
|
module Fluent
|
5
|
-
module
|
6
|
-
|
6
|
+
module Plugin
|
7
|
+
module Prometheus
|
8
|
+
class AlreadyRegisteredError < StandardError; end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
base_labels = {}
|
15
|
-
unless labels.empty?
|
16
|
-
labels.first.each do |key, value|
|
17
|
-
labels.first.has_key?(key)
|
18
|
-
base_labels[key.to_sym] = value
|
10
|
+
def self.parse_labels_elements(conf)
|
11
|
+
labels = conf.elements.select { |e| e.name == 'labels' }
|
12
|
+
if labels.size > 1
|
13
|
+
raise ConfigError, "labels section must have at most 1"
|
19
14
|
end
|
20
|
-
end
|
21
|
-
|
22
|
-
base_labels
|
23
|
-
end
|
24
15
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
when 'summary'
|
32
|
-
metrics << Fluent::Prometheus::Summary.new(element, registry, labels)
|
33
|
-
when 'gauge'
|
34
|
-
metrics << Fluent::Prometheus::Gauge.new(element, registry, labels)
|
35
|
-
when 'counter'
|
36
|
-
metrics << Fluent::Prometheus::Counter.new(element, registry, labels)
|
37
|
-
when 'histogram'
|
38
|
-
metrics << Fluent::Prometheus::Histogram.new(element, registry, labels)
|
39
|
-
else
|
40
|
-
raise ConfigError, "type option must be 'counter', 'gauge', 'summary' or 'histogram'"
|
16
|
+
base_labels = {}
|
17
|
+
unless labels.empty?
|
18
|
+
labels.first.each do |key, value|
|
19
|
+
labels.first.has_key?(key)
|
20
|
+
base_labels[key.to_sym] = value
|
21
|
+
end
|
41
22
|
end
|
42
|
-
}
|
43
|
-
metrics
|
44
|
-
end
|
45
23
|
|
46
|
-
|
47
|
-
# Use internal class in order to expand placeholder
|
48
|
-
require 'fluent/plugin/filter_record_transformer'
|
49
|
-
if defined?(Fluent::Plugin::RecordTransformerFilter::PlaceholderExpander)
|
50
|
-
# for v0.14
|
51
|
-
return Fluent::Plugin::RecordTransformerFilter::PlaceholderExpander.new(log: log)
|
52
|
-
else
|
53
|
-
# for v0.12
|
54
|
-
return Fluent::RecordTransformerFilter::PlaceholderExpander.new(log: log)
|
24
|
+
base_labels
|
55
25
|
end
|
56
|
-
rescue LoadError => e
|
57
|
-
raise ConfigError, "cannot find filter_record_transformer plugin: #{e.message}"
|
58
|
-
end
|
59
26
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
27
|
+
def self.parse_metrics_elements(conf, registry, labels = {})
|
28
|
+
metrics = []
|
29
|
+
conf.elements.select { |element|
|
30
|
+
element.name == 'metric'
|
31
|
+
}.each { |element|
|
32
|
+
case element['type']
|
33
|
+
when 'summary'
|
34
|
+
metrics << Fluent::Plugin::Prometheus::Summary.new(element, registry, labels)
|
35
|
+
when 'gauge'
|
36
|
+
metrics << Fluent::Plugin::Prometheus::Gauge.new(element, registry, labels)
|
37
|
+
when 'counter'
|
38
|
+
metrics << Fluent::Plugin::Prometheus::Counter.new(element, registry, labels)
|
39
|
+
when 'histogram'
|
40
|
+
metrics << Fluent::Plugin::Prometheus::Histogram.new(element, registry, labels)
|
41
|
+
else
|
42
|
+
raise ConfigError, "type option must be 'counter', 'gauge', 'summary' or 'histogram'"
|
43
|
+
end
|
44
|
+
}
|
45
|
+
metrics
|
46
|
+
end
|
65
47
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
}
|
48
|
+
def self.placeholder_expander(log)
|
49
|
+
# Use internal class in order to expand placeholder
|
50
|
+
Fluent::Plugin::RecordTransformerFilter::PlaceholderExpander.new(log: log)
|
51
|
+
end
|
71
52
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
53
|
+
def configure(conf)
|
54
|
+
super
|
55
|
+
@placeholder_expander = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
56
|
+
@hostname = Socket.gethostname
|
57
|
+
end
|
58
|
+
|
59
|
+
def instrument(tag, es, metrics)
|
60
|
+
placeholder_values = {
|
61
|
+
'tag' => tag,
|
62
|
+
'hostname' => @hostname,
|
63
|
+
}
|
64
|
+
|
65
|
+
es.each do |time, record|
|
66
|
+
placeholders = record.merge(placeholder_values)
|
67
|
+
placeholders = @placeholder_expander.prepare_placeholders(placeholders)
|
68
|
+
metrics.each do |metric|
|
69
|
+
begin
|
70
|
+
metric.instrument(record, @placeholder_expander, placeholders)
|
71
|
+
rescue => e
|
72
|
+
log.warn "prometheus: failed to instrument a metric.", error_class: e.class, error: e, tag: tag, name: metric.name
|
73
|
+
router.emit_error_event(tag, time, record, e)
|
74
|
+
end
|
81
75
|
end
|
82
76
|
end
|
83
77
|
end
|
84
|
-
end
|
85
78
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
79
|
+
class Metric
|
80
|
+
attr_reader :type
|
81
|
+
attr_reader :name
|
82
|
+
attr_reader :key
|
83
|
+
attr_reader :desc
|
91
84
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
85
|
+
def initialize(element, registry, labels)
|
86
|
+
['name', 'desc'].each do |key|
|
87
|
+
if element[key].nil?
|
88
|
+
raise ConfigError, "metric requires '#{key}' option"
|
89
|
+
end
|
96
90
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
@desc = element['desc']
|
91
|
+
@type = element['type']
|
92
|
+
@name = element['name']
|
93
|
+
@key = element['key']
|
94
|
+
@desc = element['desc']
|
102
95
|
|
103
|
-
|
104
|
-
|
105
|
-
|
96
|
+
@base_labels = Fluent::Plugin::Prometheus.parse_labels_elements(element)
|
97
|
+
@base_labels = labels.merge(@base_labels)
|
98
|
+
end
|
106
99
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
100
|
+
def labels(record, expander, placeholders)
|
101
|
+
label = {}
|
102
|
+
@base_labels.each do |k, v|
|
103
|
+
label[k] = expander.expand(v, placeholders)
|
104
|
+
end
|
105
|
+
label
|
111
106
|
end
|
112
|
-
label
|
113
|
-
end
|
114
107
|
|
115
|
-
|
116
|
-
|
108
|
+
def self.get(registry, name, type, docstring)
|
109
|
+
metric = registry.get(name)
|
117
110
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
111
|
+
# should have same type, docstring
|
112
|
+
if metric.type != type
|
113
|
+
raise AlreadyRegisteredError, "#{name} has already been registered as #{type} type"
|
114
|
+
end
|
115
|
+
if metric.docstring != docstring
|
116
|
+
raise AlreadyRegisteredError, "#{name} has already been registered with different docstring"
|
117
|
+
end
|
125
118
|
|
126
|
-
|
119
|
+
metric
|
120
|
+
end
|
127
121
|
end
|
128
|
-
end
|
129
122
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
123
|
+
class Gauge < Metric
|
124
|
+
def initialize(element, registry, labels)
|
125
|
+
super
|
126
|
+
if @key.nil?
|
127
|
+
raise ConfigError, "gauge metric requires 'key' option"
|
128
|
+
end
|
136
129
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
130
|
+
begin
|
131
|
+
@gauge = registry.gauge(element['name'].to_sym, element['desc'])
|
132
|
+
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
133
|
+
@gauge = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :gauge, element['desc'])
|
134
|
+
end
|
141
135
|
end
|
142
|
-
end
|
143
136
|
|
144
|
-
|
145
|
-
|
146
|
-
|
137
|
+
def instrument(record, expander, placeholders)
|
138
|
+
if record[@key]
|
139
|
+
@gauge.set(labels(record, expander, placeholders), record[@key])
|
140
|
+
end
|
147
141
|
end
|
148
142
|
end
|
149
|
-
end
|
150
143
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
144
|
+
class Counter < Metric
|
145
|
+
def initialize(element, registry, labels)
|
146
|
+
super
|
147
|
+
begin
|
148
|
+
@counter = registry.counter(element['name'].to_sym, element['desc'])
|
149
|
+
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
150
|
+
@counter = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :counter, element['desc'])
|
151
|
+
end
|
158
152
|
end
|
159
|
-
end
|
160
153
|
|
161
|
-
|
162
|
-
|
163
|
-
|
154
|
+
def instrument(record, expander, placeholders)
|
155
|
+
# use record value of the key if key is specified, otherwise just increment
|
156
|
+
value = @key ? record[@key] : 1
|
164
157
|
|
165
|
-
|
166
|
-
|
158
|
+
# ignore if record value is nil
|
159
|
+
return if value.nil?
|
167
160
|
|
168
|
-
|
161
|
+
@counter.increment(labels(record, expander, placeholders), value)
|
162
|
+
end
|
169
163
|
end
|
170
|
-
end
|
171
164
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
165
|
+
class Summary < Metric
|
166
|
+
def initialize(element, registry, labels)
|
167
|
+
super
|
168
|
+
if @key.nil?
|
169
|
+
raise ConfigError, "summary metric requires 'key' option"
|
170
|
+
end
|
178
171
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
172
|
+
begin
|
173
|
+
@summary = registry.summary(element['name'].to_sym, element['desc'])
|
174
|
+
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
175
|
+
@summary = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :summary, element['desc'])
|
176
|
+
end
|
183
177
|
end
|
184
|
-
end
|
185
178
|
|
186
|
-
|
187
|
-
|
188
|
-
|
179
|
+
def instrument(record, expander, placeholders)
|
180
|
+
if record[@key]
|
181
|
+
@summary.observe(labels(record, expander, placeholders), record[@key])
|
182
|
+
end
|
189
183
|
end
|
190
184
|
end
|
191
|
-
end
|
192
185
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
186
|
+
class Histogram < Metric
|
187
|
+
def initialize(element, registry, labels)
|
188
|
+
super
|
189
|
+
if @key.nil?
|
190
|
+
raise ConfigError, "histogram metric requires 'key' option"
|
191
|
+
end
|
199
192
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
193
|
+
begin
|
194
|
+
if element['buckets']
|
195
|
+
buckets = element['buckets'].split(/,/).map(&:strip).map do |e|
|
196
|
+
e[/\A\d+.\d+\Z/] ? e.to_f : e.to_i
|
197
|
+
end
|
198
|
+
@histogram = registry.histogram(element['name'].to_sym, element['desc'], {}, buckets)
|
199
|
+
else
|
200
|
+
@histogram = registry.histogram(element['name'].to_sym, element['desc'])
|
204
201
|
end
|
205
|
-
|
206
|
-
|
207
|
-
@histogram = registry.histogram(element['name'].to_sym, element['desc'])
|
202
|
+
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
203
|
+
@histogram = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :histogram, element['desc'])
|
208
204
|
end
|
209
|
-
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
210
|
-
@histogram = Fluent::Prometheus::Metric.get(registry, element['name'].to_sym, :histogram, element['desc'])
|
211
205
|
end
|
212
|
-
end
|
213
206
|
|
214
|
-
|
215
|
-
|
216
|
-
|
207
|
+
def instrument(record, expander, placeholders)
|
208
|
+
if record[@key]
|
209
|
+
@histogram.observe(labels(record, expander, placeholders), record[@key])
|
210
|
+
end
|
217
211
|
end
|
218
212
|
end
|
219
213
|
end
|
data/misc/fluentd_sample.conf
CHANGED
@@ -85,6 +85,13 @@
|
|
85
85
|
buffer_type memory
|
86
86
|
flush_interval 1s
|
87
87
|
max_retry_wait 2s
|
88
|
+
<buffer>
|
89
|
+
# max_retry_wait 10s
|
90
|
+
flush_interval 1s
|
91
|
+
# retry_type periodic
|
92
|
+
disable_retry_limit
|
93
|
+
</buffer>
|
94
|
+
# retry_limit 3
|
88
95
|
disable_retry_limit
|
89
96
|
<server>
|
90
97
|
host 127.0.0.1
|
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'fluent/test/driver/filter'
|
2
3
|
require 'fluent/plugin/filter_prometheus'
|
3
4
|
require_relative 'shared'
|
4
5
|
|
5
|
-
describe Fluent::PrometheusFilter do
|
6
|
+
describe Fluent::Plugin::PrometheusFilter do
|
6
7
|
let(:tag) { 'prometheus.test' }
|
7
|
-
let(:driver) { Fluent::Test::
|
8
|
+
let(:driver) { Fluent::Test::Driver::Filter.new(Fluent::Plugin::PrometheusFilter).configure(config) }
|
8
9
|
let(:registry) { ::Prometheus::Client.registry }
|
9
10
|
|
10
11
|
describe '#configure' do
|
@@ -13,7 +14,10 @@ describe Fluent::PrometheusFilter do
|
|
13
14
|
|
14
15
|
describe '#run' do
|
15
16
|
let(:message) { {"foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10} }
|
16
|
-
let(:es) {
|
17
|
+
let(:es) {
|
18
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
19
|
+
driver.filtered_records
|
20
|
+
}
|
17
21
|
|
18
22
|
context 'simple config' do
|
19
23
|
include_context 'simple_config'
|
@@ -25,7 +29,7 @@ describe Fluent::PrometheusFilter do
|
|
25
29
|
end
|
26
30
|
|
27
31
|
it 'should keep original message' do
|
28
|
-
expect(es.first
|
32
|
+
expect(es.first).to eq(message)
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'fluent/test/driver/output'
|
2
3
|
require 'fluent/plugin/out_prometheus'
|
3
4
|
require_relative 'shared'
|
4
5
|
|
5
|
-
describe Fluent::PrometheusOutput do
|
6
|
+
describe Fluent::Plugin::PrometheusOutput do
|
6
7
|
let(:tag) { 'prometheus.test' }
|
7
|
-
let(:driver) { Fluent::Test::
|
8
|
+
let(:driver) { Fluent::Test::Driver::Output.new(Fluent::Plugin::PrometheusOutput).configure(config) }
|
8
9
|
let(:registry) { ::Prometheus::Client.registry }
|
9
10
|
|
10
11
|
describe '#configure' do
|
@@ -13,7 +14,10 @@ describe Fluent::PrometheusOutput do
|
|
13
14
|
|
14
15
|
describe '#run' do
|
15
16
|
let(:message) { {"foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10} }
|
16
|
-
let(:es) {
|
17
|
+
let(:es) {
|
18
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
19
|
+
driver.events
|
20
|
+
}
|
17
21
|
|
18
22
|
context 'simple config' do
|
19
23
|
include_context 'simple_config'
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'fluent/plugin/in_prometheus'
|
3
|
+
require 'fluent/test/driver/input'
|
3
4
|
|
4
5
|
require 'net/http'
|
5
6
|
|
6
|
-
describe Fluent::PrometheusInput do
|
7
|
+
describe Fluent::Plugin::PrometheusInput do
|
7
8
|
CONFIG = %[
|
8
9
|
type prometheus
|
9
10
|
]
|
@@ -15,7 +16,7 @@ describe Fluent::PrometheusInput do
|
|
15
16
|
|
16
17
|
let(:config) { CONFIG }
|
17
18
|
let(:port) { 24231 }
|
18
|
-
let(:driver) { Fluent::Test::
|
19
|
+
let(:driver) { Fluent::Test::Driver::Input.new(Fluent::Plugin::PrometheusInput).configure(config) }
|
19
20
|
|
20
21
|
describe '#configure' do
|
21
22
|
describe 'bind' do
|
@@ -50,7 +51,7 @@ describe Fluent::PrometheusInput do
|
|
50
51
|
context '/metrics' do
|
51
52
|
let(:config) { LOCAL_CONFIG }
|
52
53
|
it 'returns 200' do
|
53
|
-
driver.run do
|
54
|
+
driver.run(timeout: 1) do
|
54
55
|
Net::HTTP.start("127.0.0.1", port) do |http|
|
55
56
|
req = Net::HTTP::Get.new("/metrics")
|
56
57
|
res = http.request(req)
|
@@ -63,7 +64,7 @@ describe Fluent::PrometheusInput do
|
|
63
64
|
context '/foo' do
|
64
65
|
let(:config) { LOCAL_CONFIG }
|
65
66
|
it 'does not return 200' do
|
66
|
-
driver.run do
|
67
|
+
driver.run(timeout: 1) do
|
67
68
|
Net::HTTP.start("127.0.0.1", port) do |http|
|
68
69
|
req = Net::HTTP::Get.new("/foo")
|
69
70
|
res = http.request(req)
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
2
|
require 'fluent/test'
|
3
|
+
require 'fluent/test/helpers'
|
3
4
|
require 'fluent/plugin/prometheus'
|
4
5
|
|
5
6
|
# Disable Test::Unit
|
6
7
|
Test::Unit::AutoRunner.need_auto_run = false
|
7
8
|
|
8
9
|
Fluent::Test.setup
|
10
|
+
include Fluent::Test::Helpers
|
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: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro Sano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.14.8
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: '2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.14.8
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
32
|
+
version: '2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: prometheus-client
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
151
|
version: '0'
|
152
152
|
requirements: []
|
153
153
|
rubyforge_project:
|
154
|
-
rubygems_version: 2.
|
154
|
+
rubygems_version: 2.6.13
|
155
155
|
signing_key:
|
156
156
|
specification_version: 4
|
157
157
|
summary: A fluent plugin that collects metrics and exposes for Prometheus.
|