fluent-plugin-prometheus 1.8.5 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/linux.yml +30 -0
- data/ChangeLog +21 -0
- data/README.md +60 -4
- data/fluent-plugin-prometheus.gemspec +2 -2
- data/lib/fluent/plugin/in_prometheus_monitor.rb +4 -4
- data/lib/fluent/plugin/in_prometheus_output_monitor.rb +30 -20
- data/lib/fluent/plugin/in_prometheus_tail_monitor.rb +18 -3
- data/lib/fluent/plugin/prometheus.rb +121 -10
- data/spec/fluent/plugin/in_prometheus_spec.rb +1 -1
- data/spec/fluent/plugin/out_prometheus_spec.rb +29 -0
- data/spec/fluent/plugin/shared.rb +211 -11
- metadata +9 -8
- data/.travis.yml +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 366793cd93075c7e1d63cb2641d2654f5eef5304aaa1293bb9e1dabed7d93e2f
|
4
|
+
data.tar.gz: 4db5c9fc80dcf10b013239bfdb6e098b53bf26c34a135f944850c70d2a36b7d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47de7cabc21f0365b8629714dbd7044e95346d5fb9ce13f7c830a8aeab66bd078769792e6af2ddf52bfc41be3b052f1f1ef912dc71d34c3db0dc94b283832238
|
7
|
+
data.tar.gz: 00c98825475166ae5f53e6bd85081766a38aa12b5ecddf079e0f1efcbb0eb729deacf996ee975893897aa2aeca84e35a741d23c2bf7e1f602c75876e08d317ee
|
@@ -0,0 +1,30 @@
|
|
1
|
+
name: linux
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches: [master]
|
5
|
+
pull_request:
|
6
|
+
branches: [master]
|
7
|
+
jobs:
|
8
|
+
build:
|
9
|
+
runs-on: ${{ matrix.os }}
|
10
|
+
continue-on-error: ${{ matrix.experimental }}
|
11
|
+
strategy:
|
12
|
+
fail-fast: false
|
13
|
+
matrix:
|
14
|
+
ruby: [ '3.2', '3.1', '3.0', '2.7' ]
|
15
|
+
os:
|
16
|
+
- ubuntu-latest
|
17
|
+
experimental: [false]
|
18
|
+
name: Ruby ${{ matrix.ruby }} unit testing on ${{ matrix.os }}
|
19
|
+
steps:
|
20
|
+
- uses: actions/checkout@v3
|
21
|
+
- uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: ${{ matrix.ruby }}
|
24
|
+
- name: unit testing
|
25
|
+
env:
|
26
|
+
CI: true
|
27
|
+
run: |
|
28
|
+
gem install bundler rake
|
29
|
+
bundle install --jobs 4 --retry 3
|
30
|
+
bundle exec rake spec
|
data/ChangeLog
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
Release 2.1.0 - 2023/06/15
|
2
|
+
|
3
|
+
* Add `initialized` and `initlabels` parameters to `<metric>` element
|
4
|
+
* in_prometheus_tail_monitor: Add file open/closed/rotation metrics
|
5
|
+
|
6
|
+
Release 2.0.3 - 2022/05/06
|
7
|
+
|
8
|
+
* in_prometheus_output_monitor: Fix a bug where output_status_num_errors metric is missing
|
9
|
+
|
10
|
+
Release 2.0.2 - 2021/08/02
|
11
|
+
|
12
|
+
* in_prometheus_output_monitor: Follow Fluentd's core metrics mechanism
|
13
|
+
|
14
|
+
Release 2.0.1 - 2021/04/08
|
15
|
+
|
16
|
+
* out_prometheus: Allow for lookup by symbol as well as string
|
17
|
+
|
18
|
+
Release 2.0.0 - 2021/02/18
|
19
|
+
|
20
|
+
* Update prometheus-client dependency to 2.1.0 or later
|
21
|
+
|
1
22
|
Release 1.8.5 - 2020/11/24
|
2
23
|
|
3
24
|
* in_prometheus_monitor: Support USR2 reload
|
data/README.md
CHANGED
@@ -162,10 +162,11 @@ This plugin uses internal class of Fluentd, so it's easy to break.
|
|
162
162
|
|
163
163
|
#### Exposed metrics
|
164
164
|
|
165
|
-
- `fluentd_tail_file_position
|
166
|
-
|
167
|
-
- `
|
168
|
-
|
165
|
+
- `fluentd_tail_file_position`: Current bytes which plugin reads from the file
|
166
|
+
- `fluentd_tail_file_inode`: inode of the file
|
167
|
+
- `fluentd_tail_file_closed`: Number of closed files
|
168
|
+
- `fluentd_tail_file_opened`: Number of opened files
|
169
|
+
- `fluentd_tail_file_rotated`: Number of rotated files
|
169
170
|
|
170
171
|
Default labels:
|
171
172
|
|
@@ -286,7 +287,9 @@ For details of each metric type, see [Prometheus documentation](http://prometheu
|
|
286
287
|
- `type`: metric type (required)
|
287
288
|
- `desc`: description of this metric (required)
|
288
289
|
- `key`: key name of record for instrumentation (**optional**)
|
290
|
+
- `initialized`: boolean controlling initilization of metric (**optional**). See [Metric initialization](#metric-initialization)
|
289
291
|
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
292
|
+
- `<initlabels>`: labels to use for initialization of ReccordAccessors/Placeholder labels (**optional**). See [Metric initialization](#metric-initialization)
|
290
293
|
|
291
294
|
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.
|
292
295
|
|
@@ -310,7 +313,9 @@ If key is empty, the metric values is treated as 1, so the counter increments by
|
|
310
313
|
- `type`: metric type (required)
|
311
314
|
- `desc`: description of metric (required)
|
312
315
|
- `key`: key name of record for instrumentation (required)
|
316
|
+
- `initialized`: boolean controlling initilization of metric (**optional**). See [Metric initialization](#metric-initialization)
|
313
317
|
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
318
|
+
- `<initlabels>`: labels to use for initialization of ReccordAccessors/Placeholder labels (**optional**). See [Metric initialization](#metric-initialization)
|
314
319
|
|
315
320
|
### summary type
|
316
321
|
|
@@ -332,7 +337,9 @@ If key is empty, the metric values is treated as 1, so the counter increments by
|
|
332
337
|
- `type`: metric type (required)
|
333
338
|
- `desc`: description of metric (required)
|
334
339
|
- `key`: key name of record for instrumentation (required)
|
340
|
+
- `initialized`: boolean controlling initilization of metric (**optional**). See [Metric initialization](#metric-initialization)
|
335
341
|
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
342
|
+
- `<initlabels>`: labels to use for initialization of ReccordAccessors/Placeholder labels (**optional**). See [Metric initialization](#metric-initialization)
|
336
343
|
|
337
344
|
### histogram type
|
338
345
|
|
@@ -355,8 +362,10 @@ If key is empty, the metric values is treated as 1, so the counter increments by
|
|
355
362
|
- `type`: metric type (required)
|
356
363
|
- `desc`: description of metric (required)
|
357
364
|
- `key`: key name of record for instrumentation (required)
|
365
|
+
- `initialized`: boolean controlling initilization of metric (**optional**). See [Metric initialization](#metric-initialization)
|
358
366
|
- `buckets`: buckets of record for instrumentation (optional)
|
359
367
|
- `<labels>`: additional labels for this metric (optional). See [Labels](#labels)
|
368
|
+
- `<initlabels>`: labels to use for initialization of ReccordAccessors/Placeholder labels (**optional**). See [Metric initialization](#metric-initialization)
|
360
369
|
|
361
370
|
## Labels
|
362
371
|
|
@@ -395,6 +404,53 @@ Reserved placeholders are:
|
|
395
404
|
- where `tagsize` is the size of tag which is splitted with `.` (when tag is `1.2.3`, then `tagsize` is 3)
|
396
405
|
- only available in Prometheus output/filter plugin
|
397
406
|
|
407
|
+
### Metric initialization
|
408
|
+
|
409
|
+
You can configure if a metric should be initialized to its zero value before receiving any event. To do so you just need to specify `initialized true`.
|
410
|
+
|
411
|
+
```
|
412
|
+
<metric>
|
413
|
+
name message_bar_counter
|
414
|
+
type counter
|
415
|
+
desc The total number of bar in message.
|
416
|
+
key bar
|
417
|
+
initialized true
|
418
|
+
<labels>
|
419
|
+
foo bar
|
420
|
+
</labels>
|
421
|
+
</metric>
|
422
|
+
```
|
423
|
+
|
424
|
+
If your labels contains ReccordAccessors or Placeholders, you must use `<initlabels>` to specify the values your ReccordAccessors/Placeholders will take. This feature is useful only if your Placeholders/ReccordAccessors contain deterministic values. Initialization will create as many zero value metrics as `<initlabels>` blocks you defined.
|
425
|
+
Potential reserved placeholders `${hostname}` and `${worker_id}`, as well as static labels, are automatically added and should not be specified in `<initlabels>` configuration.
|
426
|
+
|
427
|
+
```
|
428
|
+
<metric>
|
429
|
+
name message_bar_counter
|
430
|
+
type counter
|
431
|
+
desc The total number of bar in message.
|
432
|
+
key bar
|
433
|
+
initialized true
|
434
|
+
<labels>
|
435
|
+
key $.foo
|
436
|
+
tag ${tag}
|
437
|
+
foo bar
|
438
|
+
worker_id ${worker_id}
|
439
|
+
</labels>
|
440
|
+
<initlabels>
|
441
|
+
key foo1
|
442
|
+
tag tag1
|
443
|
+
</initlabels>
|
444
|
+
<initlabels>
|
445
|
+
key foo2
|
446
|
+
tag tag2
|
447
|
+
</initlabels>
|
448
|
+
</metric>
|
449
|
+
<labels>
|
450
|
+
hostname ${hostname}
|
451
|
+
</labels>
|
452
|
+
```
|
453
|
+
|
398
454
|
### top-level labels and labels inside metric
|
399
455
|
|
400
456
|
Prometheus output/filter plugin can have multiple metric section. Top-level labels section specifies labels for all metrics. Labels section inside metric section specifies labels for the metric. Both are specified, labels are merged.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "fluent-plugin-prometheus"
|
3
|
-
spec.version = "1.
|
3
|
+
spec.version = "2.1.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.}
|
@@ -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", "
|
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"
|
@@ -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(
|
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(
|
86
|
-
@buffer_oldest_timekey.set(
|
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
|
@@ -100,7 +100,7 @@ module Fluent::Plugin
|
|
100
100
|
if @registry.exist?(name)
|
101
101
|
@registry.get(name)
|
102
102
|
else
|
103
|
-
@registry.gauge(name, docstring)
|
103
|
+
@registry.gauge(name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :plugin_category, :type])
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
@@ -133,18 +133,26 @@ module Fluent::Plugin
|
|
133
133
|
|
134
134
|
monitor_info = {
|
135
135
|
# buffer metrics
|
136
|
-
'buffer_total_queued_size' => @metrics[:buffer_total_queued_size],
|
137
|
-
'buffer_stage_length' => @metrics[:buffer_stage_length],
|
138
|
-
'buffer_stage_byte_size' => @metrics[:buffer_stage_byte_size],
|
139
|
-
'buffer_queue_length' => @metrics[:buffer_queue_length],
|
140
|
-
'buffer_queue_byte_size' => @metrics[:buffer_queue_byte_size],
|
141
|
-
'buffer_available_buffer_space_ratios' => @metrics[:buffer_available_buffer_space_ratios],
|
142
|
-
'buffer_newest_timekey' => @metrics[:buffer_newest_timekey],
|
143
|
-
'buffer_oldest_timekey' => @metrics[:buffer_oldest_timekey],
|
136
|
+
'buffer_total_queued_size' => [@metrics[:buffer_total_queued_size]],
|
137
|
+
'buffer_stage_length' => [@metrics[:buffer_stage_length]],
|
138
|
+
'buffer_stage_byte_size' => [@metrics[:buffer_stage_byte_size]],
|
139
|
+
'buffer_queue_length' => [@metrics[:buffer_queue_length]],
|
140
|
+
'buffer_queue_byte_size' => [@metrics[:buffer_queue_byte_size]],
|
141
|
+
'buffer_available_buffer_space_ratios' => [@metrics[:buffer_available_buffer_space_ratios]],
|
142
|
+
'buffer_newest_timekey' => [@metrics[:buffer_newest_timekey]],
|
143
|
+
'buffer_oldest_timekey' => [@metrics[:buffer_oldest_timekey]],
|
144
144
|
|
145
145
|
# output metrics
|
146
|
-
'retry_count' => @metrics[:retry_counts],
|
146
|
+
'retry_count' => [@metrics[:retry_counts], @metrics[:num_errors]],
|
147
|
+
# Needed since Fluentd v1.14 due to metrics extensions.
|
148
|
+
'write_count' => [@metrics[:write_count]],
|
149
|
+
'emit_count' => [@metrics[:emit_count]],
|
150
|
+
'emit_records' => [@metrics[:emit_records]],
|
151
|
+
'rollback_count' => [@metrics[:rollback_count]],
|
152
|
+
'flush_time_count' => [@metrics[:flush_time_count]],
|
153
|
+
'slow_flush_count' => [@metrics[:slow_flush_count]],
|
147
154
|
}
|
155
|
+
# No needed for Fluentd v1.14 but leave as-is for backward compatibility.
|
148
156
|
instance_vars_info = {
|
149
157
|
num_errors: @metrics[:num_errors],
|
150
158
|
write_count: @metrics[:write_count],
|
@@ -158,12 +166,14 @@ module Fluent::Plugin
|
|
158
166
|
agent_info.each do |info|
|
159
167
|
label = labels(info)
|
160
168
|
|
161
|
-
monitor_info.each do |name,
|
162
|
-
|
163
|
-
if
|
164
|
-
metric.
|
165
|
-
|
166
|
-
|
169
|
+
monitor_info.each do |name, metrics|
|
170
|
+
metrics.each do |metric|
|
171
|
+
if info[name]
|
172
|
+
if metric.is_a?(::Prometheus::Client::Gauge)
|
173
|
+
metric.set(info[name], labels: label)
|
174
|
+
elsif metric.is_a?(::Prometheus::Client::Counter)
|
175
|
+
metric.increment(by: info[name] - metric.get(labels: label), labels: label)
|
176
|
+
end
|
167
177
|
end
|
168
178
|
end
|
169
179
|
end
|
@@ -172,9 +182,9 @@ module Fluent::Plugin
|
|
172
182
|
instance_vars_info.each do |name, metric|
|
173
183
|
if info['instance_variables'][name]
|
174
184
|
if metric.is_a?(::Prometheus::Client::Gauge)
|
175
|
-
metric.set(
|
185
|
+
metric.set(info['instance_variables'][name], labels: label)
|
176
186
|
elsif metric.is_a?(::Prometheus::Client::Counter)
|
177
|
-
metric.increment(
|
187
|
+
metric.increment(by: info['instance_variables'][name] - metric.get(labels: label), labels: label)
|
178
188
|
end
|
179
189
|
end
|
180
190
|
end
|
@@ -193,7 +203,7 @@ module Fluent::Plugin
|
|
193
203
|
if next_time && start_time
|
194
204
|
wait = next_time - start_time
|
195
205
|
end
|
196
|
-
@metrics[:retry_wait].set(
|
206
|
+
@metrics[:retry_wait].set(wait.to_f, labels: label)
|
197
207
|
end
|
198
208
|
end
|
199
209
|
end
|
@@ -209,7 +219,7 @@ module Fluent::Plugin
|
|
209
219
|
if @registry.exist?(name)
|
210
220
|
@registry.get(name)
|
211
221
|
else
|
212
|
-
@registry.gauge(name, docstring)
|
222
|
+
@registry.gauge(name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :type])
|
213
223
|
end
|
214
224
|
end
|
215
225
|
|
@@ -217,7 +227,7 @@ module Fluent::Plugin
|
|
217
227
|
if @registry.exist?(name)
|
218
228
|
@registry.get(name)
|
219
229
|
else
|
220
|
-
@registry.public_send(@gauge_or_counter, name, docstring)
|
230
|
+
@registry.public_send(@gauge_or_counter, name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :type])
|
221
231
|
end
|
222
232
|
end
|
223
233
|
end
|
@@ -51,6 +51,15 @@ module Fluent::Plugin
|
|
51
51
|
inode: get_gauge(
|
52
52
|
:fluentd_tail_file_inode,
|
53
53
|
'Current inode of file.'),
|
54
|
+
closed_file_metrics: get_gauge(
|
55
|
+
:fluentd_tail_file_closed,
|
56
|
+
'Number of files closed.'),
|
57
|
+
opened_file_metrics: get_gauge(
|
58
|
+
:fluentd_tail_file_opened,
|
59
|
+
'Number of files opened.'),
|
60
|
+
rotated_file_metrics: get_gauge(
|
61
|
+
:fluentd_tail_file_rotated,
|
62
|
+
'Number of files rotated.'),
|
54
63
|
}
|
55
64
|
timer_execute(:in_prometheus_tail_monitor, @interval, &method(:update_monitor_info))
|
56
65
|
end
|
@@ -72,9 +81,15 @@ module Fluent::Plugin
|
|
72
81
|
# Access to internal variable of internal class...
|
73
82
|
# Very fragile implementation
|
74
83
|
pe = watcher.instance_variable_get(:@pe)
|
84
|
+
monitor_info = watcher.instance_variable_get(:@metrics)
|
75
85
|
label = labels(info, watcher.path)
|
76
|
-
@metrics[:inode].set(
|
77
|
-
@metrics[:position].set(
|
86
|
+
@metrics[:inode].set(pe.read_inode, labels: label)
|
87
|
+
@metrics[:position].set(pe.read_pos, labels: label)
|
88
|
+
unless monitor_info.nil?
|
89
|
+
@metrics[:closed_file_metrics].set(monitor_info.closed.get, labels: label)
|
90
|
+
@metrics[:opened_file_metrics].set(monitor_info.opened.get, labels: label)
|
91
|
+
@metrics[:rotated_file_metrics].set(monitor_info.rotated.get, labels: label)
|
92
|
+
end
|
78
93
|
end
|
79
94
|
end
|
80
95
|
end
|
@@ -91,7 +106,7 @@ module Fluent::Plugin
|
|
91
106
|
if @registry.exist?(name)
|
92
107
|
@registry.get(name)
|
93
108
|
else
|
94
|
-
@registry.gauge(name, docstring)
|
109
|
+
@registry.gauge(name, docstring: docstring, labels: @base_labels.keys + [:plugin_id, :type, :path])
|
95
110
|
end
|
96
111
|
end
|
97
112
|
end
|
@@ -56,6 +56,69 @@ module Fluent
|
|
56
56
|
base_labels
|
57
57
|
end
|
58
58
|
|
59
|
+
def self.parse_initlabels_elements(conf, base_labels)
|
60
|
+
base_initlabels = []
|
61
|
+
|
62
|
+
# We first treat the special case of RecordAccessors and Placeholders labels if any declared
|
63
|
+
conf.elements.select { |e| e.name == 'initlabels' }.each { |block|
|
64
|
+
initlabels = {}
|
65
|
+
|
66
|
+
block.each do |key, value|
|
67
|
+
if not base_labels.has_key? key.to_sym
|
68
|
+
raise ConfigError, "Key #{key} in <initlabels> is non existent in <labels> for metric #{conf['name']}"
|
69
|
+
end
|
70
|
+
|
71
|
+
if value.start_with?('$.') || value.start_with?('$[') || value.start_with?('${')
|
72
|
+
raise ConfigError, "Cannot use RecordAccessor or placeholder #{value} (key #{key}) in a <initlabels> in metric #{conf['name']}"
|
73
|
+
end
|
74
|
+
|
75
|
+
base_label_value = base_labels[key.to_sym]
|
76
|
+
|
77
|
+
if !(base_label_value.class == Fluent::PluginHelper::RecordAccessor::Accessor) && ! (base_label_value.start_with?('${') )
|
78
|
+
raise ConfigError, "Cannot set <initlabels> on non RecordAccessor/Placeholder key #{key} (value #{value}) in metric #{conf['name']}"
|
79
|
+
end
|
80
|
+
|
81
|
+
if base_label_value == '${worker_id}' || base_label_value == '${hostname}'
|
82
|
+
raise ConfigError, "Cannot set <initlabels> on reserved placeholder #{base_label_value} for key #{key} in metric #{conf['name']}"
|
83
|
+
end
|
84
|
+
|
85
|
+
initlabels[key.to_sym] = value
|
86
|
+
end
|
87
|
+
|
88
|
+
# Now adding all labels that are not RecordAccessor nor Placeholder labels as is
|
89
|
+
base_labels.each do |key, value|
|
90
|
+
if base_labels[key.to_sym].class != Fluent::PluginHelper::RecordAccessor::Accessor
|
91
|
+
if value == '${worker_id}'
|
92
|
+
# We retrieve fluentd_worker_id this way to not overcomplicate the code
|
93
|
+
initlabels[key.to_sym] = (ENV['SERVERENGINE_WORKER_ID'] || 0).to_i
|
94
|
+
elsif value == '${hostname}'
|
95
|
+
initlabels[key.to_sym] = Socket.gethostname
|
96
|
+
elsif !(value.start_with?('${'))
|
97
|
+
initlabels[key.to_sym] = value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
base_initlabels << initlabels
|
103
|
+
}
|
104
|
+
|
105
|
+
# Testing for RecordAccessor/Placeholder labels missing a declaration in <initlabels> blocks
|
106
|
+
base_labels.each do |key, value|
|
107
|
+
if value.class == Fluent::PluginHelper::RecordAccessor::Accessor || value.start_with?('${')
|
108
|
+
if not base_initlabels.map(&:keys).flatten.include? (key.to_sym)
|
109
|
+
raise ConfigError, "RecordAccessor/Placeholder key #{key} with value #{value} has not been set in a <initlabels> for initialized metric #{conf['name']}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
if base_initlabels.length == 0
|
115
|
+
# There were no RecordAccessor nor Placeholder labels, we blunty retrieve the static base_labels
|
116
|
+
base_initlabels << base_labels
|
117
|
+
end
|
118
|
+
|
119
|
+
base_initlabels
|
120
|
+
end
|
121
|
+
|
59
122
|
def self.parse_metrics_elements(conf, registry, labels = {})
|
60
123
|
metrics = []
|
61
124
|
conf.elements.select { |element|
|
@@ -85,6 +148,18 @@ module Fluent
|
|
85
148
|
Fluent::Plugin::Prometheus::ExpandBuilder.new(log: log)
|
86
149
|
end
|
87
150
|
|
151
|
+
def stringify_keys(hash_to_stringify)
|
152
|
+
# Adapted from: https://www.jvt.me/posts/2019/09/07/ruby-hash-keys-string-symbol/
|
153
|
+
hash_to_stringify.map do |k,v|
|
154
|
+
value_or_hash = if v.instance_of? Hash
|
155
|
+
stringify_keys(v)
|
156
|
+
else
|
157
|
+
v
|
158
|
+
end
|
159
|
+
[k.to_s, value_or_hash]
|
160
|
+
end.to_h
|
161
|
+
end
|
162
|
+
|
88
163
|
def configure(conf)
|
89
164
|
super
|
90
165
|
@placeholder_values = {}
|
@@ -99,6 +174,7 @@ module Fluent
|
|
99
174
|
'worker_id' => fluentd_worker_id,
|
100
175
|
}
|
101
176
|
|
177
|
+
record = stringify_keys(record)
|
102
178
|
placeholders = record.merge(@placeholder_values[tag])
|
103
179
|
expander = @placeholder_expander_builder.build(placeholders)
|
104
180
|
metrics.each do |metric|
|
@@ -119,6 +195,7 @@ module Fluent
|
|
119
195
|
}
|
120
196
|
|
121
197
|
es.each do |time, record|
|
198
|
+
record = stringify_keys(record)
|
122
199
|
placeholders = record.merge(placeholder_values)
|
123
200
|
expander = @placeholder_expander_builder.build(placeholders)
|
124
201
|
metrics.each do |metric|
|
@@ -148,9 +225,27 @@ module Fluent
|
|
148
225
|
@name = element['name']
|
149
226
|
@key = element['key']
|
150
227
|
@desc = element['desc']
|
151
|
-
|
228
|
+
element['initialized'].nil? ? @initialized = false : @initialized = element['initialized'] == 'true'
|
229
|
+
|
152
230
|
@base_labels = Fluent::Plugin::Prometheus.parse_labels_elements(element)
|
153
231
|
@base_labels = labels.merge(@base_labels)
|
232
|
+
|
233
|
+
if @initialized
|
234
|
+
@base_initlabels = Fluent::Plugin::Prometheus.parse_initlabels_elements(element, @base_labels)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.init_label_set(metric, base_initlabels, base_labels)
|
239
|
+
base_initlabels.each { |initlabels|
|
240
|
+
# Should never happen, but handy test should code evolution break current implementation
|
241
|
+
if initlabels.keys.sort != base_labels.keys.sort
|
242
|
+
raise ConfigError, "initlabels for metric #{metric.name} must have the same signature than labels " \
|
243
|
+
"(initlabels given: #{initlabels.keys} vs." \
|
244
|
+
" expected from labels: #{base_labels.keys})"
|
245
|
+
end
|
246
|
+
|
247
|
+
metric.init_label_set(initlabels)
|
248
|
+
}
|
154
249
|
end
|
155
250
|
|
156
251
|
def labels(record, expander)
|
@@ -188,10 +283,14 @@ module Fluent
|
|
188
283
|
end
|
189
284
|
|
190
285
|
begin
|
191
|
-
@gauge = registry.gauge(element['name'].to_sym, element['desc'])
|
286
|
+
@gauge = registry.gauge(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
|
192
287
|
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
193
288
|
@gauge = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :gauge, element['desc'])
|
194
289
|
end
|
290
|
+
|
291
|
+
if @initialized
|
292
|
+
Fluent::Plugin::Prometheus::Metric.init_label_set(@gauge, @base_initlabels, @base_labels)
|
293
|
+
end
|
195
294
|
end
|
196
295
|
|
197
296
|
def instrument(record, expander)
|
@@ -201,7 +300,7 @@ module Fluent
|
|
201
300
|
value = @key.call(record)
|
202
301
|
end
|
203
302
|
if value
|
204
|
-
@gauge.set(labels(record, expander)
|
303
|
+
@gauge.set(value, labels: labels(record, expander))
|
205
304
|
end
|
206
305
|
end
|
207
306
|
end
|
@@ -210,10 +309,14 @@ module Fluent
|
|
210
309
|
def initialize(element, registry, labels)
|
211
310
|
super
|
212
311
|
begin
|
213
|
-
@counter = registry.counter(element['name'].to_sym, element['desc'])
|
312
|
+
@counter = registry.counter(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
|
214
313
|
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
215
314
|
@counter = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :counter, element['desc'])
|
216
315
|
end
|
316
|
+
|
317
|
+
if @initialized
|
318
|
+
Fluent::Plugin::Prometheus::Metric.init_label_set(@counter, @base_initlabels, @base_labels)
|
319
|
+
end
|
217
320
|
end
|
218
321
|
|
219
322
|
def instrument(record, expander)
|
@@ -229,7 +332,7 @@ module Fluent
|
|
229
332
|
# ignore if record value is nil
|
230
333
|
return if value.nil?
|
231
334
|
|
232
|
-
@counter.increment(labels(record, expander)
|
335
|
+
@counter.increment(by: value, labels: labels(record, expander))
|
233
336
|
end
|
234
337
|
end
|
235
338
|
|
@@ -241,10 +344,14 @@ module Fluent
|
|
241
344
|
end
|
242
345
|
|
243
346
|
begin
|
244
|
-
@summary = registry.summary(element['name'].to_sym, element['desc'])
|
347
|
+
@summary = registry.summary(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
|
245
348
|
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
246
349
|
@summary = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :summary, element['desc'])
|
247
350
|
end
|
351
|
+
|
352
|
+
if @initialized
|
353
|
+
Fluent::Plugin::Prometheus::Metric.init_label_set(@summary, @base_initlabels, @base_labels)
|
354
|
+
end
|
248
355
|
end
|
249
356
|
|
250
357
|
def instrument(record, expander)
|
@@ -254,7 +361,7 @@ module Fluent
|
|
254
361
|
value = @key.call(record)
|
255
362
|
end
|
256
363
|
if value
|
257
|
-
@summary.observe(labels(record, expander)
|
364
|
+
@summary.observe(value, labels: labels(record, expander))
|
258
365
|
end
|
259
366
|
end
|
260
367
|
end
|
@@ -271,13 +378,17 @@ module Fluent
|
|
271
378
|
buckets = element['buckets'].split(/,/).map(&:strip).map do |e|
|
272
379
|
e[/\A\d+.\d+\Z/] ? e.to_f : e.to_i
|
273
380
|
end
|
274
|
-
@histogram = registry.histogram(element['name'].to_sym, element['desc'],
|
381
|
+
@histogram = registry.histogram(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys, buckets: buckets)
|
275
382
|
else
|
276
|
-
@histogram = registry.histogram(element['name'].to_sym, element['desc'])
|
383
|
+
@histogram = registry.histogram(element['name'].to_sym, docstring: element['desc'], labels: @base_labels.keys)
|
277
384
|
end
|
278
385
|
rescue ::Prometheus::Client::Registry::AlreadyRegisteredError
|
279
386
|
@histogram = Fluent::Plugin::Prometheus::Metric.get(registry, element['name'].to_sym, :histogram, element['desc'])
|
280
387
|
end
|
388
|
+
|
389
|
+
if @initialized
|
390
|
+
Fluent::Plugin::Prometheus::Metric.init_label_set(@histogram, @base_initlabels, @base_labels)
|
391
|
+
end
|
281
392
|
end
|
282
393
|
|
283
394
|
def instrument(record, expander)
|
@@ -287,7 +398,7 @@ module Fluent
|
|
287
398
|
value = @key.call(record)
|
288
399
|
end
|
289
400
|
if value
|
290
|
-
@histogram.observe(labels(record, expander)
|
401
|
+
@histogram.observe(value, labels: labels(record, expander))
|
291
402
|
end
|
292
403
|
end
|
293
404
|
end
|
@@ -202,7 +202,7 @@ describe Fluent::Plugin::PrometheusInput do
|
|
202
202
|
describe '#run_multi_workers' do
|
203
203
|
context '/metrics' do
|
204
204
|
Fluent::SystemConfig.overwrite_system_config('workers' => 4) do
|
205
|
-
let(:config) {
|
205
|
+
let(:config) { FULL_CONFIG + %[
|
206
206
|
port #{port - 2}
|
207
207
|
] }
|
208
208
|
|
@@ -16,6 +16,10 @@ describe Fluent::Plugin::PrometheusOutput do
|
|
16
16
|
it_behaves_like 'output configuration'
|
17
17
|
end
|
18
18
|
|
19
|
+
describe '#testinitlabels' do
|
20
|
+
it_behaves_like 'initalized metrics'
|
21
|
+
end
|
22
|
+
|
19
23
|
describe '#run' do
|
20
24
|
let(:message) { {"foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10} }
|
21
25
|
|
@@ -40,4 +44,29 @@ describe Fluent::Plugin::PrometheusOutput do
|
|
40
44
|
|
41
45
|
it_behaves_like 'instruments record'
|
42
46
|
end
|
47
|
+
|
48
|
+
describe '#run with symbolized keys' do
|
49
|
+
let(:message) { {:foo => 100, :bar => 100, :baz => 100, :qux => 10} }
|
50
|
+
|
51
|
+
context 'simple config' do
|
52
|
+
let(:config) {
|
53
|
+
BASE_CONFIG + %(
|
54
|
+
<metric>
|
55
|
+
name simple
|
56
|
+
type counter
|
57
|
+
desc Something foo.
|
58
|
+
key foo
|
59
|
+
</metric>
|
60
|
+
)
|
61
|
+
}
|
62
|
+
|
63
|
+
it 'adds a new counter metric' do
|
64
|
+
expect(registry.metrics.map(&:name)).not_to eq([:simple])
|
65
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
66
|
+
expect(registry.metrics.map(&:name)).to eq([:simple])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it_behaves_like 'instruments record'
|
71
|
+
end
|
43
72
|
end
|
@@ -27,6 +27,7 @@ FULL_CONFIG = BASE_CONFIG + %[
|
|
27
27
|
type gauge
|
28
28
|
desc Something bar.
|
29
29
|
key bar
|
30
|
+
initialized true
|
30
31
|
<labels>
|
31
32
|
key foo2
|
32
33
|
</labels>
|
@@ -36,6 +37,7 @@ FULL_CONFIG = BASE_CONFIG + %[
|
|
36
37
|
type summary
|
37
38
|
desc Something baz.
|
38
39
|
key baz
|
40
|
+
initialized true
|
39
41
|
<labels>
|
40
42
|
key foo3
|
41
43
|
</labels>
|
@@ -46,6 +48,7 @@ FULL_CONFIG = BASE_CONFIG + %[
|
|
46
48
|
desc Something qux.
|
47
49
|
key qux
|
48
50
|
buckets 0.1, 1, 5, 10
|
51
|
+
initialized true
|
49
52
|
<labels>
|
50
53
|
key foo4
|
51
54
|
</labels>
|
@@ -62,12 +65,32 @@ FULL_CONFIG = BASE_CONFIG + %[
|
|
62
65
|
<metric>
|
63
66
|
name full_accessor2
|
64
67
|
type counter
|
65
|
-
desc Something with accessor
|
68
|
+
desc Something with accessor
|
66
69
|
key $.foo
|
70
|
+
initialized true
|
67
71
|
<labels>
|
68
72
|
key foo6
|
69
73
|
</labels>
|
70
74
|
</metric>
|
75
|
+
<metric>
|
76
|
+
name full_accessor3
|
77
|
+
type counter
|
78
|
+
desc Something with accessor and several initialized metrics
|
79
|
+
initialized true
|
80
|
+
<labels>
|
81
|
+
key $.foo
|
82
|
+
key2 $.foo2
|
83
|
+
key3 footix
|
84
|
+
</labels>
|
85
|
+
<initlabels>
|
86
|
+
key foo6
|
87
|
+
key2 foo7
|
88
|
+
</initlabels>
|
89
|
+
<initlabels>
|
90
|
+
key foo8
|
91
|
+
key2 foo9
|
92
|
+
</initlabels>
|
93
|
+
</metric>
|
71
94
|
<labels>
|
72
95
|
test_key test_value
|
73
96
|
</labels>
|
@@ -79,13 +102,20 @@ PLACEHOLDER_CONFIG = BASE_CONFIG + %[
|
|
79
102
|
type counter
|
80
103
|
desc Something foo.
|
81
104
|
key foo
|
105
|
+
initialized true
|
82
106
|
<labels>
|
83
107
|
foo ${foo}
|
108
|
+
foo2 foo2
|
84
109
|
</labels>
|
110
|
+
<initlabels>
|
111
|
+
tag tag
|
112
|
+
foo foo
|
113
|
+
</initlabels>
|
85
114
|
</metric>
|
86
115
|
<labels>
|
87
116
|
tag ${tag}
|
88
117
|
hostname ${hostname}
|
118
|
+
workerid ${worker_id}
|
89
119
|
</labels>
|
90
120
|
]
|
91
121
|
|
@@ -150,6 +180,111 @@ shared_examples_for 'output configuration' do
|
|
150
180
|
end
|
151
181
|
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
152
182
|
end
|
183
|
+
|
184
|
+
|
185
|
+
context 'with missing <initlabels>' do
|
186
|
+
let(:config) do
|
187
|
+
BASE_CONFIG + %[
|
188
|
+
<metric>
|
189
|
+
name simple_foo
|
190
|
+
type counter
|
191
|
+
desc Something foo but incorrect
|
192
|
+
key foo
|
193
|
+
initialized true
|
194
|
+
<labels>
|
195
|
+
key $.accessor
|
196
|
+
</labels>
|
197
|
+
</metric>
|
198
|
+
]
|
199
|
+
end
|
200
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
201
|
+
end
|
202
|
+
|
203
|
+
context 'with RecordAccessor set in <initlabels>' do
|
204
|
+
let(:config) do
|
205
|
+
BASE_CONFIG + %[
|
206
|
+
<metric>
|
207
|
+
name simple_foo
|
208
|
+
type counter
|
209
|
+
desc Something foo but incorrect
|
210
|
+
key foo
|
211
|
+
initialized true
|
212
|
+
<labels>
|
213
|
+
key $.accessor
|
214
|
+
</labels>
|
215
|
+
<initlabels>
|
216
|
+
key $.accessor2
|
217
|
+
<initlabels>
|
218
|
+
</metric>
|
219
|
+
]
|
220
|
+
end
|
221
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'with PlaceHolder set in <initlabels>' do
|
225
|
+
let(:config) do
|
226
|
+
BASE_CONFIG + %[
|
227
|
+
<metric>
|
228
|
+
name simple_foo
|
229
|
+
type counter
|
230
|
+
desc Something foo but incorrect
|
231
|
+
key foo
|
232
|
+
initialized true
|
233
|
+
<labels>
|
234
|
+
key ${foo}
|
235
|
+
</labels>
|
236
|
+
<initlabels>
|
237
|
+
key ${foo}
|
238
|
+
<initlabels>
|
239
|
+
</metric>
|
240
|
+
]
|
241
|
+
end
|
242
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'with non RecordAccessor label set in <initlabels>' do
|
246
|
+
let(:config) do
|
247
|
+
BASE_CONFIG + %[
|
248
|
+
<metric>
|
249
|
+
name simple_foo
|
250
|
+
type counter
|
251
|
+
desc Something foo but incorrect
|
252
|
+
key foo
|
253
|
+
initialized true
|
254
|
+
<labels>
|
255
|
+
key $.accessor
|
256
|
+
key2 foo2
|
257
|
+
</labels>
|
258
|
+
<initlabels>
|
259
|
+
key foo
|
260
|
+
key2 foo2
|
261
|
+
<initlabels>
|
262
|
+
</metric>
|
263
|
+
]
|
264
|
+
end
|
265
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
266
|
+
end
|
267
|
+
|
268
|
+
context 'with non-matching label keys set in <initlabels>' do
|
269
|
+
let(:config) do
|
270
|
+
BASE_CONFIG + %[
|
271
|
+
<metric>
|
272
|
+
name simple_foo
|
273
|
+
type counter
|
274
|
+
desc Something foo but incorrect
|
275
|
+
key foo
|
276
|
+
initialized true
|
277
|
+
<labels>
|
278
|
+
key $.accessor
|
279
|
+
</labels>
|
280
|
+
<initlabels>
|
281
|
+
key2 foo
|
282
|
+
<initlabels>
|
283
|
+
</metric>
|
284
|
+
]
|
285
|
+
end
|
286
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
287
|
+
end
|
153
288
|
end
|
154
289
|
|
155
290
|
shared_examples_for 'instruments record' do
|
@@ -165,33 +300,35 @@ shared_examples_for 'instruments record' do
|
|
165
300
|
let(:histogram) { registry.get(:full_qux) }
|
166
301
|
let(:summary_with_accessor) { registry.get(:full_accessor1) }
|
167
302
|
let(:counter_with_accessor) { registry.get(:full_accessor2) }
|
303
|
+
let(:counter_with_two_accessors) { registry.get(:full_accessor3) }
|
168
304
|
|
169
305
|
it 'adds all metrics' do
|
170
|
-
expect(registry.metrics.map(&:name)).to eq(%i[full_foo full_bar full_baz full_qux full_accessor1 full_accessor2])
|
306
|
+
expect(registry.metrics.map(&:name)).to eq(%i[full_foo full_bar full_baz full_qux full_accessor1 full_accessor2 full_accessor3])
|
171
307
|
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
172
308
|
expect(gauge).to be_kind_of(::Prometheus::Client::Metric)
|
173
309
|
expect(summary).to be_kind_of(::Prometheus::Client::Metric)
|
174
310
|
expect(summary_with_accessor).to be_kind_of(::Prometheus::Client::Metric)
|
175
311
|
expect(counter_with_accessor).to be_kind_of(::Prometheus::Client::Metric)
|
312
|
+
expect(counter_with_two_accessors).to be_kind_of(::Prometheus::Client::Metric)
|
176
313
|
expect(histogram).to be_kind_of(::Prometheus::Client::Metric)
|
177
314
|
end
|
178
315
|
|
179
316
|
it 'instruments counter metric' do
|
180
317
|
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)
|
318
|
+
expect(counter.get(labels: {test_key: 'test_value', key: 'foo1'})).to be_kind_of(Numeric)
|
319
|
+
expect(counter_with_accessor.get(labels: {test_key: 'test_value', key: 'foo6'})).to be_kind_of(Numeric)
|
320
|
+
expect(counter_with_two_accessors.get(labels: {test_key: 'test_value', key: 'foo6', key2: 'foo7', key3: 'footix'})).to be_kind_of(Numeric)
|
183
321
|
end
|
184
322
|
|
185
323
|
it 'instruments gauge metric' do
|
186
324
|
expect(gauge.type).to eq(:gauge)
|
187
|
-
expect(gauge.get({test_key: 'test_value', key: 'foo2'})).to eq(100)
|
325
|
+
expect(gauge.get(labels: {test_key: 'test_value', key: 'foo2'})).to eq(100)
|
188
326
|
end
|
189
327
|
|
190
328
|
it 'instruments summary metric' do
|
191
329
|
expect(summary.type).to eq(:summary)
|
192
|
-
expect(summary.get({test_key: 'test_value', key: 'foo3'})).to be_kind_of(Hash)
|
193
|
-
expect(
|
194
|
-
expect(summary_with_accessor.get({test_key: 'test_value', key: 'foo5'})[0.99]).to eq(100)
|
330
|
+
expect(summary.get(labels: {test_key: 'test_value', key: 'foo3'})).to be_kind_of(Hash)
|
331
|
+
expect(summary_with_accessor.get(labels: {test_key: 'test_value', key: 'foo5'})["sum"]).to eq(100)
|
195
332
|
end
|
196
333
|
|
197
334
|
it 'instruments histogram metric' do
|
@@ -200,8 +337,8 @@ shared_examples_for 'instruments record' do
|
|
200
337
|
end
|
201
338
|
|
202
339
|
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
|
340
|
+
expect(histogram.get(labels: {test_key: 'test_value', key: 'foo4'})).to be_kind_of(Hash)
|
341
|
+
expect(histogram.get(labels: {test_key: 'test_value', key: 'foo4'})["10"]).to eq(5) # 4 + `es` in before
|
205
342
|
end
|
206
343
|
end
|
207
344
|
|
@@ -231,7 +368,7 @@ shared_examples_for 'instruments record' do
|
|
231
368
|
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
232
369
|
key, _ = counter.values.find {|k,v| v == 100 }
|
233
370
|
expect(key).to be_kind_of(Hash)
|
234
|
-
expect(key[:foo]).to eq(100)
|
371
|
+
expect(key[:foo]).to eq("100")
|
235
372
|
end
|
236
373
|
end
|
237
374
|
|
@@ -247,3 +384,66 @@ shared_examples_for 'instruments record' do
|
|
247
384
|
end
|
248
385
|
end
|
249
386
|
end
|
387
|
+
|
388
|
+
shared_examples_for 'initalized metrics' do
|
389
|
+
before do
|
390
|
+
driver.run(default_tag: tag)
|
391
|
+
end
|
392
|
+
|
393
|
+
context 'full config' do
|
394
|
+
let(:config) { FULL_CONFIG }
|
395
|
+
let(:counter) { registry.get(:full_foo) }
|
396
|
+
let(:gauge) { registry.get(:full_bar) }
|
397
|
+
let(:summary) { registry.get(:full_baz) }
|
398
|
+
let(:histogram) { registry.get(:full_qux) }
|
399
|
+
let(:summary_with_accessor) { registry.get(:full_accessor1) }
|
400
|
+
let(:counter_with_accessor) { registry.get(:full_accessor2) }
|
401
|
+
let(:counter_with_two_accessors) { registry.get(:full_accessor3) }
|
402
|
+
|
403
|
+
it 'adds all metrics' do
|
404
|
+
expect(registry.metrics.map(&:name)).to eq(%i[full_foo full_bar full_baz full_qux full_accessor1 full_accessor2 full_accessor3])
|
405
|
+
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
406
|
+
expect(gauge).to be_kind_of(::Prometheus::Client::Metric)
|
407
|
+
expect(summary).to be_kind_of(::Prometheus::Client::Metric)
|
408
|
+
expect(summary_with_accessor).to be_kind_of(::Prometheus::Client::Metric)
|
409
|
+
expect(counter_with_accessor).to be_kind_of(::Prometheus::Client::Metric)
|
410
|
+
expect(counter_with_two_accessors).to be_kind_of(::Prometheus::Client::Metric)
|
411
|
+
expect(histogram).to be_kind_of(::Prometheus::Client::Metric)
|
412
|
+
end
|
413
|
+
|
414
|
+
it 'tests uninitialized metrics' do
|
415
|
+
expect(counter.values).to eq({})
|
416
|
+
expect(summary_with_accessor.values).to eq({})
|
417
|
+
end
|
418
|
+
|
419
|
+
it 'tests initialized metrics' do
|
420
|
+
expect(gauge.values).to eq({{:key=>"foo2", :test_key=>"test_value"}=>0.0})
|
421
|
+
expect(summary.values).to eq({:key=>"foo3", :test_key=>"test_value"}=>{"count"=>0.0, "sum"=>0.0})
|
422
|
+
expect(histogram.values).to eq({:key=>"foo4", :test_key=>"test_value"} => {"+Inf"=>0.0, "0.1"=>0.0, "1"=>0.0, "10"=>0.0, "5"=>0.0, "sum"=>0.0})
|
423
|
+
expect(counter_with_accessor.values).to eq({{:key=>"foo6", :test_key=>"test_value"}=>0.0})
|
424
|
+
expect(counter_with_two_accessors.values).to eq({{:key=>"foo6", :key2=>"foo7", :key3=>"footix", :test_key=>"test_value"}=>0.0, {:key=>"foo8", :key2=>"foo9", :key3=>"footix", :test_key=>"test_value"}=>0.0})
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
context 'placeholder config' do
|
429
|
+
let(:config) { PLACEHOLDER_CONFIG }
|
430
|
+
let(:counter) { registry.get(:placeholder_foo) }
|
431
|
+
|
432
|
+
it 'expands placeholders with record values' do
|
433
|
+
expect(registry.metrics.map(&:name)).to eq([:placeholder_foo])
|
434
|
+
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
435
|
+
|
436
|
+
key, _ = counter.values.find {|k,v| v == 0.0 }
|
437
|
+
expect(key).to be_kind_of(Hash)
|
438
|
+
expect(key[:foo]).to eq("foo")
|
439
|
+
expect(key[:foo2]).to eq("foo2")
|
440
|
+
expect(key[:hostname]).to be_kind_of(String)
|
441
|
+
expect(key[:hostname]).not_to eq("${hostname}")
|
442
|
+
expect(key[:hostname]).not_to be_empty
|
443
|
+
expect(key[:workerid]).to be_kind_of(String)
|
444
|
+
expect(key[:workerid]).not_to eq("${worker_id}")
|
445
|
+
expect(key[:workerid]).not_to be_empty
|
446
|
+
expect(key[:tag]).to eq("tag")
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
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.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro Sano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-15 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:
|
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:
|
46
|
+
version: 2.1.0
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -107,9 +107,10 @@ executables: []
|
|
107
107
|
extensions: []
|
108
108
|
extra_rdoc_files: []
|
109
109
|
files:
|
110
|
+
- ".github/dependabot.yml"
|
111
|
+
- ".github/workflows/linux.yml"
|
110
112
|
- ".gitignore"
|
111
113
|
- ".rspec"
|
112
|
-
- ".travis.yml"
|
113
114
|
- ChangeLog
|
114
115
|
- Gemfile
|
115
116
|
- LICENSE
|
@@ -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.
|
162
|
+
rubygems_version: 3.3.7
|
162
163
|
signing_key:
|
163
164
|
specification_version: 4
|
164
165
|
summary: A fluent plugin that collects metrics and exposes for Prometheus.
|