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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: c8de232abd7ede7d5988f3280f6c8735de2c0371c831830ee56574ca5d38a056
4
- data.tar.gz: 5042393a2e68e75dbcc35bf4ae7a857498f9d2e6ebbbd164f62a270e3274be65
2
+ SHA1:
3
+ metadata.gz: b6e00809503106fad10f9d831e67091e69ed56da
4
+ data.tar.gz: 5f84aeff3ed1a79a6da4c7ea18a5332c02304baa
5
5
  SHA512:
6
- metadata.gz: 8acba008b1f5beafae1e7cac6214083ad033def64ea5af572724cbec3337b03c122cef09b1935a9617e375abc0f83b7b33269904f567f7e17ec90d7f79e8da40
7
- data.tar.gz: 7187a5995e479c445bb0457081606b869456ad46bacd539962fb74147f5b9d72d0b78cb45b1d43a64c247328f673c91aa12ce86c53e915e171d6f5fb70e23afa
6
+ metadata.gz: 7658cc206cc8063ea61d83730b37db12a311f152a560c3c5d669c9f73dd9994c417b1a30810531d101c56821f4395f5d875fe5ef5cabb67e72948974186cdad9
7
+ data.tar.gz: ac72182e9fea379125a487f521d42a29bbf354d857abf3dc778daffdec8aa8bd346d444b3ab001cbcac951fde2b72c3ad208e0e2748aa9d5a14d35b34e73e1c3
data/.travis.yml CHANGED
@@ -1,8 +1,8 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - "2.3.3"
5
- - "2.4.0"
4
+ - "2.3.4"
5
+ - "2.4.1"
6
6
 
7
7
  gemfile:
8
8
  - Gemfile
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
- source 'https://rubygems.org/'
2
- gem 'fluentd', '~> 0.12.0'
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-prometheus.gemspec
3
4
  gemspec
data/README.md CHANGED
@@ -1,11 +1,18 @@
1
1
  # fluent-plugin-prometheus, a plugin for [Fluentd](https://www.fluentd.org)
2
2
 
3
- This is the branch to support Fluentd v0.12. If you want to use Fluentd v0.14 or later, see [master branch](https://github.com/fluent/fluent-plugin-prometheus).
4
-
5
- [![Build Status](https://travis-ci.org/fluent/fluent-plugin-prometheus.svg?branch=v0.12)](https://travis-ci.org/fluent/fluent-plugin-prometheus)
3
+ [![Build Status](https://travis-ci.org/fluent/fluent-plugin-prometheus.svg?branch=master)](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](#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](#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 prometheus_output_monitor
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](#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](#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](#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](#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](#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.5.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.12.0", "< 0.14.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
- config_param :bind, :string, :default => '0.0.0.0'
10
- config_param :port, :integer, :default => 24231
11
- config_param :metrics_path, :string, :default => '/metrics'
9
+ helpers :thread
12
10
 
13
- desc 'Enable ssl configuration for the server'
14
- config_section :ssl, multi: false, required: false do
15
- config_param :enable, :bool, required: false, default: false
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
- config = {
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
- @thread = Thread.new { @server.start }
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
- if @thread
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
- config_param :interval, :time, :default => 5
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
- @loop = Coolio::Loop.new
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
- config_param :interval, :time, :default => 5
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
- @loop = Coolio::Loop.new
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
- config_param :interval, :time, :default => 5
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
- @loop = Coolio::Loop.new
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 emit(tag, es, chain)
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 Prometheus
6
- class AlreadyRegisteredError < StandardError; end
6
+ module Plugin
7
+ module Prometheus
8
+ class AlreadyRegisteredError < StandardError; end
7
9
 
8
- def self.parse_labels_elements(conf)
9
- labels = conf.elements.select { |e| e.name == 'labels' }
10
- if labels.size > 1
11
- raise ConfigError, "labels section must have at most 1"
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
- def self.parse_metrics_elements(conf, registry, labels = {})
26
- metrics = []
27
- conf.elements.select { |element|
28
- element.name == 'metric'
29
- }.each { |element|
30
- case element['type']
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
- def self.placeholder_expander(log)
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
- def configure(conf)
61
- super
62
- @placeholder_expander = Fluent::Prometheus.placeholder_expander(log)
63
- @hostname = Socket.gethostname
64
- end
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
- def instrument(tag, es, metrics)
67
- placeholder_values = {
68
- 'tag' => tag,
69
- 'hostname' => @hostname,
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
- es.each do |time, record|
73
- placeholders = record.merge(placeholder_values)
74
- placeholders = @placeholder_expander.prepare_placeholders(placeholders)
75
- metrics.each do |metric|
76
- begin
77
- metric.instrument(record, @placeholder_expander, placeholders)
78
- rescue => e
79
- log.warn "prometheus: failed to instrument a metric.", error_class: e.class, error: e, tag: tag, name: metric.name
80
- router.emit_error_event(tag, time, record, e)
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
- class Metric
87
- attr_reader :type
88
- attr_reader :name
89
- attr_reader :key
90
- attr_reader :desc
79
+ class Metric
80
+ attr_reader :type
81
+ attr_reader :name
82
+ attr_reader :key
83
+ attr_reader :desc
91
84
 
92
- def initialize(element, registry, labels)
93
- ['name', 'desc'].each do |key|
94
- if element[key].nil?
95
- raise ConfigError, "metric requires '#{key}' option"
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
- end
98
- @type = element['type']
99
- @name = element['name']
100
- @key = element['key']
101
- @desc = element['desc']
91
+ @type = element['type']
92
+ @name = element['name']
93
+ @key = element['key']
94
+ @desc = element['desc']
102
95
 
103
- @base_labels = Fluent::Prometheus.parse_labels_elements(element)
104
- @base_labels = labels.merge(@base_labels)
105
- end
96
+ @base_labels = Fluent::Plugin::Prometheus.parse_labels_elements(element)
97
+ @base_labels = labels.merge(@base_labels)
98
+ end
106
99
 
107
- def labels(record, expander, placeholders)
108
- label = {}
109
- @base_labels.each do |k, v|
110
- label[k] = expander.expand(v, placeholders)
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
- def self.get(registry, name, type, docstring)
116
- metric = registry.get(name)
108
+ def self.get(registry, name, type, docstring)
109
+ metric = registry.get(name)
117
110
 
118
- # should have same type, docstring
119
- if metric.type != type
120
- raise AlreadyRegisteredError, "#{name} has already been registered as #{type} type"
121
- end
122
- if metric.docstring != docstring
123
- raise AlreadyRegisteredError, "#{name} has already been registered with different docstring"
124
- end
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
- metric
119
+ metric
120
+ end
127
121
  end
128
- end
129
122
 
130
- class Gauge < Metric
131
- def initialize(element, registry, labels)
132
- super
133
- if @key.nil?
134
- raise ConfigError, "gauge metric requires 'key' option"
135
- end
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
- begin
138
- @gauge = registry.gauge(element['name'].to_sym, element['desc'])
139
- rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
140
- @gauge = Fluent::Prometheus::Metric.get(registry, element['name'].to_sym, :gauge, element['desc'])
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
- def instrument(record, expander, placeholders)
145
- if record[@key]
146
- @gauge.set(labels(record, expander, placeholders), record[@key])
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
- class Counter < Metric
152
- def initialize(element, registry, labels)
153
- super
154
- begin
155
- @counter = registry.counter(element['name'].to_sym, element['desc'])
156
- rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
157
- @counter = Fluent::Prometheus::Metric.get(registry, element['name'].to_sym, :counter, element['desc'])
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
- def instrument(record, expander, placeholders)
162
- # use record value of the key if key is specified, otherwise just increment
163
- value = @key ? record[@key] : 1
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
- # ignore if record value is nil
166
- return if value.nil?
158
+ # ignore if record value is nil
159
+ return if value.nil?
167
160
 
168
- @counter.increment(labels(record, expander, placeholders), value)
161
+ @counter.increment(labels(record, expander, placeholders), value)
162
+ end
169
163
  end
170
- end
171
164
 
172
- class Summary < Metric
173
- def initialize(element, registry, labels)
174
- super
175
- if @key.nil?
176
- raise ConfigError, "summary metric requires 'key' option"
177
- end
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
- begin
180
- @summary = registry.summary(element['name'].to_sym, element['desc'])
181
- rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
182
- @summary = Fluent::Prometheus::Metric.get(registry, element['name'].to_sym, :summary, element['desc'])
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
- def instrument(record, expander, placeholders)
187
- if record[@key]
188
- @summary.observe(labels(record, expander, placeholders), record[@key])
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
- class Histogram < Metric
194
- def initialize(element, registry, labels)
195
- super
196
- if @key.nil?
197
- raise ConfigError, "histogram metric requires 'key' option"
198
- end
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
- begin
201
- if element['buckets']
202
- buckets = element['buckets'].split(/,/).map(&:strip).map do |e|
203
- e[/\A\d+.\d+\Z/] ? e.to_f : e.to_i
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
- @histogram = registry.histogram(element['name'].to_sym, element['desc'], {}, buckets)
206
- else
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
- def instrument(record, expander, placeholders)
215
- if record[@key]
216
- @histogram.observe(labels(record, expander, placeholders), record[@key])
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
@@ -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::FilterTestDriver.new(Fluent::PrometheusFilter, tag).configure(config, true) }
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) { driver.run { driver.emit(message, Time.now) }.filtered }
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[1]).to eq(message)
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::OutputTestDriver.new(Fluent::PrometheusOutput, tag).configure(config) }
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) { driver.run { driver.emit(message, Time.now) } }
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::InputTestDriver.new(Fluent::PrometheusInput).configure(config) }
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.5.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: 2018-09-09 00:00:00.000000000 Z
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.12.0
19
+ version: 0.14.8
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.14.0
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.12.0
29
+ version: 0.14.8
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.14.0
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.7.6
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.