fluentd 1.13.3 → 1.16.5

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.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/{bug_report.yaml → bug_report.yml} +2 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +2 -2
  4. data/.github/ISSUE_TEMPLATE/{feature_request.yaml → feature_request.yml} +1 -0
  5. data/.github/workflows/stale-actions.yml +11 -9
  6. data/.github/workflows/test.yml +32 -0
  7. data/CHANGELOG.md +490 -10
  8. data/CONTRIBUTING.md +2 -2
  9. data/MAINTAINERS.md +7 -5
  10. data/README.md +3 -23
  11. data/Rakefile +1 -1
  12. data/SECURITY.md +14 -0
  13. data/fluentd.gemspec +7 -8
  14. data/lib/fluent/command/cat.rb +13 -3
  15. data/lib/fluent/command/ctl.rb +6 -3
  16. data/lib/fluent/command/fluentd.rb +73 -65
  17. data/lib/fluent/command/plugin_config_formatter.rb +1 -1
  18. data/lib/fluent/compat/output.rb +9 -6
  19. data/lib/fluent/config/dsl.rb +1 -1
  20. data/lib/fluent/config/error.rb +12 -0
  21. data/lib/fluent/config/literal_parser.rb +2 -2
  22. data/lib/fluent/config/parser.rb +1 -1
  23. data/lib/fluent/config/v1_parser.rb +3 -3
  24. data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
  25. data/lib/fluent/config/yaml_parser/loader.rb +108 -0
  26. data/lib/fluent/config/yaml_parser/parser.rb +166 -0
  27. data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
  28. data/lib/fluent/config/yaml_parser.rb +56 -0
  29. data/lib/fluent/config.rb +14 -1
  30. data/lib/fluent/counter/server.rb +1 -1
  31. data/lib/fluent/counter/validator.rb +3 -3
  32. data/lib/fluent/daemon.rb +2 -4
  33. data/lib/fluent/engine.rb +1 -1
  34. data/lib/fluent/env.rb +4 -0
  35. data/lib/fluent/error.rb +3 -0
  36. data/lib/fluent/event.rb +8 -4
  37. data/lib/fluent/event_router.rb +47 -2
  38. data/lib/fluent/file_wrapper.rb +137 -0
  39. data/lib/fluent/log/console_adapter.rb +66 -0
  40. data/lib/fluent/log.rb +44 -5
  41. data/lib/fluent/match.rb +1 -1
  42. data/lib/fluent/msgpack_factory.rb +6 -1
  43. data/lib/fluent/oj_options.rb +1 -2
  44. data/lib/fluent/plugin/bare_output.rb +49 -8
  45. data/lib/fluent/plugin/base.rb +26 -9
  46. data/lib/fluent/plugin/buf_file.rb +34 -5
  47. data/lib/fluent/plugin/buf_file_single.rb +32 -3
  48. data/lib/fluent/plugin/buffer/file_chunk.rb +1 -1
  49. data/lib/fluent/plugin/buffer.rb +216 -70
  50. data/lib/fluent/plugin/filter.rb +35 -1
  51. data/lib/fluent/plugin/filter_record_transformer.rb +1 -1
  52. data/lib/fluent/plugin/in_forward.rb +2 -2
  53. data/lib/fluent/plugin/in_http.rb +39 -10
  54. data/lib/fluent/plugin/in_monitor_agent.rb +4 -2
  55. data/lib/fluent/plugin/in_sample.rb +1 -1
  56. data/lib/fluent/plugin/in_syslog.rb +13 -1
  57. data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
  58. data/lib/fluent/plugin/in_tail/position_file.rb +33 -33
  59. data/lib/fluent/plugin/in_tail.rb +216 -84
  60. data/lib/fluent/plugin/in_tcp.rb +47 -2
  61. data/lib/fluent/plugin/input.rb +39 -1
  62. data/lib/fluent/plugin/metrics.rb +119 -0
  63. data/lib/fluent/plugin/metrics_local.rb +96 -0
  64. data/lib/fluent/plugin/multi_output.rb +43 -6
  65. data/lib/fluent/plugin/out_copy.rb +1 -1
  66. data/lib/fluent/plugin/out_exec_filter.rb +2 -2
  67. data/lib/fluent/plugin/out_file.rb +20 -2
  68. data/lib/fluent/plugin/out_forward/ack_handler.rb +19 -4
  69. data/lib/fluent/plugin/out_forward/socket_cache.rb +2 -0
  70. data/lib/fluent/plugin/out_forward.rb +17 -9
  71. data/lib/fluent/plugin/out_secondary_file.rb +39 -22
  72. data/lib/fluent/plugin/output.rb +167 -78
  73. data/lib/fluent/plugin/parser.rb +3 -4
  74. data/lib/fluent/plugin/parser_apache2.rb +1 -1
  75. data/lib/fluent/plugin/parser_json.rb +1 -1
  76. data/lib/fluent/plugin/parser_syslog.rb +1 -1
  77. data/lib/fluent/plugin/storage_local.rb +3 -5
  78. data/lib/fluent/plugin.rb +10 -1
  79. data/lib/fluent/plugin_helper/child_process.rb +3 -0
  80. data/lib/fluent/plugin_helper/event_emitter.rb +8 -1
  81. data/lib/fluent/plugin_helper/event_loop.rb +2 -2
  82. data/lib/fluent/plugin_helper/http_server/server.rb +2 -1
  83. data/lib/fluent/plugin_helper/metrics.rb +129 -0
  84. data/lib/fluent/plugin_helper/record_accessor.rb +1 -1
  85. data/lib/fluent/plugin_helper/retry_state.rb +14 -4
  86. data/lib/fluent/plugin_helper/server.rb +35 -6
  87. data/lib/fluent/plugin_helper/service_discovery.rb +2 -2
  88. data/lib/fluent/plugin_helper/socket.rb +13 -2
  89. data/lib/fluent/plugin_helper/thread.rb +3 -3
  90. data/lib/fluent/plugin_helper.rb +1 -0
  91. data/lib/fluent/plugin_id.rb +3 -2
  92. data/lib/fluent/registry.rb +2 -1
  93. data/lib/fluent/root_agent.rb +6 -0
  94. data/lib/fluent/rpc.rb +4 -3
  95. data/lib/fluent/supervisor.rb +283 -259
  96. data/lib/fluent/system_config.rb +13 -3
  97. data/lib/fluent/test/driver/base.rb +11 -5
  98. data/lib/fluent/test/driver/filter.rb +4 -0
  99. data/lib/fluent/test/startup_shutdown.rb +6 -8
  100. data/lib/fluent/time.rb +21 -20
  101. data/lib/fluent/version.rb +1 -1
  102. data/lib/fluent/win32api.rb +38 -0
  103. data/lib/fluent/winsvc.rb +5 -8
  104. data/templates/new_gem/test/helper.rb.erb +0 -1
  105. data/test/command/test_cat.rb +31 -2
  106. data/test/command/test_ctl.rb +1 -2
  107. data/test/command/test_fluentd.rb +209 -24
  108. data/test/command/test_plugin_config_formatter.rb +0 -1
  109. data/test/compat/test_parser.rb +6 -6
  110. data/test/config/test_system_config.rb +13 -11
  111. data/test/config/test_types.rb +1 -1
  112. data/test/log/test_console_adapter.rb +110 -0
  113. data/test/plugin/in_tail/test_io_handler.rb +26 -8
  114. data/test/plugin/in_tail/test_position_file.rb +48 -59
  115. data/test/plugin/out_forward/test_ack_handler.rb +39 -0
  116. data/test/plugin/out_forward/test_socket_cache.rb +26 -1
  117. data/test/plugin/test_bare_output.rb +14 -1
  118. data/test/plugin/test_base.rb +133 -1
  119. data/test/plugin/test_buf_file.rb +62 -23
  120. data/test/plugin/test_buf_file_single.rb +65 -0
  121. data/test/plugin/test_buffer.rb +267 -3
  122. data/test/plugin/test_buffer_chunk.rb +11 -0
  123. data/test/plugin/test_filter.rb +12 -1
  124. data/test/plugin/test_filter_parser.rb +1 -1
  125. data/test/plugin/test_filter_stdout.rb +2 -2
  126. data/test/plugin/test_in_forward.rb +9 -11
  127. data/test/plugin/test_in_http.rb +65 -3
  128. data/test/plugin/test_in_monitor_agent.rb +216 -11
  129. data/test/plugin/test_in_object_space.rb +9 -3
  130. data/test/plugin/test_in_syslog.rb +35 -0
  131. data/test/plugin/test_in_tail.rb +1393 -385
  132. data/test/plugin/test_in_tcp.rb +87 -2
  133. data/test/plugin/test_in_udp.rb +28 -0
  134. data/test/plugin/test_in_unix.rb +2 -2
  135. data/test/plugin/test_input.rb +12 -1
  136. data/test/plugin/test_metrics.rb +294 -0
  137. data/test/plugin/test_metrics_local.rb +96 -0
  138. data/test/plugin/test_multi_output.rb +25 -1
  139. data/test/plugin/test_out_exec.rb +6 -4
  140. data/test/plugin/test_out_exec_filter.rb +6 -2
  141. data/test/plugin/test_out_file.rb +34 -17
  142. data/test/plugin/test_out_forward.rb +78 -77
  143. data/test/plugin/test_out_http.rb +1 -0
  144. data/test/plugin/test_out_stdout.rb +2 -2
  145. data/test/plugin/test_output.rb +297 -12
  146. data/test/plugin/test_output_as_buffered.rb +44 -44
  147. data/test/plugin/test_output_as_buffered_compress.rb +32 -18
  148. data/test/plugin/test_output_as_buffered_retries.rb +54 -7
  149. data/test/plugin/test_output_as_buffered_secondary.rb +4 -4
  150. data/test/plugin/test_parser_regexp.rb +1 -6
  151. data/test/plugin/test_parser_syslog.rb +1 -1
  152. data/test/plugin_helper/test_cert_option.rb +1 -1
  153. data/test/plugin_helper/test_child_process.rb +38 -16
  154. data/test/plugin_helper/test_event_emitter.rb +29 -0
  155. data/test/plugin_helper/test_http_server_helper.rb +1 -1
  156. data/test/plugin_helper/test_metrics.rb +137 -0
  157. data/test/plugin_helper/test_retry_state.rb +602 -38
  158. data/test/plugin_helper/test_server.rb +78 -6
  159. data/test/plugin_helper/test_timer.rb +2 -2
  160. data/test/test_config.rb +191 -24
  161. data/test/test_event_router.rb +17 -0
  162. data/test/test_file_wrapper.rb +53 -0
  163. data/test/test_formatter.rb +24 -21
  164. data/test/test_log.rb +122 -40
  165. data/test/test_msgpack_factory.rb +32 -0
  166. data/test/test_plugin_classes.rb +102 -0
  167. data/test/test_root_agent.rb +30 -1
  168. data/test/test_supervisor.rb +477 -257
  169. data/test/test_time_parser.rb +22 -0
  170. metadata +55 -34
  171. data/.drone.yml +0 -35
  172. data/.github/workflows/issue-auto-closer.yml +0 -12
  173. data/.github/workflows/linux-test.yaml +0 -36
  174. data/.github/workflows/macos-test.yaml +0 -30
  175. data/.github/workflows/windows-test.yaml +0 -46
  176. data/.gitlab-ci.yml +0 -103
  177. data/lib/fluent/plugin/file_wrapper.rb +0 -187
  178. data/test/plugin/test_file_wrapper.rb +0 -126
  179. data/test/test_logger_initializer.rb +0 -46
@@ -156,6 +156,19 @@ class TcpInputTest < Test::Unit::TestCase
156
156
  assert_equal hostname, event[2]['host']
157
157
  end
158
158
 
159
+ test "send_keepalive_packet_can_be_enabled" do
160
+ d = create_driver(base_config + %!
161
+ format none
162
+ send_keepalive_packet true
163
+ !)
164
+ assert_true d.instance.send_keepalive_packet
165
+
166
+ d = create_driver(base_config + %!
167
+ format none
168
+ !)
169
+ assert_false d.instance.send_keepalive_packet
170
+ end
171
+
159
172
  test 'source_address_key' do
160
173
  d = create_driver(base_config + %!
161
174
  format none
@@ -205,13 +218,13 @@ class TcpInputTest < Test::Unit::TestCase
205
218
  </client>
206
219
  </security>
207
220
  !)
208
- d.run(shutdown: false, expect_records: 1, timeout: 2) do
221
+ d.run(expect_records: 1, timeout: 2) do
209
222
  create_tcp_socket('127.0.0.1', @port) do |sock|
210
223
  sock.send("hello\n", 0)
211
224
  end
212
225
  end
213
226
 
214
- assert_equal 1, d.instance.log.logs.count { |l| l =~ /anonymous client/ }
227
+ assert_equal 1, d.logs.count { |l| l =~ /anonymous client/ }
215
228
  assert_equal 0, d.events.size
216
229
  end
217
230
  end
@@ -240,4 +253,76 @@ class TcpInputTest < Test::Unit::TestCase
240
253
  assert_equal 'hello', event[2]['msg']
241
254
  end
242
255
  end
256
+
257
+ sub_test_case "message_length_limit" do
258
+ data("batch_emit", { extract: "" }, keep: true)
259
+ data("single_emit", { extract: "<extract>\ntag_key tag\n</extract>\n" }, keep: true)
260
+ test "drop records exceeding limit" do |data|
261
+ message_length_limit = 10
262
+ d = create_driver(base_config + %!
263
+ message_length_limit #{message_length_limit}
264
+ <parse>
265
+ @type none
266
+ </parse>
267
+ #{data[:extract]}
268
+ !)
269
+ d.run(expect_records: 2, timeout: 10) do
270
+ create_tcp_socket('127.0.0.1', @port) do |sock|
271
+ sock.send("a" * message_length_limit + "\n", 0)
272
+ sock.send("b" * (message_length_limit + 1) + "\n", 0)
273
+ sock.send("c" * (message_length_limit - 1) + "\n", 0)
274
+ end
275
+ end
276
+
277
+ expected_records = [
278
+ "a" * message_length_limit,
279
+ "c" * (message_length_limit - 1)
280
+ ]
281
+ actual_records = d.events.collect do |event|
282
+ event[2]["message"]
283
+ end
284
+
285
+ assert_equal expected_records, actual_records
286
+ end
287
+
288
+ test "clear buffer and discard the subsequent data until the next delimiter" do |data|
289
+ message_length_limit = 12
290
+ d = create_driver(base_config + %!
291
+ message_length_limit #{message_length_limit}
292
+ delimiter ";"
293
+ <parse>
294
+ @type json
295
+ </parse>
296
+ #{data[:extract]}
297
+ !)
298
+ d.run(expect_records: 1, timeout: 10) do
299
+ create_tcp_socket('127.0.0.1', @port) do |sock|
300
+ sock.send('{"message":', 0)
301
+ sock.send('"hello', 0)
302
+ sleep 1 # To make the server read data and clear the buffer here.
303
+ sock.send('world!"};', 0) # This subsequent data must be discarded so that a parsing failure doesn't occur.
304
+ sock.send('{"k":"v"};', 0) # This will succeed to parse.
305
+ end
306
+ end
307
+
308
+ logs = d.logs.collect do |log|
309
+ log.gsub(/\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4} /, "")
310
+ end
311
+ actual_records = d.events.collect do |event|
312
+ event[2]
313
+ end
314
+
315
+ assert_equal(
316
+ {
317
+ # Asserting that '[warn]: pattern not matched message="world!\"}"' warning does not occur.
318
+ logs: ['[info]: The buffer size exceeds \'message_length_limit\', cleared: limit=12 size=17 head="{\"message\":\"hello"' + "\n"],
319
+ records: [{"k" => "v"}],
320
+ },
321
+ {
322
+ logs: logs[1..],
323
+ records: actual_records,
324
+ }
325
+ )
326
+ end
327
+ end
243
328
  end
@@ -265,4 +265,32 @@ class UdpInputTest < Test::Unit::TestCase
265
265
  end
266
266
  end
267
267
  end
268
+
269
+ test 'message_length_limit' do
270
+ message_length_limit = 32
271
+ d = create_driver(base_config + %!
272
+ format none
273
+ message_length_limit #{message_length_limit}
274
+ !)
275
+ d.run(expect_records: 3) do
276
+ create_udp_socket('127.0.0.1', @port) do |u|
277
+ 3.times do |i|
278
+ u.send("#{i}" * 40 + "\n", 0)
279
+ end
280
+ end
281
+ end
282
+
283
+ if Fluent.windows?
284
+ expected_records = []
285
+ else
286
+ expected_records = 3.times.collect do |i|
287
+ "#{i}" * message_length_limit
288
+ end
289
+ end
290
+ actual_records = d.events.collect do |event|
291
+ event[2]["message"]
292
+ end
293
+
294
+ assert_equal expected_records, actual_records
295
+ end
268
296
  end
@@ -174,8 +174,8 @@ class UnixInputTest < Test::Unit::TestCase
174
174
  assert_equal 0, @d.events.size
175
175
 
176
176
  logs = @d.instance.log.logs
177
- assert_equal 1, logs.select { |line|
177
+ assert_equal 1, logs.count { |line|
178
178
  line =~ / \[warn\]: incoming data is broken: msg=#{data.inspect}/
179
- }.size, "should not accept broken chunk"
179
+ }, "should not accept broken chunk"
180
180
  end
181
181
  end unless Fluent.windows?
@@ -73,7 +73,7 @@ class InputTest < Test::Unit::TestCase
73
73
 
74
74
  @p.configure(config_element('ROOT', '', {'@log_level' => 'debug'}))
75
75
 
76
- assert{ @p.log.object_id != original_logger.object_id }
76
+ assert(@p.log.object_id != original_logger.object_id)
77
77
  assert_equal Fluent::Log::LEVEL_DEBUG, @p.log.level
78
78
  end
79
79
 
@@ -85,6 +85,17 @@ class InputTest < Test::Unit::TestCase
85
85
  end
86
86
  end
87
87
 
88
+ test 'can use metrics plugins and fallback methods' do
89
+ @p.configure(config_element('ROOT', '', {'@log_level' => 'debug'}))
90
+
91
+ %w[emit_size_metrics emit_records_metrics].each do |metric_name|
92
+ assert_true @p.instance_variable_get(:"@#{metric_name}").is_a?(Fluent::Plugin::Metrics)
93
+ end
94
+
95
+ assert_equal 0, @p.emit_size
96
+ assert_equal 0, @p.emit_records
97
+ end
98
+
88
99
  test 'are not available with multi workers configuration in default' do
89
100
  assert_false @p.multi_workers_ready?
90
101
  end
@@ -0,0 +1,294 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin/metrics'
3
+ require 'fluent/plugin/base'
4
+ require 'fluent/system_config'
5
+
6
+ class BareMetrics < Fluent::Plugin::Metrics
7
+ Fluent::Plugin.register_metrics('bare', self)
8
+
9
+ private
10
+
11
+ # Just override for tests.
12
+ def has_methods_for_counter?
13
+ false
14
+ end
15
+ end
16
+
17
+ class BasicCounterMetrics < Fluent::Plugin::Metrics
18
+ Fluent::Plugin.register_metrics('example', self)
19
+
20
+ attr_reader :data
21
+
22
+ def initialize
23
+ super
24
+ @data = 0
25
+ end
26
+ def get
27
+ @data
28
+ end
29
+ def inc
30
+ @data +=1
31
+ end
32
+ def add(value)
33
+ @data += value
34
+ end
35
+ def set(value)
36
+ @data = value
37
+ end
38
+ def close
39
+ @data = 0
40
+ super
41
+ end
42
+ end
43
+
44
+ class AliasedCounterMetrics < Fluent::Plugin::Metrics
45
+ Fluent::Plugin.register_metrics('example', self)
46
+
47
+ attr_reader :data
48
+
49
+ def initialize
50
+ super
51
+ @data = 0
52
+ end
53
+ def configure(conf)
54
+ super
55
+ class << self
56
+ alias_method :set, :set_counter
57
+ end
58
+ end
59
+ def get
60
+ @data
61
+ end
62
+ def inc
63
+ @data +=1
64
+ end
65
+ def add(value)
66
+ @data += value
67
+ end
68
+ def set_counter(value)
69
+ @data = value
70
+ end
71
+ def close
72
+ @data = 0
73
+ super
74
+ end
75
+ end
76
+
77
+ class BasicGaugeMetrics < Fluent::Plugin::Metrics
78
+ Fluent::Plugin.register_metrics('example', self)
79
+
80
+ attr_reader :data
81
+
82
+ def initialize
83
+ super
84
+ @data = 0
85
+ end
86
+ def get
87
+ @data
88
+ end
89
+ def inc
90
+ @data +=1
91
+ end
92
+ def dec
93
+ @data -=1
94
+ end
95
+ def add(value)
96
+ @data += value
97
+ end
98
+ def sub(value)
99
+ @data -= value
100
+ end
101
+ def set(value)
102
+ @data = value
103
+ end
104
+ def close
105
+ @data = 0
106
+ super
107
+ end
108
+ end
109
+
110
+ class AliasedGaugeMetrics < Fluent::Plugin::Metrics
111
+ Fluent::Plugin.register_metrics('example', self)
112
+
113
+ attr_reader :data
114
+
115
+ def initialize
116
+ super
117
+ @data = 0
118
+ end
119
+ def configure(conf)
120
+ super
121
+ class << self
122
+ alias_method :dec, :dec_gauge
123
+ alias_method :set, :set_gauge
124
+ alias_method :sub, :sub_gauge
125
+ end
126
+ end
127
+ def get
128
+ @data
129
+ end
130
+ def inc
131
+ @data +=1
132
+ end
133
+ def dec_gauge
134
+ @data -=1
135
+ end
136
+ def add(value)
137
+ @data += value
138
+ end
139
+ def sub_gauge(value)
140
+ @data -= value
141
+ end
142
+ def set_gauge(value)
143
+ @data = value
144
+ end
145
+ def close
146
+ @data = 0
147
+ super
148
+ end
149
+ end
150
+
151
+ class StorageTest < Test::Unit::TestCase
152
+ sub_test_case 'BareMetrics' do
153
+ setup do
154
+ @m = BareMetrics.new
155
+ @m.configure(config_element())
156
+ end
157
+
158
+ test 'is configured with plugin information and system config' do
159
+ m = BareMetrics.new
160
+ m.configure(config_element('metrics', '', {}))
161
+
162
+ assert_false m.use_gauge_metric
163
+ assert_false m.has_methods_for_counter
164
+ assert_false m.has_methods_for_gauge
165
+ end
166
+
167
+ test 'all bare operations are not defined yet' do
168
+ assert_raise NotImplementedError do
169
+ @m.get
170
+ end
171
+ assert_raise NotImplementedError do
172
+ @m.inc
173
+ end
174
+ assert_raise NotImplementedError do
175
+ @m.dec
176
+ end
177
+ assert_raise NotImplementedError do
178
+ @m.add(10)
179
+ end
180
+ assert_raise NotImplementedError do
181
+ @m.sub(11)
182
+ end
183
+ assert_raise NotImplementedError do
184
+ @m.set(123)
185
+ end
186
+ end
187
+ end
188
+
189
+ sub_test_case 'BasicCounterMetric' do
190
+ setup do
191
+ @m = BasicCounterMetrics.new
192
+ @m.configure(config_element('metrics', '', {'@id' => '1'}))
193
+ end
194
+
195
+ test 'all basic counter operations work well' do
196
+ assert_true @m.has_methods_for_counter
197
+ assert_false @m.has_methods_for_gauge
198
+
199
+ assert_equal 0, @m.get
200
+ assert_equal 1, @m.inc
201
+
202
+ @m.add(20)
203
+ assert_equal 21, @m.get
204
+ assert_raise NotImplementedError do
205
+ @m.dec
206
+ end
207
+
208
+ @m.set(100)
209
+ assert_equal 100, @m.get
210
+ assert_raise NotImplementedError do
211
+ @m.sub(11)
212
+ end
213
+ end
214
+ end
215
+
216
+ sub_test_case 'AliasedCounterMetric' do
217
+ setup do
218
+ @m = AliasedCounterMetrics.new
219
+ @m.configure(config_element('metrics', '', {}))
220
+ end
221
+
222
+ test 'all aliased counter operations work well' do
223
+ assert_true @m.has_methods_for_counter
224
+ assert_false @m.has_methods_for_gauge
225
+
226
+ assert_equal 0, @m.get
227
+ assert_equal 1, @m.inc
228
+
229
+ @m.add(20)
230
+ assert_equal 21, @m.get
231
+ assert_raise NotImplementedError do
232
+ @m.dec
233
+ end
234
+
235
+ @m.set(100)
236
+ assert_equal 100, @m.get
237
+ assert_raise NotImplementedError do
238
+ @m.sub(11)
239
+ end
240
+ end
241
+ end
242
+
243
+ sub_test_case 'BasicGaugeMetric' do
244
+ setup do
245
+ @m = BasicGaugeMetrics.new
246
+ @m.use_gauge_metric = true
247
+ @m.configure(config_element('metrics', '', {}))
248
+ end
249
+
250
+ test 'all basic gauge operations work well' do
251
+ assert_false @m.has_methods_for_counter
252
+ assert_true @m.has_methods_for_gauge
253
+
254
+ assert_equal 0, @m.get
255
+ assert_equal 1, @m.inc
256
+
257
+ @m.add(20)
258
+ assert_equal 21, @m.get
259
+ @m.dec
260
+ assert_equal 20, @m.get
261
+
262
+ @m.set(100)
263
+ assert_equal 100, @m.get
264
+ @m.sub(11)
265
+ assert_equal 89, @m.get
266
+ end
267
+ end
268
+
269
+ sub_test_case 'AliasedGaugeMetric' do
270
+ setup do
271
+ @m = AliasedGaugeMetrics.new
272
+ @m.use_gauge_metric = true
273
+ @m.configure(config_element('metrics', '', {}))
274
+ end
275
+
276
+ test 'all aliased gauge operations work well' do
277
+ assert_false @m.has_methods_for_counter
278
+ assert_true @m.has_methods_for_gauge
279
+
280
+ assert_equal 0, @m.get
281
+ assert_equal 1, @m.inc
282
+
283
+ @m.add(20)
284
+ assert_equal 21, @m.get
285
+ @m.dec
286
+ assert_equal 20, @m.get
287
+
288
+ @m.set(100)
289
+ assert_equal 100, @m.get
290
+ @m.sub(11)
291
+ assert_equal 89, @m.get
292
+ end
293
+ end
294
+ end
@@ -0,0 +1,96 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin/metrics_local'
3
+ require 'fluent/system_config'
4
+
5
+ class LocalMetricsTest < ::Test::Unit::TestCase
6
+ sub_test_case 'configure' do
7
+ test "configured for counter mode" do
8
+ m = Fluent::Plugin::LocalMetrics.new
9
+ m.configure(config_element('metrics', '', {"labels" => {test: "test-unit", language: "Ruby"}}))
10
+
11
+ assert_false m.use_gauge_metric
12
+ assert_equal({agent: "Fluentd", hostname: "#{Socket.gethostname}"}, m.default_labels)
13
+ assert_equal({test: "test-unit", language: "Ruby"}, m.labels)
14
+ assert_true m.has_methods_for_counter
15
+ assert_false m.has_methods_for_gauge
16
+ end
17
+
18
+ test "configured for gauge mode" do
19
+ m = Fluent::Plugin::LocalMetrics.new
20
+ m.use_gauge_metric = true
21
+ m.configure(config_element('metrics', '', {"labels" => {test: "test-unit", language: "Ruby"}}))
22
+
23
+ assert_true m.use_gauge_metric
24
+ assert_equal({agent: "Fluentd", hostname: "#{Socket.gethostname}"}, m.default_labels)
25
+ assert_equal({test: "test-unit", language: "Ruby"}, m.labels)
26
+ assert_false m.has_methods_for_counter
27
+ assert_true m.has_methods_for_gauge
28
+ end
29
+ end
30
+
31
+ sub_test_case 'LocalMetric' do
32
+ sub_test_case "counter" do
33
+ setup do
34
+ @m = Fluent::Plugin::LocalMetrics.new
35
+ @m.configure(config_element('metrics', '', {}))
36
+ end
37
+
38
+ test '#configure' do
39
+ assert_true @m.has_methods_for_counter
40
+ assert_false @m.has_methods_for_gauge
41
+ end
42
+
43
+ test 'all local counter operations work well' do
44
+ assert_equal 0, @m.get
45
+ assert_equal 1, @m.inc
46
+
47
+ @m.add(20)
48
+ assert_equal 21, @m.get
49
+ assert_raise NotImplementedError do
50
+ @m.dec
51
+ end
52
+
53
+ @m.set(100)
54
+ assert_equal 100, @m.get
55
+
56
+ @m.set(10)
57
+ assert_equal 100, @m.get # On counter, value should be overwritten bigger than stored one.
58
+ assert_raise NotImplementedError do
59
+ @m.sub(11)
60
+ end
61
+ end
62
+ end
63
+
64
+ sub_test_case "gauge" do
65
+ setup do
66
+ @m = Fluent::Plugin::LocalMetrics.new
67
+ @m.use_gauge_metric = true
68
+ @m.configure(config_element('metrics', '', {}))
69
+ end
70
+
71
+ test '#configure' do
72
+ assert_false @m.has_methods_for_counter
73
+ assert_true @m.has_methods_for_gauge
74
+ end
75
+
76
+ test 'all local gauge operations work well' do
77
+ assert_equal 0, @m.get
78
+ assert_equal 1, @m.inc
79
+
80
+ @m.add(20)
81
+ assert_equal 21, @m.get
82
+ @m.dec
83
+ assert_equal 20, @m.get
84
+
85
+ @m.set(100)
86
+ assert_equal 100, @m.get
87
+
88
+ @m.sub(11)
89
+ assert_equal 89, @m.get
90
+
91
+ @m.set(10)
92
+ assert_equal 10, @m.get # On gauge, value always should be overwritten.
93
+ end
94
+ end
95
+ end
96
+ end
@@ -146,8 +146,11 @@ class MultiOutputTest < Test::Unit::TestCase
146
146
  @i.configure(conf)
147
147
  assert_equal 4, @i.outputs.size
148
148
 
149
+ log_size_for_multi_output_itself = 4
150
+ log_size_for_metrics_plugin_helper = 4
151
+ expected_warn_log_size = log_size_for_multi_output_itself + log_size_for_metrics_plugin_helper
149
152
  logs = @i.log.out.logs
150
- assert{ logs.select{|log| log.include?('[warn]') && log.include?("'type' is deprecated parameter name. use '@type' instead.") }.size == 4 }
153
+ assert{ logs.count{|log| log.include?('[warn]') && log.include?("'type' is deprecated parameter name. use '@type' instead.") } == expected_warn_log_size }
151
154
  end
152
155
 
153
156
  test '#emit_events calls #process always' do
@@ -176,5 +179,26 @@ class MultiOutputTest < Test::Unit::TestCase
176
179
 
177
180
  assert_equal 2, @i.events.size
178
181
  end
182
+
183
+ test 'can use metrics plugins and fallback methods' do
184
+ conf = config_element('ROOT', '', { '@type' => 'dummy_test_multi_output' },
185
+ [
186
+ config_element('store', '', { 'type' => 'dummy_test_multi_output_1' }),
187
+ config_element('store', '', { 'type' => 'dummy_test_multi_output_2' }),
188
+ config_element('store', '', { 'type' => 'dummy_test_multi_output_3' }),
189
+ config_element('store', '', { 'type' => 'dummy_test_multi_output_4' }),
190
+ ]
191
+ )
192
+ @i.configure(conf)
193
+
194
+ %w[num_errors_metrics emit_count_metrics emit_size_metrics emit_records_metrics].each do |metric_name|
195
+ assert_true @i.instance_variable_get(:"@#{metric_name}").is_a?(Fluent::Plugin::Metrics)
196
+ end
197
+
198
+ assert_equal 0, @i.num_errors
199
+ assert_equal 0, @i.emit_count
200
+ assert_equal 0, @i.emit_size
201
+ assert_equal 0, @i.emit_records
202
+ end
179
203
  end
180
204
  end
@@ -243,7 +243,7 @@ class ExecOutputTest < Test::Unit::TestCase
243
243
  sub_test_case 'when executed process dies unexpectedly' do
244
244
  setup do
245
245
  @gen_config = ->(num){ <<EOC
246
- command ruby -e "ARGV.first.to_i == 0 ? open(ARGV[1]){|f| STDOUT.write f.read} : (sleep 1 ; exit ARGV.first.to_i)" #{num} >#{TMP_DIR}/fail_out
246
+ command ruby -e "ARGV.first.to_i == 0 ? open(ARGV[1]){|f| STDOUT.write(f.read); STDOUT.flush} : (sleep 1 ; exit ARGV.first.to_i)" #{num} >#{TMP_DIR}/fail_out
247
247
  <inject>
248
248
  tag_key tag
249
249
  time_key time
@@ -265,7 +265,7 @@ EOC
265
265
  expect_path = "#{TMP_DIR}/fail_out"
266
266
 
267
267
  d.end_if{ File.exist?(expect_path) }
268
- d.run(default_tag: 'test', flush: true, wait_flush_completion: false, shutdown: false) do
268
+ d.run(default_tag: 'test', flush: true, wait_flush_completion: true, shutdown: false) do
269
269
  d.feed(time, records[0])
270
270
  d.feed(time, records[1])
271
271
  end
@@ -281,7 +281,8 @@ EOC
281
281
  assert{ d.instance.buffer.queue.empty? }
282
282
  assert{ d.instance.dequeued_chunks.empty? }
283
283
 
284
- d.instance_shutdown
284
+ ensure
285
+ d.instance_shutdown if d && d.instance
285
286
  end
286
287
 
287
288
  test 'flushed chunk will be taken back after child process unexpectedly exits' do
@@ -304,7 +305,8 @@ EOC
304
305
 
305
306
  assert{ File.exist?(expect_path) && File.size(expect_path) == 0 }
306
307
 
307
- d.instance_shutdown
308
+ ensure
309
+ d.instance_shutdown if d && d.instance
308
310
  end
309
311
  end
310
312
  end
@@ -524,6 +524,9 @@ class ExecFilterOutputTest < Test::Unit::TestCase
524
524
  assert_equal pid_list[1], events[1][2]['child_pid']
525
525
  assert_equal pid_list[0], events[2][2]['child_pid']
526
526
  assert_equal pid_list[1], events[3][2]['child_pid']
527
+
528
+ ensure
529
+ d.run(start: false, shutdown: true)
527
530
  end
528
531
 
529
532
  # child process exits per 3 lines
@@ -594,9 +597,10 @@ class ExecFilterOutputTest < Test::Unit::TestCase
594
597
  # the number of pids should be same with number of child processes
595
598
  assert_equal 2, pid_list.size
596
599
  logs = d.instance.log.out.logs
597
- assert_equal 2, logs.select { |l| l.include?('child process exits with error code') }.size
598
- assert_equal 2, logs.select { |l| l.include?('respawning child process') }.size
600
+ assert_equal 2, logs.count { |l| l.include?('child process exits with error code') }
601
+ assert_equal 2, logs.count { |l| l.include?('respawning child process') }
599
602
 
603
+ ensure
600
604
  d.run(start: false, shutdown: true)
601
605
  end
602
606
  end