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,13 @@
1
+ # A job to scrape an endpoint of Fluentd running on localhost.
2
+ scrape_configs:
3
+ - job_name: 'prometheus'
4
+ scrape_interval: 5s
5
+ static_configs:
6
+ - targets:
7
+ - 'localhost:9090'
8
+ - job_name: fluentd
9
+ scrape_interval: 5s
10
+ static_configs:
11
+ - targets:
12
+ - 'localhost:24231'
13
+ metrics_path: /metrics
@@ -0,0 +1,59 @@
1
+ ALERT FluentdNodeDown
2
+ IF up{job="fluentd"} == 0
3
+ FOR 10m
4
+ LABELS {
5
+ service = "fluentd",
6
+ severity = "warning"
7
+ }
8
+ ANNOTATIONS {
9
+ summary = "fluentd cannot be scraped",
10
+ description = "Prometheus could not scrape {{ $labels.job }} for more than 10 minutes",
11
+ }
12
+
13
+ ALERT FluentdNodeDown
14
+ IF up{job="fluentd"} == 0
15
+ FOR 30m
16
+ LABELS {
17
+ service = "fluentd",
18
+ severity = "critical"
19
+ }
20
+ ANNOTATIONS {
21
+ summary = "fluentd cannot be scraped",
22
+ description = "Prometheus could not scrape {{ $labels.job }} for more than 30 minutes",
23
+ }
24
+
25
+ ALERT FluentdQueueLength
26
+ IF rate(fluentd_status_buffer_queue_length[5m]) > 0.3
27
+ FOR 1m
28
+ LABELS {
29
+ service = "fluentd",
30
+ severity = "warning"
31
+ }
32
+ ANNOTATIONS {
33
+ summary = "fluentd node are failing",
34
+ description = "In the last 5 minutes, fluentd queues increased 30%. Current value is {{ $value }} ",
35
+ }
36
+
37
+ ALERT FluentdQueueLength
38
+ IF rate(fluentd_status_buffer_queue_length[5m]) > 0.5
39
+ FOR 1m
40
+ LABELS {
41
+ service = "fluentd",
42
+ severity = "critical"
43
+ }
44
+ ANNOTATIONS {
45
+ summary = "fluentd node are critical",
46
+ description = "In the last 5 minutes, fluentd queues increased 50%. Current value is {{ $value }} ",
47
+ }
48
+
49
+ ALERT FluentdRecordsCountsHigh
50
+ IF sum(rate(fluentd_output_status_emit_records{job="fluentd"}[5m])) BY (instance) > (3 * sum(rate(fluentd_output_status_emit_records{job="fluentd"}[15m])) BY (instance))
51
+ FOR 1m
52
+ LABELS {
53
+ service = "fluentd",
54
+ severity = "critical"
55
+ }
56
+ ANNOTATIONS {
57
+ summary = "fluentd records count are critical",
58
+ description = "In the last 5m, records counts increased 3 times, comparing to the latest 15 min.",
59
+ }
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+ require 'fluent/test/driver/filter'
3
+ require 'fluent/plugin/filter_prometheus'
4
+ require_relative 'shared'
5
+
6
+ describe Fluent::Plugin::PrometheusFilter do
7
+ let(:tag) { 'prometheus.test' }
8
+ let(:driver) { Fluent::Test::Driver::Filter.new(Fluent::Plugin::PrometheusFilter).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
+
40
+ it 'should keep original message' do
41
+ driver.run(default_tag: tag) { driver.feed(event_time, message) }
42
+ expect(driver.filtered_records.first).to eq(message)
43
+ end
44
+ end
45
+
46
+ it_behaves_like 'instruments record'
47
+ end
48
+
49
+ describe '#run with retention' do
50
+ let(:message) { { "foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10 } }
51
+
52
+ context 'config with retention 1' do
53
+ let(:config) {
54
+ BASE_CONFIG + %(
55
+ <metric>
56
+ name simple
57
+ type counter
58
+ desc Something foo.
59
+ key foo
60
+ <labels>
61
+ bar ${bar}
62
+ baz ${baz}
63
+ qux ${qux}
64
+ </labels>
65
+ retention 1
66
+ retention_check_interval 1
67
+ </metric>
68
+ )
69
+ }
70
+
71
+ it 'expires metric after max 2s' do
72
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
73
+ driver.run(default_tag: tag) {
74
+ driver.feed(event_time, message)
75
+ expect(registry.metrics[0].get(labels: { :bar => 100, :baz => 100, :qux => 10 })).to eq(100)
76
+ sleep(2)
77
+ expect(registry.metrics[0].get(labels: { :bar => 100, :baz => 100, :qux => 10 })).to eq(0.0)
78
+ }
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '#run with topk' do
84
+ let(:message1) { { "foo" => 200, "bar" => "a" } }
85
+ let(:message2) { { "foo" => 300, "bar" => "b" } }
86
+ let(:message3) { { "foo" => 100, "bar" => "c" } }
87
+
88
+ context 'config with topk 2' do
89
+ let(:config) {
90
+ BASE_CONFIG + %(
91
+ <metric>
92
+ name simple
93
+ type counter
94
+ desc Something foo.
95
+ key foo
96
+ <labels>
97
+ bar ${bar}
98
+ </labels>
99
+ topk 2
100
+ </metric>
101
+ )
102
+ }
103
+
104
+ it 'shows only top 2 metrics' do
105
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
106
+ driver.run(default_tag: tag) {
107
+ driver.feed(event_time, message1)
108
+ driver.feed(event_time, message2)
109
+ driver.feed(event_time, message3)
110
+ }
111
+ expect(registry.metrics[0].values).to eq({
112
+ { :bar => "a" } => 200,
113
+ { :bar => "b" } => 300,
114
+ })
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#run with reset_after' do
120
+ let(:message) { { "foo" => 100 } }
121
+
122
+ context 'config with reset_after 1' do
123
+ let(:config) {
124
+ BASE_CONFIG + %(
125
+ <metric>
126
+ name simple
127
+ type counter
128
+ desc Something foo.
129
+ key foo
130
+ reset_after 1
131
+ </metric>
132
+ )
133
+ }
134
+
135
+ it 'resets metric values after max 2s' do
136
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
137
+ driver.run(default_tag: tag) {
138
+ driver.feed(event_time, message)
139
+ sleep(2)
140
+ }
141
+ expect(registry.metrics[0].values).to eq({ {} => 0 })
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'fluent/plugin/in_prometheus_monitor'
3
+ require 'fluent/test/driver/input'
4
+
5
+ describe Fluent::Plugin::PrometheusMonitorInput do
6
+ MONITOR_CONFIG = %[
7
+ @type prometheus_monitor
8
+ <labels>
9
+ host ${hostname}
10
+ foo bar
11
+ </labels>
12
+ ]
13
+
14
+ INVALID_MONITOR_CONFIG = %[
15
+ @type prometheus_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::PrometheusMonitorInput).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,225 @@
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::PrometheusInput do
8
+ CONFIG = %[
9
+ @type prometheus
10
+ ]
11
+
12
+ LOCAL_CONFIG = %[
13
+ @type prometheus
14
+ bind 127.0.0.1
15
+ ]
16
+
17
+ let(:config) { CONFIG }
18
+ let(:port) { 24231 }
19
+ let(:driver) { Fluent::Test::Driver::Input.new(Fluent::Plugin::PrometheusInput).configure(config) }
20
+
21
+ describe '#configure' do
22
+ describe 'bind' do
23
+ let(:config) { CONFIG + %[
24
+ bind 127.0.0.1
25
+ ] }
26
+ it 'should be configurable' do
27
+ expect(driver.instance.bind).to eq('127.0.0.1')
28
+ end
29
+ end
30
+
31
+ describe 'port' do
32
+ let(:config) { CONFIG + %[
33
+ port 8888
34
+ ] }
35
+ it 'should be configurable' do
36
+ expect(driver.instance.port).to eq(8888)
37
+ end
38
+ end
39
+
40
+ describe 'metrics_path' do
41
+ let(:config) { CONFIG + %[
42
+ metrics_path /_test
43
+ ] }
44
+ it 'should be configurable' do
45
+ expect(driver.instance.metrics_path).to eq('/_test')
46
+ end
47
+ end
48
+ end
49
+
50
+ describe '#start' do
51
+ context 'with transport section' do
52
+ let(:config) do
53
+ %[
54
+ @type prometheus
55
+ bind 127.0.0.1
56
+ <transport tls>
57
+ insecure true
58
+ </transport>
59
+ ]
60
+ end
61
+
62
+ it 'returns 200' do
63
+ driver.run(timeout: 1) do
64
+ Net::HTTP.start('127.0.0.1', port, verify_mode: OpenSSL::SSL::VERIFY_NONE, use_ssl: true) do |http|
65
+ req = Net::HTTP::Get.new('/metrics')
66
+ res = http.request(req)
67
+ expect(res.code).to eq('200')
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'old parameters are given' do
74
+ context 'when extra_conf is used' do
75
+ let(:config) do
76
+ %[
77
+ @type prometheus
78
+ bind 127.0.0.1
79
+ <ssl>
80
+ enable true
81
+ extra_conf { "SSLCertName": [["CN", "nobody"], ["DC", "example"]] }
82
+ </ssl>
83
+ ]
84
+ end
85
+
86
+ it 'uses webrick' do
87
+ expect(driver.instance).to receive(:start_webrick).once
88
+ driver.run(timeout: 1)
89
+ end
90
+
91
+ it 'returns 200' do
92
+ driver.run(timeout: 1) do
93
+ Net::HTTP.start('127.0.0.1', port, verify_mode: OpenSSL::SSL::VERIFY_NONE, use_ssl: true) do |http|
94
+ req = Net::HTTP::Get.new('/metrics')
95
+ res = http.request(req)
96
+ expect(res.code).to eq('200')
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ context 'cert_path and private_key_path combination' do
103
+ let(:config) do
104
+ %[
105
+ @type prometheus
106
+ bind 127.0.0.1
107
+ <ssl>
108
+ enable true
109
+ certificate_path path
110
+ private_key_path path1
111
+ </ssl>
112
+ ]
113
+ end
114
+
115
+ it 'converts them into new transport section' do
116
+ expect(driver.instance).to receive(:http_server_create_http_server).with(
117
+ :in_prometheus_server,
118
+ addr: anything,
119
+ logger: anything,
120
+ port: anything,
121
+ proto: :tls,
122
+ tls_opts: { 'cert_path' => 'path', 'private_key_path' => 'path1' }
123
+ ).once
124
+
125
+ driver.run(timeout: 1)
126
+ end
127
+ end
128
+
129
+ context 'insecure and ca_path' do
130
+ let(:config) do
131
+ %[
132
+ @type prometheus
133
+ bind 127.0.0.1
134
+ <ssl>
135
+ enable true
136
+ ca_path path
137
+ </ssl>
138
+ ]
139
+ end
140
+
141
+ it 'converts them into new transport section' do
142
+ expect(driver.instance).to receive(:http_server_create_http_server).with(
143
+ :in_prometheus_server,
144
+ addr: anything,
145
+ logger: anything,
146
+ port: anything,
147
+ proto: :tls,
148
+ tls_opts: { 'ca_path' => 'path', 'insecure' => true }
149
+ ).once
150
+
151
+ driver.run(timeout: 1)
152
+ end
153
+ end
154
+
155
+ context 'when only private_key_path is geven' do
156
+ let(:config) do
157
+ %[
158
+ @type prometheus
159
+ bind 127.0.0.1
160
+ <ssl>
161
+ enable true
162
+ private_key_path path
163
+ </ssl>
164
+ ]
165
+ end
166
+
167
+ it 'raises ConfigError' do
168
+ expect { driver.run(timeout: 1) }.to raise_error(Fluent::ConfigError, 'both certificate_path and private_key_path must be defined')
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ describe '#run' do
175
+ context '/metrics' do
176
+ let(:config) { LOCAL_CONFIG }
177
+ it 'returns 200' do
178
+ driver.run(timeout: 1) do
179
+ Net::HTTP.start("127.0.0.1", port) do |http|
180
+ req = Net::HTTP::Get.new("/metrics")
181
+ res = http.request(req)
182
+ expect(res.code).to eq('200')
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ context '/foo' do
189
+ let(:config) { LOCAL_CONFIG }
190
+ it 'does not return 200' do
191
+ driver.run(timeout: 1) do
192
+ Net::HTTP.start("127.0.0.1", port) do |http|
193
+ req = Net::HTTP::Get.new("/foo")
194
+ res = http.request(req)
195
+ expect(res.code).not_to eq('200')
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+ describe '#run_multi_workers' do
203
+ context '/metrics' do
204
+ Fluent::SystemConfig.overwrite_system_config('workers' => 4) do
205
+ let(:config) { CONFIG + %[
206
+ port #{port - 2}
207
+ ] }
208
+
209
+ it 'should configure port using sequential number' do
210
+ driver = Fluent::Test::Driver::Input.new(Fluent::Plugin::PrometheusInput)
211
+ driver.instance.instance_eval{ @_fluentd_worker_id = 2 }
212
+ driver.configure(config)
213
+ expect(driver.instance.port).to eq(port)
214
+ driver.run(timeout: 1) do
215
+ Net::HTTP.start("127.0.0.1", port) do |http|
216
+ req = Net::HTTP::Get.new("/metrics")
217
+ res = http.request(req)
218
+ expect(res.code).to eq('200')
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
@@ -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,166 @@
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
+
44
+ describe '#run with symbolized keys' do
45
+ let(:message) { {:foo => 100, :bar => 100, :baz => 100, :qux => 10} }
46
+
47
+ context 'simple config' do
48
+ let(:config) {
49
+ BASE_CONFIG + %(
50
+ <metric>
51
+ name simple
52
+ type counter
53
+ desc Something foo.
54
+ key foo
55
+ </metric>
56
+ )
57
+ }
58
+
59
+ it 'adds a new counter metric' do
60
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
61
+ driver.run(default_tag: tag) { driver.feed(event_time, message) }
62
+ expect(registry.metrics.map(&:name)).to eq([:simple])
63
+ end
64
+ end
65
+
66
+ it_behaves_like 'instruments record'
67
+ end
68
+
69
+ describe '#run with retention' do
70
+ let(:message) { { "foo" => 100, "bar" => 100, "baz" => 100, "qux" => 10 } }
71
+ let(:labels) { { :bar => 100, :baz => 100, :qux => 10 } }
72
+
73
+ context 'config with retention 1' do
74
+ let(:config) {
75
+ BASE_CONFIG + %(
76
+ <metric>
77
+ name simple
78
+ type counter
79
+ desc Something foo.
80
+ key foo
81
+ <labels>
82
+ bar ${bar}
83
+ baz ${baz}
84
+ qux ${qux}
85
+ </labels>
86
+ retention 1
87
+ retention_check_interval 1
88
+ </metric>
89
+ )
90
+ }
91
+
92
+ it 'expires metric after max 2s' do
93
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
94
+ driver.run(default_tag: tag) {
95
+ driver.feed(event_time, message)
96
+ expect(registry.metrics[0].get(labels: labels)).to eq(100)
97
+ sleep(2)
98
+ expect(registry.metrics[0].get(labels: labels)).to eq(0.0)
99
+ }
100
+ end
101
+ end
102
+ end
103
+
104
+ describe '#run with topk' do
105
+ let(:message1) { { "foo" => 200, "bar" => "a" } }
106
+ let(:message2) { { "foo" => 300, "bar" => "b" } }
107
+ let(:message3) { { "foo" => 100, "bar" => "c" } }
108
+
109
+ context 'config with topk 2' do
110
+ let(:config) {
111
+ BASE_CONFIG + %(
112
+ <metric>
113
+ name simple
114
+ type counter
115
+ desc Something foo.
116
+ key foo
117
+ <labels>
118
+ bar ${bar}
119
+ </labels>
120
+ topk 2
121
+ </metric>
122
+ )
123
+ }
124
+
125
+ it 'shows only top 2 metrics' do
126
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
127
+ driver.run(default_tag: tag) {
128
+ driver.feed(event_time, message1)
129
+ driver.feed(event_time, message2)
130
+ driver.feed(event_time, message3)
131
+ }
132
+ expect(registry.metrics[0].values).to eq({
133
+ { :bar => "a" } => 200,
134
+ { :bar => "b" } => 300,
135
+ })
136
+ end
137
+ end
138
+ end
139
+
140
+ describe '#run with reset_after' do
141
+ let(:message) { { "foo" => 100 } }
142
+
143
+ context 'config with reset_after 1' do
144
+ let(:config) {
145
+ BASE_CONFIG + %(
146
+ <metric>
147
+ name simple
148
+ type counter
149
+ desc Something foo.
150
+ key foo
151
+ reset_after 1
152
+ </metric>
153
+ )
154
+ }
155
+
156
+ it 'resets metric values after max 2s' do
157
+ expect(registry.metrics.map(&:name)).not_to eq([:simple])
158
+ driver.run(default_tag: tag) {
159
+ driver.feed(event_time, message)
160
+ sleep(2)
161
+ }
162
+ expect(registry.metrics[0].values).to eq({ {} => 0 })
163
+ end
164
+ end
165
+ end
166
+ end