karafka-core 2.5.11 → 2.5.13
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/workflows/ci.yml +3 -3
- data/.github/workflows/push.yml +2 -2
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/karafka-core.gemspec +1 -1
- data/lib/karafka/core/monitoring/statistics_decorator.rb +14 -4
- data/lib/karafka/core/version.rb +1 -1
- metadata +1 -25
- data/test/lib/karafka/core/configurable/leaf_test.rb +0 -3
- data/test/lib/karafka/core/configurable/node_test.rb +0 -3
- data/test/lib/karafka/core/configurable_test.rb +0 -504
- data/test/lib/karafka/core/contractable/contract_test.rb +0 -241
- data/test/lib/karafka/core/contractable/result_test.rb +0 -106
- data/test/lib/karafka/core/contractable/rule_test.rb +0 -5
- data/test/lib/karafka/core/contractable_test.rb +0 -3
- data/test/lib/karafka/core/helpers/time_test.rb +0 -29
- data/test/lib/karafka/core/instrumentation/callbacks_manager_test.rb +0 -81
- data/test/lib/karafka/core/instrumentation_test.rb +0 -35
- data/test/lib/karafka/core/monitoring/event_test.rb +0 -62
- data/test/lib/karafka/core/monitoring/monitor_test.rb +0 -237
- data/test/lib/karafka/core/monitoring/notifications_test.rb +0 -275
- data/test/lib/karafka/core/monitoring/statistics_decorator_test.rb +0 -503
- data/test/lib/karafka/core/monitoring_test.rb +0 -3
- data/test/lib/karafka/core/patches/rdkafka/bindings_test.rb +0 -25
- data/test/lib/karafka/core/taggable/tags_test.rb +0 -66
- data/test/lib/karafka/core/taggable_test.rb +0 -36
- data/test/lib/karafka/core/version_test.rb +0 -5
- data/test/lib/karafka/core_test.rb +0 -13
- data/test/lib/karafka-core_test.rb +0 -3
- data/test/support/class_builder.rb +0 -24
- data/test/support/describe_current_helper.rb +0 -41
- data/test/test_helper.rb +0 -55
|
@@ -1,503 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe_current do
|
|
4
|
-
subject(:decorator) { described_class.new }
|
|
5
|
-
|
|
6
|
-
let(:emitted_stats1) do
|
|
7
|
-
{
|
|
8
|
-
"string" => "value1",
|
|
9
|
-
"float" => 10.4,
|
|
10
|
-
"int" => 112,
|
|
11
|
-
"nested" => {
|
|
12
|
-
"brokers" => {
|
|
13
|
-
"localhost:9092/2" => {
|
|
14
|
-
"txbytes" => 123
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
let(:emitted_stats2) do
|
|
22
|
-
{
|
|
23
|
-
"string" => "value2",
|
|
24
|
-
"float" => 10.8,
|
|
25
|
-
"int" => 130,
|
|
26
|
-
"nested" => {
|
|
27
|
-
"brokers" => {
|
|
28
|
-
"localhost:9092/2" => {
|
|
29
|
-
"txbytes" => 153
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
let(:emitted_stats3) do
|
|
37
|
-
{
|
|
38
|
-
"string" => "value3",
|
|
39
|
-
"float" => 11.8,
|
|
40
|
-
"int" => 10,
|
|
41
|
-
"nested" => {
|
|
42
|
-
"brokers" => {
|
|
43
|
-
"localhost:9092/2" => {
|
|
44
|
-
"txbytes" => 2
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
let(:broker_scope) { %w[nested brokers localhost:9092/2] }
|
|
52
|
-
|
|
53
|
-
context "when it is a first stats emit" do
|
|
54
|
-
subject(:decorated) { decorator.call(emitted_stats1) }
|
|
55
|
-
|
|
56
|
-
it { assert_equal "value1", decorated["string"] }
|
|
57
|
-
it { refute decorated.key?("string_d") }
|
|
58
|
-
it { assert_equal 0, decorated["float_d"] }
|
|
59
|
-
it { assert_equal 0, decorated["int_d"] }
|
|
60
|
-
it { assert_equal 0, decorated.dig(*broker_scope)["txbytes_d"] }
|
|
61
|
-
it { assert_predicate decorated, :frozen? }
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
context "when it is a second stats emit" do
|
|
65
|
-
subject(:decorated) do
|
|
66
|
-
decorator.call(emitted_stats1)
|
|
67
|
-
decorator.call(emitted_stats2)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
it { assert_equal "value2", decorated["string"] }
|
|
71
|
-
it { refute decorated.key?("string_d") }
|
|
72
|
-
it { assert_in_delta(0.4, decorated["float_d"].round(10)) }
|
|
73
|
-
it { assert_equal 18, decorated["int_d"] }
|
|
74
|
-
it { assert_equal 30, decorated.dig(*broker_scope)["txbytes_d"] }
|
|
75
|
-
it { assert_predicate decorated, :frozen? }
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
context "when it is a third stats emit" do
|
|
79
|
-
subject(:decorated) do
|
|
80
|
-
decorator.call(emitted_stats1)
|
|
81
|
-
decorator.call(emitted_stats2)
|
|
82
|
-
decorator.call(emitted_stats3)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it { assert_equal "value3", decorated["string"] }
|
|
86
|
-
it { refute decorated.key?("string_d") }
|
|
87
|
-
it { refute decorated.key?("string_fd") }
|
|
88
|
-
it { assert_in_delta(1.0, decorated["float_d"].round(10)) }
|
|
89
|
-
it { assert_in_delta 0, decorated["float_fd"], 5 }
|
|
90
|
-
it { assert_equal(-120, decorated["int_d"]) }
|
|
91
|
-
it { assert_in_delta 0, decorated["int_fd"], 5 }
|
|
92
|
-
it { assert_equal(-151, decorated.dig(*broker_scope)["txbytes_d"]) }
|
|
93
|
-
it { assert_in_delta 0, decorated.dig(*broker_scope)["txbytes_fd"], 5 }
|
|
94
|
-
it { assert_predicate decorated, :frozen? }
|
|
95
|
-
it { refute decorated.key?("float_d_d") }
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
context "when a broker is no longer present" do
|
|
99
|
-
subject(:decorated) do
|
|
100
|
-
decorator.call(emitted_stats1)
|
|
101
|
-
decorator.call(emitted_stats2)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
before { emitted_stats2["nested"] = {} }
|
|
105
|
-
|
|
106
|
-
it { assert_equal "value2", decorated["string"] }
|
|
107
|
-
it { refute decorated.key?("string_d") }
|
|
108
|
-
it { refute decorated.key?("string_fd") }
|
|
109
|
-
it { assert_in_delta(0.4, decorated["float_d"].round(10)) }
|
|
110
|
-
it { assert_in_delta 0, decorated["float_fd"], 5 }
|
|
111
|
-
it { assert_equal 18, decorated["int_d"] }
|
|
112
|
-
it { assert_in_delta 0, decorated["int_fd"], 5 }
|
|
113
|
-
it { assert_equal({}, decorated["nested"]) }
|
|
114
|
-
it { assert_predicate decorated, :frozen? }
|
|
115
|
-
it { refute decorated.key?("float_d_d") }
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
context "when broker was introduced later on" do
|
|
119
|
-
subject(:decorated) do
|
|
120
|
-
decorator.call(emitted_stats1)
|
|
121
|
-
decorator.call(emitted_stats2)
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
before { emitted_stats1["nested"] = {} }
|
|
125
|
-
|
|
126
|
-
it { assert_equal "value2", decorated["string"] }
|
|
127
|
-
it { refute decorated.key?("string_d") }
|
|
128
|
-
it { assert_in_delta(0.4, decorated["float_d"].round(10)) }
|
|
129
|
-
it { assert_in_delta 0, decorated["float_fd"], 5 }
|
|
130
|
-
it { assert_equal 18, decorated["int_d"] }
|
|
131
|
-
it { assert_in_delta 0, decorated["int_fd"], 5 }
|
|
132
|
-
it { assert_equal 0, decorated.dig(*broker_scope)["txbytes_d"] }
|
|
133
|
-
it { assert_in_delta 0, decorated.dig(*broker_scope)["txbytes_fd"], 5 }
|
|
134
|
-
it { assert_predicate decorated, :frozen? }
|
|
135
|
-
it { refute decorated.key?("float_d_d") }
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
context "when value remains unchanged over time" do
|
|
139
|
-
subject(:decorated) do
|
|
140
|
-
# First one will set initial state
|
|
141
|
-
decorator.call(deep_copy.call)
|
|
142
|
-
# Second one will build first deltas with freeze duration of zero
|
|
143
|
-
decorator.call(deep_copy.call)
|
|
144
|
-
sleep(0.01)
|
|
145
|
-
# Third one will allow for proper freeze duration computation
|
|
146
|
-
decorator.call(deep_copy.call)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
let(:deep_copy) { -> { Marshal.load(Marshal.dump(emitted_stats1)) } }
|
|
150
|
-
|
|
151
|
-
it { refute decorated.key?("string_d") }
|
|
152
|
-
it { refute decorated.key?("string_fd") }
|
|
153
|
-
it { assert_equal 0, decorated["float_d"] }
|
|
154
|
-
it { assert_in_delta 10, decorated["float_fd"], 5 }
|
|
155
|
-
it { assert_equal 0, decorated["int_d"] }
|
|
156
|
-
it { assert_in_delta 10, decorated["int_fd"], 5 }
|
|
157
|
-
it { assert_predicate decorated, :frozen? }
|
|
158
|
-
it { refute decorated.key?("float_d_d") }
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
context "when value remains unchanged over multiple occurrences and time" do
|
|
162
|
-
subject(:decorated) do
|
|
163
|
-
# First one will set initial state
|
|
164
|
-
decorator.call(deep_copy.call)
|
|
165
|
-
# Second one will build first deltas with freeze duration of zero
|
|
166
|
-
decorator.call(deep_copy.call)
|
|
167
|
-
sleep(0.01)
|
|
168
|
-
# Third one will allow for proper freeze duration computation
|
|
169
|
-
decorator.call(deep_copy.call)
|
|
170
|
-
sleep(0.01)
|
|
171
|
-
decorator.call(deep_copy.call)
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
let(:deep_copy) { -> { Marshal.load(Marshal.dump(emitted_stats1)) } }
|
|
175
|
-
|
|
176
|
-
it { refute decorated.key?("string_d") }
|
|
177
|
-
it { refute decorated.key?("string_fd") }
|
|
178
|
-
it { assert_equal 0, decorated["float_d"] }
|
|
179
|
-
it { assert_in_delta 20, decorated["float_fd"], 5 }
|
|
180
|
-
it { assert_equal 0, decorated["int_d"] }
|
|
181
|
-
# On slow CIs this value tends to grow and crash
|
|
182
|
-
it { assert_in_delta 20, decorated["int_fd"], 15 }
|
|
183
|
-
it { assert_predicate decorated, :frozen? }
|
|
184
|
-
it { refute decorated.key?("float_d_d") }
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
context "when a value type changed from non-numeric to numeric between emissions" do
|
|
188
|
-
subject(:decorated) do
|
|
189
|
-
decorator.call(emitted_stats1)
|
|
190
|
-
decorator.call(emitted_stats2)
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
before do
|
|
194
|
-
# In the first emission, txbytes is a string (unusual but defensive)
|
|
195
|
-
emitted_stats1["nested"]["brokers"]["localhost:9092/2"]["txbytes"] = "not_a_number"
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
# When previous value was non-numeric but current is numeric, no delta should be computed
|
|
199
|
-
it { refute decorated.dig(*broker_scope).key?("txbytes_d") }
|
|
200
|
-
it { refute decorated.dig(*broker_scope).key?("txbytes_fd") }
|
|
201
|
-
it { assert_equal 153, decorated.dig(*broker_scope)["txbytes"] }
|
|
202
|
-
it { assert_predicate decorated, :frozen? }
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
context "when excluded_keys are configured" do
|
|
206
|
-
subject(:decorator) { described_class.new(excluded_keys: %w[nested]) }
|
|
207
|
-
|
|
208
|
-
context "when it is a first stats emit" do
|
|
209
|
-
subject(:decorated) { decorator.call(emitted_stats1) }
|
|
210
|
-
|
|
211
|
-
it { assert_equal 0, decorated["float_d"] }
|
|
212
|
-
it { assert_equal 0, decorated["int_d"] }
|
|
213
|
-
it { assert_predicate decorated, :frozen? }
|
|
214
|
-
|
|
215
|
-
it "does not decorate excluded subtrees" do
|
|
216
|
-
expected = { "brokers" => { "localhost:9092/2" => { "txbytes" => 123 } } }
|
|
217
|
-
|
|
218
|
-
assert_equal(expected, decorated["nested"])
|
|
219
|
-
refute decorated["nested"]["brokers"]["localhost:9092/2"].key?("txbytes_d")
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
context "when it is a second stats emit" do
|
|
224
|
-
subject(:decorated) do
|
|
225
|
-
decorator.call(emitted_stats1)
|
|
226
|
-
decorator.call(emitted_stats2)
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
it { assert_in_delta(0.4, decorated["float_d"].round(10)) }
|
|
230
|
-
it { assert_equal 18, decorated["int_d"] }
|
|
231
|
-
it { assert_predicate decorated, :frozen? }
|
|
232
|
-
|
|
233
|
-
it "does not decorate excluded subtrees" do
|
|
234
|
-
refute decorated["nested"]["brokers"]["localhost:9092/2"].key?("txbytes_d")
|
|
235
|
-
refute decorated["nested"]["brokers"]["localhost:9092/2"].key?("txbytes_fd")
|
|
236
|
-
end
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
context "when excluded_keys target a numeric key" do
|
|
241
|
-
let(:decorator) { described_class.new(excluded_keys: %w[int]) }
|
|
242
|
-
|
|
243
|
-
subject(:decorated) do
|
|
244
|
-
decorator.call(emitted_stats1)
|
|
245
|
-
decorator.call(emitted_stats2)
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
it { assert_in_delta(0.4, decorated["float_d"].round(10)) }
|
|
249
|
-
it { assert_equal 130, decorated["int"] }
|
|
250
|
-
it { refute decorated.key?("int_d") }
|
|
251
|
-
it { refute decorated.key?("int_fd") }
|
|
252
|
-
it { assert_predicate decorated, :frozen? }
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
context "when no excluded_keys are configured" do
|
|
256
|
-
let(:decorator) { described_class.new }
|
|
257
|
-
|
|
258
|
-
subject(:decorated) do
|
|
259
|
-
decorator.call(emitted_stats1)
|
|
260
|
-
decorator.call(emitted_stats2)
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
it { assert_equal 18, decorated["int_d"] }
|
|
264
|
-
it { assert_equal 30, decorated.dig(*broker_scope)["txbytes_d"] }
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
context "when only_keys are configured" do
|
|
268
|
-
let(:decorator) { described_class.new(only_keys: %w[int]) }
|
|
269
|
-
|
|
270
|
-
context "when it is a first stats emit" do
|
|
271
|
-
subject(:decorated) { decorator.call(emitted_stats1) }
|
|
272
|
-
|
|
273
|
-
it { assert_equal 0, decorated["int_d"] }
|
|
274
|
-
it { assert_predicate decorated, :frozen? }
|
|
275
|
-
|
|
276
|
-
it "does not decorate non-listed numeric keys" do
|
|
277
|
-
refute decorated.key?("float_d")
|
|
278
|
-
refute decorated.key?("float_fd")
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
it "preserves non-listed numeric values" do
|
|
282
|
-
assert_in_delta 10.4, decorated["float"]
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
it "preserves string values" do
|
|
286
|
-
assert_equal "value1", decorated["string"]
|
|
287
|
-
end
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
context "when it is a second stats emit" do
|
|
291
|
-
subject(:decorated) do
|
|
292
|
-
decorator.call(emitted_stats1)
|
|
293
|
-
decorator.call(emitted_stats2)
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
it { assert_equal 18, decorated["int_d"] }
|
|
297
|
-
it { assert_predicate decorated, :frozen? }
|
|
298
|
-
|
|
299
|
-
it "does not decorate non-listed numeric keys" do
|
|
300
|
-
refute decorated.key?("float_d")
|
|
301
|
-
refute decorated.key?("float_fd")
|
|
302
|
-
end
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
context "when only_keys targets a nested value" do
|
|
306
|
-
let(:decorator) { described_class.new(only_keys: %w[txbytes]) }
|
|
307
|
-
|
|
308
|
-
subject(:decorated) do
|
|
309
|
-
decorator.call(emitted_stats1)
|
|
310
|
-
decorator.call(emitted_stats2)
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
it "decorates matching keys in nested hashes" do
|
|
314
|
-
assert_equal 30, decorated.dig(*broker_scope)["txbytes_d"]
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
it "does not decorate non-listed root keys" do
|
|
318
|
-
refute decorated.key?("int_d")
|
|
319
|
-
refute decorated.key?("float_d")
|
|
320
|
-
end
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
context "when only_keys and excluded_keys are combined" do
|
|
325
|
-
let(:decorator) { described_class.new(excluded_keys: %w[nested], only_keys: %w[int]) }
|
|
326
|
-
|
|
327
|
-
subject(:decorated) do
|
|
328
|
-
decorator.call(emitted_stats1)
|
|
329
|
-
decorator.call(emitted_stats2)
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
it { assert_equal 18, decorated["int_d"] }
|
|
333
|
-
it { assert_predicate decorated, :frozen? }
|
|
334
|
-
|
|
335
|
-
it "does not decorate non-listed keys" do
|
|
336
|
-
refute decorated.key?("float_d")
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
it "does not recurse into excluded subtrees" do
|
|
340
|
-
refute decorated.dig(*broker_scope).key?("txbytes_d")
|
|
341
|
-
end
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
context "when only_keys value remains unchanged over time" do
|
|
345
|
-
subject(:decorated) do
|
|
346
|
-
decorator.call(deep_copy.call)
|
|
347
|
-
decorator.call(deep_copy.call)
|
|
348
|
-
sleep(0.01)
|
|
349
|
-
decorator.call(deep_copy.call)
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
let(:decorator) { described_class.new(only_keys: %w[int]) }
|
|
353
|
-
let(:deep_copy) { -> { Marshal.load(Marshal.dump(emitted_stats1)) } }
|
|
354
|
-
|
|
355
|
-
it { assert_equal 0, decorated["int_d"] }
|
|
356
|
-
it { assert_in_delta 10, decorated["int_fd"], 5 }
|
|
357
|
-
|
|
358
|
-
it "does not decorate non-listed keys" do
|
|
359
|
-
refute decorated.key?("float_d")
|
|
360
|
-
refute decorated.key?("float_fd")
|
|
361
|
-
end
|
|
362
|
-
end
|
|
363
|
-
|
|
364
|
-
context "when only_keys is used with librdkafka-like structure" do
|
|
365
|
-
let(:decorator) { described_class.new(only_keys: %w[rxmsgs txbytes consumer_lag]) }
|
|
366
|
-
|
|
367
|
-
let(:rdkafka_stats1) do
|
|
368
|
-
{
|
|
369
|
-
"rxmsgs" => 100,
|
|
370
|
-
"name" => "consumer-1",
|
|
371
|
-
"brokers" => {
|
|
372
|
-
"localhost:9092/0" => {
|
|
373
|
-
"txbytes" => 500,
|
|
374
|
-
"rxbytes" => 300,
|
|
375
|
-
"nodeid" => 0
|
|
376
|
-
}
|
|
377
|
-
},
|
|
378
|
-
"topics" => {
|
|
379
|
-
"events" => {
|
|
380
|
-
"age" => 1000,
|
|
381
|
-
"partitions" => {
|
|
382
|
-
"0" => {
|
|
383
|
-
"consumer_lag" => 50,
|
|
384
|
-
"hi_offset" => 1000,
|
|
385
|
-
"txmsgs" => 200
|
|
386
|
-
},
|
|
387
|
-
"1" => {
|
|
388
|
-
"consumer_lag" => 30,
|
|
389
|
-
"hi_offset" => 800,
|
|
390
|
-
"txmsgs" => 150
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
},
|
|
395
|
-
"cgrp" => {
|
|
396
|
-
"stateage" => 5000,
|
|
397
|
-
"rebalance_cnt" => 2
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
let(:rdkafka_stats2) do
|
|
403
|
-
{
|
|
404
|
-
"rxmsgs" => 150,
|
|
405
|
-
"name" => "consumer-1",
|
|
406
|
-
"brokers" => {
|
|
407
|
-
"localhost:9092/0" => {
|
|
408
|
-
"txbytes" => 700,
|
|
409
|
-
"rxbytes" => 500,
|
|
410
|
-
"nodeid" => 0
|
|
411
|
-
}
|
|
412
|
-
},
|
|
413
|
-
"topics" => {
|
|
414
|
-
"events" => {
|
|
415
|
-
"age" => 2000,
|
|
416
|
-
"partitions" => {
|
|
417
|
-
"0" => {
|
|
418
|
-
"consumer_lag" => 40,
|
|
419
|
-
"hi_offset" => 1100,
|
|
420
|
-
"txmsgs" => 250
|
|
421
|
-
},
|
|
422
|
-
"1" => {
|
|
423
|
-
"consumer_lag" => 25,
|
|
424
|
-
"hi_offset" => 900,
|
|
425
|
-
"txmsgs" => 200
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
},
|
|
430
|
-
"cgrp" => {
|
|
431
|
-
"stateage" => 6000,
|
|
432
|
-
"rebalance_cnt" => 2
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
subject(:decorated) do
|
|
438
|
-
decorator.call(rdkafka_stats1)
|
|
439
|
-
decorator.call(rdkafka_stats2)
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
it "decorates root only_keys" do
|
|
443
|
-
assert_equal 50, decorated["rxmsgs_d"]
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
it "does not decorate non-listed root keys" do
|
|
447
|
-
refute decorated.key?("name_d")
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
it "decorates broker only_keys" do
|
|
451
|
-
assert_equal 200, decorated["brokers"]["localhost:9092/0"]["txbytes_d"]
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
it "does not decorate non-listed broker keys" do
|
|
455
|
-
refute decorated["brokers"]["localhost:9092/0"].key?("rxbytes_d")
|
|
456
|
-
end
|
|
457
|
-
|
|
458
|
-
it "decorates partition only_keys" do
|
|
459
|
-
assert_equal(-10, decorated.dig("topics", "events", "partitions", "0")["consumer_lag_d"])
|
|
460
|
-
assert_equal(-5, decorated.dig("topics", "events", "partitions", "1")["consumer_lag_d"])
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
it "does not decorate non-listed partition keys" do
|
|
464
|
-
refute decorated.dig("topics", "events", "partitions", "0").key?("txmsgs_d")
|
|
465
|
-
refute decorated.dig("topics", "events", "partitions", "0").key?("hi_offset_d")
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
it "does not decorate non-listed topic keys" do
|
|
469
|
-
refute decorated.dig("topics", "events").key?("age_d")
|
|
470
|
-
end
|
|
471
|
-
|
|
472
|
-
it { assert_predicate decorated, :frozen? }
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
context "when only_keys previous value type changed to non-numeric" do
|
|
476
|
-
let(:decorator) { described_class.new(only_keys: %w[val]) }
|
|
477
|
-
|
|
478
|
-
subject(:decorated) do
|
|
479
|
-
decorator.call({ "val" => "not_numeric" })
|
|
480
|
-
decorator.call({ "val" => 10 })
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
it { refute decorated.key?("val_d") }
|
|
484
|
-
end
|
|
485
|
-
|
|
486
|
-
context "when a value type changed from numeric to non-numeric between emissions" do
|
|
487
|
-
subject(:decorated) do
|
|
488
|
-
decorator.call(emitted_stats1)
|
|
489
|
-
decorator.call(emitted_stats2)
|
|
490
|
-
end
|
|
491
|
-
|
|
492
|
-
before do
|
|
493
|
-
# In the second emission, txbytes changed to a string
|
|
494
|
-
emitted_stats2["nested"]["brokers"]["localhost:9092/2"]["txbytes"] = "not_a_number"
|
|
495
|
-
end
|
|
496
|
-
|
|
497
|
-
# Non-numeric values are never decorated
|
|
498
|
-
it { refute decorated.dig(*broker_scope).key?("txbytes_d") }
|
|
499
|
-
it { refute decorated.dig(*broker_scope).key?("txbytes_fd") }
|
|
500
|
-
it { assert_equal "not_a_number", decorated.dig(*broker_scope)["txbytes"] }
|
|
501
|
-
it { assert_predicate decorated, :frozen? }
|
|
502
|
-
end
|
|
503
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe_current do
|
|
4
|
-
subject(:producer) do
|
|
5
|
-
config = { "bootstrap.servers": "localhost:10092" }
|
|
6
|
-
Rdkafka::Config.new(config).producer
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
describe "#build_error_callback" do
|
|
10
|
-
let(:errors) { [] }
|
|
11
|
-
let(:callback) { ->(*args) { errors << args } }
|
|
12
|
-
|
|
13
|
-
before { Rdkafka::Config.error_callback.add("test", callback) }
|
|
14
|
-
|
|
15
|
-
after { Rdkafka::Config.error_callback.delete("test") }
|
|
16
|
-
|
|
17
|
-
it "expect to inject instance name to the error callback" do
|
|
18
|
-
producer.produce(topic: "test", payload: "1")
|
|
19
|
-
sleep(0.01) while errors.empty?
|
|
20
|
-
|
|
21
|
-
assert_includes errors.first.first, "rdkafka#producer"
|
|
22
|
-
assert_equal :transport, errors.first.last.code
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe_current do
|
|
4
|
-
subject(:tags) { described_class.new }
|
|
5
|
-
|
|
6
|
-
it { assert_empty tags.to_a }
|
|
7
|
-
|
|
8
|
-
describe "#add" do
|
|
9
|
-
context "when few under same name" do
|
|
10
|
-
before { 3.times { |value| tags.add(:name, value) } }
|
|
11
|
-
|
|
12
|
-
it { assert_equal %w[2], tags.to_a }
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
context "when with different names" do
|
|
16
|
-
before do
|
|
17
|
-
tags.add(:name1, 1)
|
|
18
|
-
tags.add(:name2, 2)
|
|
19
|
-
tags.add(:name3, 3)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it { assert_equal %w[1 2 3], tags.to_a }
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
context "when with different names but same value" do
|
|
26
|
-
before do
|
|
27
|
-
tags.add(:name1, 1)
|
|
28
|
-
tags.add(:name2, 1)
|
|
29
|
-
tags.add(:name3, 1)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it { assert_equal %w[1], tags.to_a }
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
describe "#clear" do
|
|
37
|
-
before do
|
|
38
|
-
tags.add(:name, 1)
|
|
39
|
-
tags.clear
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it { assert_empty tags.to_a }
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
describe "#delete" do
|
|
46
|
-
before do
|
|
47
|
-
tags.add(:name1, 1)
|
|
48
|
-
tags.delete(:name1)
|
|
49
|
-
tags.add(:name3, 2)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it { assert_equal %w[2], tags.to_a }
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
describe "#to_json" do
|
|
56
|
-
before { tags.add(:test, "abc") }
|
|
57
|
-
|
|
58
|
-
it { assert_equal %w[abc].to_json, tags.to_json }
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
describe "#as_json" do
|
|
62
|
-
before { tags.add(:test, "abc") }
|
|
63
|
-
|
|
64
|
-
it { assert_equal %w[abc], tags.as_json }
|
|
65
|
-
end
|
|
66
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe_current do
|
|
4
|
-
context "when operating on an instance basis" do
|
|
5
|
-
subject(:tagged) { tagged_class.new }
|
|
6
|
-
|
|
7
|
-
let(:other_tagged) { tagged_class.new }
|
|
8
|
-
let(:tagged_class) do
|
|
9
|
-
Class.new do
|
|
10
|
-
include Karafka::Core::Taggable
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it { assert_empty tagged.tags.to_a }
|
|
15
|
-
it { refute_equal other_tagged.tags, tagged.tags }
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
context "when operating on a class basis" do
|
|
19
|
-
subject(:tagged) { tagged_class }
|
|
20
|
-
|
|
21
|
-
let(:other_tagged) { other_tagged_class }
|
|
22
|
-
let(:tagged_class) do
|
|
23
|
-
Class.new do
|
|
24
|
-
extend Karafka::Core::Taggable
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
let(:other_tagged_class) do
|
|
28
|
-
Class.new do
|
|
29
|
-
extend Karafka::Core::Taggable
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it { assert_empty tagged.tags.to_a }
|
|
34
|
-
it { refute_equal other_tagged.tags, tagged.tags }
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
describe_current do
|
|
4
|
-
subject(:core) { described_class }
|
|
5
|
-
|
|
6
|
-
describe "#gem_root" do
|
|
7
|
-
context "when we want to get gem root path" do
|
|
8
|
-
let(:path) { Dir.pwd }
|
|
9
|
-
|
|
10
|
-
it { assert_equal path, core.gem_root.to_path }
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Class builder helps creating anonymous classes that we can use to spec our code
|
|
4
|
-
# We need co create new class instances to have an "empty" and "clear" class for each spec
|
|
5
|
-
# This module acts as an interface to create classes
|
|
6
|
-
module ClassBuilder
|
|
7
|
-
class << self
|
|
8
|
-
# Creates an empty class without any predefined methods
|
|
9
|
-
# @return [Class] created anonymous class
|
|
10
|
-
def build(&)
|
|
11
|
-
klass = Class.new
|
|
12
|
-
|
|
13
|
-
klass.class_eval(&) if block_given?
|
|
14
|
-
klass
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# This method allows us to create a class that inherits from any other
|
|
18
|
-
# @param klass [Class] any class from which we want to inherit in our anonymous class
|
|
19
|
-
# @return [Class] new anonymous class
|
|
20
|
-
def inherit(klass, &)
|
|
21
|
-
Class.new(klass, &)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|