fluent-plugin-prometheus 0.2.1 → 0.3.0

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
  SHA1:
3
- metadata.gz: bc459ea9922aeb0b292c93035e176c4a3c2dfa03
4
- data.tar.gz: c2598bbe1b5e3cd7de282d7db394c0f5b0a89723
3
+ metadata.gz: 85a4bc3e525bcf86677e899b7e6fc565cff5cfff
4
+ data.tar.gz: 76db50326565b85f18ef1ddf5bbf08dd7d4f3de8
5
5
  SHA512:
6
- metadata.gz: 7da56621296f4f7f279334f998e5f238fadf881ce08d4aef8dfaab2d96a81e490db42689a276b544e3830b87ba83a8507168d33c3006df17164ed3551a14c2b0
7
- data.tar.gz: ea09dd18c3d52d3b852c917c661318d5143ba4a9946c34eaa03adfc160d6fc1179676fdb635d44ca15fa99dacb3b3676f1ab6e688883835c17de3c8ad7b79ea7
6
+ metadata.gz: ca87c98ff6ffb9b0c2b7ad82b8f5d5a875fcc70f5b6e539e59fa15f1d3624d08d0cfc13ae47ccaa1eeed6c5d2087655ec9d21b8c8ff342f69fe96c42789fb095
7
+ data.tar.gz: 80d39b58eb5289f0d8f2b5d5b4f8e7eec58ce3b7bcae4dcfa00abdf6699e6dc73c61498806803f7d2eac80ce9f95dfa42a8ffc1d220ef243396701ac64d3ae80
@@ -1,13 +1,18 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.2
5
- - 2.3.1
4
+ - "2.3.3"
5
+ - "2.4.0"
6
6
 
7
7
  gemfile:
8
8
  - Gemfile
9
- - Gemfile.fluentd.0.10
10
9
  - Gemfile.fluentd.0.12
10
+ - Gemfile.fluentd.0.10
11
+
12
+ matrix:
13
+ allow_failures:
14
+ - gemfile: Gemfile.fluentd.0.10
15
+ rvm: 2.4.0
11
16
 
12
17
  script:
13
18
  - bundle exec rake spec
data/README.md CHANGED
@@ -73,6 +73,70 @@ More configuration parameters:
73
73
  - `<labels>`: additional labels for this metric (optional). See [Labels](#Labels)
74
74
  - `interval`: interval to update monitor_agent information in seconds (default: 5)
75
75
 
76
+ ### prometheus_output_monitor input plugin
77
+
78
+ This plugin collects internal metrics for output plugin in Fluentd. This is similar to `prometheus_monitor` plugin, but specialized for input plugin. There are Many metrics `prometheus_monitor` does not include, such as `num_errors`, `retry_wait` and so on.
79
+
80
+ Current exposed metrics:
81
+
82
+ - `fluentd_output_status_buffer_queue_length`
83
+ - `fluentd_output_status_buffer_total_bytes`
84
+ - `fluentd_output_status_retry_count`
85
+ - `fluentd_output_status_num_errors`
86
+ - `fluentd_output_status_emit_count`
87
+ - `fluentd_output_status_retry_wait`
88
+ - current retry_wait computed from last retry time and next retry time
89
+ - `fluentd_output_status_emit_records`
90
+ - only for v0.14
91
+ - `fluentd_output_status_write_count`
92
+ - only for v0.14
93
+ - `fluentd_output_status_rollback_count`
94
+ - only for v0.14
95
+
96
+
97
+ With following configuration, those metrics are collected.
98
+
99
+ <source>
100
+ type prometheus_output_monitor
101
+ </source>
102
+
103
+ More configuration parameters:
104
+
105
+ - `<labels>`: additional labels for this metric (optional). See [Labels](#Labels)
106
+ - `interval`: interval to update monitor_agent information in seconds (default: 5)
107
+
108
+ ### prometheus_tail_monitor input plugin
109
+
110
+ **experimental**
111
+
112
+ This plugin collects internal metrics for in_tail plugin in Fluentd. in_tail plugin holds internal state for files that the plugin is watching. The state is sometimes important to monitor plugins work correctly.
113
+
114
+ This plugin uses internal class of Fluentd, so it's easy to break.
115
+
116
+ Current exposed metrics:
117
+
118
+ - `fluentd_tail_file_position`
119
+ - Current bytes which plugin reads from the file
120
+ - `fluentd_tail_file_inode`
121
+ - inode of the file
122
+
123
+ Default labels:
124
+
125
+ - `plugin_id`: a value set for a plugin in configuration.
126
+ - `type`: plugin name. `in_tail` only for now.
127
+ - `path`: file path
128
+
129
+ With following configuration, those metrics are collected.
130
+
131
+ <source>
132
+ type prometheus_output_monitor
133
+ </source>
134
+
135
+ More configuration parameters:
136
+
137
+ - `<labels>`: additional labels for this metric (optional). See [Labels](#Labels)
138
+ - `interval`: interval to update monitor_agent information in seconds (default: 5)
139
+
76
140
  ### prometheus output/filter plugin
77
141
 
78
142
  Both output/filter plugins instrument metrics from records. Both plugins have no impact against values of each records, just read.
@@ -315,8 +379,8 @@ $ bundle install --path vendor/bundle
315
379
  Download pre-compiled prometheus binary and start it. It listens on 9090.
316
380
 
317
381
  ```
318
- $ wget https://github.com/prometheus/prometheus/releases/download/v1.0.1/prometheus-1.0.1.linux-amd64.tar.gz -O - | tar zxf -
319
- $ ./prometheus-1.0.1.linux-amd64/prometheus -config.file=./misc/prometheus.yaml -storage.local.path=./prometheus/metrics
382
+ $ wget https://github.com/prometheus/prometheus/releases/download/v1.5.2/prometheus-1.5.2.linux-amd64.tar.gz -O - | tar zxf -
383
+ $ ./prometheus-1.5.2.linux-amd64/prometheus -config.file=./misc/prometheus.yaml -storage.local.path=./prometheus/metrics
320
384
  ```
321
385
 
322
386
  Install Nginx for sample metrics. It listens on 80 and 9999.
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "fluent-plugin-prometheus"
3
- spec.version = "0.2.1"
3
+ spec.version = "0.3.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.}
@@ -22,6 +22,7 @@ module Fluent
22
22
  end
23
23
 
24
24
  def start
25
+ super
25
26
  @server = WEBrick::HTTPServer.new(
26
27
  BindAddress: @bind,
27
28
  Port: @port,
@@ -33,6 +34,7 @@ module Fluent
33
34
  end
34
35
 
35
36
  def shutdown
37
+ super
36
38
  if @server
37
39
  @server.shutdown
38
40
  @server = nil
@@ -1,7 +1,6 @@
1
1
  require 'fluent/input'
2
2
  require 'fluent/plugin/in_monitor_agent'
3
3
  require 'fluent/plugin/prometheus'
4
- require 'webrick'
5
4
 
6
5
  module Fluent
7
6
  class PrometheusMonitorInput < Input
@@ -65,6 +64,7 @@ module Fluent
65
64
  end
66
65
 
67
66
  def start
67
+ super
68
68
  @loop = Coolio::Loop.new
69
69
  @timer = TimerWatcher.new(@interval, true, log, &method(:update_monitor_info))
70
70
  @loop.attach(@timer)
@@ -72,6 +72,7 @@ module Fluent
72
72
  end
73
73
 
74
74
  def shutdown
75
+ super
75
76
  @loop.watchers.each {|w| w.detach }
76
77
  @loop.stop
77
78
  @thread.join
@@ -0,0 +1,178 @@
1
+ require 'fluent/input'
2
+ require 'fluent/plugin/in_monitor_agent'
3
+ require 'fluent/plugin/prometheus'
4
+
5
+ module Fluent
6
+ class PrometheusOutputMonitorInput < Input
7
+ Plugin.register_input('prometheus_output_monitor', self)
8
+
9
+ config_param :interval, :time, :default => 5
10
+ attr_reader :registry
11
+
12
+ MONITOR_IVARS = [
13
+ :num_errors,
14
+ :emit_count,
15
+
16
+ # for v0.12
17
+ :last_retry_time,
18
+
19
+ # from v0.14
20
+ :emit_records,
21
+ :write_count,
22
+ :rollback_count,
23
+ ]
24
+
25
+ def initialize
26
+ super
27
+ @registry = ::Prometheus::Client.registry
28
+ end
29
+
30
+ def configure(conf)
31
+ super
32
+ hostname = Socket.gethostname
33
+ expander = Fluent::Prometheus.placeholder_expander(log)
34
+ placeholders = expander.prepare_placeholders({'hostname' => hostname})
35
+ @base_labels = Fluent::Prometheus.parse_labels_elements(conf)
36
+ @base_labels.each do |key, value|
37
+ @base_labels[key] = expander.expand(value, placeholders)
38
+ end
39
+
40
+ if defined?(Fluent::Plugin) && defined?(Fluent::Plugin::MonitorAgentInput)
41
+ # from v0.14.6
42
+ @monitor_agent = Fluent::Plugin::MonitorAgentInput.new
43
+ else
44
+ @monitor_agent = Fluent::MonitorAgentInput.new
45
+ end
46
+
47
+ @metrics = {
48
+ buffer_queue_length: @registry.gauge(
49
+ :fluentd_output_status_buffer_queue_length,
50
+ 'Current buffer queue length.'),
51
+ buffer_total_queued_size: @registry.gauge(
52
+ :fluentd_output_status_buffer_total_bytes,
53
+ 'Current total size of queued buffers.'),
54
+ retry_counts: @registry.gauge(
55
+ :fluentd_output_status_retry_count,
56
+ 'Current retry counts.'),
57
+ num_errors: @registry.gauge(
58
+ :fluentd_output_status_num_errors,
59
+ 'Current number of errors.'),
60
+ emit_count: @registry.gauge(
61
+ :fluentd_output_status_emit_count,
62
+ 'Current emit counts.'),
63
+ emit_records: @registry.gauge(
64
+ :fluentd_output_status_emit_records,
65
+ 'Current emit records.'),
66
+ write_count: @registry.gauge(
67
+ :fluentd_output_status_write_count,
68
+ 'Current write counts.'),
69
+ rollback_count: @registry.gauge(
70
+ :fluentd_output_status_rollback_count,
71
+ 'Current rollback counts.'),
72
+ retry_wait: @registry.gauge(
73
+ :fluentd_output_status_retry_wait,
74
+ 'Current retry wait'),
75
+ }
76
+ end
77
+
78
+ class TimerWatcher < Coolio::TimerWatcher
79
+ def initialize(interval, repeat, log, &callback)
80
+ @callback = callback
81
+ @log = log
82
+ super(interval, repeat)
83
+ end
84
+
85
+ def on_timer
86
+ @callback.call
87
+ rescue
88
+ @log.error $!.to_s
89
+ @log.error_backtrace
90
+ end
91
+ end
92
+
93
+ def start
94
+ super
95
+ @loop = Coolio::Loop.new
96
+ @timer = TimerWatcher.new(@interval, true, log, &method(:update_monitor_info))
97
+ @loop.attach(@timer)
98
+ @thread = Thread.new(&method(:run))
99
+ end
100
+
101
+ def shutdown
102
+ super
103
+ @loop.watchers.each {|w| w.detach }
104
+ @loop.stop
105
+ @thread.join
106
+ end
107
+
108
+ def run
109
+ @loop.run
110
+ rescue
111
+ log.error "unexpected error", :error=>$!.to_s
112
+ log.error_backtrace
113
+ end
114
+
115
+ def update_monitor_info
116
+ opts = {
117
+ ivars: MONITOR_IVARS,
118
+ with_retry: true,
119
+ }
120
+
121
+ agent_info = @monitor_agent.plugins_info_all(opts).select {|info|
122
+ info['plugin_category'] == 'output'.freeze
123
+ }
124
+
125
+ monitor_info = {
126
+ 'buffer_queue_length' => @metrics[:buffer_queue_length],
127
+ 'buffer_total_queued_size' => @metrics[:buffer_total_queued_size],
128
+ 'retry_count' => @metrics[:retry_counts],
129
+ }
130
+ instance_vars_info = {
131
+ num_errors: @metrics[:num_errors],
132
+ write_count: @metrics[:write_count],
133
+ emit_count: @metrics[:emit_count],
134
+ emit_records: @metrics[:emit_records],
135
+ rollback_count: @metrics[:rollback_count],
136
+ }
137
+
138
+ agent_info.each do |info|
139
+ label = labels(info)
140
+
141
+ monitor_info.each do |name, metric|
142
+ if info[name]
143
+ metric.set(label, info[name])
144
+ end
145
+ end
146
+
147
+ if info['instance_variables']
148
+ instance_vars_info.each do |name, metric|
149
+ if info['instance_variables'][name]
150
+ metric.set(label, info['instance_variables'][name])
151
+ end
152
+ end
153
+ end
154
+
155
+ # compute current retry_wait
156
+ if info['retry']
157
+ next_time = info['retry']['next_time']
158
+ start_time = info['retry']['start']
159
+ if start_time.nil? && info['instance_variables']
160
+ # v0.12 does not include start, use last_retry_time instead
161
+ start_time = info['instance_variables'][:last_retry_time]
162
+ end
163
+ if next_time && start_time
164
+ wait = next_time - start_time
165
+ @metrics[:retry_wait].set(label, wait.to_f)
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ def labels(plugin_info)
172
+ @base_labels.merge(
173
+ plugin_id: plugin_info["plugin_id"],
174
+ type: plugin_info["type"],
175
+ )
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,117 @@
1
+ require 'fluent/input'
2
+ require 'fluent/plugin/in_monitor_agent'
3
+ require 'fluent/plugin/prometheus'
4
+
5
+ module Fluent
6
+ class PrometheusTailMonitorInput < Input
7
+ Plugin.register_input('prometheus_tail_monitor', self)
8
+
9
+ config_param :interval, :time, :default => 5
10
+ attr_reader :registry
11
+
12
+ MONITOR_IVARS = [
13
+ :tails,
14
+ ]
15
+
16
+ def initialize
17
+ super
18
+ @registry = ::Prometheus::Client.registry
19
+ end
20
+
21
+ def configure(conf)
22
+ super
23
+ hostname = Socket.gethostname
24
+ expander = Fluent::Prometheus.placeholder_expander(log)
25
+ placeholders = expander.prepare_placeholders({'hostname' => hostname})
26
+ @base_labels = Fluent::Prometheus.parse_labels_elements(conf)
27
+ @base_labels.each do |key, value|
28
+ @base_labels[key] = expander.expand(value, placeholders)
29
+ end
30
+
31
+ if defined?(Fluent::Plugin) && defined?(Fluent::Plugin::MonitorAgentInput)
32
+ # from v0.14.6
33
+ @monitor_agent = Fluent::Plugin::MonitorAgentInput.new
34
+ else
35
+ @monitor_agent = Fluent::MonitorAgentInput.new
36
+ end
37
+
38
+ @metrics = {
39
+ position: @registry.gauge(
40
+ :fluentd_tail_file_position,
41
+ 'Current position of file.'),
42
+ inode: @registry.gauge(
43
+ :fluentd_tail_file_inode,
44
+ 'Current inode of file.'),
45
+ }
46
+ end
47
+
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
+ def start
64
+ 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
83
+ end
84
+
85
+ def update_monitor_info
86
+ opts = {
87
+ ivars: MONITOR_IVARS,
88
+ }
89
+
90
+ agent_info = @monitor_agent.plugins_info_all(opts).select {|info|
91
+ info['type'] == 'tail'.freeze
92
+ }
93
+
94
+ agent_info.each do |info|
95
+ tails = info['instance_variables'][:tails]
96
+ next if tails.nil?
97
+
98
+ tails.each do |_, watcher|
99
+ # Access to internal variable of internal class...
100
+ # Very fragile implementation
101
+ pe = watcher.instance_variable_get(:@pe)
102
+ label = labels(info, watcher.path)
103
+ @metrics[:inode].set(label, pe.read_inode)
104
+ @metrics[:position].set(label, pe.read_pos)
105
+ end
106
+ end
107
+ end
108
+
109
+ def labels(plugin_info, path)
110
+ @base_labels.merge(
111
+ plugin_id: plugin_info["plugin_id"],
112
+ type: plugin_info["type"],
113
+ path: path,
114
+ )
115
+ end
116
+ end
117
+ end
@@ -13,6 +13,22 @@
13
13
  </labels>
14
14
  </source>
15
15
 
16
+ # input plugin that collects metrics for output plugin
17
+ <source>
18
+ @type prometheus_output_monitor
19
+ <labels>
20
+ host ${hostname}
21
+ </labels>
22
+ </source>
23
+
24
+ # input plugin that collects metrics for in_tail plugin
25
+ <source>
26
+ @type prometheus_tail_monitor
27
+ <labels>
28
+ host ${hostname}
29
+ </labels>
30
+ </source>
31
+
16
32
  ## Nginx Access Log Configuration
17
33
 
18
34
  <source>
@@ -1,8 +1,13 @@
1
1
  # A job to scrape an endpoint of Fluentd running on localhost.
2
2
  scrape_configs:
3
+ - job_name: 'prometheus'
4
+ scrape_interval: 5s
5
+ static_configs:
6
+ - targets:
7
+ - 'localhost:9090'
3
8
  - job_name: fluentd
4
9
  scrape_interval: 5s
5
10
  static_configs:
6
11
  - targets:
7
- - 'localhost:24231'
12
+ - 'localhost:24231'
8
13
  metrics_path: /metrics
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.2.1
4
+ version: 0.3.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: 2016-09-11 00:00:00.000000000 Z
11
+ date: 2017-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -114,6 +114,8 @@ files:
114
114
  - lib/fluent/plugin/filter_prometheus.rb
115
115
  - lib/fluent/plugin/in_prometheus.rb
116
116
  - lib/fluent/plugin/in_prometheus_monitor.rb
117
+ - lib/fluent/plugin/in_prometheus_output_monitor.rb
118
+ - lib/fluent/plugin/in_prometheus_tail_monitor.rb
117
119
  - lib/fluent/plugin/out_prometheus.rb
118
120
  - lib/fluent/plugin/prometheus.rb
119
121
  - misc/fluentd_sample.conf
@@ -144,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
146
  version: '0'
145
147
  requirements: []
146
148
  rubyforge_project:
147
- rubygems_version: 2.2.3
149
+ rubygems_version: 2.6.11
148
150
  signing_key:
149
151
  specification_version: 4
150
152
  summary: A fluent plugin that collects metrics and exposes for Prometheus.