phihos-fluent-plugin-prometheus 2.0.3.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/linux.yml +34 -0
  3. data/.gitignore +16 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +14 -0
  6. data/ChangeLog +43 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +202 -0
  9. data/README.md +537 -0
  10. data/Rakefile +7 -0
  11. data/fluent-plugin-prometheus.gemspec +22 -0
  12. data/lib/fluent/plugin/filter_prometheus.rb +50 -0
  13. data/lib/fluent/plugin/in_prometheus/async_wrapper.rb +47 -0
  14. data/lib/fluent/plugin/in_prometheus.rb +230 -0
  15. data/lib/fluent/plugin/in_prometheus_monitor.rb +107 -0
  16. data/lib/fluent/plugin/in_prometheus_output_monitor.rb +234 -0
  17. data/lib/fluent/plugin/in_prometheus_tail_monitor.rb +98 -0
  18. data/lib/fluent/plugin/out_prometheus.rb +49 -0
  19. data/lib/fluent/plugin/prometheus/data_store.rb +103 -0
  20. data/lib/fluent/plugin/prometheus/placeholder_expander.rb +132 -0
  21. data/lib/fluent/plugin/prometheus.rb +445 -0
  22. data/lib/fluent/plugin/prometheus_metrics.rb +77 -0
  23. data/misc/fluentd_sample.conf +170 -0
  24. data/misc/nginx_proxy.conf +22 -0
  25. data/misc/prometheus.yaml +13 -0
  26. data/misc/prometheus_alerts.yaml +59 -0
  27. data/spec/fluent/plugin/filter_prometheus_spec.rb +145 -0
  28. data/spec/fluent/plugin/in_prometheus_monitor_spec.rb +42 -0
  29. data/spec/fluent/plugin/in_prometheus_spec.rb +225 -0
  30. data/spec/fluent/plugin/in_prometheus_tail_monitor_spec.rb +42 -0
  31. data/spec/fluent/plugin/out_prometheus_spec.rb +166 -0
  32. data/spec/fluent/plugin/prometheus/placeholder_expander_spec.rb +110 -0
  33. data/spec/fluent/plugin/prometheus_metrics_spec.rb +138 -0
  34. data/spec/fluent/plugin/shared.rb +248 -0
  35. data/spec/spec_helper.rb +10 -0
  36. metadata +176 -0
@@ -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,248 @@
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(labels: {test_key: 'test_value', key: 'foo1'})).to be_kind_of(Numeric)
182
+ expect(counter_with_accessor.get(labels: {test_key: 'test_value', key: 'foo6'})).to be_kind_of(Numeric)
183
+ end
184
+
185
+ it 'instruments gauge metric' do
186
+ expect(gauge.type).to eq(:gauge)
187
+ expect(gauge.get(labels: {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(labels: {test_key: 'test_value', key: 'foo3'})).to be_kind_of(Hash)
193
+ expect(summary_with_accessor.get(labels: {test_key: 'test_value', key: 'foo5'})["sum"]).to eq(100)
194
+ end
195
+
196
+ it 'instruments histogram metric' do
197
+ driver.run(default_tag: tag) do
198
+ 4.times { driver.feed(event_time, message) }
199
+ end
200
+
201
+ expect(histogram.type).to eq(:histogram)
202
+ expect(histogram.get(labels: {test_key: 'test_value', key: 'foo4'})).to be_kind_of(Hash)
203
+ expect(histogram.get(labels: {test_key: 'test_value', key: 'foo4'})["10"]).to eq(5) # 4 + `es` in before
204
+ end
205
+ end
206
+
207
+ context 'placeholder config' do
208
+ let(:config) { PLACEHOLDER_CONFIG }
209
+ let(:counter) { registry.get(:placeholder_foo) }
210
+
211
+ it 'expands placeholders with record values' do
212
+ expect(registry.metrics.map(&:name)).to eq([:placeholder_foo])
213
+ expect(counter).to be_kind_of(::Prometheus::Client::Metric)
214
+ key, _ = counter.values.find {|k,v| v == 100 }
215
+ expect(key).to be_kind_of(Hash)
216
+ expect(key[:tag]).to eq(tag)
217
+ expect(key[:hostname]).to be_kind_of(String)
218
+ expect(key[:hostname]).not_to eq("${hostname}")
219
+ expect(key[:hostname]).not_to be_empty
220
+ expect(key[:foo]).to eq("100")
221
+ end
222
+ end
223
+
224
+ context 'accessor config' do
225
+ let(:config) { ACCESSOR_CONFIG }
226
+ let(:counter) { registry.get(:accessor_foo) }
227
+
228
+ it 'expands accessor with record values' do
229
+ expect(registry.metrics.map(&:name)).to eq([:accessor_foo])
230
+ expect(counter).to be_kind_of(::Prometheus::Client::Metric)
231
+ key, _ = counter.values.find {|k,v| v == 100 }
232
+ expect(key).to be_kind_of(Hash)
233
+ expect(key[:foo]).to eq("100")
234
+ end
235
+ end
236
+
237
+ context 'counter_without config' do
238
+ let(:config) { COUNTER_WITHOUT_KEY_CONFIG }
239
+ let(:counter) { registry.get(:without_key_foo) }
240
+
241
+ it 'just increments by 1' do
242
+ expect(registry.metrics.map(&:name)).to eq([:without_key_foo])
243
+ expect(counter).to be_kind_of(::Prometheus::Client::Metric)
244
+ _, value = counter.values.find {|k,v| k == {} }
245
+ expect(value).to eq(1)
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'fluent/test'
3
+ require 'fluent/test/helpers'
4
+ require 'fluent/plugin/prometheus'
5
+
6
+ # Disable Test::Unit
7
+ Test::Unit::AutoRunner.need_auto_run = false
8
+
9
+ Fluent::Test.setup
10
+ include Fluent::Test::Helpers
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phihos-fluent-plugin-prometheus
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.3.pre.1
5
+ platform: ruby
6
+ authors:
7
+ - Philipp Hossner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-08-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.1
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 1.9.1
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: prometheus-client
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 2.1.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.1.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: test-unit
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ description: A fluent plugin that collects metrics and exposes for Prometheus.
104
+ email:
105
+ - philipp.hossner@posteo.de
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".github/workflows/linux.yml"
111
+ - ".gitignore"
112
+ - ".rspec"
113
+ - ".travis.yml"
114
+ - ChangeLog
115
+ - Gemfile
116
+ - LICENSE
117
+ - README.md
118
+ - Rakefile
119
+ - fluent-plugin-prometheus.gemspec
120
+ - lib/fluent/plugin/filter_prometheus.rb
121
+ - lib/fluent/plugin/in_prometheus.rb
122
+ - lib/fluent/plugin/in_prometheus/async_wrapper.rb
123
+ - lib/fluent/plugin/in_prometheus_monitor.rb
124
+ - lib/fluent/plugin/in_prometheus_output_monitor.rb
125
+ - lib/fluent/plugin/in_prometheus_tail_monitor.rb
126
+ - lib/fluent/plugin/out_prometheus.rb
127
+ - lib/fluent/plugin/prometheus.rb
128
+ - lib/fluent/plugin/prometheus/data_store.rb
129
+ - lib/fluent/plugin/prometheus/placeholder_expander.rb
130
+ - lib/fluent/plugin/prometheus_metrics.rb
131
+ - misc/fluentd_sample.conf
132
+ - misc/nginx_proxy.conf
133
+ - misc/prometheus.yaml
134
+ - misc/prometheus_alerts.yaml
135
+ - spec/fluent/plugin/filter_prometheus_spec.rb
136
+ - spec/fluent/plugin/in_prometheus_monitor_spec.rb
137
+ - spec/fluent/plugin/in_prometheus_spec.rb
138
+ - spec/fluent/plugin/in_prometheus_tail_monitor_spec.rb
139
+ - spec/fluent/plugin/out_prometheus_spec.rb
140
+ - spec/fluent/plugin/prometheus/placeholder_expander_spec.rb
141
+ - spec/fluent/plugin/prometheus_metrics_spec.rb
142
+ - spec/fluent/plugin/shared.rb
143
+ - spec/spec_helper.rb
144
+ homepage: https://github.com/phihos/fluent-plugin-prometheus
145
+ licenses:
146
+ - Apache-2.0
147
+ metadata: {}
148
+ post_install_message:
149
+ rdoc_options: []
150
+ require_paths:
151
+ - lib
152
+ required_ruby_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">"
160
+ - !ruby/object:Gem::Version
161
+ version: 1.3.1
162
+ requirements: []
163
+ rubygems_version: 3.3.5
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: A fluent plugin that collects metrics and exposes for Prometheus.
167
+ test_files:
168
+ - spec/fluent/plugin/filter_prometheus_spec.rb
169
+ - spec/fluent/plugin/in_prometheus_monitor_spec.rb
170
+ - spec/fluent/plugin/in_prometheus_spec.rb
171
+ - spec/fluent/plugin/in_prometheus_tail_monitor_spec.rb
172
+ - spec/fluent/plugin/out_prometheus_spec.rb
173
+ - spec/fluent/plugin/prometheus/placeholder_expander_spec.rb
174
+ - spec/fluent/plugin/prometheus_metrics_spec.rb
175
+ - spec/fluent/plugin/shared.rb
176
+ - spec/spec_helper.rb