fluent-plugin-prometheus 1.8.5 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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.
|