fluent-plugin-opensearch 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.editorconfig +9 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  6. data/.github/workflows/coverage.yaml +22 -0
  7. data/.github/workflows/issue-auto-closer.yml +12 -0
  8. data/.github/workflows/linux.yml +26 -0
  9. data/.github/workflows/macos.yml +26 -0
  10. data/.github/workflows/windows.yml +26 -0
  11. data/.gitignore +18 -0
  12. data/CONTRIBUTING.md +24 -0
  13. data/Gemfile +10 -0
  14. data/History.md +6 -0
  15. data/ISSUE_TEMPLATE.md +26 -0
  16. data/LICENSE.txt +201 -0
  17. data/PULL_REQUEST_TEMPLATE.md +9 -0
  18. data/README.OpenSearchGenID.md +116 -0
  19. data/README.OpenSearchInput.md +291 -0
  20. data/README.Troubleshooting.md +482 -0
  21. data/README.md +1556 -0
  22. data/Rakefile +37 -0
  23. data/fluent-plugin-opensearch.gemspec +38 -0
  24. data/gemfiles/Gemfile.elasticsearch.v6 +12 -0
  25. data/lib/fluent/log-ext.rb +64 -0
  26. data/lib/fluent/plugin/filter_opensearch_genid.rb +103 -0
  27. data/lib/fluent/plugin/in_opensearch.rb +351 -0
  28. data/lib/fluent/plugin/oj_serializer.rb +48 -0
  29. data/lib/fluent/plugin/opensearch_constants.rb +39 -0
  30. data/lib/fluent/plugin/opensearch_error.rb +31 -0
  31. data/lib/fluent/plugin/opensearch_error_handler.rb +166 -0
  32. data/lib/fluent/plugin/opensearch_fallback_selector.rb +36 -0
  33. data/lib/fluent/plugin/opensearch_index_template.rb +155 -0
  34. data/lib/fluent/plugin/opensearch_simple_sniffer.rb +36 -0
  35. data/lib/fluent/plugin/opensearch_tls.rb +96 -0
  36. data/lib/fluent/plugin/out_opensearch.rb +1124 -0
  37. data/lib/fluent/plugin/out_opensearch_data_stream.rb +214 -0
  38. data/test/helper.rb +61 -0
  39. data/test/plugin/test_alias_template.json +9 -0
  40. data/test/plugin/test_filter_opensearch_genid.rb +241 -0
  41. data/test/plugin/test_in_opensearch.rb +493 -0
  42. data/test/plugin/test_index_alias_template.json +11 -0
  43. data/test/plugin/test_index_template.json +25 -0
  44. data/test/plugin/test_oj_serializer.rb +45 -0
  45. data/test/plugin/test_opensearch_error_handler.rb +689 -0
  46. data/test/plugin/test_opensearch_fallback_selector.rb +100 -0
  47. data/test/plugin/test_opensearch_tls.rb +171 -0
  48. data/test/plugin/test_out_opensearch.rb +3953 -0
  49. data/test/plugin/test_out_opensearch_data_stream.rb +474 -0
  50. data/test/plugin/test_template.json +23 -0
  51. data/test/test_log-ext.rb +61 -0
  52. metadata +262 -0
@@ -0,0 +1,474 @@
1
+ require_relative '../helper'
2
+ require 'date'
3
+ require 'fluent/test/helpers'
4
+ require 'fluent/test/driver/output'
5
+ require 'flexmock/test_unit'
6
+ require 'fluent/plugin/out_opensearch_data_stream'
7
+
8
+ class OpenSearchOutputDataStreamTest < Test::Unit::TestCase
9
+ include FlexMock::TestCase
10
+ include Fluent::Test::Helpers
11
+
12
+ attr_accessor :bulk_records
13
+
14
+ OPENSEARCH_DATA_STREAM_TYPE = "opensearch_data_stream"
15
+
16
+ def setup
17
+ Fluent::Test.setup
18
+ @driver = nil
19
+ log = Fluent::Engine.log
20
+ log.out.logs.slice!(0, log.out.logs.length)
21
+ @bulk_records = 0
22
+ end
23
+
24
+ def driver(conf='', os_version=1, client_version="\"1.0\"")
25
+ # For request stub to detect compatibility.
26
+ @os_version ||= os_version
27
+ @client_version ||= client_version
28
+ Fluent::Plugin::OpenSearchOutputDataStream.module_eval(<<-CODE)
29
+ def detect_os_major_version
30
+ #{@os_version}
31
+ end
32
+ CODE
33
+ @driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::OpenSearchOutputDataStream) {
34
+ # v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
35
+ if !defined?(Fluent::Plugin::Output)
36
+ def format(tag, time, record)
37
+ [time, record].to_msgpack
38
+ end
39
+ end
40
+ }.configure(conf)
41
+ end
42
+
43
+ def sample_data_stream
44
+ {
45
+ 'data_streams': [
46
+ {
47
+ 'name' => 'foo',
48
+ 'timestamp_field' => {
49
+ 'name' => '@timestamp'
50
+ }
51
+ }
52
+ ]
53
+ }
54
+ end
55
+
56
+ def sample_record
57
+ {'@timestamp' => Time.now.iso8601, 'message' => 'Sample record'}
58
+ end
59
+
60
+ RESPONSE_ACKNOWLEDGED = {"acknowledged": true}
61
+ DUPLICATED_DATA_STREAM_EXCEPTION = {"error": {}, "status": 400}
62
+ NONEXISTENT_DATA_STREAM_EXCEPTION = {"error": {}, "status": 404}
63
+
64
+ def stub_index_template(name="foo_tpl")
65
+ stub_request(:put, "http://localhost:9200/_index_template/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
66
+ end
67
+
68
+ def stub_data_stream(name="foo")
69
+ stub_request(:put, "http://localhost:9200/_data_stream/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
70
+ end
71
+
72
+ def stub_existent_data_stream?(name="foo")
73
+ stub_request(:get, "http://localhost:9200/_data_stream/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
74
+ end
75
+
76
+ def stub_existent_template?(name="foo_tpl")
77
+ stub_request(:get, "http://localhost:9200/_index_template/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
78
+ end
79
+
80
+ def stub_nonexistent_data_stream?(name="foo")
81
+ stub_request(:get, "http://localhost:9200/_data_stream/#{name}").to_return(:status => [404, OpenSearch::Transport::Transport::Errors::NotFound])
82
+ end
83
+
84
+ def stub_nonexistent_template?(name="foo_tpl")
85
+ stub_request(:get, "http://localhost:9200/_index_template/#{name}").to_return(:status => [404, OpenSearch::Transport::Transport::Errors::NotFound])
86
+ end
87
+
88
+ def stub_bulk_feed(datastream_name="foo", template_name="foo_tpl")
89
+ stub_request(:post, "http://localhost:9200/#{datastream_name}/_bulk").with do |req|
90
+ # bulk data must be pair of OP and records
91
+ # {"create": {}}\nhttp://localhost:9200/_data_stream/foo_bar
92
+ # {"@timestamp": ...}
93
+ @bulk_records += req.body.split("\n").size / 2
94
+ end
95
+ stub_request(:post, "http://localhost:9200/#{template_name}/_bulk").with do |req|
96
+ # bulk data must be pair of OP and records
97
+ # {"create": {}}\nhttp://localhost:9200/_data_stream/foo_bar
98
+ # {"@timestamp": ...}
99
+ @bulk_records += req.body.split("\n").size / 2
100
+ end
101
+ end
102
+
103
+ def stub_elastic_info(url="http://localhost:9200/", version="1.2.2")
104
+ body ="{\"version\":{\"number\":\"#{version}\", \"distribution\":\"opensearch\"},\"tagline\":\"The OpenSearch Project: https://opensearch.org/\"}"
105
+ stub_request(:get, url).to_return({:status => 200, :body => body, :headers => { 'Content-Type' => 'json' } })
106
+ end
107
+
108
+ def stub_default(datastream_name="foo", template_name="foo_tpl", host="http://localhost:9200")
109
+ stub_elastic_info(host)
110
+ stub_nonexistent_template?(template_name)
111
+ stub_index_template(template_name)
112
+ stub_nonexistent_data_stream?(datastream_name)
113
+ stub_data_stream(datastream_name)
114
+ end
115
+
116
+ # ref. https://opensearch.org/docs/latest/opensearch/data-streams/
117
+ class DataStreamNameTest < self
118
+
119
+ def test_missing_data_stream_name
120
+ conf = config_element(
121
+ 'ROOT', '', {
122
+ '@type' => 'opensearch_datastream'
123
+ })
124
+ assert_raise Fluent::ConfigError.new("'data_stream_name' parameter is required") do
125
+ driver(conf).run
126
+ end
127
+ end
128
+
129
+ sub_test_case "invalid uppercase" do
130
+ def test_stream_name
131
+ conf = config_element(
132
+ 'ROOT', '', {
133
+ '@type' => 'opensearch_datastream',
134
+ 'data_stream_name' => 'TEST',
135
+ 'data_stream_template_name' => 'template'
136
+ })
137
+ assert_raise Fluent::ConfigError.new("'data_stream_name' must be lowercase only: <TEST>") do
138
+ driver(conf)
139
+ end
140
+ end
141
+ def test_stream_template_name
142
+ conf = config_element(
143
+ 'ROOT', '', {
144
+ '@type' => 'opensearch_datastream',
145
+ 'data_stream_name' => 'default',
146
+ 'data_stream_template_name' => 'TEST-TPL'
147
+ })
148
+ assert_raise Fluent::ConfigError.new("'data_stream_template_name' must be lowercase only: <TEST-TPL>") do
149
+ driver(conf)
150
+ end
151
+ end
152
+ end
153
+
154
+ sub_test_case "invalid parameters" do
155
+ data("backslash" => "\\",
156
+ "slash" => "/",
157
+ "asterisk" => "*",
158
+ "question" => "?",
159
+ "doublequote" => "\"",
160
+ "lt" => "<",
161
+ "gt" => ">",
162
+ "bar" => "|",
163
+ "space" => " ",
164
+ "comma" => ",",
165
+ "sharp" => "#",
166
+ "colon" => ":")
167
+ def test_stream_name(data)
168
+ c, _ = data
169
+ conf = config_element(
170
+ 'ROOT', '', {
171
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
172
+ 'data_stream_name' => "TEST#{c}",
173
+ 'data_stream_template_name' => "data_stream"
174
+ })
175
+ label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_CHARACTERS.join(',')
176
+ assert_raise Fluent::ConfigError.new("'data_stream_name' must not contain invalid characters #{label}: <TEST#{c}>") do
177
+ driver(conf)
178
+ end
179
+ end
180
+
181
+ data("backslash" => "\\",
182
+ "slash" => "/",
183
+ "asterisk" => "*",
184
+ "question" => "?",
185
+ "doublequote" => "\"",
186
+ "lt" => "<",
187
+ "gt" => ">",
188
+ "bar" => "|",
189
+ "space" => " ",
190
+ "comma" => ",",
191
+ "sharp" => "#",
192
+ "colon" => ":")
193
+ def test_stream_template_name(data)
194
+ c, _ = data
195
+ conf = config_element(
196
+ 'ROOT', '', {
197
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
198
+ 'data_stream_name' => "default",
199
+ 'data_stream_template_name' => "TEST#{c}"
200
+ })
201
+ label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_CHARACTERS.join(',')
202
+ assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not contain invalid characters #{label}: <TEST#{c}>") do
203
+ driver(conf)
204
+ end
205
+ end
206
+ end
207
+
208
+ sub_test_case "invalid start characters" do
209
+ data("hyphen" => "-",
210
+ "underscore" => "_",
211
+ "plus" => "+",
212
+ "period" => ".")
213
+ def test_stream_name(data)
214
+ c, _ = data
215
+ conf = config_element(
216
+ 'ROOT', '', {
217
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
218
+ 'data_stream_name' => "#{c}TEST",
219
+ 'data_stream_template_name' => "template"
220
+ })
221
+ label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_START_CHRACTERS.join(',')
222
+ assert_raise Fluent::ConfigError.new("'data_stream_name' must not start with #{label}: <#{c}TEST>") do
223
+ driver(conf)
224
+ end
225
+ end
226
+
227
+ data("hyphen" => "-",
228
+ "underscore" => "_",
229
+ "plus" => "+",
230
+ "period" => ".")
231
+ def test_stream_template_name(data)
232
+ c, _ = data
233
+ conf = config_element(
234
+ 'ROOT', '', {
235
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
236
+ 'data_stream_name' => "default",
237
+ 'data_stream_template_name' => "#{c}TEST"
238
+ })
239
+ label = Fluent::Plugin::OpenSearchOutputDataStream::INVALID_START_CHRACTERS.join(',')
240
+ assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not start with #{label}: <#{c}TEST>") do
241
+ driver(conf)
242
+ end
243
+ end
244
+ end
245
+
246
+ sub_test_case "invalid dots" do
247
+ data("current" => ".",
248
+ "parents" => "..")
249
+ def test_stream_name
250
+ c, _ = data
251
+ conf = config_element(
252
+ 'ROOT', '', {
253
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
254
+ 'data_stream_name' => "#{c}",
255
+ 'data_stream_template_name' => "template"
256
+ })
257
+ assert_raise Fluent::ConfigError.new("'data_stream_name' must not be . or ..: <#{c}>") do
258
+ driver(conf)
259
+ end
260
+ end
261
+
262
+ data("current" => ".",
263
+ "parents" => "..")
264
+ def test_stream_template_name
265
+ c, _ = data
266
+ conf = config_element(
267
+ 'ROOT', '', {
268
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
269
+ 'data_stream_name' => "default",
270
+ 'data_stream_template_name' => "#{c}"
271
+ })
272
+ assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not be . or ..: <#{c}>") do
273
+ driver(conf)
274
+ end
275
+ end
276
+ end
277
+
278
+ sub_test_case "invalid length" do
279
+ def test_stream_name
280
+ c = "a" * 256
281
+ conf = config_element(
282
+ 'ROOT', '', {
283
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
284
+ 'data_stream_name' => "#{c}",
285
+ 'data_stream_template_name' => "template"
286
+ })
287
+ assert_raise Fluent::ConfigError.new("'data_stream_name' must not be longer than 255 bytes: <#{c}>") do
288
+ driver(conf)
289
+ end
290
+ end
291
+
292
+ def test_stream_template_name
293
+ c = "a" * 256
294
+ conf = config_element(
295
+ 'ROOT', '', {
296
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
297
+ 'data_stream_name' => "default",
298
+ 'data_stream_template_name' => "#{c}"
299
+ })
300
+ assert_raise Fluent::ConfigError.new("'data_stream_template_name' must not be longer than 255 bytes: <#{c}>") do
301
+ driver(conf)
302
+ end
303
+ end
304
+ end
305
+ end
306
+
307
+ def test_datastream_configure
308
+ stub_default
309
+ conf = config_element(
310
+ 'ROOT', '', {
311
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
312
+ 'data_stream_name' => 'foo',
313
+ 'data_stream_template_name' => "foo_tpl"
314
+ })
315
+ assert_equal "foo", driver(conf).instance.data_stream_name
316
+ end
317
+
318
+ def test_existent_data_stream
319
+ stub_index_template
320
+ stub_existent_data_stream?
321
+ stub_data_stream
322
+ stub_elastic_info
323
+ conf = config_element(
324
+ 'ROOT', '', {
325
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
326
+ 'data_stream_name' => 'foo',
327
+ 'data_stream_template_name' => "foo_tpl"
328
+ })
329
+ assert_equal "foo", driver(conf).instance.data_stream_name
330
+ end
331
+
332
+ def test_template_unset
333
+ stub_index_template
334
+ stub_existent_data_stream?
335
+ stub_data_stream
336
+ stub_elastic_info
337
+ conf = config_element(
338
+ 'ROOT', '', {
339
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
340
+ 'data_stream_name' => 'foo',
341
+ })
342
+ assert_equal "foo", driver(conf).instance.data_stream_name
343
+ assert_equal "foo_template", driver(conf).instance.data_stream_template_name
344
+ end
345
+
346
+ def test_placeholder
347
+ dsname = "foo_test"
348
+ tplname = "foo_tpl_test"
349
+ stub_default(dsname, tplname)
350
+ stub_bulk_feed(dsname, tplname)
351
+ conf = config_element(
352
+ 'ROOT', '', {
353
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
354
+ 'data_stream_name' => 'foo_${tag}',
355
+ 'data_stream_template_name' => "foo_tpl_${tag}"
356
+ })
357
+ driver(conf).run(default_tag: 'test') do
358
+ driver.feed(sample_record)
359
+ end
360
+ assert_equal 1, @bulk_records
361
+ end
362
+
363
+ def test_placeholder_params_unset
364
+ dsname = "foo_test"
365
+ tplname = "foo_test_template"
366
+ stub_default(dsname, tplname)
367
+ stub_bulk_feed(dsname, tplname)
368
+ conf = config_element(
369
+ 'ROOT', '', {
370
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
371
+ 'data_stream_name' => 'foo_${tag}',
372
+ })
373
+ driver(conf).run(default_tag: 'test') do
374
+ driver.feed(sample_record)
375
+ end
376
+ assert_equal 1, @bulk_records
377
+ end
378
+
379
+
380
+ def test_time_placeholder
381
+ time = Time.now
382
+ dsname = "foo_#{time.strftime("%Y%m%d")}"
383
+ tplname = "foo_tpl_#{time.strftime("%Y%m%d")}"
384
+ stub_default(dsname, tplname)
385
+ stub_bulk_feed(dsname, tplname)
386
+ conf = config_element(
387
+ 'ROOT', '', {
388
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
389
+ 'data_stream_name' => 'foo_%Y%m%d',
390
+ 'data_stream_template_name' => 'foo_tpl_%Y%m%d'
391
+ }, [config_element('buffer', 'time', {
392
+ 'timekey' => '1d'
393
+ }, [])]
394
+ )
395
+ driver(conf).run(default_tag: 'test') do
396
+ driver.feed(sample_record)
397
+ end
398
+ assert_equal 1, @bulk_records
399
+ end
400
+
401
+ def test_custom_record_placeholder
402
+ keys = ["bar", "baz"]
403
+ keys.each do |key|
404
+ dsname = "foo_#{key}"
405
+ tplname = "foo_tpl_#{key}"
406
+ stub_default(dsname, tplname)
407
+ stub_bulk_feed(dsname, tplname)
408
+ end
409
+ conf = config_element(
410
+ 'ROOT', '', {
411
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
412
+ 'data_stream_name' => 'foo_${key1}',
413
+ 'data_stream_template_name' => 'foo_tpl_${key1}'
414
+ }, [config_element('buffer', 'tag,key1', {
415
+ 'timekey' => '1d'
416
+ }, [])]
417
+ )
418
+ driver(conf).run(default_tag: 'test') do
419
+ keys.each do |key|
420
+ record = sample_record.merge({"key1" => key})
421
+ driver.feed(record)
422
+ end
423
+ end
424
+ assert_equal keys.count, @bulk_records
425
+ end
426
+
427
+ def test_bulk_insert_feed
428
+ stub_default
429
+ stub_bulk_feed
430
+ conf = config_element(
431
+ 'ROOT', '', {
432
+ '@type' => OPENSEARCH_DATA_STREAM_TYPE,
433
+ 'data_stream_name' => 'foo',
434
+ 'data_stream_template_name' => 'foo_tpl'
435
+ })
436
+ driver(conf).run(default_tag: 'test') do
437
+ driver.feed(sample_record)
438
+ end
439
+ assert_equal 1, @bulk_records
440
+ end
441
+
442
+ def test_template_retry_install_fails
443
+ cwd = File.dirname(__FILE__)
444
+ template_file = File.join(cwd, 'test_index_template.json')
445
+
446
+ config = %{
447
+ host logs.google.com
448
+ port 778
449
+ scheme https
450
+ data_stream_name foo
451
+ data_stream_template_name foo_tpl
452
+ user john
453
+ password doe
454
+ template_name logstash
455
+ template_file #{template_file}
456
+ max_retry_putting_template 3
457
+ }
458
+
459
+ connection_resets = 0
460
+ # check if template exists
461
+ stub_request(:get, "https://logs.google.com:778/_index_template/logstash")
462
+ .with(basic_auth: ['john', 'doe']) do |req|
463
+ connection_resets += 1
464
+ raise Faraday::ConnectionFailed, "Test message"
465
+ end
466
+ stub_elastic_info("https://logs.google.com:778/")
467
+
468
+ assert_raise(Fluent::Plugin::OpenSearchError::RetryableOperationExhaustedFailure) do
469
+ driver(config)
470
+ end
471
+
472
+ assert_equal(4, connection_resets)
473
+ end
474
+ end
@@ -0,0 +1,23 @@
1
+ {
2
+ "template": "te*",
3
+ "settings": {
4
+ "number_of_shards": 1
5
+ },
6
+ "mappings": {
7
+ "type1": {
8
+ "_source": {
9
+ "enabled": false
10
+ },
11
+ "properties": {
12
+ "host_name": {
13
+ "type": "string",
14
+ "index": "not_analyzed"
15
+ },
16
+ "created_at": {
17
+ "type": "date",
18
+ "format": "EEE MMM dd HH:mm:ss Z YYYY"
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,61 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ #
3
+ # The fluent-plugin-opensearch Contributors require contributions made to
4
+ # this file be licensed under the Apache-2.0 license or a
5
+ # compatible open source license.
6
+ #
7
+ # Modifications Copyright fluent-plugin-opensearch Contributors. See
8
+ # GitHub history for details.
9
+ #
10
+ # Licensed to Uken Inc. under one or more contributor
11
+ # license agreements. See the NOTICE file distributed with
12
+ # this work for additional information regarding copyright
13
+ # ownership. Uken Inc. licenses this file to you under
14
+ # the Apache License, Version 2.0 (the "License"); you may
15
+ # not use this file except in compliance with the License.
16
+ # You may obtain a copy of the License at
17
+ #
18
+ # http://www.apache.org/licenses/LICENSE-2.0
19
+ #
20
+ # Unless required by applicable law or agreed to in writing,
21
+ # software distributed under the License is distributed on an
22
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23
+ # KIND, either express or implied. See the License for the
24
+ # specific language governing permissions and limitations
25
+ # under the License.
26
+
27
+ require 'helper'
28
+ require 'fluent/log-ext'
29
+
30
+ class TestFluentLogExtHandler < Test::Unit::TestCase
31
+ def setup
32
+ @log_device = Fluent::Test::DummyLogDevice.new
33
+ dl_opts = {:log_level => ServerEngine::DaemonLogger::INFO}
34
+ logger = ServerEngine::DaemonLogger.new(@log_device, dl_opts)
35
+ @log = Fluent::Log.new(logger)
36
+ end
37
+
38
+ def test_trace?
39
+ assert_false @log.respond_to?(:trace?)
40
+ end
41
+
42
+ def test_debug?
43
+ assert_true @log.respond_to?(:debug?)
44
+ end
45
+
46
+ def test_info?
47
+ assert_true @log.respond_to?(:info?)
48
+ end
49
+
50
+ def test_warn?
51
+ assert_true @log.respond_to?(:warn?)
52
+ end
53
+
54
+ def test_error?
55
+ assert_true @log.respond_to?(:error?)
56
+ end
57
+
58
+ def test_fatal?
59
+ assert_true @log.respond_to?(:fatal?)
60
+ end
61
+ end