fluentd 0.12.32 → 0.12.33
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ChangeLog +24 -0
- data/README.md +25 -0
- data/lib/fluent/config/types.rb +2 -2
- data/lib/fluent/log.rb +3 -0
- data/lib/fluent/parser.rb +41 -2
- data/lib/fluent/plugin/in_forward.rb +47 -10
- data/lib/fluent/plugin/in_tail.rb +11 -3
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_types.rb +19 -0
- data/test/plugin/data/log/foo/bar2 +0 -0
- data/test/plugin/test_in_forward.rb +89 -37
- data/test/plugin/test_in_tail.rb +59 -0
- data/test/test_log.rb +4 -0
- data/test/test_parser.rb +189 -9
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: daedf4abbe7d43acdd8df2b8ac75f4f93dc8f252
|
4
|
+
data.tar.gz: 99ea120dbf1257a4be97fc480a4f022b7cc638bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9440abbc6e21242e9281fe3c9ca469fa12f9b47abe8115559c4702fdb5f763fa8576d986434ea76829da45b21a05edfead3217d8ab5cfc798f28de2dea0d982
|
7
|
+
data.tar.gz: dab81f6a5f102c884c0ab0ec6628934aeb5fff690e87ea24148b421fae70e8efab72425b59e8f558052fb8e7f6dd3a097a1268b9af794abd8e4f5e0397b67176
|
data/ChangeLog
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
# v0.12
|
2
2
|
|
3
|
+
## Release 0.12.33 - 2017/03/09
|
4
|
+
|
5
|
+
### New features / Enhancement
|
6
|
+
|
7
|
+
* in_syslog: Backport 'Support rfc5424 syslog format'
|
8
|
+
https://github.com/fluent/fluentd/pull/1495
|
9
|
+
* in_forward: Add source_address_key and fix source_hostname_key parameters
|
10
|
+
https://github.com/fluent/fluentd/pull/1490
|
11
|
+
* in_tail: Skip directories when use **/* in path
|
12
|
+
https://github.com/fluent/fluentd/pull/1464
|
13
|
+
* in_tail: Add limit_recently_modified parameter to limit watching files
|
14
|
+
https://github.com/fluent/fluentd/pull/1474
|
15
|
+
* in_tail: Skip the refresh of watching list on startup
|
16
|
+
https://github.com/fluent/fluentd/pull/1487
|
17
|
+
* parser: Allow escape sequence in Apache access log
|
18
|
+
https://github.com/fluent/fluentd/pull/1479
|
19
|
+
* log: Add Fluent::Log#<< to support some SDKs
|
20
|
+
https://github.com/fluent/fluentd/pull/1478
|
21
|
+
|
22
|
+
### Bug fixes
|
23
|
+
|
24
|
+
* config: Set encoding forcefully to avoid UndefinedConversionError
|
25
|
+
https://github.com/fluent/fluentd/pull/1477
|
26
|
+
|
3
27
|
## Release 0.12.32 - 2017/02/02
|
4
28
|
|
5
29
|
### New features / Enhancement
|
data/README.md
CHANGED
@@ -26,6 +26,31 @@ Mobile/Web Application Logging | Fluentd can function as middleware to enable as
|
|
26
26
|
$ fluentd -c conf/fluent.conf &
|
27
27
|
$ echo '{"json":"message"}' | fluent-cat debug.test
|
28
28
|
|
29
|
+
## Development
|
30
|
+
|
31
|
+
### Prerequisites
|
32
|
+
|
33
|
+
- Ruby 2.1 or later
|
34
|
+
- git
|
35
|
+
|
36
|
+
`git` should be in `PATH`. On Windows, you can use `Github for Windows` and `GitShell` for easy setup.
|
37
|
+
|
38
|
+
### Install dependent gems
|
39
|
+
|
40
|
+
Use bundler:
|
41
|
+
|
42
|
+
$ gem install bundler
|
43
|
+
$ bundle install --path vendor/bundle
|
44
|
+
|
45
|
+
### Run test
|
46
|
+
|
47
|
+
$ bundle exec rake test
|
48
|
+
|
49
|
+
You can run specified test via `TEST` environment variable:
|
50
|
+
|
51
|
+
$ bundle exec rake test TEST=test/test_specified_path.rb
|
52
|
+
$ bundle exec rake test TEST=test/test_*.rb
|
53
|
+
|
29
54
|
## Fluentd UI: Admin GUI
|
30
55
|
|
31
56
|
[Fluentd UI](https://github.com/fluent/fluentd-ui) is a graphical user interface to start/stop/configure Fluentd.
|
data/lib/fluent/config/types.rb
CHANGED
@@ -65,7 +65,7 @@ module Fluent
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
STRING_TYPE = Proc.new { |val, opts| val }
|
68
|
+
STRING_TYPE = Proc.new { |val, opts| val.to_s.force_encoding(Encoding::UTF_8) }
|
69
69
|
ENUM_TYPE = Proc.new { |val, opts|
|
70
70
|
s = val.to_sym
|
71
71
|
list = opts[:list]
|
@@ -86,7 +86,7 @@ module Fluent
|
|
86
86
|
value
|
87
87
|
else
|
88
88
|
case type
|
89
|
-
when :string then value.to_s
|
89
|
+
when :string then value.to_s.force_encoding(Encoding::UTF_8)
|
90
90
|
when :integer then value.to_i
|
91
91
|
when :float then value.to_f
|
92
92
|
when :size then Config.size_value(value)
|
data/lib/fluent/log.rb
CHANGED
data/lib/fluent/parser.rb
CHANGED
@@ -463,7 +463,7 @@ module Fluent
|
|
463
463
|
end
|
464
464
|
|
465
465
|
class ApacheParser < Parser
|
466
|
-
REGEXP = /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/
|
466
|
+
REGEXP = /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>(?:[^\"]|\\.)*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>(?:[^\"]|\\.)*)" "(?<agent>(?:[^\"]|\\.)*)")?$/
|
467
467
|
TIME_FORMAT = "%d/%b/%Y:%H:%M:%S %z"
|
468
468
|
|
469
469
|
def initialize
|
@@ -536,9 +536,13 @@ module Fluent
|
|
536
536
|
REGEXP = /^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
|
537
537
|
# From in_syslog default pattern
|
538
538
|
REGEXP_WITH_PRI = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
|
539
|
+
REGEXP_RFC5424 = /\A^\<(?<pri>[0-9]{1,3})\>[1-9]\d{0,2} (?<time>[^ ]+) (?<host>[^ ]+) (?<ident>[^ ]+) (?<pid>[-0-9]+) (?<msgid>[^ ]+) (?<extradata>(\[(.*)\]|[^ ])) (?<message>.+)$\z/
|
540
|
+
REGEXP_DETECT_RFC5424 = /^\<.*\>[1-9]\d{0,2}/
|
539
541
|
|
540
542
|
config_param :time_format, :string, default: "%b %d %H:%M:%S"
|
541
543
|
config_param :with_priority, :bool, default: false
|
544
|
+
config_param :message_format, :enum, list: [:rfc3164, :rfc5424, :auto], default: :rfc3164
|
545
|
+
config_param :rfc5424_time_format, :string, default: "%Y-%m-%dT%H:%M:%S.%L%z"
|
542
546
|
|
543
547
|
def initialize
|
544
548
|
super
|
@@ -548,7 +552,27 @@ module Fluent
|
|
548
552
|
def configure(conf)
|
549
553
|
super
|
550
554
|
|
551
|
-
@
|
555
|
+
@time_parser_rfc3164 = @time_parser_rfc5424 = nil
|
556
|
+
@regexp = case @message_format
|
557
|
+
when :rfc3164
|
558
|
+
class << self
|
559
|
+
alias_method :parse, :parse_plain
|
560
|
+
end
|
561
|
+
@with_priority ? REGEXP_WITH_PRI : REGEXP
|
562
|
+
when :rfc5424
|
563
|
+
class << self
|
564
|
+
alias_method :parse, :parse_plain
|
565
|
+
end
|
566
|
+
@time_format = @rfc5424_time_format unless conf.has_key?('time_format')
|
567
|
+
REGEXP_RFC5424
|
568
|
+
when :auto
|
569
|
+
class << self
|
570
|
+
alias_method :parse, :parse_auto
|
571
|
+
end
|
572
|
+
@time_parser_rfc3164 = TextParser::TimeParser.new(@time_format)
|
573
|
+
@time_parser_rfc5424 = TextParser::TimeParser.new(@rfc5424_time_format)
|
574
|
+
nil
|
575
|
+
end
|
552
576
|
@time_parser = TextParser::TimeParser.new(@time_format)
|
553
577
|
end
|
554
578
|
|
@@ -557,6 +581,21 @@ module Fluent
|
|
557
581
|
end
|
558
582
|
|
559
583
|
def parse(text)
|
584
|
+
# This is overwritten in configure
|
585
|
+
end
|
586
|
+
|
587
|
+
def parse_auto(text, &block)
|
588
|
+
if REGEXP_DETECT_RFC5424.match(text)
|
589
|
+
@regexp = REGEXP_RFC5424
|
590
|
+
@time_parser = @time_parser_rfc5424
|
591
|
+
else
|
592
|
+
@regexp = @with_priority ? REGEXP_WITH_PRI : REGEXP
|
593
|
+
@time_parser = @time_parser_rfc3164
|
594
|
+
end
|
595
|
+
parse_plain(text, &block)
|
596
|
+
end
|
597
|
+
|
598
|
+
def parse_plain(text, &block)
|
560
599
|
m = @regexp.match(text)
|
561
600
|
unless m
|
562
601
|
if block_given?
|
@@ -47,11 +47,24 @@ module Fluent
|
|
47
47
|
config_param :chunk_size_limit, :size, default: nil
|
48
48
|
desc 'Skip an event if incoming event is invalid.'
|
49
49
|
config_param :skip_invalid_event, :bool, default: false
|
50
|
+
desc 'Try to resolve hostname from IP addresses or not.'
|
51
|
+
config_param :resolve_hostname, :bool, default: nil
|
52
|
+
desc "The field name of the client's source address."
|
53
|
+
config_param :source_address_key, :string, default: nil
|
50
54
|
desc "The field name of the client's hostname."
|
51
55
|
config_param :source_hostname_key, :string, default: nil
|
52
56
|
|
53
57
|
def configure(conf)
|
54
58
|
super
|
59
|
+
|
60
|
+
if @source_hostname_key
|
61
|
+
if @resolve_hostname.nil?
|
62
|
+
@resolve_hostname = true
|
63
|
+
elsif !@resolve_hostname # user specifies "false" in configure
|
64
|
+
raise Fluent::ConfigError, "resolve_hostname must be true with source_hostname_key"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@enable_field_injection = @source_address_key || @source_hostname_key
|
55
68
|
end
|
56
69
|
|
57
70
|
def start
|
@@ -88,7 +101,7 @@ module Fluent
|
|
88
101
|
|
89
102
|
def listen
|
90
103
|
log.info "listening fluent socket on #{@bind}:#{@port}"
|
91
|
-
s = Coolio::TCPServer.new(@bind, @port, Handler, @linger_timeout, log, method(:on_message))
|
104
|
+
s = Coolio::TCPServer.new(@bind, @port, Handler, @linger_timeout, log, @resolve_hostname, method(:on_message))
|
92
105
|
s.listen(@backlog) unless @backlog.nil?
|
93
106
|
s
|
94
107
|
end
|
@@ -161,7 +174,7 @@ module Fluent
|
|
161
174
|
# PackedForward
|
162
175
|
es = MessagePackEventStream.new(entries)
|
163
176
|
es = check_and_skip_invalid_event(tag, es, peeraddr) if @skip_invalid_event
|
164
|
-
es = add_source_host(es, peeraddr
|
177
|
+
es = add_source_host(es, peeraddr) if @enable_field_injection
|
165
178
|
router.emit_stream(tag, es)
|
166
179
|
option = msg[2]
|
167
180
|
|
@@ -180,7 +193,7 @@ module Fluent
|
|
180
193
|
}
|
181
194
|
es
|
182
195
|
end
|
183
|
-
es = add_source_host(es, peeraddr
|
196
|
+
es = add_source_host(es, peeraddr) if @enable_field_injection
|
184
197
|
router.emit_stream(tag, es)
|
185
198
|
option = msg[2]
|
186
199
|
|
@@ -194,7 +207,10 @@ module Fluent
|
|
194
207
|
end
|
195
208
|
return if record.nil?
|
196
209
|
time = Engine.now if time == 0
|
197
|
-
|
210
|
+
if @enable_field_injection
|
211
|
+
record[@source_hostname_key] = peeraddr[2] if @source_hostname_key
|
212
|
+
record[@source_address_key] = peeraddr[3] if @source_address_key
|
213
|
+
end
|
198
214
|
router.emit(tag, time, record)
|
199
215
|
option = msg[3]
|
200
216
|
end
|
@@ -219,12 +235,31 @@ module Fluent
|
|
219
235
|
new_es
|
220
236
|
end
|
221
237
|
|
222
|
-
def add_source_host(es,
|
238
|
+
def add_source_host(es, peeraddr)
|
223
239
|
new_es = MultiEventStream.new
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
240
|
+
if @source_address_key && @source_hostname_key
|
241
|
+
address = peeraddr[3]
|
242
|
+
hostname = peeraddr[2]
|
243
|
+
es.each { |time, record|
|
244
|
+
record[@source_address_key] = address
|
245
|
+
record[@source_hostname_key] = hostname
|
246
|
+
new_es.add(time, record)
|
247
|
+
}
|
248
|
+
elsif @source_address_key
|
249
|
+
address = peeraddr[3]
|
250
|
+
es.each { |time, record|
|
251
|
+
record[@source_address_key] = address
|
252
|
+
new_es.add(time, record)
|
253
|
+
}
|
254
|
+
elsif @source_hostname_key
|
255
|
+
hostname = peeraddr[2]
|
256
|
+
es.each { |time, record|
|
257
|
+
record[@source_hostname_key] = hostname
|
258
|
+
new_es.add(time, record)
|
259
|
+
}
|
260
|
+
else
|
261
|
+
raise "BUG: don't call this method in this case"
|
262
|
+
end
|
228
263
|
new_es
|
229
264
|
end
|
230
265
|
|
@@ -236,11 +271,13 @@ module Fluent
|
|
236
271
|
class Handler < Coolio::Socket
|
237
272
|
PEERADDR_FAILED = ["?", "?", "name resolusion failed", "?"]
|
238
273
|
|
239
|
-
def initialize(io, linger_timeout, log, on_message)
|
274
|
+
def initialize(io, linger_timeout, log, resolve_hostname, on_message)
|
240
275
|
super(io)
|
241
276
|
|
242
277
|
@peeraddr = nil
|
243
278
|
if io.is_a?(TCPSocket) # for unix domain socket support in the future
|
279
|
+
io.do_not_reverse_lookup = !resolve_hostname unless resolve_hostname.nil?
|
280
|
+
|
244
281
|
@peeraddr = (io.peeraddr rescue PEERADDR_FAILED)
|
245
282
|
opt = [1, linger_timeout].pack('I!I!') # { int l_onoff; int l_linger; }
|
246
283
|
io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
|
@@ -58,6 +58,10 @@ module Fluent
|
|
58
58
|
config_param :from_encoding, :string, default: nil
|
59
59
|
desc 'Add the log path being tailed to records. Specify the field name to be used.'
|
60
60
|
config_param :path_key, :string, default: nil
|
61
|
+
desc 'Limit the watching files that the modification time is within the specified time range (when use \'*\' in path).'
|
62
|
+
config_param :limit_recently_modified, :time, default: nil
|
63
|
+
desc 'Enable the option to skip the refresh of watching list on startup.'
|
64
|
+
config_param :skip_refresh_on_startup, :bool, default: false
|
61
65
|
|
62
66
|
attr_reader :paths
|
63
67
|
|
@@ -128,7 +132,7 @@ module Fluent
|
|
128
132
|
end
|
129
133
|
|
130
134
|
@loop = Coolio::Loop.new
|
131
|
-
refresh_watchers
|
135
|
+
refresh_watchers unless @skip_refresh_on_startup
|
132
136
|
|
133
137
|
@refresh_trigger = TailWatcher::TimerWatcher.new(@refresh_interval, true, log, &method(:refresh_watchers))
|
134
138
|
@refresh_trigger.attach(@loop)
|
@@ -153,8 +157,12 @@ module Fluent
|
|
153
157
|
path = date.strftime(path)
|
154
158
|
if path.include?('*')
|
155
159
|
paths += Dir.glob(path).select { |p|
|
156
|
-
if File.readable?(p)
|
157
|
-
|
160
|
+
if File.readable?(p) && !File.directory?(p)
|
161
|
+
if @limit_recently_modified && File.mtime(p) < (date - @limit_recently_modified)
|
162
|
+
false
|
163
|
+
else
|
164
|
+
true
|
165
|
+
end
|
158
166
|
else
|
159
167
|
log.warn "#{p} unreadable. It is excluded and would be examined next time."
|
160
168
|
false
|
data/lib/fluent/version.rb
CHANGED
data/test/config/test_types.rb
CHANGED
@@ -68,6 +68,17 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
68
68
|
assert_equal ' ', Config::STRING_TYPE.call(' ', {})
|
69
69
|
end
|
70
70
|
|
71
|
+
data('latin' => 'Märch',
|
72
|
+
'ascii' => 'ascii',
|
73
|
+
'space' => ' ',
|
74
|
+
'number' => '1',
|
75
|
+
'Hiragana' => 'あいうえお')
|
76
|
+
test 'string w/ binary' do |str|
|
77
|
+
actual = Config::STRING_TYPE.call(str.b, {})
|
78
|
+
assert_equal str, actual
|
79
|
+
assert_equal Encoding::UTF_8, actual.encoding
|
80
|
+
end
|
81
|
+
|
71
82
|
test 'enum' do
|
72
83
|
assert_equal :val, Config::ENUM_TYPE.call('val', {list: [:val, :value, :v]})
|
73
84
|
assert_equal :v, Config::ENUM_TYPE.call('v', {list: [:val, :value, :v]})
|
@@ -142,6 +153,14 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
142
153
|
assert_raise(RuntimeError.new("unknown type in REFORMAT: foo")){ Config::HASH_TYPE.call("x:1,y:2", {value_type: :foo}) }
|
143
154
|
end
|
144
155
|
|
156
|
+
data('latin' => ['3:Märch', {"3"=>"Märch"}],
|
157
|
+
'ascii' => ['ascii:ascii', {"ascii"=>"ascii"}],
|
158
|
+
'number' => ['number:1', {"number"=>"1"}],
|
159
|
+
'Hiragana' => ['hiragana:あいうえお', {"hiragana"=>"あいうえお"}])
|
160
|
+
test 'hash w/ binary' do |(target, expected)|
|
161
|
+
assert_equal(expected, Config::HASH_TYPE.call(target.b, { value_type: :string }))
|
162
|
+
end
|
163
|
+
|
145
164
|
test 'array' do
|
146
165
|
assert_equal(["1","2",1], Config::ARRAY_TYPE.call('["1","2",1]', {}))
|
147
166
|
assert_equal(["1","2","1"], Config::ARRAY_TYPE.call('1,2,1', {}))
|
File without changes
|
@@ -498,52 +498,104 @@ class ForwardInputTest < Test::Unit::TestCase
|
|
498
498
|
@responses << res if try_to_receive_response
|
499
499
|
end
|
500
500
|
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
501
|
+
LOCALHOST_HOSTNAME_GETTER = ->(){sock = UDPSocket.new(::Socket::AF_INET); sock.do_not_reverse_lookup = false; sock.connect("127.0.0.1", 2048); sock.peeraddr[2] }
|
502
|
+
LOCALHOST_HOSTNAME = LOCALHOST_HOSTNAME_GETTER.call
|
503
|
+
DUMMY_SOCK = Struct.new(:remote_host, :remote_addr, :remote_port).new(LOCALHOST_HOSTNAME, "127.0.0.1", 0)
|
504
|
+
|
505
|
+
sub_test_case 'source_hostname_key and source_address_key features' do
|
506
|
+
test 'resolve_hostname must be true with source_hostname_key' do
|
507
|
+
assert_raise(Fluent::ConfigError) {
|
508
|
+
create_driver(CONFIG + <<EOS)
|
509
|
+
resolve_hostname false
|
510
|
+
source_hostname_key hostname
|
511
|
+
EOS
|
506
512
|
}
|
507
|
-
|
508
|
-
|
513
|
+
end
|
514
|
+
data(
|
515
|
+
both: [:hostname, :address],
|
516
|
+
hostname: [:hostname],
|
517
|
+
address: [:address],
|
518
|
+
)
|
519
|
+
test 'message protocol' do |keys|
|
520
|
+
execute_test(*keys) { |events|
|
521
|
+
events.each { |tag, time, record|
|
522
|
+
send_data [tag, time, record].to_msgpack
|
523
|
+
}
|
524
|
+
}
|
525
|
+
end
|
509
526
|
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
527
|
+
data(
|
528
|
+
both: [:hostname, :address],
|
529
|
+
hostname: [:hostname],
|
530
|
+
address: [:address],
|
531
|
+
)
|
532
|
+
test 'forward protocol' do |keys|
|
533
|
+
execute_test(*keys) { |events|
|
534
|
+
entries = []
|
535
|
+
events.each {|tag,time,record|
|
536
|
+
entries << [time, record]
|
537
|
+
}
|
538
|
+
send_data ['tag1', entries].to_msgpack
|
515
539
|
}
|
516
|
-
|
517
|
-
}
|
518
|
-
end
|
540
|
+
end
|
519
541
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
542
|
+
data(
|
543
|
+
both: [:hostname, :address],
|
544
|
+
hostname: [:hostname],
|
545
|
+
address: [:address],
|
546
|
+
)
|
547
|
+
test 'packed forward protocol' do |keys|
|
548
|
+
execute_test(*keys) { |events|
|
549
|
+
entries = ''
|
550
|
+
events.each { |tag, time, record|
|
551
|
+
Fluent::Engine.msgpack_factory.packer(entries).write([time, record]).flush
|
552
|
+
}
|
553
|
+
send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
|
525
554
|
}
|
526
|
-
|
527
|
-
}
|
528
|
-
end
|
555
|
+
end
|
529
556
|
|
530
|
-
|
531
|
-
|
557
|
+
def execute_test(*keys, &block)
|
558
|
+
conf = CONFIG.dup
|
559
|
+
if keys.include?(:hostname)
|
560
|
+
conf << <<EOL
|
561
|
+
source_hostname_key source_hostname
|
562
|
+
EOL
|
563
|
+
end
|
564
|
+
if keys.include?(:address)
|
565
|
+
conf << <<EOL
|
566
|
+
source_address_key source_address
|
567
|
+
EOL
|
568
|
+
end
|
569
|
+
d = create_driver(conf)
|
532
570
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
571
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
572
|
+
events = [
|
573
|
+
["tag1", time, {"a"=>1}],
|
574
|
+
["tag1", time, {"a"=>2}]
|
575
|
+
]
|
576
|
+
d.expected_emits_length = events.length
|
539
577
|
|
540
|
-
|
541
|
-
|
542
|
-
|
578
|
+
d.run do
|
579
|
+
block.call(events)
|
580
|
+
end
|
543
581
|
|
544
|
-
|
545
|
-
|
546
|
-
|
582
|
+
d.emits.each { |tag, _time, record|
|
583
|
+
if keys.include?(:hostname)
|
584
|
+
assert_true record.has_key?('source_hostname')
|
585
|
+
assert_equal DUMMY_SOCK.remote_host, record['source_hostname']
|
586
|
+
unless keys.include?(:address)
|
587
|
+
assert_false record.has_key?('source_address')
|
588
|
+
end
|
589
|
+
end
|
590
|
+
if keys.include?(:address)
|
591
|
+
assert_true record.has_key?('source_address')
|
592
|
+
assert_equal DUMMY_SOCK.remote_addr, record['source_address']
|
593
|
+
unless keys.include?(:hostname)
|
594
|
+
assert_false record.has_key?('source_hostname')
|
595
|
+
end
|
596
|
+
end
|
597
|
+
}
|
598
|
+
end
|
547
599
|
end
|
548
600
|
|
549
601
|
# TODO heartbeat
|
data/test/plugin/test_in_tail.rb
CHANGED
@@ -2,6 +2,7 @@ require_relative '../helper'
|
|
2
2
|
require 'fluent/test'
|
3
3
|
require 'net/http'
|
4
4
|
require 'flexmock/test_unit'
|
5
|
+
require 'timecop'
|
5
6
|
|
6
7
|
class TailInputTest < Test::Unit::TestCase
|
7
8
|
include FlexMock::TestCase
|
@@ -697,6 +698,25 @@ class TailInputTest < Test::Unit::TestCase
|
|
697
698
|
assert_equal EX_PATHS - [EX_PATHS.last], plugin.expand_paths.sort
|
698
699
|
end
|
699
700
|
|
701
|
+
def test_log_file_without_extension
|
702
|
+
expected_files = [
|
703
|
+
'test/plugin/data/log/bar',
|
704
|
+
'test/plugin/data/log/foo/bar.log',
|
705
|
+
'test/plugin/data/log/foo/bar2',
|
706
|
+
'test/plugin/data/log/test.log'
|
707
|
+
]
|
708
|
+
|
709
|
+
config = config_element("", "", {
|
710
|
+
"tag" => "tail",
|
711
|
+
"path" => "test/plugin/data/log/**/*",
|
712
|
+
"format" => "none",
|
713
|
+
"pos_file" => "#{TMP_DIR}/tail.pos"
|
714
|
+
})
|
715
|
+
|
716
|
+
plugin = create_driver(config, false).instance
|
717
|
+
assert_equal expected_files, plugin.expand_paths.sort
|
718
|
+
end
|
719
|
+
|
700
720
|
def test_refresh_watchers
|
701
721
|
plugin = create_driver(EX_CONFIG, false).instance
|
702
722
|
sio = StringIO.new
|
@@ -992,4 +1012,43 @@ class TailInputTest < Test::Unit::TestCase
|
|
992
1012
|
assert_equal(files, [emits[2][2]["path"], emits[3][2]["path"]].sort)
|
993
1013
|
end
|
994
1014
|
end
|
1015
|
+
|
1016
|
+
def test_limit_recently_modified
|
1017
|
+
now = Time.new(2010, 1, 2, 3, 4, 5)
|
1018
|
+
FileUtils.touch("#{TMP_DIR}/tail_unwatch.txt", mtime: (now - 3601))
|
1019
|
+
FileUtils.touch("#{TMP_DIR}/tail_watch1.txt", mtime: (now - 3600))
|
1020
|
+
FileUtils.touch("#{TMP_DIR}/tail_watch2.txt", mtime: now)
|
1021
|
+
|
1022
|
+
config = config_element('', '', {
|
1023
|
+
'tag' => 'tail',
|
1024
|
+
'path' => "#{TMP_DIR}/*.txt",
|
1025
|
+
'format' => 'none',
|
1026
|
+
'limit_recently_modified' => '3600s'
|
1027
|
+
})
|
1028
|
+
|
1029
|
+
expected_files = [
|
1030
|
+
"#{TMP_DIR}/tail_watch1.txt",
|
1031
|
+
"#{TMP_DIR}/tail_watch2.txt"
|
1032
|
+
]
|
1033
|
+
|
1034
|
+
Timecop.freeze(now) do
|
1035
|
+
plugin = create_driver(config, false).instance
|
1036
|
+
assert_equal expected_files, plugin.expand_paths.sort
|
1037
|
+
end
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
def test_skip_refresh_on_startup
|
1041
|
+
FileUtils.touch("#{TMP_DIR}/tail.txt")
|
1042
|
+
config = config_element('', '', {
|
1043
|
+
'tag' => 'tail',
|
1044
|
+
'path' => "#{TMP_DIR}/*.txt",
|
1045
|
+
'format' => 'none',
|
1046
|
+
'refresh_interval' => 1,
|
1047
|
+
'skip_refresh_on_startup' => true
|
1048
|
+
})
|
1049
|
+
d = create_driver(config, false)
|
1050
|
+
d.run {
|
1051
|
+
sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size == 1
|
1052
|
+
}
|
1053
|
+
end
|
995
1054
|
end
|
data/test/test_log.rb
CHANGED
data/test/test_parser.rb
CHANGED
@@ -292,6 +292,14 @@ module ParserTest
|
|
292
292
|
assert_equal(@expected, record)
|
293
293
|
}
|
294
294
|
end
|
295
|
+
|
296
|
+
def test_parse_with_escape_sequence
|
297
|
+
@parser.parse('192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] "GET /\" HTTP/1.1" 200 777 "referer \\\ \"" "user agent \\\ \""') { |_, record|
|
298
|
+
assert_equal('/\"', record['path'])
|
299
|
+
assert_equal('referer \\\ \"', record['referer'])
|
300
|
+
assert_equal('user agent \\\ \"', record['agent'])
|
301
|
+
}
|
302
|
+
end
|
295
303
|
end
|
296
304
|
|
297
305
|
class SyslogParserTest < ::Test::Unit::TestCase
|
@@ -356,6 +364,182 @@ module ParserTest
|
|
356
364
|
assert_equal "Feb 28 00:00:12", record['time']
|
357
365
|
end
|
358
366
|
end
|
367
|
+
|
368
|
+
class TestRFC5424Regexp < self
|
369
|
+
def test_parse_with_rfc5424_message
|
370
|
+
@parser.configure(
|
371
|
+
'time_format' => '%Y-%m-%dT%H:%M:%S.%L%z',
|
372
|
+
'message_format' => 'rfc5424',
|
373
|
+
)
|
374
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd - - - Hi, from Fluentd!'
|
375
|
+
@parser.parse(text) do |time, record|
|
376
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
377
|
+
assert_equal "-", record["pid"]
|
378
|
+
assert_equal "-", record["msgid"]
|
379
|
+
assert_equal "-", record["extradata"]
|
380
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_parse_with_rfc5424_message_without_time_format
|
385
|
+
@parser.configure(
|
386
|
+
'message_format' => 'rfc5424',
|
387
|
+
)
|
388
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd - - - Hi, from Fluentd!'
|
389
|
+
@parser.instance.parse(text) do |time, record|
|
390
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
391
|
+
assert_equal "-", record["pid"]
|
392
|
+
assert_equal "-", record["msgid"]
|
393
|
+
assert_equal "-", record["extradata"]
|
394
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_parse_with_rfc5424_structured_message
|
399
|
+
@parser.configure(
|
400
|
+
'time_format' => '%Y-%m-%dT%H:%M:%S.%L%z',
|
401
|
+
'message_format' => 'rfc5424',
|
402
|
+
)
|
403
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd 11111 ID24224 [exampleSDID@20224 iut="3" eventSource="Application" eventID="11211"] Hi, from Fluentd!'
|
404
|
+
@parser.parse(text) do |time, record|
|
405
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
406
|
+
assert_equal "11111", record["pid"]
|
407
|
+
assert_equal "ID24224", record["msgid"]
|
408
|
+
assert_equal "[exampleSDID@20224 iut=\"3\" eventSource=\"Application\" eventID=\"11211\"]",
|
409
|
+
record["extradata"]
|
410
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
class TestAutoRegexp < self
|
416
|
+
def test_auto_with_legacy_syslog_message
|
417
|
+
@parser.configure(
|
418
|
+
'time_format' => '%b %d %M:%S:%H',
|
419
|
+
'mseeage_format' => 'auto',
|
420
|
+
)
|
421
|
+
text = 'Feb 28 00:00:12 192.168.0.1 fluentd[11111]: [error] Syslog test'
|
422
|
+
@parser.parse(text) do |time, record|
|
423
|
+
assert_equal(event_time("Feb 28 00:00:12", format: '%b %d %M:%S:%H'), time)
|
424
|
+
assert_equal(@expected, record)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_auto_with_legacy_syslog_priority_message
|
429
|
+
@parser.configure(
|
430
|
+
'time_format' => '%b %d %M:%S:%H',
|
431
|
+
'with_priority' => true,
|
432
|
+
'mseeage_format' => 'auto',
|
433
|
+
)
|
434
|
+
text = '<6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test'
|
435
|
+
@parser.parse(text) do |time, record|
|
436
|
+
assert_equal(event_time("Feb 28 12:00:00", format: '%b %d %M:%S:%H'), time)
|
437
|
+
assert_equal(@expected.merge('pri' => 6), record)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
def test_parse_with_rfc5424_message
|
442
|
+
@parser.configure(
|
443
|
+
'time_format' => '%Y-%m-%dT%H:%M:%S.%L%z',
|
444
|
+
'message_format' => 'auto',
|
445
|
+
)
|
446
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd - - - Hi, from Fluentd!'
|
447
|
+
@parser.parse(text) do |time, record|
|
448
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
449
|
+
assert_equal "-", record["pid"]
|
450
|
+
assert_equal "-", record["msgid"]
|
451
|
+
assert_equal "-", record["extradata"]
|
452
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
def test_parse_with_rfc5424_structured_message
|
457
|
+
@parser.configure(
|
458
|
+
'time_format' => '%Y-%m-%dT%H:%M:%S.%L%z',
|
459
|
+
'message_format' => 'auto',
|
460
|
+
)
|
461
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd 11111 ID24224 [exampleSDID@20224 iut="3" eventSource="Application" eventID="11211"] Hi, from Fluentd!'
|
462
|
+
@parser.parse(text) do |time, record|
|
463
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
464
|
+
assert_equal "11111", record["pid"]
|
465
|
+
assert_equal "ID24224", record["msgid"]
|
466
|
+
assert_equal "[exampleSDID@20224 iut=\"3\" eventSource=\"Application\" eventID=\"11211\"]",
|
467
|
+
record["extradata"]
|
468
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
def test_parse_with_both_message_type
|
473
|
+
@parser.configure(
|
474
|
+
'time_format' => '%b %d %M:%S:%H',
|
475
|
+
'rfc5424_time_format' => '%Y-%m-%dT%H:%M:%S.%L%z',
|
476
|
+
'message_format' => 'auto',
|
477
|
+
)
|
478
|
+
text = 'Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test'
|
479
|
+
@parser.parse(text) do |time, record|
|
480
|
+
assert_equal(event_time("Feb 28 12:00:00", format: '%b %d %M:%S:%H'), time)
|
481
|
+
assert_equal(@expected, record)
|
482
|
+
end
|
483
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd 11111 ID24224 [exampleSDID@20224 iut="3" eventSource="Application" eventID="11211"] Hi, from Fluentd!'
|
484
|
+
@parser.parse(text) do |time, record|
|
485
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
486
|
+
assert_equal "11111", record["pid"]
|
487
|
+
assert_equal "ID24224", record["msgid"]
|
488
|
+
assert_equal "[exampleSDID@20224 iut=\"3\" eventSource=\"Application\" eventID=\"11211\"]",
|
489
|
+
record["extradata"]
|
490
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
491
|
+
end
|
492
|
+
text = 'Feb 28 12:00:02 192.168.0.1 fluentd[11111]: [error] Syslog test'
|
493
|
+
@parser.parse(text) do |time, record|
|
494
|
+
assert_equal(event_time("Feb 28 12:00:02", format: '%b %d %M:%S:%H'), time)
|
495
|
+
assert_equal(@expected, record)
|
496
|
+
end
|
497
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd - - - Hi, from Fluentd!'
|
498
|
+
@parser.parse(text) do |time, record|
|
499
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
500
|
+
assert_equal "-", record["pid"]
|
501
|
+
assert_equal "-", record["msgid"]
|
502
|
+
assert_equal "-", record["extradata"]
|
503
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
504
|
+
end
|
505
|
+
end
|
506
|
+
|
507
|
+
def test_parse_with_both_message_type_and_priority
|
508
|
+
@parser.configure(
|
509
|
+
'time_format' => '%b %d %M:%S:%H',
|
510
|
+
'rfc5424_time_format' => '%Y-%m-%dT%H:%M:%S.%L%z',
|
511
|
+
'with_priority' => true,
|
512
|
+
'message_format' => 'auto',
|
513
|
+
)
|
514
|
+
text = '<6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test'
|
515
|
+
@parser.parse(text) do |time, record|
|
516
|
+
assert_equal(event_time("Feb 28 12:00:00", format: '%b %d %M:%S:%H'), time)
|
517
|
+
assert_equal(@expected.merge('pri' => 6), record)
|
518
|
+
end
|
519
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd 11111 ID24224 [exampleSDID@20224 iut="3" eventSource="Application" eventID="11211"] Hi, from Fluentd!'
|
520
|
+
@parser.parse(text) do |time, record|
|
521
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
522
|
+
assert_equal "11111", record["pid"]
|
523
|
+
assert_equal "ID24224", record["msgid"]
|
524
|
+
assert_equal "[exampleSDID@20224 iut=\"3\" eventSource=\"Application\" eventID=\"11211\"]",
|
525
|
+
record["extradata"]
|
526
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
527
|
+
end
|
528
|
+
text = '<16>Feb 28 12:00:02 192.168.0.1 fluentd[11111]: [error] Syslog test'
|
529
|
+
@parser.parse(text) do |time, record|
|
530
|
+
assert_equal(event_time("Feb 28 12:00:02", format: '%b %d %M:%S:%H'), time)
|
531
|
+
assert_equal(@expected.merge('pri' => 16), record)
|
532
|
+
end
|
533
|
+
text = '<16>1 2017-02-06T13:14:15.003Z 192.168.0.1 fluentd - - - Hi, from Fluentd!'
|
534
|
+
@parser.parse(text) do |time, record|
|
535
|
+
assert_equal(event_time("2017-02-06T13:14:15.003Z", format: '%Y-%m-%dT%H:%M:%S.%L%z'), time)
|
536
|
+
assert_equal "-", record["pid"]
|
537
|
+
assert_equal "-", record["msgid"]
|
538
|
+
assert_equal "-", record["extradata"]
|
539
|
+
assert_equal "Hi, from Fluentd!", record["message"]
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|
359
543
|
end
|
360
544
|
|
361
545
|
class JsonParserTest < ::Test::Unit::TestCase
|
@@ -572,11 +756,10 @@ module ParserTest
|
|
572
756
|
end
|
573
757
|
|
574
758
|
data('array param' => '["a","b","c","d","e","f"]', 'string param' => 'a,b,c,d,e,f')
|
575
|
-
def test_parse_with_null_value_pattern
|
759
|
+
def test_parse_with_null_value_pattern(param)
|
576
760
|
parser = TextParser::TSVParser.new
|
577
761
|
parser.configure(
|
578
762
|
'keys'=>param,
|
579
|
-
'time_key'=>'time',
|
580
763
|
'null_value_pattern'=>'^(-|null|NULL)$'
|
581
764
|
)
|
582
765
|
parser.parse("-\tnull\tNULL\t\t--\tnuLL") do |time, record|
|
@@ -590,11 +773,10 @@ module ParserTest
|
|
590
773
|
end
|
591
774
|
|
592
775
|
data('array param' => '["a","b"]', 'string param' => 'a,b')
|
593
|
-
def test_parse_with_null_empty_string
|
776
|
+
def test_parse_with_null_empty_string(param)
|
594
777
|
parser = TextParser::TSVParser.new
|
595
778
|
parser.configure(
|
596
779
|
'keys'=>param,
|
597
|
-
'time_key'=>'time',
|
598
780
|
'null_empty_string'=>true
|
599
781
|
)
|
600
782
|
parser.parse("\t ") do |time, record|
|
@@ -661,29 +843,27 @@ module ParserTest
|
|
661
843
|
end
|
662
844
|
|
663
845
|
data('array param' => '["a","b","c","d","e","f"]', 'string param' => 'a,b,c,d,e,f')
|
664
|
-
def test_parse_with_null_value_pattern
|
846
|
+
def test_parse_with_null_value_pattern(param)
|
665
847
|
parser = TextParser::CSVParser.new
|
666
848
|
parser.configure(
|
667
849
|
'keys'=>param,
|
668
|
-
'time_key'=>'time',
|
669
850
|
'null_value_pattern'=>'^(-|null|NULL)$'
|
670
851
|
)
|
671
852
|
parser.parse("-,null,NULL,,--,nuLL") do |time, record|
|
672
853
|
assert_nil record['a']
|
673
854
|
assert_nil record['b']
|
674
855
|
assert_nil record['c']
|
675
|
-
|
856
|
+
assert_nil record['d']
|
676
857
|
assert_equal record['e'], '--'
|
677
858
|
assert_equal record['f'], 'nuLL'
|
678
859
|
end
|
679
860
|
end
|
680
861
|
|
681
862
|
data('array param' => '["a","b"]', 'string param' => 'a,b')
|
682
|
-
def test_parse_with_null_empty_string
|
863
|
+
def test_parse_with_null_empty_string(param)
|
683
864
|
parser = TextParser::CSVParser.new
|
684
865
|
parser.configure(
|
685
866
|
'keys'=>param,
|
686
|
-
'time_key'=>'time',
|
687
867
|
'null_empty_string'=>true
|
688
868
|
)
|
689
869
|
parser.parse(", ") do |time, record|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluentd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.33
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -425,6 +425,7 @@ files:
|
|
425
425
|
- test/plugin/data/2010/01/20100102.log
|
426
426
|
- test/plugin/data/log/bar
|
427
427
|
- test/plugin/data/log/foo/bar.log
|
428
|
+
- test/plugin/data/log/foo/bar2
|
428
429
|
- test/plugin/data/log/test.log
|
429
430
|
- test/plugin/test_buf_file.rb
|
430
431
|
- test/plugin/test_buf_memory.rb
|
@@ -515,6 +516,7 @@ test_files:
|
|
515
516
|
- test/plugin/data/2010/01/20100102.log
|
516
517
|
- test/plugin/data/log/bar
|
517
518
|
- test/plugin/data/log/foo/bar.log
|
519
|
+
- test/plugin/data/log/foo/bar2
|
518
520
|
- test/plugin/data/log/test.log
|
519
521
|
- test/plugin/test_buf_file.rb
|
520
522
|
- test/plugin/test_buf_memory.rb
|