fluent-plugin-prometheus-test 1.7.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 +7 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/LICENSE +202 -0
- data/README.md +484 -0
- data/Rakefile +7 -0
- data/fluent-plugin-prometheus.gemspec +22 -0
- data/lib/fluent/plugin/filter_prometheus.rb +30 -0
- data/lib/fluent/plugin/in_prometheus.rb +222 -0
- data/lib/fluent/plugin/in_prometheus_monitor.rb +99 -0
- data/lib/fluent/plugin/in_prometheus_output_monitor.rb +202 -0
- data/lib/fluent/plugin/in_prometheus_tail_monitor.rb +95 -0
- data/lib/fluent/plugin/out_prometheus.rb +29 -0
- data/lib/fluent/plugin/prometheus.rb +296 -0
- data/lib/fluent/plugin/prometheus/placeholder_expander.rb +132 -0
- data/lib/fluent/plugin/prometheus_metrics.rb +77 -0
- data/misc/fluentd_sample.conf +170 -0
- data/misc/nginx_proxy.conf +22 -0
- data/misc/prometheus.yaml +13 -0
- data/misc/prometheus_alerts.yaml +59 -0
- data/spec/fluent/plugin/filter_prometheus_spec.rb +48 -0
- data/spec/fluent/plugin/in_prometheus_monitor_spec.rb +42 -0
- data/spec/fluent/plugin/in_prometheus_spec.rb +225 -0
- data/spec/fluent/plugin/in_prometheus_tail_monitor_spec.rb +42 -0
- data/spec/fluent/plugin/out_prometheus_spec.rb +43 -0
- data/spec/fluent/plugin/prometheus/placeholder_expander_spec.rb +110 -0
- data/spec/fluent/plugin/prometheus_metrics_spec.rb +138 -0
- data/spec/fluent/plugin/shared.rb +249 -0
- data/spec/spec_helper.rb +10 -0
- metadata +173 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fluent/plugin/in_prometheus_tail_monitor'
|
3
|
+
require 'fluent/test/driver/input'
|
4
|
+
|
5
|
+
describe Fluent::Plugin::PrometheusTailMonitorInput do
|
6
|
+
MONITOR_CONFIG = %[
|
7
|
+
@type prometheus_tail_monitor
|
8
|
+
<labels>
|
9
|
+
host ${hostname}
|
10
|
+
foo bar
|
11
|
+
</labels>
|
12
|
+
]
|
13
|
+
|
14
|
+
INVALID_MONITOR_CONFIG = %[
|
15
|
+
@type prometheus_tail_monitor
|
16
|
+
|
17
|
+
<labels>
|
18
|
+
host ${hostname}
|
19
|
+
foo bar
|
20
|
+
invalid_use1 $.foo.bar
|
21
|
+
invalid_use2 $[0][1]
|
22
|
+
</labels>
|
23
|
+
]
|
24
|
+
|
25
|
+
let(:config) { MONITOR_CONFIG }
|
26
|
+
let(:driver) { Fluent::Test::Driver::Input.new(Fluent::Plugin::PrometheusTailMonitorInput).configure(config) }
|
27
|
+
|
28
|
+
describe '#configure' do
|
29
|
+
describe 'valid' do
|
30
|
+
it 'does not raise error' do
|
31
|
+
expect { driver }.not_to raise_error
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'invalid' do
|
36
|
+
let(:config) { INVALID_MONITOR_CONFIG }
|
37
|
+
it 'expect raise error' do
|
38
|
+
expect { driver }.to raise_error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fluent/test/driver/output'
|
3
|
+
require 'fluent/plugin/out_prometheus'
|
4
|
+
require_relative 'shared'
|
5
|
+
|
6
|
+
describe Fluent::Plugin::PrometheusOutput do
|
7
|
+
let(:tag) { 'prometheus.test' }
|
8
|
+
let(:driver) { Fluent::Test::Driver::Output.new(Fluent::Plugin::PrometheusOutput).configure(config) }
|
9
|
+
let(:registry) { ::Prometheus::Client::Registry.new }
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(Prometheus::Client).to receive(:registry).and_return(registry)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#configure' do
|
16
|
+
it_behaves_like 'output configuration'
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#run' do
|
20
|
+
let(:message) { {"foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10} }
|
21
|
+
|
22
|
+
context 'simple config' do
|
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
|
+
}
|
33
|
+
|
34
|
+
it 'adds a new counter metric' do
|
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])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it_behaves_like 'instruments record'
|
42
|
+
end
|
43
|
+
end
|
@@ -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
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fluent/plugin/in_prometheus'
|
3
|
+
require 'fluent/test/driver/input'
|
4
|
+
|
5
|
+
require 'net/http'
|
6
|
+
|
7
|
+
describe Fluent::Plugin::PromMetricsAggregator do
|
8
|
+
|
9
|
+
metrics_worker_1 = %[# TYPE fluentd_status_buffer_queue_length gauge
|
10
|
+
# HELP fluentd_status_buffer_queue_length Current buffer queue length.
|
11
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="0",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
12
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="0",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
13
|
+
# TYPE fluentd_status_buffer_total_bytes gauge
|
14
|
+
# HELP fluentd_status_buffer_total_bytes Current total size of queued buffers.
|
15
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="0",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
16
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="0",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
17
|
+
# TYPE log_counter counter
|
18
|
+
# HELP log_counter the number of received logs
|
19
|
+
log_counter{worker_id="0",host="0123456789ab",tag="fluent.info"} 1.0
|
20
|
+
# HELP empty_metric A metric with no data
|
21
|
+
# TYPE empty_metric gauge
|
22
|
+
# HELP http_request_duration_seconds The HTTP request latencies in seconds.
|
23
|
+
# TYPE http_request_duration_seconds histogram
|
24
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.005"} 58
|
25
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.01"} 58
|
26
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.05"} 59
|
27
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.1"} 59
|
28
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="1"} 59
|
29
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="10"} 59
|
30
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="+Inf"} 59
|
31
|
+
http_request_duration_seconds_sum{code="200",worker_id="0",method="GET"} 0.05046115500000003
|
32
|
+
http_request_duration_seconds_count{code="200",worker_id="0",method="GET"} 59
|
33
|
+
]
|
34
|
+
|
35
|
+
metrics_worker_2 = %[# TYPE fluentd_output_status_buffer_queue_length gauge
|
36
|
+
# HELP fluentd_output_status_buffer_queue_length Current buffer queue length.
|
37
|
+
fluentd_output_status_buffer_queue_length{host="0123456789ab",worker_id="0",plugin_id="plugin-1",type="s3"} 0.0
|
38
|
+
fluentd_output_status_buffer_queue_length{host="0123456789ab",worker_id="0",plugin_id="plugin-2",type="s3"} 0.0
|
39
|
+
# TYPE fluentd_output_status_buffer_total_bytes gauge
|
40
|
+
# HELP fluentd_output_status_buffer_total_bytes Current total size of queued buffers.
|
41
|
+
fluentd_output_status_buffer_total_bytes{host="0123456789ab",worker_id="0",plugin_id="plugin-1",type="s3"} 0.0
|
42
|
+
fluentd_output_status_buffer_total_bytes{host="0123456789ab",worker_id="0",plugin_id="plugin-2",type="s3"} 0.0
|
43
|
+
]
|
44
|
+
|
45
|
+
metrics_worker_3 = %[# TYPE fluentd_status_buffer_queue_length gauge
|
46
|
+
# HELP fluentd_status_buffer_queue_length Current buffer queue length.
|
47
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="1",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
48
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="1",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
49
|
+
# TYPE fluentd_status_buffer_total_bytes gauge
|
50
|
+
# HELP fluentd_status_buffer_total_bytes Current total size of queued buffers.
|
51
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="1",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
52
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="1",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
53
|
+
# HELP http_request_duration_seconds The HTTP request latencies in seconds.
|
54
|
+
# TYPE http_request_duration_seconds histogram
|
55
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.005"} 70
|
56
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.01"} 70
|
57
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.05"} 71
|
58
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.1"} 71
|
59
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="1"} 71
|
60
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="10"} 71
|
61
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="+Inf"} 71
|
62
|
+
http_request_duration_seconds_sum{code="200",worker_id="1",method="GET"} 0.05646315600000003
|
63
|
+
http_request_duration_seconds_count{code="200",worker_id="1",method="GET"} 71
|
64
|
+
]
|
65
|
+
|
66
|
+
metrics_merged_1_and_3 = %[# TYPE fluentd_status_buffer_queue_length gauge
|
67
|
+
# HELP fluentd_status_buffer_queue_length Current buffer queue length.
|
68
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="0",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
69
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="0",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
70
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="1",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
71
|
+
fluentd_status_buffer_queue_length{host="0123456789ab",worker_id="1",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
72
|
+
# TYPE fluentd_status_buffer_total_bytes gauge
|
73
|
+
# HELP fluentd_status_buffer_total_bytes Current total size of queued buffers.
|
74
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="0",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
75
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="0",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
76
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="1",plugin_id="plugin-1",plugin_category="output",type="s3"} 0.0
|
77
|
+
fluentd_status_buffer_total_bytes{host="0123456789ab",worker_id="1",plugin_id="plugin-2",plugin_category="output",type="s3"} 0.0
|
78
|
+
# TYPE log_counter counter
|
79
|
+
# HELP log_counter the number of received logs
|
80
|
+
log_counter{worker_id="0",host="0123456789ab",tag="fluent.info"} 1.0
|
81
|
+
# HELP empty_metric A metric with no data
|
82
|
+
# TYPE empty_metric gauge
|
83
|
+
# HELP http_request_duration_seconds The HTTP request latencies in seconds.
|
84
|
+
# TYPE http_request_duration_seconds histogram
|
85
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.005"} 58
|
86
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.01"} 58
|
87
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.05"} 59
|
88
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="0.1"} 59
|
89
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="1"} 59
|
90
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="10"} 59
|
91
|
+
http_request_duration_seconds_bucket{code="200",worker_id="0",method="GET",le="+Inf"} 59
|
92
|
+
http_request_duration_seconds_sum{code="200",worker_id="0",method="GET"} 0.05046115500000003
|
93
|
+
http_request_duration_seconds_count{code="200",worker_id="0",method="GET"} 59
|
94
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.005"} 70
|
95
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.01"} 70
|
96
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.05"} 71
|
97
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="0.1"} 71
|
98
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="1"} 71
|
99
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="10"} 71
|
100
|
+
http_request_duration_seconds_bucket{code="200",worker_id="1",method="GET",le="+Inf"} 71
|
101
|
+
http_request_duration_seconds_sum{code="200",worker_id="1",method="GET"} 0.05646315600000003
|
102
|
+
http_request_duration_seconds_count{code="200",worker_id="1",method="GET"} 71
|
103
|
+
]
|
104
|
+
|
105
|
+
describe 'add_metrics' do
|
106
|
+
context '1st_metrics' do
|
107
|
+
it 'adds all fields' do
|
108
|
+
all_metrics = Fluent::Plugin::PromMetricsAggregator.new
|
109
|
+
all_metrics.add_metrics(metrics_worker_1)
|
110
|
+
result_str = all_metrics.get_metrics
|
111
|
+
|
112
|
+
expect(result_str).to eq(metrics_worker_1)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
context '2nd_metrics' do
|
116
|
+
it 'append new metrics' do
|
117
|
+
all_metrics = Fluent::Plugin::PromMetricsAggregator.new
|
118
|
+
all_metrics.add_metrics(metrics_worker_1)
|
119
|
+
all_metrics.add_metrics(metrics_worker_2)
|
120
|
+
result_str = all_metrics.get_metrics
|
121
|
+
|
122
|
+
expect(result_str).to eq(metrics_worker_1 + metrics_worker_2)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context '3rd_metrics' do
|
127
|
+
it 'append existing metrics in the right place' do
|
128
|
+
all_metrics = Fluent::Plugin::PromMetricsAggregator.new
|
129
|
+
all_metrics.add_metrics(metrics_worker_1)
|
130
|
+
all_metrics.add_metrics(metrics_worker_2)
|
131
|
+
all_metrics.add_metrics(metrics_worker_3)
|
132
|
+
result_str = all_metrics.get_metrics
|
133
|
+
|
134
|
+
expect(result_str).to eq(metrics_merged_1_and_3 + metrics_worker_2)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
|
2
|
+
BASE_CONFIG = %[
|
3
|
+
@type prometheus
|
4
|
+
]
|
5
|
+
|
6
|
+
SIMPLE_CONFIG = BASE_CONFIG + %[
|
7
|
+
<metric>
|
8
|
+
name simple_foo
|
9
|
+
type counter
|
10
|
+
desc Something foo.
|
11
|
+
key foo
|
12
|
+
</metric>
|
13
|
+
]
|
14
|
+
|
15
|
+
FULL_CONFIG = BASE_CONFIG + %[
|
16
|
+
<metric>
|
17
|
+
name full_foo
|
18
|
+
type counter
|
19
|
+
desc Something foo.
|
20
|
+
key foo
|
21
|
+
<labels>
|
22
|
+
key foo1
|
23
|
+
</labels>
|
24
|
+
</metric>
|
25
|
+
<metric>
|
26
|
+
name full_bar
|
27
|
+
type gauge
|
28
|
+
desc Something bar.
|
29
|
+
key bar
|
30
|
+
<labels>
|
31
|
+
key foo2
|
32
|
+
</labels>
|
33
|
+
</metric>
|
34
|
+
<metric>
|
35
|
+
name full_baz
|
36
|
+
type summary
|
37
|
+
desc Something baz.
|
38
|
+
key baz
|
39
|
+
<labels>
|
40
|
+
key foo3
|
41
|
+
</labels>
|
42
|
+
</metric>
|
43
|
+
<metric>
|
44
|
+
name full_qux
|
45
|
+
type histogram
|
46
|
+
desc Something qux.
|
47
|
+
key qux
|
48
|
+
buckets 0.1, 1, 5, 10
|
49
|
+
<labels>
|
50
|
+
key foo4
|
51
|
+
</labels>
|
52
|
+
</metric>
|
53
|
+
<metric>
|
54
|
+
name full_accessor1
|
55
|
+
type summary
|
56
|
+
desc Something with accessor.
|
57
|
+
key $.foo
|
58
|
+
<labels>
|
59
|
+
key foo5
|
60
|
+
</labels>
|
61
|
+
</metric>
|
62
|
+
<metric>
|
63
|
+
name full_accessor2
|
64
|
+
type counter
|
65
|
+
desc Something with accessor.
|
66
|
+
key $.foo
|
67
|
+
<labels>
|
68
|
+
key foo6
|
69
|
+
</labels>
|
70
|
+
</metric>
|
71
|
+
<labels>
|
72
|
+
test_key test_value
|
73
|
+
</labels>
|
74
|
+
]
|
75
|
+
|
76
|
+
PLACEHOLDER_CONFIG = BASE_CONFIG + %[
|
77
|
+
<metric>
|
78
|
+
name placeholder_foo
|
79
|
+
type counter
|
80
|
+
desc Something foo.
|
81
|
+
key foo
|
82
|
+
<labels>
|
83
|
+
foo ${foo}
|
84
|
+
</labels>
|
85
|
+
</metric>
|
86
|
+
<labels>
|
87
|
+
tag ${tag}
|
88
|
+
hostname ${hostname}
|
89
|
+
</labels>
|
90
|
+
]
|
91
|
+
|
92
|
+
ACCESSOR_CONFIG = BASE_CONFIG + %[
|
93
|
+
<metric>
|
94
|
+
name accessor_foo
|
95
|
+
type counter
|
96
|
+
desc Something foo.
|
97
|
+
key foo
|
98
|
+
<labels>
|
99
|
+
foo $.foo
|
100
|
+
</labels>
|
101
|
+
</metric>
|
102
|
+
]
|
103
|
+
|
104
|
+
COUNTER_WITHOUT_KEY_CONFIG = BASE_CONFIG + %[
|
105
|
+
<metric>
|
106
|
+
name without_key_foo
|
107
|
+
type counter
|
108
|
+
desc Something foo.
|
109
|
+
</metric>
|
110
|
+
]
|
111
|
+
|
112
|
+
shared_examples_for 'output configuration' do
|
113
|
+
context 'base config' do
|
114
|
+
let(:config) { BASE_CONFIG }
|
115
|
+
it { expect { driver }.not_to raise_error }
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'with simple configuration' do
|
119
|
+
let(:config) { SIMPLE_CONFIG }
|
120
|
+
it { expect { driver }.not_to raise_error }
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'with full configuration' do
|
124
|
+
let(:config) { FULL_CONFIG }
|
125
|
+
it { expect { driver }.not_to raise_error }
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'with placeholder configuration' do
|
129
|
+
let(:config) { PLACEHOLDER_CONFIG }
|
130
|
+
it { expect { driver }.not_to raise_error }
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'with accessor configuration' do
|
134
|
+
let(:config) { ACCESSOR_CONFIG }
|
135
|
+
it { expect { driver }.not_to raise_error }
|
136
|
+
end
|
137
|
+
|
138
|
+
describe 'with counter without key configuration' do
|
139
|
+
let(:config) { COUNTER_WITHOUT_KEY_CONFIG }
|
140
|
+
it { expect { driver }.not_to raise_error }
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'with unknown type' do
|
144
|
+
let(:config) do
|
145
|
+
BASE_CONFIG + %[
|
146
|
+
<metric>
|
147
|
+
type foo
|
148
|
+
</metric>
|
149
|
+
]
|
150
|
+
end
|
151
|
+
it { expect { driver }.to raise_error(Fluent::ConfigError) }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
shared_examples_for 'instruments record' do
|
156
|
+
before do
|
157
|
+
driver.run(default_tag: tag) { driver.feed(event_time, message) }
|
158
|
+
end
|
159
|
+
|
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) }
|
168
|
+
|
169
|
+
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])
|
171
|
+
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
172
|
+
expect(gauge).to be_kind_of(::Prometheus::Client::Metric)
|
173
|
+
expect(summary).to be_kind_of(::Prometheus::Client::Metric)
|
174
|
+
expect(summary_with_accessor).to be_kind_of(::Prometheus::Client::Metric)
|
175
|
+
expect(counter_with_accessor).to be_kind_of(::Prometheus::Client::Metric)
|
176
|
+
expect(histogram).to be_kind_of(::Prometheus::Client::Metric)
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'instruments counter metric' do
|
180
|
+
expect(counter.type).to eq(:counter)
|
181
|
+
expect(counter.get({test_key: 'test_value', key: 'foo1'})).to be_kind_of(Numeric)
|
182
|
+
expect(counter_with_accessor.get({test_key: 'test_value', key: 'foo6'})).to be_kind_of(Numeric)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'instruments gauge metric' do
|
186
|
+
expect(gauge.type).to eq(:gauge)
|
187
|
+
expect(gauge.get({test_key: 'test_value', key: 'foo2'})).to eq(100)
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'instruments summary metric' do
|
191
|
+
expect(summary.type).to eq(:summary)
|
192
|
+
expect(summary.get({test_key: 'test_value', key: 'foo3'})).to be_kind_of(Hash)
|
193
|
+
expect(summary.get({test_key: 'test_value', key: 'foo3'})[0.99]).to eq(100)
|
194
|
+
expect(summary_with_accessor.get({test_key: 'test_value', key: 'foo5'})[0.99]).to eq(100)
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'instruments histogram metric' do
|
198
|
+
driver.run(default_tag: tag) do
|
199
|
+
4.times { driver.feed(event_time, message) }
|
200
|
+
end
|
201
|
+
|
202
|
+
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
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'placeholder config' do
|
209
|
+
let(:config) { PLACEHOLDER_CONFIG }
|
210
|
+
let(:counter) { registry.get(:placeholder_foo) }
|
211
|
+
|
212
|
+
it 'expands placeholders with record values' do
|
213
|
+
expect(registry.metrics.map(&:name)).to eq([:placeholder_foo])
|
214
|
+
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
215
|
+
key, _ = counter.values.find {|k,v| v == 100 }
|
216
|
+
expect(key).to be_kind_of(Hash)
|
217
|
+
expect(key[:tag]).to eq(tag)
|
218
|
+
expect(key[:hostname]).to be_kind_of(String)
|
219
|
+
expect(key[:hostname]).not_to eq("${hostname}")
|
220
|
+
expect(key[:hostname]).not_to be_empty
|
221
|
+
expect(key[:foo]).to eq("100")
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context 'accessor config' do
|
226
|
+
let(:config) { ACCESSOR_CONFIG }
|
227
|
+
let(:counter) { registry.get(:accessor_foo) }
|
228
|
+
|
229
|
+
it 'expands accessor with record values' do
|
230
|
+
expect(registry.metrics.map(&:name)).to eq([:accessor_foo])
|
231
|
+
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
232
|
+
key, _ = counter.values.find {|k,v| v == 100 }
|
233
|
+
expect(key).to be_kind_of(Hash)
|
234
|
+
expect(key[:foo]).to eq(100)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
context 'counter_without config' do
|
239
|
+
let(:config) { COUNTER_WITHOUT_KEY_CONFIG }
|
240
|
+
let(:counter) { registry.get(:without_key_foo) }
|
241
|
+
|
242
|
+
it 'just increments by 1' do
|
243
|
+
expect(registry.metrics.map(&:name)).to eq([:without_key_foo])
|
244
|
+
expect(counter).to be_kind_of(::Prometheus::Client::Metric)
|
245
|
+
_, value = counter.values.find {|k,v| k == {} }
|
246
|
+
expect(value).to eq(1)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|