fluentd 0.14.18 → 0.14.19
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 +18 -0
- data/README.md +3 -2
- data/lib/fluent/plugin/filter_grep.rb +39 -12
- data/lib/fluent/plugin/in_syslog.rb +11 -3
- data/lib/fluent/plugin/output.rb +1 -1
- data/lib/fluent/plugin/parser_syslog.rb +2 -2
- data/lib/fluent/version.rb +1 -1
- data/test/plugin/test_filter_grep.rb +73 -2
- data/test/plugin/test_in_syslog.rb +18 -0
- data/test/plugin/test_in_tail.rb +4 -4
- data/test/plugin/test_parser_syslog.rb +18 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e8cde86e1ab8e515cd2573c413a821fd7fec5ac
|
4
|
+
data.tar.gz: f182030e17d2e1f72c63dffd08dd854e84544923
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 490ef9c95652e18a65713eefdb0003876991c9a0d504b26edd73904cc24d7e9e7048205e056073d6637d10e75e2226ed5e1deb302596916a59dd4a82555f88e3
|
7
|
+
data.tar.gz: dfc41329fc70c653505d251fc9c66f51c4547693723c216c1d01dafa5c8ee38ecca561a3e4cf7aeb11b24879c0c35199265abcf02f659e366029cfcafdb7b96b
|
data/ChangeLog
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# v0.14
|
2
2
|
|
3
|
+
## Release v0.14.19 - 2017/07/12
|
4
|
+
|
5
|
+
### New features / Enhancements
|
6
|
+
|
7
|
+
* in_syslog: More characters are available in tag part of syslog format
|
8
|
+
https://github.com/fluent/fluentd/pull/1610
|
9
|
+
* in_syslog: Add resolve_hostname parameter
|
10
|
+
https://github.com/fluent/fluentd/pull/1616
|
11
|
+
* filter_grep: Support new configuration format by config_section
|
12
|
+
https://github.com/fluent/fluentd/pull/1611
|
13
|
+
|
14
|
+
### Bug fixes
|
15
|
+
|
16
|
+
* output: Fix race condition of retry state in flush thread
|
17
|
+
https://github.com/fluent/fluentd/pull/1623
|
18
|
+
* test: Fix typo in test_in_tail.rb
|
19
|
+
https://github.com/fluent/fluentd/pull/1622
|
20
|
+
|
3
21
|
## Release v0.14.18 - 2017/06/21
|
4
22
|
|
5
23
|
### New features / Enhancements
|
data/README.md
CHANGED
@@ -64,15 +64,16 @@ Many enterprises run Fluentd in production to handle all of their logging needs.
|
|
64
64
|
|
65
65
|
## More Information
|
66
66
|
|
67
|
-
- Website:
|
67
|
+
- Website: https://www.fluentd.org/
|
68
68
|
- Documentation: http://docs.fluentd.org/
|
69
|
-
-
|
69
|
+
- Project repository: http://github.com/fluent
|
70
70
|
- Discussion: http://groups.google.com/group/fluentd
|
71
71
|
- Slack / Community: http://slack.fluentd.org
|
72
72
|
- Newsletters: http://get.treasuredata.com/Fluentd_education
|
73
73
|
- Author: Sadayuki Furuhashi
|
74
74
|
- Copyright: (c) 2011 FURUHASHI Sadayuki
|
75
75
|
- License: Apache License, Version 2.0
|
76
|
+
|
76
77
|
## Contributors:
|
77
78
|
|
78
79
|
Patches contributed by [great developers](https://github.com/fluent/fluentd/contributors).
|
@@ -24,32 +24,59 @@ module Fluent::Plugin
|
|
24
24
|
|
25
25
|
REGEXP_MAX_NUM = 20
|
26
26
|
|
27
|
-
(1..REGEXP_MAX_NUM).each {|i| config_param :"regexp#{i}", :string, default: nil }
|
28
|
-
(1..REGEXP_MAX_NUM).each {|i| config_param :"exclude#{i}", :string, default: nil }
|
27
|
+
(1..REGEXP_MAX_NUM).each {|i| config_param :"regexp#{i}", :string, default: nil, deprecated: "Use <regexp> section" }
|
28
|
+
(1..REGEXP_MAX_NUM).each {|i| config_param :"exclude#{i}", :string, default: nil, deprecated: "Use <exclude> section" }
|
29
|
+
|
30
|
+
config_section :regexp, param_name: :regexps, multi: true do
|
31
|
+
desc "The field name to which the regular expression is applied."
|
32
|
+
config_param :key, :string
|
33
|
+
desc "The regular expression."
|
34
|
+
config_param :pattern do |value|
|
35
|
+
Regexp.compile(value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
config_section :exclude, param_name: :excludes, multi: true do
|
40
|
+
desc "The field name to which the regular expression is applied."
|
41
|
+
config_param :key, :string
|
42
|
+
desc "The regular expression."
|
43
|
+
config_param :pattern do |value|
|
44
|
+
Regexp.compile(value)
|
45
|
+
end
|
46
|
+
end
|
29
47
|
|
30
48
|
# for test
|
31
|
-
attr_reader :
|
32
|
-
attr_reader :
|
49
|
+
attr_reader :_regexps
|
50
|
+
attr_reader :_excludes
|
33
51
|
|
34
52
|
def configure(conf)
|
35
53
|
super
|
36
54
|
|
37
|
-
@
|
55
|
+
@_regexps = {}
|
38
56
|
(1..REGEXP_MAX_NUM).each do |i|
|
39
57
|
next unless conf["regexp#{i}"]
|
40
58
|
key, regexp = conf["regexp#{i}"].split(/ /, 2)
|
41
59
|
raise Fluent::ConfigError, "regexp#{i} does not contain 2 parameters" unless regexp
|
42
|
-
raise Fluent::ConfigError, "regexp#{i} contains a duplicated key, #{key}" if @
|
43
|
-
@
|
60
|
+
raise Fluent::ConfigError, "regexp#{i} contains a duplicated key, #{key}" if @_regexps[key]
|
61
|
+
@_regexps[key] = Regexp.compile(regexp)
|
44
62
|
end
|
45
63
|
|
46
|
-
@
|
64
|
+
@_excludes = {}
|
47
65
|
(1..REGEXP_MAX_NUM).each do |i|
|
48
66
|
next unless conf["exclude#{i}"]
|
49
67
|
key, exclude = conf["exclude#{i}"].split(/ /, 2)
|
50
68
|
raise Fluent::ConfigError, "exclude#{i} does not contain 2 parameters" unless exclude
|
51
|
-
raise Fluent::ConfigError, "exclude#{i} contains a duplicated key, #{key}" if @
|
52
|
-
@
|
69
|
+
raise Fluent::ConfigError, "exclude#{i} contains a duplicated key, #{key}" if @_excludes[key]
|
70
|
+
@_excludes[key] = Regexp.compile(exclude)
|
71
|
+
end
|
72
|
+
|
73
|
+
@regexps.each do |e|
|
74
|
+
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if @_regexps.key?(e.key)
|
75
|
+
@_regexps[e.key] = e.pattern
|
76
|
+
end
|
77
|
+
@excludes.each do |e|
|
78
|
+
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if @_excludes.key?(e.key)
|
79
|
+
@_excludes[e.key] = e.pattern
|
53
80
|
end
|
54
81
|
end
|
55
82
|
|
@@ -57,10 +84,10 @@ module Fluent::Plugin
|
|
57
84
|
result = nil
|
58
85
|
begin
|
59
86
|
catch(:break_loop) do
|
60
|
-
@
|
87
|
+
@_regexps.each do |key, regexp|
|
61
88
|
throw :break_loop unless ::Fluent::StringUtil.match_regexp(regexp, record[key].to_s)
|
62
89
|
end
|
63
|
-
@
|
90
|
+
@_excludes.each do |key, exclude|
|
64
91
|
throw :break_loop if ::Fluent::StringUtil.match_regexp(exclude, record[key].to_s)
|
65
92
|
end
|
66
93
|
result = record
|
@@ -83,6 +83,8 @@ module Fluent::Plugin
|
|
83
83
|
|
84
84
|
desc 'The field name of hostname of sender.'
|
85
85
|
config_param :source_hostname_key, :string, default: nil
|
86
|
+
config_param :resolve_hostname, :bool, default: nil
|
87
|
+
desc 'Connections will be disconnected right after receiving first message if this value is true.'
|
86
88
|
desc 'The field name of source address of sender.'
|
87
89
|
config_param :source_address_key, :string, default: nil
|
88
90
|
desc 'The field name of the priority.'
|
@@ -116,7 +118,13 @@ module Fluent::Plugin
|
|
116
118
|
end
|
117
119
|
@source_address_key = @source_host_key
|
118
120
|
end
|
119
|
-
@
|
121
|
+
if @source_hostname_key
|
122
|
+
if @resolve_hostname.nil?
|
123
|
+
@resolve_hostname = true
|
124
|
+
elsif !@resolve_hostname # user specifies "false" in config
|
125
|
+
raise Fluent::ConfigError, "resolve_hostname must be true with source_hostname_key"
|
126
|
+
end
|
127
|
+
end
|
120
128
|
|
121
129
|
@_event_loop_run_timeout = @blocking_timeout
|
122
130
|
end
|
@@ -138,7 +146,7 @@ module Fluent::Plugin
|
|
138
146
|
end
|
139
147
|
|
140
148
|
def start_udp_server
|
141
|
-
server_create_udp(:in_syslog_udp_server, @port, bind: @bind, max_bytes: @message_length_limit, resolve_name: @
|
149
|
+
server_create_udp(:in_syslog_udp_server, @port, bind: @bind, max_bytes: @message_length_limit, resolve_name: @resolve_hostname) do |data, sock|
|
142
150
|
message_handler(data.chomp, sock)
|
143
151
|
end
|
144
152
|
end
|
@@ -147,7 +155,7 @@ module Fluent::Plugin
|
|
147
155
|
# syslog family add "\n" to each message and this seems only way to split messages in tcp stream
|
148
156
|
delimiter = "\n"
|
149
157
|
delimiter_size = delimiter.size
|
150
|
-
server_create_connection(:in_syslog_tcp_server, @port, bind: @bind, resolve_name: @
|
158
|
+
server_create_connection(:in_syslog_tcp_server, @port, bind: @bind, resolve_name: @resolve_hostname) do |conn|
|
151
159
|
buffer = ""
|
152
160
|
conn.data do |data|
|
153
161
|
buffer << data
|
data/lib/fluent/plugin/output.rb
CHANGED
@@ -1264,7 +1264,7 @@ module Fluent
|
|
1264
1264
|
current_clock = Fluent::Clock.now
|
1265
1265
|
interval = state.next_clock - current_clock
|
1266
1266
|
|
1267
|
-
if state.next_clock <= current_clock &&
|
1267
|
+
if state.next_clock <= current_clock && @retry_mutex.synchronize { @retry ? @retry.next_time <= Time.now : true }
|
1268
1268
|
try_flush
|
1269
1269
|
|
1270
1270
|
# next_flush_time uses flush_thread_interval or flush_thread_burst_interval (or retrying)
|
@@ -24,9 +24,9 @@ module Fluent
|
|
24
24
|
Plugin.register_parser('syslog', self)
|
25
25
|
|
26
26
|
# From existence TextParser pattern
|
27
|
-
REGEXP = /^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[
|
27
|
+
REGEXP = /^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[^ :\[]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
|
28
28
|
# From in_syslog default pattern
|
29
|
-
REGEXP_WITH_PRI = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[
|
29
|
+
REGEXP_WITH_PRI = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[^ :\[]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
|
30
30
|
REGEXP_RFC5424 = /\A^(?<time>[^ ]+) (?<host>[^ ]+) (?<ident>[^ ]+) (?<pid>[-0-9]+) (?<msgid>[^ ]+) (?<extradata>(\[(.*)\]|[^ ])) (?<message>.+)$\z/
|
31
31
|
REGEXP_RFC5424_WITH_PRI = /\A^\<(?<pri>[0-9]{1,3})\>[1-9]\d{0,2} (?<time>[^ ]+) (?<host>[^ ]+) (?<ident>[^ ]+) (?<pid>[-0-9]+) (?<msgid>[^ ]+) (?<extradata>(\[(.*)\]|[^ ])) (?<message>.+)$\z/
|
32
32
|
REGEXP_DETECT_RFC5424 = /^\<.*\>[1-9]\d{0,2}/
|
data/lib/fluent/version.rb
CHANGED
@@ -23,12 +23,51 @@ class GrepFilterTest < Test::Unit::TestCase
|
|
23
23
|
|
24
24
|
test "regexpN can contain a space" do
|
25
25
|
d = create_driver(%[regexp1 message foo])
|
26
|
-
assert_equal(Regexp.compile(/ foo/), d.instance.
|
26
|
+
assert_equal(Regexp.compile(/ foo/), d.instance._regexps['message'])
|
27
27
|
end
|
28
28
|
|
29
29
|
test "excludeN can contain a space" do
|
30
30
|
d = create_driver(%[exclude1 message foo])
|
31
|
-
assert_equal(Regexp.compile(/ foo/), d.instance.
|
31
|
+
assert_equal(Regexp.compile(/ foo/), d.instance._excludes['message'])
|
32
|
+
end
|
33
|
+
|
34
|
+
sub_test_case "duplicate key" do
|
35
|
+
test "flat" do
|
36
|
+
conf = %[
|
37
|
+
regexp1 message test
|
38
|
+
regexp2 message test2
|
39
|
+
]
|
40
|
+
assert_raise(Fluent::ConfigError) do
|
41
|
+
create_driver(conf)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
test "section" do
|
45
|
+
conf = %[
|
46
|
+
<regexp>
|
47
|
+
key message
|
48
|
+
pattern test
|
49
|
+
</regexp>
|
50
|
+
<regexp>
|
51
|
+
key message
|
52
|
+
pattern test2
|
53
|
+
</regexp>
|
54
|
+
]
|
55
|
+
assert_raise(Fluent::ConfigError) do
|
56
|
+
create_driver(conf)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
test "mix" do
|
60
|
+
conf = %[
|
61
|
+
regexp1 message test
|
62
|
+
<regexp>
|
63
|
+
key message
|
64
|
+
pattern test
|
65
|
+
</regexp>
|
66
|
+
]
|
67
|
+
assert_raise(Fluent::ConfigError) do
|
68
|
+
create_driver(conf)
|
69
|
+
end
|
70
|
+
end
|
32
71
|
end
|
33
72
|
end
|
34
73
|
|
@@ -77,6 +116,38 @@ class GrepFilterTest < Test::Unit::TestCase
|
|
77
116
|
end
|
78
117
|
end
|
79
118
|
|
119
|
+
test 'regexps' do
|
120
|
+
conf = %[
|
121
|
+
<regexp>
|
122
|
+
key message
|
123
|
+
pattern WARN
|
124
|
+
</regexp>
|
125
|
+
]
|
126
|
+
filtered_records = filter(conf, messages)
|
127
|
+
assert_equal(3, filtered_records.size)
|
128
|
+
assert_block('only WARN logs') do
|
129
|
+
filtered_records.all? { |r|
|
130
|
+
!r['message'].include?('INFO')
|
131
|
+
}
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
test 'excludes' do
|
136
|
+
conf = %[
|
137
|
+
<exclude>
|
138
|
+
key message
|
139
|
+
pattern favicon
|
140
|
+
</exclude>
|
141
|
+
]
|
142
|
+
filtered_records = filter(conf, messages)
|
143
|
+
assert_equal(3, filtered_records.size)
|
144
|
+
assert_block('remove favicon logs') do
|
145
|
+
filtered_records.all? { |r|
|
146
|
+
!r['message'].include?('favicon')
|
147
|
+
}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
80
151
|
sub_test_case 'with invalid sequence' do
|
81
152
|
def messages
|
82
153
|
[
|
@@ -37,6 +37,24 @@ class SyslogInputTest < Test::Unit::TestCase
|
|
37
37
|
assert_equal bind_addr, d.instance.bind
|
38
38
|
end
|
39
39
|
|
40
|
+
sub_test_case 'source_hostname_key and source_address_key features' do
|
41
|
+
test 'resolve_hostname must be true with source_hostname_key' do
|
42
|
+
assert_raise(Fluent::ConfigError) {
|
43
|
+
create_driver(CONFIG + <<EOS)
|
44
|
+
resolve_hostname false
|
45
|
+
source_hostname_key hostname
|
46
|
+
EOS
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
data('resolve_hostname' => 'resolve_hostname true',
|
51
|
+
'source_hostname_key' => 'source_hostname_key source_host')
|
52
|
+
def test_configure_reslove_hostname(param)
|
53
|
+
d = create_driver([CONFIG, param].join("\n"))
|
54
|
+
assert_true d.instance.resolve_hostname
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
40
58
|
data(
|
41
59
|
ipv4: ['127.0.0.1', CONFIG, ::Socket::AF_INET],
|
42
60
|
ipv6: ['::1', IPv6_CONFIG, ::Socket::AF_INET6],
|
data/test/plugin/test_in_tail.rb
CHANGED
@@ -823,7 +823,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
823
823
|
sub_test_case "path" do
|
824
824
|
# * path test
|
825
825
|
# TODO: Clean up tests
|
826
|
-
|
826
|
+
EX_ROTATE_WAIT = 0
|
827
827
|
|
828
828
|
EX_CONFIG = config_element("", "", {
|
829
829
|
"tag" => "tail",
|
@@ -832,7 +832,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
832
832
|
"pos_file" => "#{TMP_DIR}/tail.pos",
|
833
833
|
"read_from_head" => true,
|
834
834
|
"refresh_interval" => 30,
|
835
|
-
"rotate_wait" => "#{
|
835
|
+
"rotate_wait" => "#{EX_ROTATE_WAIT}s",
|
836
836
|
})
|
837
837
|
EX_PATHS = [
|
838
838
|
'test/plugin/data/2010/01/20100102-030405.log',
|
@@ -926,7 +926,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
926
926
|
Timecop.freeze(2010, 1, 2, 3, 4, 5) do
|
927
927
|
flexstub(Fluent::Plugin::TailInput::TailWatcher) do |watcherclass|
|
928
928
|
EX_PATHS.each do |path|
|
929
|
-
watcherclass.should_receive(:new).with(path,
|
929
|
+
watcherclass.should_receive(:new).with(path, EX_ROTATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, 1000, any, any, any, any, any, any).once.and_return do
|
930
930
|
flexmock('TailWatcher') { |watcher|
|
931
931
|
watcher.should_receive(:attach).once
|
932
932
|
watcher.should_receive(:unwatched=).zero_or_more_times
|
@@ -944,7 +944,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
944
944
|
|
945
945
|
Timecop.freeze(2010, 1, 2, 3, 4, 6) do
|
946
946
|
flexstub(Fluent::Plugin::TailInput::TailWatcher) do |watcherclass|
|
947
|
-
watcherclass.should_receive(:new).with('test/plugin/data/2010/01/20100102-030406.log',
|
947
|
+
watcherclass.should_receive(:new).with('test/plugin/data/2010/01/20100102-030406.log', EX_ROTATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, 1000, any, any, any, any, any, any).once.and_return do
|
948
948
|
flexmock('TailWatcher') do |watcher|
|
949
949
|
watcher.should_receive(:attach).once
|
950
950
|
watcher.should_receive(:unwatched=).zero_or_more_times
|
@@ -64,6 +64,24 @@ class SyslogParserTest < ::Test::Unit::TestCase
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
+
def test_parse_various_characters_for_tag
|
68
|
+
ident = '~!@#$%^&*()_+=-`]{};"\'/?\\,.<>'
|
69
|
+
@parser.configure({})
|
70
|
+
@parser.instance.parse("Feb 28 12:00:00 192.168.0.1 #{ident}[11111]: [error] Syslog test") { |time, record|
|
71
|
+
assert_equal(event_time('Feb 28 12:00:00', format: '%b %d %H:%M:%S'), time)
|
72
|
+
assert_equal(@expected.merge('ident' => ident), record)
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_parse_various_characters_for_tag_with_priority
|
77
|
+
ident = '~!@#$%^&*()_+=-`]{};"\'/?\\,.<>'
|
78
|
+
@parser.configure('with_priority' => true)
|
79
|
+
@parser.instance.parse("<6>Feb 28 12:00:00 192.168.0.1 #{ident}[11111]: [error] Syslog test") { |time, record|
|
80
|
+
assert_equal(event_time('Feb 28 12:00:00', format: '%b %d %H:%M:%S'), time)
|
81
|
+
assert_equal(@expected.merge('pri' => 6, 'ident' => ident), record)
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
67
85
|
class TestRFC5424Regexp < self
|
68
86
|
def test_parse_with_rfc5424_message
|
69
87
|
@parser.configure(
|
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.14.
|
4
|
+
version: 0.14.19
|
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-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|