fluent-plugin-prometheus 1.7.0 → 1.7.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 +4 -4
- data/README.md +7 -1
- data/fluent-plugin-prometheus.gemspec +1 -1
- data/lib/fluent/plugin/in_prometheus_monitor.rb +3 -3
- data/lib/fluent/plugin/in_prometheus_output_monitor.rb +3 -3
- data/lib/fluent/plugin/in_prometheus_tail_monitor.rb +3 -3
- data/lib/fluent/plugin/prometheus.rb +17 -18
- data/lib/fluent/plugin/prometheus/placeholder_expander.rb +132 -0
- data/spec/fluent/plugin/filter_prometheus_spec.rb +20 -10
- data/spec/fluent/plugin/in_prometheus_monitor_spec.rb +0 -1
- data/spec/fluent/plugin/{prometheus_spec.rb → in_prometheus_spec.rb} +0 -0
- data/spec/fluent/plugin/out_prometheus_spec.rb +18 -9
- data/spec/fluent/plugin/prometheus/placeholder_expander_spec.rb +110 -0
- data/spec/fluent/plugin/shared.rb +50 -101
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32e8a803f1394e445d273b41ec9bde5f238f4193956c431a0866c93b2a2a0426
|
4
|
+
data.tar.gz: 281024e977c3aee02030691ffb7cd86361b759dae259bb8103934db7e195f751
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e784fec1bca9a2ea8f725b5970ed5f08069b6d457ae11b23e1c22017d188046cab4718573c67a94b230acff1583ac12d6378a372a3713f311470c2b9a5818e3
|
7
|
+
data.tar.gz: 805673a26e562f4607cefbbf256c12e3557317e115a88096357ddde30f6d5f8dea67835e580100c6bfb5aa9abfb542d0f5b0bff9374b6d4b48046034fea5527a
|
data/README.md
CHANGED
@@ -369,7 +369,13 @@ Reserved placeholders are:
|
|
369
369
|
- `${worker_id}`: fluent worker id
|
370
370
|
- `${tag}`: tag name
|
371
371
|
- only available in Prometheus output/filter plugin
|
372
|
-
|
372
|
+
- `${tag_parts[N]}` refers to the Nth part of the tag.
|
373
|
+
- only available in Prometheus output/filter plugin
|
374
|
+
- `${tag_prefix[N]}` refers to the [0..N] part of the tag.
|
375
|
+
- only available in Prometheus output/filter plugin
|
376
|
+
- `${tag_suffix[N]}` refers to the [`tagsize`-1-N..] part of the tag.
|
377
|
+
- where `tagsize` is the size of tag which is splitted with `.` (when tag is `1.2.3`, then `tagsize` is 3)
|
378
|
+
- only available in Prometheus output/filter plugin
|
373
379
|
|
374
380
|
### top-level labels and labels inside metric
|
375
381
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "fluent-plugin-prometheus"
|
3
|
-
spec.version = "1.7.
|
3
|
+
spec.version = "1.7.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.}
|
@@ -24,14 +24,14 @@ module Fluent::Plugin
|
|
24
24
|
def configure(conf)
|
25
25
|
super
|
26
26
|
hostname = Socket.gethostname
|
27
|
-
|
28
|
-
|
27
|
+
expander_builder = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
28
|
+
expander = expander_builder.build({ 'hostname' => hostname, 'worker_id' => fluentd_worker_id })
|
29
29
|
@base_labels = parse_labels_elements(conf)
|
30
30
|
@base_labels.each do |key, value|
|
31
31
|
unless value.is_a?(String)
|
32
32
|
raise Fluent::ConfigError, "record accessor syntax is not available in prometheus_monitor"
|
33
33
|
end
|
34
|
-
@base_labels[key] = expander.expand(value
|
34
|
+
@base_labels[key] = expander.expand(value)
|
35
35
|
end
|
36
36
|
|
37
37
|
if defined?(Fluent::Plugin) && defined?(Fluent::Plugin::MonitorAgentInput)
|
@@ -43,14 +43,14 @@ module Fluent::Plugin
|
|
43
43
|
def configure(conf)
|
44
44
|
super
|
45
45
|
hostname = Socket.gethostname
|
46
|
-
|
47
|
-
|
46
|
+
expander_builder = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
47
|
+
expander = expander_builder.buidl({ 'hostname' => hostname, 'worker_id' => fluentd_worker_id })
|
48
48
|
@base_labels = parse_labels_elements(conf)
|
49
49
|
@base_labels.each do |key, value|
|
50
50
|
unless value.is_a?(String)
|
51
51
|
raise Fluent::ConfigError, "record accessor syntax is not available in prometheus_output_monitor"
|
52
52
|
end
|
53
|
-
@base_labels[key] = expander.expand(value
|
53
|
+
@base_labels[key] = expander.expand(value)
|
54
54
|
end
|
55
55
|
|
56
56
|
if defined?(Fluent::Plugin) && defined?(Fluent::Plugin::MonitorAgentInput)
|
@@ -28,14 +28,14 @@ module Fluent::Plugin
|
|
28
28
|
def configure(conf)
|
29
29
|
super
|
30
30
|
hostname = Socket.gethostname
|
31
|
-
|
32
|
-
|
31
|
+
expander_builder = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
32
|
+
expander = expander_builder.prepare_placeholders({ 'hostname' => hostname, 'worker_id' => fluentd_worker_id })
|
33
33
|
@base_labels = parse_labels_elements(conf)
|
34
34
|
@base_labels.each do |key, value|
|
35
35
|
unless value.is_a?(String)
|
36
36
|
raise Fluent::ConfigError, "record accessor syntax is not available in prometheus_tail_monitor"
|
37
37
|
end
|
38
|
-
@base_labels[key] = expander.expand(value
|
38
|
+
@base_labels[key] = expander.expand(value)
|
39
39
|
end
|
40
40
|
|
41
41
|
if defined?(Fluent::Plugin) && defined?(Fluent::Plugin::MonitorAgentInput)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'prometheus/client'
|
2
2
|
require 'prometheus/client/formats/text'
|
3
|
-
require 'fluent/plugin/
|
3
|
+
require 'fluent/plugin/prometheus/placeholder_expander'
|
4
4
|
|
5
5
|
module Fluent
|
6
6
|
module Plugin
|
@@ -82,14 +82,13 @@ module Fluent
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def self.placeholder_expander(log)
|
85
|
-
|
86
|
-
Fluent::Plugin::RecordTransformerFilter::PlaceholderExpander.new(log: log)
|
85
|
+
Fluent::Plugin::Prometheus::ExpandBuilder.new(log: log)
|
87
86
|
end
|
88
87
|
|
89
88
|
def configure(conf)
|
90
89
|
super
|
91
90
|
@placeholder_values = {}
|
92
|
-
@
|
91
|
+
@placeholder_expander_builder = Fluent::Plugin::Prometheus.placeholder_expander(log)
|
93
92
|
@hostname = Socket.gethostname
|
94
93
|
end
|
95
94
|
|
@@ -101,10 +100,10 @@ module Fluent
|
|
101
100
|
}
|
102
101
|
|
103
102
|
placeholders = record.merge(@placeholder_values[tag])
|
104
|
-
|
103
|
+
expander = @placeholder_expander_builder.build(placeholders)
|
105
104
|
metrics.each do |metric|
|
106
105
|
begin
|
107
|
-
metric.instrument(record,
|
106
|
+
metric.instrument(record, expander)
|
108
107
|
rescue => e
|
109
108
|
log.warn "prometheus: failed to instrument a metric.", error_class: e.class, error: e, tag: tag, name: metric.name
|
110
109
|
router.emit_error_event(tag, time, record, e)
|
@@ -121,10 +120,10 @@ module Fluent
|
|
121
120
|
|
122
121
|
es.each do |time, record|
|
123
122
|
placeholders = record.merge(placeholder_values)
|
124
|
-
|
123
|
+
expander = @placeholder_expander_builder.build(placeholders)
|
125
124
|
metrics.each do |metric|
|
126
125
|
begin
|
127
|
-
metric.instrument(record,
|
126
|
+
metric.instrument(record, expander)
|
128
127
|
rescue => e
|
129
128
|
log.warn "prometheus: failed to instrument a metric.", error_class: e.class, error: e, tag: tag, name: metric.name
|
130
129
|
router.emit_error_event(tag, time, record, e)
|
@@ -154,11 +153,11 @@ module Fluent
|
|
154
153
|
@base_labels = labels.merge(@base_labels)
|
155
154
|
end
|
156
155
|
|
157
|
-
def labels(record, expander
|
156
|
+
def labels(record, expander)
|
158
157
|
label = {}
|
159
158
|
@base_labels.each do |k, v|
|
160
159
|
if v.is_a?(String)
|
161
|
-
label[k] = expander.expand(v
|
160
|
+
label[k] = expander.expand(v)
|
162
161
|
else
|
163
162
|
label[k] = v.call(record)
|
164
163
|
end
|
@@ -195,14 +194,14 @@ module Fluent
|
|
195
194
|
end
|
196
195
|
end
|
197
196
|
|
198
|
-
def instrument(record, expander
|
197
|
+
def instrument(record, expander)
|
199
198
|
if @key.is_a?(String)
|
200
199
|
value = record[@key]
|
201
200
|
else
|
202
201
|
value = @key.call(record)
|
203
202
|
end
|
204
203
|
if value
|
205
|
-
@gauge.set(labels(record, expander
|
204
|
+
@gauge.set(labels(record, expander), value)
|
206
205
|
end
|
207
206
|
end
|
208
207
|
end
|
@@ -217,7 +216,7 @@ module Fluent
|
|
217
216
|
end
|
218
217
|
end
|
219
218
|
|
220
|
-
def instrument(record, expander
|
219
|
+
def instrument(record, expander)
|
221
220
|
# use record value of the key if key is specified, otherwise just increment
|
222
221
|
if @key.nil?
|
223
222
|
value = 1
|
@@ -230,7 +229,7 @@ module Fluent
|
|
230
229
|
# ignore if record value is nil
|
231
230
|
return if value.nil?
|
232
231
|
|
233
|
-
@counter.increment(labels(record, expander
|
232
|
+
@counter.increment(labels(record, expander), value)
|
234
233
|
end
|
235
234
|
end
|
236
235
|
|
@@ -248,14 +247,14 @@ module Fluent
|
|
248
247
|
end
|
249
248
|
end
|
250
249
|
|
251
|
-
def instrument(record, expander
|
250
|
+
def instrument(record, expander)
|
252
251
|
if @key.is_a?(String)
|
253
252
|
value = record[@key]
|
254
253
|
else
|
255
254
|
value = @key.call(record)
|
256
255
|
end
|
257
256
|
if value
|
258
|
-
@summary.observe(labels(record, expander
|
257
|
+
@summary.observe(labels(record, expander), value)
|
259
258
|
end
|
260
259
|
end
|
261
260
|
end
|
@@ -281,14 +280,14 @@ module Fluent
|
|
281
280
|
end
|
282
281
|
end
|
283
282
|
|
284
|
-
def instrument(record, expander
|
283
|
+
def instrument(record, expander)
|
285
284
|
if @key.is_a?(String)
|
286
285
|
value = record[@key]
|
287
286
|
else
|
288
287
|
value = @key.call(record)
|
289
288
|
end
|
290
289
|
if value
|
291
|
-
@histogram.observe(labels(record, expander
|
290
|
+
@histogram.observe(labels(record, expander), value)
|
292
291
|
end
|
293
292
|
end
|
294
293
|
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Fluent
|
2
|
+
module Plugin
|
3
|
+
module Prometheus
|
4
|
+
class ExpandBuilder
|
5
|
+
def self.build(placeholder, log:)
|
6
|
+
new(log: log).build(placeholder)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(log:)
|
10
|
+
@log = log
|
11
|
+
end
|
12
|
+
|
13
|
+
def build(placeholder_values)
|
14
|
+
placeholders = {}
|
15
|
+
placeholder_values.each do |key, value|
|
16
|
+
case value
|
17
|
+
when Array
|
18
|
+
size = value.size
|
19
|
+
value.each_with_index do |v, i|
|
20
|
+
placeholders["${#{key}[#{i}]}"] = v
|
21
|
+
placeholders["${#{key}[#{i - size}]}"] = v
|
22
|
+
end
|
23
|
+
when Hash
|
24
|
+
value.each do |k, v|
|
25
|
+
placeholders[%(${#{key}["#{k}"]})] = v
|
26
|
+
end
|
27
|
+
else
|
28
|
+
if key == 'tag'
|
29
|
+
placeholders.merge!(build_tag(value))
|
30
|
+
else
|
31
|
+
placeholders["${#{key}}"] = value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Fluent::Plugin::Prometheus::ExpandBuilder::PlaceholderExpander.new(@log, placeholders)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def build_tag(tag)
|
42
|
+
tags = tag.split('.')
|
43
|
+
|
44
|
+
placeholders = { '${tag}' => tag }
|
45
|
+
|
46
|
+
size = tags.size
|
47
|
+
|
48
|
+
tags.each_with_index do |v, i|
|
49
|
+
placeholders["${tag_parts[#{i}]}"] = v
|
50
|
+
placeholders["${tag_parts[#{i - size}]}"] = v
|
51
|
+
end
|
52
|
+
|
53
|
+
tag_prefix(tags).each_with_index do |v, i|
|
54
|
+
placeholders["${tag_prefix[#{i}]}"] = v
|
55
|
+
end
|
56
|
+
|
57
|
+
tag_suffix(tags).each_with_index do |v, i|
|
58
|
+
placeholders["${tag_suffix[#{i}]}"] = v
|
59
|
+
end
|
60
|
+
|
61
|
+
placeholders
|
62
|
+
end
|
63
|
+
|
64
|
+
def tag_prefix(tags)
|
65
|
+
tags = tags.dup
|
66
|
+
return [] if tags.empty?
|
67
|
+
|
68
|
+
ret = [tags.shift]
|
69
|
+
tags.each.with_index(1) do |tag, i|
|
70
|
+
ret[i] = "#{ret[i-1]}.#{tag}"
|
71
|
+
end
|
72
|
+
ret
|
73
|
+
end
|
74
|
+
|
75
|
+
def tag_suffix(tags)
|
76
|
+
return [] if tags.empty?
|
77
|
+
|
78
|
+
tags = tags.dup.reverse
|
79
|
+
ret = [tags.shift]
|
80
|
+
tags.each.with_index(1) do |tag, i|
|
81
|
+
ret[i] = "#{tag}.#{ret[i-1]}"
|
82
|
+
end
|
83
|
+
ret
|
84
|
+
end
|
85
|
+
|
86
|
+
class PlaceholderExpander
|
87
|
+
PLACEHOLDER_REGEX = /(\${[^\[}]+(\[[^\]]+\])?})/.freeze
|
88
|
+
|
89
|
+
attr_reader :placeholder
|
90
|
+
|
91
|
+
def initialize(log, placeholder)
|
92
|
+
@placeholder = placeholder
|
93
|
+
@log = log
|
94
|
+
@expander_cache = {}
|
95
|
+
end
|
96
|
+
|
97
|
+
def merge_placeholder(placeholder)
|
98
|
+
@placeholder.merge!(placeholder)
|
99
|
+
end
|
100
|
+
|
101
|
+
def expand(str, dynamic_placeholders: nil)
|
102
|
+
expander = if dynamic_placeholders
|
103
|
+
if @expander_cache[dynamic_placeholders]
|
104
|
+
@expander_cache[dynamic_placeholders]
|
105
|
+
else
|
106
|
+
e = ExpandBuilder.build(dynamic_placeholders, log: @log)
|
107
|
+
e.merge_placeholder(@placeholder)
|
108
|
+
@expander_cache[dynamic_placeholders] = e
|
109
|
+
e
|
110
|
+
end
|
111
|
+
else
|
112
|
+
self
|
113
|
+
end
|
114
|
+
|
115
|
+
expander.expand!(str)
|
116
|
+
end
|
117
|
+
|
118
|
+
protected
|
119
|
+
|
120
|
+
def expand!(str)
|
121
|
+
str.gsub(PLACEHOLDER_REGEX) { |value|
|
122
|
+
@placeholder.fetch(value) do
|
123
|
+
@log.warn("unknown placeholder `#{value}` found")
|
124
|
+
value # return as it is
|
125
|
+
end
|
126
|
+
}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -6,7 +6,11 @@ require_relative 'shared'
|
|
6
6
|
describe Fluent::Plugin::PrometheusFilter do
|
7
7
|
let(:tag) { 'prometheus.test' }
|
8
8
|
let(:driver) { Fluent::Test::Driver::Filter.new(Fluent::Plugin::PrometheusFilter).configure(config) }
|
9
|
-
let(:registry) { ::Prometheus::Client.
|
9
|
+
let(:registry) { ::Prometheus::Client::Registry.new }
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(Prometheus::Client).to receive(:registry).and_return(registry)
|
13
|
+
end
|
10
14
|
|
11
15
|
describe '#configure' do
|
12
16
|
it_behaves_like 'output configuration'
|
@@ -14,22 +18,28 @@ describe Fluent::Plugin::PrometheusFilter do
|
|
14
18
|
|
15
19
|
describe '#run' do
|
16
20
|
let(:message) { {"foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10} }
|
17
|
-
let(:es) {
|
18
|
-
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
19
|
-
driver.filtered_records
|
20
|
-
}
|
21
21
|
|
22
22
|
context 'simple config' do
|
23
|
-
|
23
|
+
let(:config) {
|
24
|
+
BASE_CONFIG + %(
|
25
|
+
<metric>
|
26
|
+
name simple
|
27
|
+
type counter
|
28
|
+
desc Something foo.
|
29
|
+
key foo
|
30
|
+
</metric>
|
31
|
+
)
|
32
|
+
}
|
24
33
|
|
25
34
|
it 'adds a new counter metric' do
|
26
|
-
expect(registry.metrics.map(&:name)).not_to
|
27
|
-
|
28
|
-
expect(registry.metrics.map(&:name)).to
|
35
|
+
expect(registry.metrics.map(&:name)).not_to eq([:simple])
|
36
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
37
|
+
expect(registry.metrics.map(&:name)).to eq([:simple])
|
29
38
|
end
|
30
39
|
|
31
40
|
it 'should keep original message' do
|
32
|
-
|
41
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
42
|
+
expect(driver.filtered_records.first).to eq(message)
|
33
43
|
end
|
34
44
|
end
|
35
45
|
|
File without changes
|
@@ -6,7 +6,11 @@ require_relative 'shared'
|
|
6
6
|
describe Fluent::Plugin::PrometheusOutput do
|
7
7
|
let(:tag) { 'prometheus.test' }
|
8
8
|
let(:driver) { Fluent::Test::Driver::Output.new(Fluent::Plugin::PrometheusOutput).configure(config) }
|
9
|
-
let(:registry) { ::Prometheus::Client.
|
9
|
+
let(:registry) { ::Prometheus::Client::Registry.new }
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(Prometheus::Client).to receive(:registry).and_return(registry)
|
13
|
+
end
|
10
14
|
|
11
15
|
describe '#configure' do
|
12
16
|
it_behaves_like 'output configuration'
|
@@ -14,18 +18,23 @@ describe Fluent::Plugin::PrometheusOutput do
|
|
14
18
|
|
15
19
|
describe '#run' do
|
16
20
|
let(:message) { {"foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10} }
|
17
|
-
let(:es) {
|
18
|
-
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
19
|
-
driver.events
|
20
|
-
}
|
21
21
|
|
22
22
|
context 'simple config' do
|
23
|
-
|
23
|
+
let(:config) {
|
24
|
+
BASE_CONFIG + %(
|
25
|
+
<metric>
|
26
|
+
name simple
|
27
|
+
type counter
|
28
|
+
desc Something foo.
|
29
|
+
key foo
|
30
|
+
</metric>
|
31
|
+
)
|
32
|
+
}
|
24
33
|
|
25
34
|
it 'adds a new counter metric' do
|
26
|
-
expect(registry.metrics.map(&:name)).not_to
|
27
|
-
|
28
|
-
expect(registry.metrics.map(&:name)).to
|
35
|
+
expect(registry.metrics.map(&:name)).not_to eq([:simple])
|
36
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
37
|
+
expect(registry.metrics.map(&:name)).to eq([:simple])
|
29
38
|
end
|
30
39
|
end
|
31
40
|
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'fluent/plugin/prometheus/placeholder_expander'
|
5
|
+
require_relative '../shared'
|
6
|
+
|
7
|
+
describe Fluent::Plugin::Prometheus::ExpandBuilder::PlaceholderExpander do
|
8
|
+
let(:log) do
|
9
|
+
Logger.new('/dev/null')
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:builder) do
|
13
|
+
Fluent::Plugin::Prometheus::ExpandBuilder.new(log: log)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#expand' do
|
17
|
+
context 'with static placeholder' do
|
18
|
+
let(:static_placeholder) do
|
19
|
+
{
|
20
|
+
'hostname' => 'host_value',
|
21
|
+
'tag' => '1.2.3',
|
22
|
+
'ary_value' => ['1', '2', '3'],
|
23
|
+
'hash_value' => { 'key1' => 'val1' },
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:dynamic_placeholder) do
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'expands values' do
|
31
|
+
expander = builder.build(static_placeholder)
|
32
|
+
expect(expander.expand('${hostname}')).to eq('host_value')
|
33
|
+
expect(expander.expand('${ary_value[0]}.${ary_value[1]}.${ary_value[2]}')).to eq('1.2.3')
|
34
|
+
expect(expander.expand('${ary_value[-3]}.${ary_value[-2]}.${ary_value[-1]}')).to eq('1.2.3')
|
35
|
+
expect(expander.expand('${hash_value["key1"]}')).to eq('val1')
|
36
|
+
|
37
|
+
expect(expander.expand('${tag}')).to eq('1.2.3')
|
38
|
+
expect(expander.expand('${tag_parts[0]}.${tag_parts[1]}.${tag_parts[2]}')).to eq('1.2.3')
|
39
|
+
expect(expander.expand('${tag_parts[-3]}.${tag_parts[-2]}.${tag_parts[-1]}')).to eq('1.2.3')
|
40
|
+
expect(expander.expand('${tag_prefix[0]}.${tag_prefix[1]}.${tag_prefix[2]}')).to eq('1.1.2.1.2.3')
|
41
|
+
expect(expander.expand('${tag_suffix[0]}.${tag_suffix[1]}.${tag_suffix[2]}')).to eq('3.2.3.1.2.3')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'does not create new expander' do
|
45
|
+
builder # cached before mock
|
46
|
+
|
47
|
+
expect(Fluent::Plugin::Prometheus::ExpandBuilder).to receive(:build).with(anything, log: anything).never
|
48
|
+
expander = builder.build(static_placeholder)
|
49
|
+
expander.expand('${hostname}')
|
50
|
+
expander.expand('${hostname}')
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when not found placeholder' do
|
54
|
+
it 'prints wanring log and as it is' do
|
55
|
+
expect(log).to receive(:warn).with('unknown placeholder `${tag_prefix[100]}` found').once
|
56
|
+
|
57
|
+
expander = builder.build(static_placeholder)
|
58
|
+
expect(expander.expand('${tag_prefix[100]}')).to eq('${tag_prefix[100]}')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'with dynamic placeholder' do
|
64
|
+
let(:static_placeholder) do
|
65
|
+
{
|
66
|
+
'hostname' => 'host_value',
|
67
|
+
'ary_value' => ['1', '2', '3'],
|
68
|
+
'hash_value' => { 'key1' => 'val1' },
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
let(:dynamic_placeholder) do
|
73
|
+
{ 'tag' => '1.2.3'}
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'expands values' do
|
77
|
+
expander = builder.build(static_placeholder)
|
78
|
+
expect(expander.expand('${hostname}', dynamic_placeholders: dynamic_placeholder)).to eq('host_value')
|
79
|
+
expect(expander.expand('${ary_value[0]}.${ary_value[1]}.${ary_value[2]}', dynamic_placeholders: dynamic_placeholder)).to eq('1.2.3')
|
80
|
+
expect(expander.expand('${ary_value[-3]}.${ary_value[-2]}.${ary_value[-1]}', dynamic_placeholders: dynamic_placeholder)).to eq('1.2.3')
|
81
|
+
expect(expander.expand('${hash_value["key1"]}', dynamic_placeholders: dynamic_placeholder)).to eq('val1')
|
82
|
+
|
83
|
+
expect(expander.expand('${tag}', dynamic_placeholders: dynamic_placeholder)).to eq('1.2.3')
|
84
|
+
expect(expander.expand('${tag_parts[0]}.${tag_parts[1]}.${tag_parts[2]}', dynamic_placeholders: dynamic_placeholder)).to eq('1.2.3')
|
85
|
+
expect(expander.expand('${tag_parts[-3]}.${tag_parts[-2]}.${tag_parts[-1]}', dynamic_placeholders: dynamic_placeholder)).to eq('1.2.3')
|
86
|
+
expect(expander.expand('${tag_prefix[0]}.${tag_prefix[1]}.${tag_prefix[2]}', dynamic_placeholders: dynamic_placeholder)).to eq('1.1.2.1.2.3')
|
87
|
+
expect(expander.expand('${tag_suffix[0]}.${tag_suffix[1]}.${tag_suffix[2]}', dynamic_placeholders: dynamic_placeholder)).to eq('3.2.3.1.2.3')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'does not create expander twice if given the same placeholder' do
|
91
|
+
builder # cached before mock
|
92
|
+
|
93
|
+
expect(Fluent::Plugin::Prometheus::ExpandBuilder).to receive(:build).with(anything, log: anything).once.and_call_original
|
94
|
+
expander = builder.build(static_placeholder)
|
95
|
+
placeholder = { 'tag' => 'val.test' }
|
96
|
+
expander.expand('${hostname}', dynamic_placeholders: placeholder)
|
97
|
+
expander.expand('${hostname}', dynamic_placeholders: placeholder)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'creates new expander for each placeholder' do
|
101
|
+
builder # cached before mock
|
102
|
+
|
103
|
+
expect(Fluent::Plugin::Prometheus::ExpandBuilder).to receive(:build).with(anything, log: anything).twice.and_call_original
|
104
|
+
expander = builder.build(static_placeholder)
|
105
|
+
expander.expand('${hostname}', dynamic_placeholders: { 'tag' => 'val.test' })
|
106
|
+
expander.expand('${hostname}', dynamic_placeholders: { 'tag' => 'val.test2' })
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -3,9 +3,7 @@ BASE_CONFIG = %[
|
|
3
3
|
type prometheus
|
4
4
|
]
|
5
5
|
|
6
|
-
|
7
6
|
SIMPLE_CONFIG = BASE_CONFIG + %[
|
8
|
-
type prometheus
|
9
7
|
<metric>
|
10
8
|
name simple_foo
|
11
9
|
type counter
|
@@ -111,109 +109,65 @@ COUNTER_WITHOUT_KEY_CONFIG = BASE_CONFIG + %[
|
|
111
109
|
</metric>
|
112
110
|
]
|
113
111
|
|
114
|
-
def gen_time_suffix
|
115
|
-
return Time.now.to_f.to_s.gsub('.', '')
|
116
|
-
end
|
117
|
-
|
118
|
-
shared_context 'simple_config' do
|
119
|
-
let(:orig_name) { 'simple_foo' }
|
120
|
-
let(:config) { SIMPLE_CONFIG.gsub(orig_name, name.to_s) }
|
121
|
-
let(:name) { "#{orig_name}_#{gen_time_suffix}".to_sym }
|
122
|
-
let(:counter) { registry.get(name) }
|
123
|
-
end
|
124
|
-
|
125
|
-
shared_context 'full_config' do
|
126
|
-
let(:config) { FULL_CONFIG }
|
127
|
-
let(:counter) { registry.get(:full_foo) }
|
128
|
-
let(:gauge) { registry.get(:full_bar) }
|
129
|
-
let(:summary) { registry.get(:full_baz) }
|
130
|
-
let(:histogram) { registry.get(:full_qux) }
|
131
|
-
let(:summary_with_accessor) { registry.get(:full_accessor1) }
|
132
|
-
let(:counter_with_accessor) { registry.get(:full_accessor2) }
|
133
|
-
end
|
134
|
-
|
135
|
-
shared_context 'placeholder_config' do
|
136
|
-
let(:orig_name) { 'placeholder_foo' }
|
137
|
-
let(:config) { PLACEHOLDER_CONFIG.gsub(orig_name, name.to_s) }
|
138
|
-
let(:name) { "#{orig_name}_#{gen_time_suffix}".to_sym }
|
139
|
-
let(:counter) { registry.get(name) }
|
140
|
-
end
|
141
|
-
|
142
|
-
shared_context 'accessor_config' do
|
143
|
-
let(:orig_name) { 'accessor_foo' }
|
144
|
-
let(:config) { ACCESSOR_CONFIG.gsub(orig_name, name.to_s) }
|
145
|
-
let(:name) { "#{orig_name}_#{gen_time_suffix}".to_sym }
|
146
|
-
let(:counter) { registry.get(name) }
|
147
|
-
end
|
148
|
-
|
149
|
-
shared_context 'counter_without_key_config' do
|
150
|
-
let(:orig_name) { 'without_key_foo' }
|
151
|
-
let(:config) { COUNTER_WITHOUT_KEY_CONFIG.gsub(orig_name, name.to_s) }
|
152
|
-
let(:name) { "#{orig_name}_#{gen_time_suffix}".to_sym }
|
153
|
-
let(:counter) { registry.get(name) }
|
154
|
-
end
|
155
|
-
|
156
112
|
shared_examples_for 'output configuration' do
|
157
113
|
context 'base config' do
|
158
114
|
let(:config) { BASE_CONFIG }
|
159
|
-
it
|
160
|
-
expect{driver}.not_to raise_error
|
161
|
-
end
|
115
|
+
it { expect { driver }.not_to raise_error }
|
162
116
|
end
|
163
117
|
|
164
|
-
|
165
|
-
|
166
|
-
it { expect{driver}.not_to raise_error }
|
118
|
+
context 'with simple configuration' do
|
119
|
+
let(:config) { SIMPLE_CONFIG }
|
120
|
+
it { expect { driver }.not_to raise_error }
|
167
121
|
end
|
168
122
|
|
169
|
-
|
170
|
-
|
171
|
-
it { expect{driver}.not_to raise_error }
|
123
|
+
context 'with full configuration' do
|
124
|
+
let(:config) { FULL_CONFIG }
|
125
|
+
it { expect { driver }.not_to raise_error }
|
172
126
|
end
|
173
127
|
|
174
|
-
|
175
|
-
|
176
|
-
it { expect{driver}.not_to raise_error }
|
128
|
+
context 'with placeholder configuration' do
|
129
|
+
let(:config) { PLACEHOLDER_CONFIG }
|
130
|
+
it { expect { driver }.not_to raise_error }
|
177
131
|
end
|
178
132
|
|
179
|
-
|
180
|
-
|
181
|
-
it { expect{driver}.not_to raise_error }
|
133
|
+
context 'with accessor configuration' do
|
134
|
+
let(:config) { ACCESSOR_CONFIG }
|
135
|
+
it { expect { driver }.not_to raise_error }
|
182
136
|
end
|
183
137
|
|
184
|
-
describe '
|
185
|
-
|
186
|
-
it { expect{driver}.not_to raise_error }
|
138
|
+
describe 'with counter without key configuration' do
|
139
|
+
let(:config) { COUNTER_WITHOUT_KEY_CONFIG }
|
140
|
+
it { expect { driver }.not_to raise_error }
|
187
141
|
end
|
188
142
|
|
189
|
-
context 'unknown type' do
|
190
|
-
let(:config)
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
expect{driver}.to raise_error Fluent::ConfigError
|
143
|
+
context 'with unknown type' do
|
144
|
+
let(:config) do
|
145
|
+
BASE_CONFIG + %[
|
146
|
+
<metric>
|
147
|
+
type foo
|
148
|
+
</metric>
|
149
|
+
]
|
197
150
|
end
|
151
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
198
152
|
end
|
199
153
|
end
|
200
154
|
|
201
|
-
emit_count = 0
|
202
155
|
shared_examples_for 'instruments record' do
|
203
|
-
|
204
|
-
|
156
|
+
before do
|
157
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
158
|
+
end
|
205
159
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
160
|
+
context 'full config' do
|
161
|
+
let(:config) { FULL_CONFIG }
|
162
|
+
let(:counter) { registry.get(:full_foo) }
|
163
|
+
let(:gauge) { registry.get(:full_bar) }
|
164
|
+
let(:summary) { registry.get(:full_baz) }
|
165
|
+
let(:histogram) { registry.get(:full_qux) }
|
166
|
+
let(:summary_with_accessor) { registry.get(:full_accessor1) }
|
167
|
+
let(:counter_with_accessor) { registry.get(:full_accessor2) }
|
210
168
|
|
211
169
|
it 'adds all metrics' do
|
212
|
-
expect(registry.metrics.map(&:name)).to
|
213
|
-
expect(registry.metrics.map(&:name)).to include(:full_bar)
|
214
|
-
expect(registry.metrics.map(&:name)).to include(:full_baz)
|
215
|
-
expect(registry.metrics.map(&:name)).to include(:full_accessor1)
|
216
|
-
expect(registry.metrics.map(&:name)).to include(:full_accessor2)
|
170
|
+
expect(registry.metrics.map(&:name)).to eq(%i[full_foo full_bar full_baz full_qux full_accessor1 full_accessor2])
|
217
171
|
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
218
172
|
expect(gauge).to be_kind_of(::Prometheus::Client::Metric)
|
219
173
|
expect(summary).to be_kind_of(::Prometheus::Client::Metric)
|
@@ -241,21 +195,22 @@ shared_examples_for 'instruments record' do
|
|
241
195
|
end
|
242
196
|
|
243
197
|
it 'instruments histogram metric' do
|
198
|
+
driver.run(default_tag: tag) do
|
199
|
+
4.times { driver.feed(event_time, message) }
|
200
|
+
end
|
201
|
+
|
244
202
|
expect(histogram.type).to eq(:histogram)
|
245
203
|
expect(histogram.get({test_key: 'test_value', key: 'foo4'})).to be_kind_of(Hash)
|
246
|
-
expect(histogram.get({test_key: 'test_value', key: 'foo4'})[10]).to eq(
|
204
|
+
expect(histogram.get({test_key: 'test_value', key: 'foo4'})[10]).to eq(5) # 4 + `es` in before
|
247
205
|
end
|
248
206
|
end
|
249
207
|
|
250
208
|
context 'placeholder config' do
|
251
|
-
|
252
|
-
|
253
|
-
before :each do
|
254
|
-
es
|
255
|
-
end
|
209
|
+
let(:config) { PLACEHOLDER_CONFIG }
|
210
|
+
let(:counter) { registry.get(:placeholder_foo) }
|
256
211
|
|
257
212
|
it 'expands placeholders with record values' do
|
258
|
-
expect(registry.metrics.map(&:name)).to
|
213
|
+
expect(registry.metrics.map(&:name)).to eq([:placeholder_foo])
|
259
214
|
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
260
215
|
key, _ = counter.values.find {|k,v| v == 100 }
|
261
216
|
expect(key).to be_kind_of(Hash)
|
@@ -268,14 +223,11 @@ shared_examples_for 'instruments record' do
|
|
268
223
|
end
|
269
224
|
|
270
225
|
context 'accessor config' do
|
271
|
-
|
272
|
-
|
273
|
-
before :each do
|
274
|
-
es
|
275
|
-
end
|
226
|
+
let(:config) { ACCESSOR_CONFIG }
|
227
|
+
let(:counter) { registry.get(:accessor_foo) }
|
276
228
|
|
277
229
|
it 'expands accessor with record values' do
|
278
|
-
expect(registry.metrics.map(&:name)).to
|
230
|
+
expect(registry.metrics.map(&:name)).to eq([:accessor_foo])
|
279
231
|
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
280
232
|
key, _ = counter.values.find {|k,v| v == 100 }
|
281
233
|
expect(key).to be_kind_of(Hash)
|
@@ -284,14 +236,11 @@ shared_examples_for 'instruments record' do
|
|
284
236
|
end
|
285
237
|
|
286
238
|
context 'counter_without config' do
|
287
|
-
|
288
|
-
|
289
|
-
before :each do
|
290
|
-
es
|
291
|
-
end
|
239
|
+
let(:config) { COUNTER_WITHOUT_KEY_CONFIG }
|
240
|
+
let(:counter) { registry.get(:without_key_foo) }
|
292
241
|
|
293
242
|
it 'just increments by 1' do
|
294
|
-
expect(registry.metrics.map(&:name)).to
|
243
|
+
expect(registry.metrics.map(&:name)).to eq([:without_key_foo])
|
295
244
|
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
296
245
|
_, value = counter.values.find {|k,v| k == {} }
|
297
246
|
expect(value).to eq(1)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-prometheus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.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:
|
11
|
+
date: 2020-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- lib/fluent/plugin/in_prometheus_tail_monitor.rb
|
123
123
|
- lib/fluent/plugin/out_prometheus.rb
|
124
124
|
- lib/fluent/plugin/prometheus.rb
|
125
|
+
- lib/fluent/plugin/prometheus/placeholder_expander.rb
|
125
126
|
- lib/fluent/plugin/prometheus_metrics.rb
|
126
127
|
- misc/fluentd_sample.conf
|
127
128
|
- misc/nginx_proxy.conf
|
@@ -129,9 +130,10 @@ files:
|
|
129
130
|
- misc/prometheus_alerts.yaml
|
130
131
|
- spec/fluent/plugin/filter_prometheus_spec.rb
|
131
132
|
- spec/fluent/plugin/in_prometheus_monitor_spec.rb
|
133
|
+
- spec/fluent/plugin/in_prometheus_spec.rb
|
132
134
|
- spec/fluent/plugin/out_prometheus_spec.rb
|
135
|
+
- spec/fluent/plugin/prometheus/placeholder_expander_spec.rb
|
133
136
|
- spec/fluent/plugin/prometheus_metrics_spec.rb
|
134
|
-
- spec/fluent/plugin/prometheus_spec.rb
|
135
137
|
- spec/fluent/plugin/shared.rb
|
136
138
|
- spec/spec_helper.rb
|
137
139
|
homepage: https://github.com/fluent/fluent-plugin-prometheus
|
@@ -160,8 +162,9 @@ summary: A fluent plugin that collects metrics and exposes for Prometheus.
|
|
160
162
|
test_files:
|
161
163
|
- spec/fluent/plugin/filter_prometheus_spec.rb
|
162
164
|
- spec/fluent/plugin/in_prometheus_monitor_spec.rb
|
165
|
+
- spec/fluent/plugin/in_prometheus_spec.rb
|
163
166
|
- spec/fluent/plugin/out_prometheus_spec.rb
|
167
|
+
- spec/fluent/plugin/prometheus/placeholder_expander_spec.rb
|
164
168
|
- spec/fluent/plugin/prometheus_metrics_spec.rb
|
165
|
-
- spec/fluent/plugin/prometheus_spec.rb
|
166
169
|
- spec/fluent/plugin/shared.rb
|
167
170
|
- spec/spec_helper.rb
|