fluent-plugin-prometheus 1.8.2 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6be199d6eb3693d4fe35be96961c05475a667ce8a7fe4b344fb6c5f7c269e820
4
- data.tar.gz: 3cb81f50d84773da036d7bafadfa41c05928a7fb062310eeea0eea6546382900
3
+ metadata.gz: 53ce03bc02b89a80dbb46f166e91ad0e4a71011c54dcf1b2999fe5ef24aab7b8
4
+ data.tar.gz: d8a764f2a0ba7ffeb6ae383002aef2705e0a8c7a76550d8647452bfa032edf37
5
5
  SHA512:
6
- metadata.gz: fc05d9f8283546700cc401c771d5444470e806fd4193cc47f661e01fd91bcd402ac2b0aa7fd52f2fa92ff5811f76d19aca378e3ae9919b93de27bca8e0300581
7
- data.tar.gz: e614db8e23a6dad5a0d416b224e49ca1895b641b4b0d41933954d709080344f90cb79bc51869533d0efc43e93422dd401e4b547fa85ea316fa1f13457236933f
6
+ metadata.gz: d4187d6c44ae90bcbcb357efe3b6502c4a62250aa61d77779ded61c80e6be76d04e33a87ade92e9b5e4684d3b7b8d8d89a3eef9d622e9824d4801fc93ee0d6ca
7
+ data.tar.gz: c9a8db411e69763e3759ac7b3b0b9b14bd4eaf64d0c33ac0b97ac33fdcfdae2bf014c1e76de13e4c400251000faf9494e0258eddd8802f052885637003392960
@@ -0,0 +1,26 @@
1
+ name: linux
2
+ on:
3
+ - push
4
+ - pull_request
5
+ jobs:
6
+ build:
7
+ runs-on: ${{ matrix.os }}
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby: [ '2.4', '2.5', '2.6', '2.7' ]
12
+ os:
13
+ - ubuntu-latest
14
+ name: Ruby ${{ matrix.ruby }} unit testing on ${{ matrix.os }}
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby }}
20
+ - name: unit testing
21
+ env:
22
+ CI: true
23
+ run: |
24
+ gem install bundler rake
25
+ bundle install --jobs 4 --retry 3
26
+ bundle exec rake spec
data/ChangeLog CHANGED
@@ -1,3 +1,23 @@
1
+ Release 2.0.1 - 2021/04/08
2
+
3
+ * out_prometheus: Allow for lookup by symbol as well as string
4
+
5
+ Release 2.0.0 - 2021/02/18
6
+
7
+ * Update prometheus-client dependency to 2.1.0 or later
8
+
9
+ Release 1.8.5 - 2020/11/24
10
+
11
+ * in_prometheus_monitor: Support USR2 reload
12
+
13
+ Release 1.8.4 - 2020/09/24
14
+
15
+ * in_prometheus_output_monitor: Add gauge_all parameter
16
+
17
+ Release 1.8.3 - 2020/08/24
18
+
19
+ * Fix resourcr leak in async-http based server
20
+
1
21
  Release 1.8.2 - 2020/07/17
2
22
 
3
23
  * in_prometheus_output_monitor/in_prometheus_tail_monitor: Support USR2 reload
data/README.md CHANGED
@@ -152,6 +152,7 @@ More configuration parameters:
152
152
 
153
153
  - `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
154
154
  - `interval`: interval to update monitor_agent information in seconds (default: 5)
155
+ - `gauge_all`: Specify metric type. If `true`, use `gauge` type. If `false`, use `counter` type. Since v2, this parameter will be removed and use `counter` type.
155
156
 
156
157
  ### prometheus_tail_monitor input plugin
157
158
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "fluent-plugin-prometheus"
3
- spec.version = "1.8.2"
3
+ spec.version = "2.0.1"
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.}
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.require_paths = ["lib"]
15
15
 
16
16
  spec.add_dependency "fluentd", ">= 1.9.1", "< 2"
17
- spec.add_dependency "prometheus-client", "< 0.10"
17
+ spec.add_dependency "prometheus-client", ">= 2.1.0"
18
18
  spec.add_development_dependency "bundler"
19
19
  spec.add_development_dependency "rake"
20
20
  spec.add_development_dependency "rspec"
@@ -13,8 +13,9 @@ module Fluent::Plugin
13
13
  Async::HTTP::Endpoint.parse("http://#{host}:#{port}")
14
14
  end
15
15
 
16
- client = Async::HTTP::Client.new(endpoint)
17
- yield(AsyncHttpWrapper.new(client))
16
+ Async::HTTP::Client.open(endpoint) do |client|
17
+ yield(AsyncHttpWrapper.new(client))
18
+ end
18
19
  end
19
20
 
20
21
  Response = Struct.new(:code, :body, :headers)
@@ -38,7 +39,7 @@ module Fluent::Plugin
38
39
  raise error
39
40
  end
40
41
 
41
- Response.new(response.status.to_s, response.body.read, response.headers)
42
+ Response.new(response.status.to_s, response.read || '', response.headers)
42
43
  end
43
44
  end
44
45
  end
@@ -46,19 +46,19 @@ module Fluent::Plugin
46
46
  def start
47
47
  super
48
48
 
49
- @buffer_newest_timekey = @registry.gauge(
49
+ @buffer_newest_timekey = get_gauge(
50
50
  :fluentd_status_buffer_newest_timekey,
51
51
  'Newest timekey in buffer.')
52
- @buffer_oldest_timekey = @registry.gauge(
52
+ @buffer_oldest_timekey = get_gauge(
53
53
  :fluentd_status_buffer_oldest_timekey,
54
54
  'Oldest timekey in buffer.')
55
- buffer_queue_length = @registry.gauge(
55
+ buffer_queue_length = get_gauge(
56
56
  :fluentd_status_buffer_queue_length,
57
57
  'Current buffer queue length.')
58
- buffer_total_queued_size = @registry.gauge(
58
+ buffer_total_queued_size = get_gauge(
59
59
  :fluentd_status_buffer_total_bytes,
60
60
  'Current total size of queued buffers.')
61
- retry_counts = @registry.gauge(
61
+ retry_counts = get_gauge(
62
62
  :fluentd_status_retry_count,
63
63
  'Current retry counts.')
64
64
 
@@ -76,14 +76,14 @@ module Fluent::Plugin
76
76
 
77
77
  @monitor_info.each do |name, metric|
78
78
  if info[name]
79
- metric.set(label, info[name])
79
+ metric.set(info[name], labels: label)
80
80
  end
81
81
  end
82
82
 
83
83
  timekeys = info["buffer_timekeys"]
84
84
  if timekeys && !timekeys.empty?
85
- @buffer_newest_timekey.set(label, timekeys.max)
86
- @buffer_oldest_timekey.set(label, timekeys.min)
85
+ @buffer_newest_timekey.set(timekeys.max, labels: label)
86
+ @buffer_oldest_timekey.set(timekeys.min, labels: label)
87
87
  end
88
88
  end
89
89
  end
@@ -95,5 +95,13 @@ module Fluent::Plugin
95
95
  type: plugin_info["type"],
96
96
  )
97
97
  end
98
+
99
+ def get_gauge(name, docstring)
100
+ if @registry.exist?(name)
101
+ @registry.get(name)
102
+ else
103
+ @registry.gauge(name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :plugin_category, :type])
104
+ end
105
+ end
98
106
  end
99
107
  end
@@ -10,6 +10,7 @@ module Fluent::Plugin
10
10
  helpers :timer
11
11
 
12
12
  config_param :interval, :time, default: 5
13
+ config_param :gauge_all, :bool, default: true
13
14
  attr_reader :registry
14
15
 
15
16
  MONITOR_IVARS = [
@@ -54,6 +55,8 @@ module Fluent::Plugin
54
55
  end
55
56
 
56
57
  @monitor_agent = Fluent::Plugin::MonitorAgentInput.new
58
+
59
+ @gauge_or_counter = @gauge_all ? :gauge : :counter
57
60
  end
58
61
 
59
62
  def start
@@ -87,28 +90,28 @@ module Fluent::Plugin
87
90
  'Oldest timekey in buffer.'),
88
91
 
89
92
  # Output metrics
90
- retry_counts: get_gauge(
93
+ retry_counts: get_gauge_or_counter(
91
94
  :fluentd_output_status_retry_count,
92
95
  'Current retry counts.'),
93
- num_errors: get_gauge(
96
+ num_errors: get_gauge_or_counter(
94
97
  :fluentd_output_status_num_errors,
95
98
  'Current number of errors.'),
96
- emit_count: get_gauge(
99
+ emit_count: get_gauge_or_counter(
97
100
  :fluentd_output_status_emit_count,
98
101
  'Current emit counts.'),
99
- emit_records: get_gauge(
102
+ emit_records: get_gauge_or_counter(
100
103
  :fluentd_output_status_emit_records,
101
104
  'Current emit records.'),
102
- write_count: get_gauge(
105
+ write_count: get_gauge_or_counter(
103
106
  :fluentd_output_status_write_count,
104
107
  'Current write counts.'),
105
108
  rollback_count: get_gauge(
106
109
  :fluentd_output_status_rollback_count,
107
110
  'Current rollback counts.'),
108
- flush_time_count: get_gauge(
111
+ flush_time_count: get_gauge_or_counter(
109
112
  :fluentd_output_status_flush_time_count,
110
113
  'Total flush time.'),
111
- slow_flush_count: get_gauge(
114
+ slow_flush_count: get_gauge_or_counter(
112
115
  :fluentd_output_status_slow_flush_count,
113
116
  'Current slow flush counts.'),
114
117
  retry_wait: get_gauge(
@@ -157,14 +160,22 @@ module Fluent::Plugin
157
160
 
158
161
  monitor_info.each do |name, metric|
159
162
  if info[name]
160
- metric.set(label, info[name])
163
+ if metric.is_a?(::Prometheus::Client::Gauge)
164
+ metric.set(info[name], labels: label)
165
+ elsif metric.is_a?(::Prometheus::Client::Counter)
166
+ metric.increment(by: info[name] - metric.get(labels: label), labels: label)
167
+ end
161
168
  end
162
169
  end
163
170
 
164
171
  if info['instance_variables']
165
172
  instance_vars_info.each do |name, metric|
166
173
  if info['instance_variables'][name]
167
- metric.set(label, info['instance_variables'][name])
174
+ if metric.is_a?(::Prometheus::Client::Gauge)
175
+ metric.set(info['instance_variables'][name], labels: label)
176
+ elsif metric.is_a?(::Prometheus::Client::Counter)
177
+ metric.increment(by: info['instance_variables'][name] - metric.get(labels: label), labels: label)
178
+ end
168
179
  end
169
180
  end
170
181
  end
@@ -182,7 +193,7 @@ module Fluent::Plugin
182
193
  if next_time && start_time
183
194
  wait = next_time - start_time
184
195
  end
185
- @metrics[:retry_wait].set(label, wait.to_f)
196
+ @metrics[:retry_wait].set(wait.to_f, labels: label)
186
197
  end
187
198
  end
188
199
  end
@@ -198,7 +209,15 @@ module Fluent::Plugin
198
209
  if @registry.exist?(name)
199
210
  @registry.get(name)
200
211
  else
201
- @registry.gauge(name, docstring)
212
+ @registry.gauge(name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :type])
213
+ end
214
+ end
215
+
216
+ def get_gauge_or_counter(name, docstring)
217
+ if @registry.exist?(name)
218
+ @registry.get(name)
219
+ else
220
+ @registry.public_send(@gauge_or_counter, name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :type])
202
221
  end
203
222
  end
204
223
  end
@@ -73,8 +73,8 @@ module Fluent::Plugin
73
73
  # Very fragile implementation
74
74
  pe = watcher.instance_variable_get(:@pe)
75
75
  label = labels(info, watcher.path)
76
- @metrics[:inode].set(label, pe.read_inode)
77
- @metrics[:position].set(label, pe.read_pos)
76
+ @metrics[:inode].set(pe.read_inode, labels: label)
77
+ @metrics[:position].set(pe.read_pos, labels: label)
78
78
  end
79
79
  end
80
80
  end
@@ -91,7 +91,7 @@ module Fluent::Plugin
91
91
  if @registry.exist?(name)
92
92
  @registry.get(name)
93
93
  else
94
- @registry.gauge(name, docstring)
94
+ @registry.gauge(name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :type, :path])
95
95
  end
96
96
  end
97
97
  end
@@ -85,6 +85,18 @@ module Fluent
85
85
  Fluent::Plugin::Prometheus::ExpandBuilder.new(log: log)
86
86
  end
87
87
 
88
+ def stringify_keys(hash_to_stringify)
89
+ # Adapted from: https://www.jvt.me/posts/2019/09/07/ruby-hash-keys-string-symbol/
90
+ hash_to_stringify.map do |k,v|
91
+ value_or_hash = if v.instance_of? Hash
92
+ stringify_keys(v)
93
+ else
94
+ v
95
+ end
96
+ [k.to_s, value_or_hash]
97
+ end.to_h
98
+ end
99
+
88
100
  def configure(conf)
89
101
  super
90
102
  @placeholder_values = {}
@@ -99,6 +111,7 @@ module Fluent
99
111
  'worker_id' => fluentd_worker_id,
100
112
  }
101
113
 
114
+ record = stringify_keys(record)
102
115
  placeholders = record.merge(@placeholder_values[tag])
103
116
  expander = @placeholder_expander_builder.build(placeholders)
104
117
  metrics.each do |metric|
@@ -119,6 +132,7 @@ module Fluent
119
132
  }
120
133
 
121
134
  es.each do |time, record|
135
+ record = stringify_keys(record)
122
136
  placeholders = record.merge(placeholder_values)
123
137
  expander = @placeholder_expander_builder.build(placeholders)
124
138
  metrics.each do |metric|
@@ -188,7 +202,7 @@ module Fluent
188
202
  end
189
203
 
190
204
  begin
191
- @gauge = registry.gauge(element['name'].to_sym, element['desc'])
205
+ @gauge = registry.gauge(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
192
206
  rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
193
207
  @gauge = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :gauge, element['desc'])
194
208
  end
@@ -201,7 +215,7 @@ module Fluent
201
215
  value = @key.call(record)
202
216
  end
203
217
  if value
204
- @gauge.set(labels(record, expander), value)
218
+ @gauge.set(value, labels: labels(record, expander))
205
219
  end
206
220
  end
207
221
  end
@@ -210,7 +224,7 @@ module Fluent
210
224
  def initialize(element, registry, labels)
211
225
  super
212
226
  begin
213
- @counter = registry.counter(element['name'].to_sym, element['desc'])
227
+ @counter = registry.counter(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
214
228
  rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
215
229
  @counter = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :counter, element['desc'])
216
230
  end
@@ -229,7 +243,7 @@ module Fluent
229
243
  # ignore if record value is nil
230
244
  return if value.nil?
231
245
 
232
- @counter.increment(labels(record, expander), value)
246
+ @counter.increment(by: value, labels: labels(record, expander))
233
247
  end
234
248
  end
235
249
 
@@ -241,7 +255,7 @@ module Fluent
241
255
  end
242
256
 
243
257
  begin
244
- @summary = registry.summary(element['name'].to_sym, element['desc'])
258
+ @summary = registry.summary(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
245
259
  rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
246
260
  @summary = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :summary, element['desc'])
247
261
  end
@@ -254,7 +268,7 @@ module Fluent
254
268
  value = @key.call(record)
255
269
  end
256
270
  if value
257
- @summary.observe(labels(record, expander), value)
271
+ @summary.observe(value, labels: labels(record, expander))
258
272
  end
259
273
  end
260
274
  end
@@ -271,9 +285,9 @@ module Fluent
271
285
  buckets = element['buckets'].split(/,/).map(&:strip).map do |e|
272
286
  e[/\A\d+.\d+\Z/] ? e.to_f : e.to_i
273
287
  end
274
- @histogram = registry.histogram(element['name'].to_sym, element['desc'], {}, buckets)
288
+ @histogram = registry.histogram(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys, buckets: buckets)
275
289
  else
276
- @histogram = registry.histogram(element['name'].to_sym, element['desc'])
290
+ @histogram = registry.histogram(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
277
291
  end
278
292
  rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
279
293
  @histogram = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :histogram, element['desc'])
@@ -287,7 +301,7 @@ module Fluent
287
301
  value = @key.call(record)
288
302
  end
289
303
  if value
290
- @histogram.observe(labels(record, expander), value)
304
+ @histogram.observe(value, labels: labels(record, expander))
291
305
  end
292
306
  end
293
307
  end
@@ -40,4 +40,29 @@ describe Fluent::Plugin::PrometheusOutput do
40
40
 
41
41
  it_behaves_like 'instruments record'
42
42
  end
43
+
44
+ describe '#run with symbolized keys' do
45
+ let(:message) { {:foo => 100, :bar => 100, :baz => 100, :qux => 10} }
46
+
47
+ context 'simple config' do
48
+ let(:config) {
49
+ BASE_CONFIG + %(
50
+ <metric>
51
+ name simple
52
+ type counter
53
+ desc Something foo.
54
+ key foo
55
+ </metric>
56
+ )
57
+ }
58
+
59
+ it 'adds a new counter metric' do
60
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
61
+ driver.run(default_tag: tag) { driver.feed(event_time, message) }
62
+ expect(registry.metrics.map(&:name)).to eq([:simple])
63
+ end
64
+ end
65
+
66
+ it_behaves_like 'instruments record'
67
+ end
43
68
  end
@@ -178,20 +178,19 @@ shared_examples_for 'instruments record' do
178
178
 
179
179
  it 'instruments counter metric' do
180
180
  expect(counter.type).to eq(:counter)
181
- expect(counter.get({test_key: 'test_value', key: 'foo1'})).to be_kind_of(Numeric)
182
- expect(counter_with_accessor.get({test_key: 'test_value', key: 'foo6'})).to be_kind_of(Numeric)
181
+ expect(counter.get(labels: {test_key: 'test_value', key: 'foo1'})).to be_kind_of(Numeric)
182
+ expect(counter_with_accessor.get(labels: {test_key: 'test_value', key: 'foo6'})).to be_kind_of(Numeric)
183
183
  end
184
184
 
185
185
  it 'instruments gauge metric' do
186
186
  expect(gauge.type).to eq(:gauge)
187
- expect(gauge.get({test_key: 'test_value', key: 'foo2'})).to eq(100)
187
+ expect(gauge.get(labels: {test_key: 'test_value', key: 'foo2'})).to eq(100)
188
188
  end
189
189
 
190
190
  it 'instruments summary metric' do
191
191
  expect(summary.type).to eq(:summary)
192
- expect(summary.get({test_key: 'test_value', key: 'foo3'})).to be_kind_of(Hash)
193
- expect(summary.get({test_key: 'test_value', key: 'foo3'})[0.99]).to eq(100)
194
- expect(summary_with_accessor.get({test_key: 'test_value', key: 'foo5'})[0.99]).to eq(100)
192
+ expect(summary.get(labels: {test_key: 'test_value', key: 'foo3'})).to be_kind_of(Hash)
193
+ expect(summary_with_accessor.get(labels: {test_key: 'test_value', key: 'foo5'})["sum"]).to eq(100)
195
194
  end
196
195
 
197
196
  it 'instruments histogram metric' do
@@ -200,8 +199,8 @@ shared_examples_for 'instruments record' do
200
199
  end
201
200
 
202
201
  expect(histogram.type).to eq(:histogram)
203
- expect(histogram.get({test_key: 'test_value', key: 'foo4'})).to be_kind_of(Hash)
204
- expect(histogram.get({test_key: 'test_value', key: 'foo4'})[10]).to eq(5) # 4 + `es` in before
202
+ expect(histogram.get(labels: {test_key: 'test_value', key: 'foo4'})).to be_kind_of(Hash)
203
+ expect(histogram.get(labels: {test_key: 'test_value', key: 'foo4'})["10"]).to eq(5) # 4 + `es` in before
205
204
  end
206
205
  end
207
206
 
@@ -231,7 +230,7 @@ shared_examples_for 'instruments record' do
231
230
  expect(counter).to be_kind_of(::Prometheus::Client::Metric)
232
231
  key, _ = counter.values.find {|k,v| v == 100 }
233
232
  expect(key).to be_kind_of(Hash)
234
- expect(key[:foo]).to eq(100)
233
+ expect(key[:foo]).to eq("100")
235
234
  end
236
235
  end
237
236
 
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.8.2
4
+ version: 2.0.1
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-07-17 00:00:00.000000000 Z
11
+ date: 2021-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -34,16 +34,16 @@ dependencies:
34
34
  name: prometheus-client
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - "<"
37
+ - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: '0.10'
39
+ version: 2.1.0
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "<"
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '0.10'
46
+ version: 2.1.0
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +107,7 @@ executables: []
107
107
  extensions: []
108
108
  extra_rdoc_files: []
109
109
  files:
110
+ - ".github/workflows/linux.yml"
110
111
  - ".gitignore"
111
112
  - ".rspec"
112
113
  - ".travis.yml"
@@ -158,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
159
  - !ruby/object:Gem::Version
159
160
  version: '0'
160
161
  requirements: []
161
- rubygems_version: 3.0.3
162
+ rubygems_version: 3.1.2
162
163
  signing_key:
163
164
  specification_version: 4
164
165
  summary: A fluent plugin that collects metrics and exposes for Prometheus.