fluentd 1.1.3 → 1.2.0.pre1
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.md +7 -7
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/lib/fluent/config/types.rb +13 -0
- data/lib/fluent/configurable.rb +1 -0
- data/lib/fluent/plugin/filter_grep.rb +103 -36
- data/lib/fluent/plugin/parser_apache.rb +1 -1
- data/lib/fluent/plugin/parser_apache_error.rb +1 -1
- data/lib/fluent/plugin/parser_ltsv.rb +1 -3
- data/lib/fluent/plugin/parser_multiline.rb +1 -1
- data/lib/fluent/plugin/parser_nginx.rb +1 -1
- data/lib/fluent/plugin/parser_regexp.rb +12 -14
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_config_parser.rb +5 -0
- data/test/config/test_configure_proxy.rb +4 -3
- data/test/config/test_types.rb +29 -0
- data/test/plugin/test_filter_grep.rb +437 -4
- data/test/plugin/test_in_exec.rb +3 -5
- data/test/plugin/test_parser_nginx.rb +20 -0
- data/test/plugin/test_parser_regexp.rb +6 -7
- metadata +4 -5
- data/COPYING +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e457fdb0637a4e2ca90d91766e53db7d1a35b44c
|
4
|
+
data.tar.gz: 71aad06bb2784901e8e1517b6433536321fdeeae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98f12edb338eb087180087c0d10ed0d23070d06333ee39784faf24c4190ae39cce899e43f0644728a50768743b872954ad90fbd9a962caf67efe0c8ea0b12547
|
7
|
+
data.tar.gz: 7ce0e7b63dcbd094c3c9452851fc91c3660e44ed69fbc3cc7aa67d53cf96ac615f9c172957d0092c054250aa4c12a09837c0f1965e3caa02153a7d092070e449
|
data/CHANGELOG.md
CHANGED
@@ -31,7 +31,7 @@
|
|
31
31
|
|
32
32
|
* in_tail: Handle records in the correct order on file rotation
|
33
33
|
https://github.com/fluent/fluentd/pull/1880
|
34
|
-
* out_forward: Fix race condition with
|
34
|
+
* out_forward: Fix race condition with `<security>` on multi thread environment
|
35
35
|
https://github.com/fluent/fluentd/pull/1893
|
36
36
|
* output: Prevent flushing threads consume too much CPU when retry happens
|
37
37
|
https://github.com/fluent/fluentd/pull/1901
|
@@ -261,7 +261,7 @@ See [CNCF announcment](https://www.cncf.io/blog/2017/12/06/fluentd-v1-0/) :)
|
|
261
261
|
|
262
262
|
* plugin: Add record_accessor plugin helper
|
263
263
|
https://github.com/fluent/fluentd/pull/1637
|
264
|
-
* log: Add format and time_format parameters to
|
264
|
+
* log: Add format and time_format parameters to `<system>` setting
|
265
265
|
https://github.com/fluent/fluentd/pull/1644
|
266
266
|
|
267
267
|
### Bug fixes
|
@@ -355,7 +355,7 @@ See [CNCF announcment](https://www.cncf.io/blog/2017/12/06/fluentd-v1-0/) :)
|
|
355
355
|
|
356
356
|
### New features / Enhancements
|
357
357
|
|
358
|
-
* Add
|
358
|
+
* Add `<worker N>` directive
|
359
359
|
https://github.com/fluent/fluentd/pull/1507
|
360
360
|
* in_tail: Do not warn that directories are unreadable in the in_tail plugin
|
361
361
|
https://github.com/fluent/fluentd/pull/1540
|
@@ -410,7 +410,7 @@ See [CNCF announcment](https://www.cncf.io/blog/2017/12/06/fluentd-v1-0/) :)
|
|
410
410
|
https://github.com/fluent/fluentd/pull/1477
|
411
411
|
* Fix Input and Output deadlock when buffer is full during startup
|
412
412
|
https://github.com/fluent/fluentd/pull/1502
|
413
|
-
* config: Fix log_level handling in
|
413
|
+
* config: Fix log_level handling in `<system>`
|
414
414
|
https://github.com/fluent/fluentd/pull/1501
|
415
415
|
* Fix typo in root agent error log
|
416
416
|
https://github.com/fluent/fluentd/pull/1491
|
@@ -505,7 +505,7 @@ See [CNCF announcment](https://www.cncf.io/blog/2017/12/06/fluentd-v1-0/) :)
|
|
505
505
|
## Release v0.14.11 - 2016/12/26
|
506
506
|
|
507
507
|
### New features / Enhancements
|
508
|
-
* Add "root_dir" parameter in
|
508
|
+
* Add "root_dir" parameter in `<system>` directive to configure server root directory, used for buffer/storage paths
|
509
509
|
https://github.com/fluent/fluentd/pull/1374
|
510
510
|
* Fix not to restart Fluentd processes when unrecoverable errors occur
|
511
511
|
https://github.com/fluent/fluentd/pull/1359
|
@@ -633,7 +633,7 @@ See [CNCF announcment](https://www.cncf.io/blog/2017/12/06/fluentd-v1-0/) :)
|
|
633
633
|
https://github.com/fluent/fluentd/pull/1207
|
634
634
|
* Add a feature to parse/format numeric time (unix time [+ subsecond value])
|
635
635
|
https://github.com/fluent/fluentd/pull/1254
|
636
|
-
* Raise configuration errors for inconsistent
|
636
|
+
* Raise configuration errors for inconsistent `<label>` configurations
|
637
637
|
https://github.com/fluent/fluentd/pull/1233
|
638
638
|
* Fix to instantiate an unconfigured section even for multi: true
|
639
639
|
https://github.com/fluent/fluentd/pull/1210
|
@@ -959,7 +959,7 @@ This list includes changes of 0.14.0.pre.1 and release candidates.
|
|
959
959
|
https://github.com/fluent/fluentd/pull/838
|
960
960
|
* Move TypeConverter mixin to mixin.rb
|
961
961
|
https://github.com/fluent/fluentd/pull/842
|
962
|
-
* Override default configurations by
|
962
|
+
* Override default configurations by `<system>`
|
963
963
|
https://github.com/fluent/fluentd/pull/854
|
964
964
|
* Suppress Ruby level warnings
|
965
965
|
https://github.com/fluent/fluentd/pull/846
|
data/LICENSE
CHANGED
@@ -187,7 +187,7 @@
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
188
188
|
identification within third-party archives.
|
189
189
|
|
190
|
-
Copyright
|
190
|
+
Copyright 2011-2018 Fluentd Authors
|
191
191
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
193
193
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
@@ -73,7 +73,7 @@ Many enterprises run Fluentd in production to handle all of their logging needs.
|
|
73
73
|
- Slack / Community: https://slack.fluentd.org
|
74
74
|
- Newsletters: https://www.fluentd.org/newsletter_signup
|
75
75
|
- Author: Sadayuki Furuhashi
|
76
|
-
- Copyright:
|
76
|
+
- Copyright: 2011-2018 Fluentd Authors
|
77
77
|
- License: Apache License, Version 2.0
|
78
78
|
|
79
79
|
## Contributors:
|
data/lib/fluent/config/types.rb
CHANGED
@@ -70,6 +70,17 @@ module Fluent
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
def self.regexp_value(str)
|
74
|
+
return nil unless str
|
75
|
+
return Regexp.compile(str) unless str.start_with?("/")
|
76
|
+
right_slash_position = str.rindex("/")
|
77
|
+
options = str[(right_slash_position + 1)..-1]
|
78
|
+
option = 0
|
79
|
+
option |= Regexp::IGNORECASE if options.include?("i")
|
80
|
+
option |= Regexp::MULTILINE if options.include?("m")
|
81
|
+
Regexp.compile(str[1...right_slash_position], option)
|
82
|
+
end
|
83
|
+
|
73
84
|
STRING_TYPE = Proc.new { |val, opts|
|
74
85
|
v = val.to_s
|
75
86
|
v = v.frozen? ? v.dup : v # config_param can't assume incoming string is mutable
|
@@ -89,6 +100,7 @@ module Fluent
|
|
89
100
|
SIZE_TYPE = Proc.new { |val, opts| Config.size_value(val) }
|
90
101
|
BOOL_TYPE = Proc.new { |val, opts| Config.bool_value(val) }
|
91
102
|
TIME_TYPE = Proc.new { |val, opts| Config.time_value(val) }
|
103
|
+
REGEXP_TYPE = Proc.new { |val, opts| Config.regexp_value(val) }
|
92
104
|
|
93
105
|
REFORMAT_VALUE = ->(type, value) {
|
94
106
|
if value.nil?
|
@@ -101,6 +113,7 @@ module Fluent
|
|
101
113
|
when :size then Config.size_value(value)
|
102
114
|
when :bool then Config.bool_value(value)
|
103
115
|
when :time then Config.time_value(value)
|
116
|
+
when :regexp then Config.regexp_value(value)
|
104
117
|
else
|
105
118
|
raise "unknown type in REFORMAT: #{type}"
|
106
119
|
end
|
data/lib/fluent/configurable.rb
CHANGED
@@ -25,10 +25,15 @@ module Fluent::Plugin
|
|
25
25
|
def initialize
|
26
26
|
super
|
27
27
|
|
28
|
-
@
|
29
|
-
@
|
28
|
+
@_regexp_and_conditions = []
|
29
|
+
@_exclude_and_conditions = []
|
30
|
+
@_regexp_or_conditions = []
|
31
|
+
@_exclude_or_conditions = []
|
30
32
|
end
|
31
33
|
|
34
|
+
# for test
|
35
|
+
attr_reader :_regexp_and_conditions, :_exclude_and_conditions, :_regexp_or_conditions, :_exclude_or_conditions
|
36
|
+
|
32
37
|
helpers :record_accessor
|
33
38
|
|
34
39
|
REGEXP_MAX_NUM = 20
|
@@ -40,79 +45,135 @@ module Fluent::Plugin
|
|
40
45
|
desc "The field name to which the regular expression is applied."
|
41
46
|
config_param :key, :string
|
42
47
|
desc "The regular expression."
|
43
|
-
config_param :pattern
|
44
|
-
if value.start_with?("/") and value.end_with?("/")
|
45
|
-
Regexp.compile(value[1..-2])
|
46
|
-
else
|
47
|
-
Regexp.compile(value)
|
48
|
-
end
|
49
|
-
end
|
48
|
+
config_param :pattern, :regexp
|
50
49
|
end
|
51
50
|
|
52
51
|
config_section :exclude, param_name: :excludes, multi: true do
|
53
52
|
desc "The field name to which the regular expression is applied."
|
54
53
|
config_param :key, :string
|
55
54
|
desc "The regular expression."
|
56
|
-
config_param :pattern
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
config_param :pattern, :regexp
|
56
|
+
end
|
57
|
+
|
58
|
+
config_section :and, param_name: :and_conditions, multi: true do
|
59
|
+
config_section :regexp, param_name: :regexps, multi: true do
|
60
|
+
desc "The field name to which the regular expression is applied."
|
61
|
+
config_param :key, :string
|
62
|
+
desc "The regular expression."
|
63
|
+
config_param :pattern, :regexp
|
64
|
+
end
|
65
|
+
config_section :exclude, param_name: :excludes, multi: true do
|
66
|
+
desc "The field name to which the regular expression is applied."
|
67
|
+
config_param :key, :string
|
68
|
+
desc "The regular expression."
|
69
|
+
config_param :pattern, :regexp
|
62
70
|
end
|
63
71
|
end
|
64
72
|
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
config_section :or, param_name: :or_conditions, multi: true do
|
74
|
+
config_section :regexp, param_name: :regexps, multi: true do
|
75
|
+
desc "The field name to which the regular expression is applied."
|
76
|
+
config_param :key, :string
|
77
|
+
desc "The regular expression."
|
78
|
+
config_param :pattern, :regexp
|
79
|
+
end
|
80
|
+
config_section :exclude, param_name: :excludes, multi: true do
|
81
|
+
desc "The field name to which the regular expression is applied."
|
82
|
+
config_param :key, :string
|
83
|
+
desc "The regular expression."
|
84
|
+
config_param :pattern, :regexp
|
85
|
+
end
|
86
|
+
end
|
68
87
|
|
69
88
|
def configure(conf)
|
70
89
|
super
|
71
90
|
|
72
|
-
|
91
|
+
regexp_and_conditions = {}
|
92
|
+
regexp_or_conditions = {}
|
93
|
+
exclude_and_conditions = {}
|
94
|
+
exclude_or_conditions = {}
|
95
|
+
|
73
96
|
(1..REGEXP_MAX_NUM).each do |i|
|
74
97
|
next unless conf["regexp#{i}"]
|
75
98
|
key, regexp = conf["regexp#{i}"].split(/ /, 2)
|
76
99
|
raise Fluent::ConfigError, "regexp#{i} does not contain 2 parameters" unless regexp
|
77
|
-
raise Fluent::ConfigError, "regexp#{i} contains a duplicated key, #{key}" if
|
78
|
-
|
100
|
+
raise Fluent::ConfigError, "regexp#{i} contains a duplicated key, #{key}" if regexp_and_conditions[key]
|
101
|
+
regexp_and_conditions[key] = Expression.new(record_accessor_create(key), Regexp.compile(regexp))
|
79
102
|
end
|
80
103
|
|
81
|
-
es = {}
|
82
104
|
(1..REGEXP_MAX_NUM).each do |i|
|
83
105
|
next unless conf["exclude#{i}"]
|
84
106
|
key, exclude = conf["exclude#{i}"].split(/ /, 2)
|
85
107
|
raise Fluent::ConfigError, "exclude#{i} does not contain 2 parameters" unless exclude
|
86
|
-
raise Fluent::ConfigError, "exclude#{i} contains a duplicated key, #{key}" if
|
87
|
-
|
108
|
+
raise Fluent::ConfigError, "exclude#{i} contains a duplicated key, #{key}" if exclude_or_conditions[key]
|
109
|
+
exclude_or_conditions[key] = Expression.new(record_accessor_create(key), Regexp.compile(exclude))
|
88
110
|
end
|
89
111
|
|
112
|
+
if @regexps.size > 1
|
113
|
+
log.info "Top level multiple <regexp> is intepreted as 'and' condition"
|
114
|
+
end
|
90
115
|
@regexps.each do |e|
|
91
|
-
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if
|
92
|
-
|
116
|
+
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if regexp_and_conditions.key?(e.key)
|
117
|
+
regexp_and_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
118
|
+
end
|
119
|
+
|
120
|
+
if @excludes.size > 1
|
121
|
+
log.info "Top level multiple <exclude> is intepreted as 'or' condition"
|
93
122
|
end
|
94
123
|
@excludes.each do |e|
|
95
|
-
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if
|
96
|
-
|
124
|
+
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if exclude_or_conditions.key?(e.key)
|
125
|
+
exclude_or_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
97
126
|
end
|
98
127
|
|
99
|
-
|
100
|
-
|
128
|
+
@and_conditions.each do |and_condition|
|
129
|
+
if !and_condition.regexps.empty? && !and_condition.excludes.empty?
|
130
|
+
raise Fluent::ConfigError, "Do not specify both <regexp> and <exclude> in <and>"
|
131
|
+
end
|
132
|
+
and_condition.regexps.each do |e|
|
133
|
+
raise Fluent::ConfigError, "Duplicate key in <and>: #{e.key}" if regexp_and_conditions.key?(e.key)
|
134
|
+
regexp_and_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
135
|
+
end
|
136
|
+
and_condition.excludes.each do |e|
|
137
|
+
raise Fluent::ConfigError, "Duplicate key in <and>: #{e.key}" if exclude_and_conditions.key?(e.key)
|
138
|
+
exclude_and_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
139
|
+
end
|
101
140
|
end
|
102
|
-
|
103
|
-
|
141
|
+
|
142
|
+
@or_conditions.each do |or_condition|
|
143
|
+
if !or_condition.regexps.empty? && !or_condition.excludes.empty?
|
144
|
+
raise Fluent::ConfigError, "Do not specify both <regexp> and <exclude> in <or>"
|
145
|
+
end
|
146
|
+
or_condition.regexps.each do |e|
|
147
|
+
raise Fluent::ConfigError, "Duplicate key in <or>: #{e.key}" if regexp_or_conditions.key?(e.key)
|
148
|
+
regexp_or_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
149
|
+
end
|
150
|
+
or_condition.excludes.each do |e|
|
151
|
+
raise Fluent::ConfigError, "Duplicate key in <or>: #{e.key}" if exclude_or_conditions.key?(e.key)
|
152
|
+
exclude_or_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
153
|
+
end
|
104
154
|
end
|
155
|
+
|
156
|
+
@_regexp_and_conditions = regexp_and_conditions.values
|
157
|
+
@_exclude_and_conditions = exclude_and_conditions.values
|
158
|
+
@_regexp_or_conditions = regexp_or_conditions.values
|
159
|
+
@_exclude_or_conditions = exclude_or_conditions.values
|
105
160
|
end
|
106
161
|
|
107
162
|
def filter(tag, time, record)
|
108
163
|
result = nil
|
109
164
|
begin
|
110
165
|
catch(:break_loop) do
|
111
|
-
@
|
112
|
-
throw :break_loop unless
|
166
|
+
@_regexp_and_conditions.each do |expression|
|
167
|
+
throw :break_loop unless expression.match?(record)
|
168
|
+
end
|
169
|
+
if !@_regexp_or_conditions.empty? && @_regexp_or_conditions.none? {|expression| expression.match?(record) }
|
170
|
+
throw :break_loop
|
171
|
+
end
|
172
|
+
if !@_exclude_and_conditions.empty? && @_exclude_and_conditions.all? {|expression| expression.match?(record) }
|
173
|
+
throw :break_loop
|
113
174
|
end
|
114
|
-
@
|
115
|
-
throw :break_loop if
|
175
|
+
@_exclude_or_conditions.each do |expression|
|
176
|
+
throw :break_loop if expression.match?(record)
|
116
177
|
end
|
117
178
|
result = record
|
118
179
|
end
|
@@ -122,5 +183,11 @@ module Fluent::Plugin
|
|
122
183
|
end
|
123
184
|
result
|
124
185
|
end
|
186
|
+
|
187
|
+
Expression = Struct.new(:key, :pattern) do
|
188
|
+
def match?(record)
|
189
|
+
::Fluent::StringUtil.match_regexp(pattern, key.call(record).to_s)
|
190
|
+
end
|
191
|
+
end
|
125
192
|
end
|
126
193
|
end
|
@@ -21,7 +21,7 @@ module Fluent
|
|
21
21
|
class ApacheParser < RegexpParser
|
22
22
|
Plugin.register_parser("apache", self)
|
23
23
|
|
24
|
-
config_set_default :expression,
|
24
|
+
config_set_default :expression, /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/
|
25
25
|
config_set_default :time_format, "%d/%b/%Y:%H:%M:%S %z"
|
26
26
|
end
|
27
27
|
end
|
@@ -20,7 +20,7 @@ module Fluent
|
|
20
20
|
module Plugin
|
21
21
|
class ApacheErrorParser < RegexpParser
|
22
22
|
Plugin.register_parser("apache_error", self)
|
23
|
-
config_set_default :expression,
|
23
|
+
config_set_default :expression, /^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])?( \[client (?<client>[^\]]*)\])? (?<message>.*)$/
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -24,9 +24,7 @@ module Fluent
|
|
24
24
|
desc 'The delimiter character (or string) of TSV values'
|
25
25
|
config_param :delimiter, :string, default: "\t"
|
26
26
|
desc 'The delimiter pattern of TSV values'
|
27
|
-
config_param :delimiter_pattern, default: nil
|
28
|
-
Regexp.compile(value[1..-2]) if value
|
29
|
-
end
|
27
|
+
config_param :delimiter_pattern, :regexp, default: nil
|
30
28
|
desc 'The delimiter character between field name and value'
|
31
29
|
config_param :label_delimiter, :string, default: ":"
|
32
30
|
|
@@ -36,7 +36,7 @@ module Fluent
|
|
36
36
|
if regexp.named_captures.empty?
|
37
37
|
raise "No named captures"
|
38
38
|
end
|
39
|
-
regexp_conf = Fluent::Config::Element.new("", "", { "expression" => "/#{formats}/"
|
39
|
+
regexp_conf = Fluent::Config::Element.new("", "", { "expression" => "/#{formats}/m" }, [])
|
40
40
|
@parser = Fluent::Plugin::RegexpParser.new
|
41
41
|
@parser.configure(conf + regexp_conf)
|
42
42
|
rescue => e
|
@@ -21,7 +21,7 @@ module Fluent
|
|
21
21
|
class NginxParser < RegexpParser
|
22
22
|
Plugin.register_parser("nginx", self)
|
23
23
|
|
24
|
-
config_set_default :expression,
|
24
|
+
config_set_default :expression, /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?:\s+(?<http_x_forwarded_for>[^ ]+))?)?$/
|
25
25
|
config_set_default :time_format, "%d/%b/%Y:%H:%M:%S %z"
|
26
26
|
end
|
27
27
|
end
|
@@ -22,30 +22,28 @@ module Fluent
|
|
22
22
|
Plugin.register_parser("regexp", self)
|
23
23
|
|
24
24
|
desc 'Regular expression for matching logs'
|
25
|
-
config_param :expression, :
|
25
|
+
config_param :expression, :regexp
|
26
26
|
desc 'Ignore case in matching'
|
27
|
-
config_param :ignorecase, :bool, default: false
|
27
|
+
config_param :ignorecase, :bool, default: false, deprecated: "Use /pattern/i instead, this option is no longer effective"
|
28
28
|
desc 'Build regular expression as a multline mode'
|
29
|
-
config_param :multiline, :bool, default: false
|
29
|
+
config_param :multiline, :bool, default: false, deprecated: "Use /pattern/m instead, this option is no longer effective"
|
30
30
|
|
31
31
|
config_set_default :time_key, 'time'
|
32
32
|
|
33
33
|
def configure(conf)
|
34
34
|
super
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
regexp_option |= Regexp::MULTILINE if @multiline
|
44
|
-
@regexp = Regexp.new(expr, regexp_option)
|
35
|
+
# For compat layer
|
36
|
+
if @ignorecase || @multiline
|
37
|
+
options = 0
|
38
|
+
options |= Regexp::IGNORECASE if @ignorecase
|
39
|
+
options |= Regexp::MULTILINE if @multiline
|
40
|
+
@expression = Regexp.compile(@expression.source, options)
|
41
|
+
end
|
42
|
+
@regexp = @expression # For backward compatibility
|
45
43
|
end
|
46
44
|
|
47
45
|
def parse(text)
|
48
|
-
m = @
|
46
|
+
m = @expression.match(text)
|
49
47
|
unless m
|
50
48
|
yield nil, nil
|
51
49
|
return
|
data/lib/fluent/version.rb
CHANGED
@@ -35,6 +35,7 @@ module Fluent::Config
|
|
35
35
|
config_param :param_time, :time
|
36
36
|
config_param :param_hash, :hash
|
37
37
|
config_param :param_array, :array
|
38
|
+
config_param :param_regexp, :regexp
|
38
39
|
end
|
39
40
|
|
40
41
|
class TestV1Parser < ::Test::Unit::TestCase
|
@@ -451,6 +452,7 @@ module Fluent::Config
|
|
451
452
|
param_time 10m
|
452
453
|
param_hash { "key1": "value1", "key2": 2 }
|
453
454
|
param_array ["value1", "value2", 100]
|
455
|
+
param_regexp /pattern/
|
454
456
|
])
|
455
457
|
target = AllTypes.new.configure(conf)
|
456
458
|
assert_equal(conf.to_s, target.config.to_s)
|
@@ -465,6 +467,7 @@ module Fluent::Config
|
|
465
467
|
param_time 10m
|
466
468
|
param_hash {"key1":"value1","key2":2}
|
467
469
|
param_array ["value1","value2",100]
|
470
|
+
param_regexp /pattern/
|
468
471
|
</ROOT>
|
469
472
|
DUMP
|
470
473
|
assert_equal(expected, conf.to_s)
|
@@ -490,6 +493,7 @@ DUMP
|
|
490
493
|
param_time 10m
|
491
494
|
param_hash { "key1": "value1", "key2": 2 }
|
492
495
|
param_array ["value1", "value2", 100]
|
496
|
+
param_regexp /pattern/
|
493
497
|
])
|
494
498
|
target = AllTypes.new.configure(conf)
|
495
499
|
assert_equal(conf.to_s, target.config.to_s)
|
@@ -504,6 +508,7 @@ DUMP
|
|
504
508
|
param_time 10m
|
505
509
|
param_hash { "key1": "value1", "key2": 2 }
|
506
510
|
param_array ["value1", "value2", 100]
|
511
|
+
param_regexp /pattern/
|
507
512
|
</ROOT>
|
508
513
|
DUMP
|
509
514
|
assert_equal(expected, conf.to_s)
|
@@ -193,9 +193,10 @@ module Fluent::Config
|
|
193
193
|
assert_nothing_raised{ @proxy.config_param(:p7, :time, **opt) }
|
194
194
|
assert_nothing_raised{ @proxy.config_param(:p8, :hash, **opt) }
|
195
195
|
assert_nothing_raised{ @proxy.config_param(:p9, :array, **opt) }
|
196
|
+
assert_nothing_raised{ @proxy.config_param(:pa, :regexp, **opt) }
|
196
197
|
end
|
197
198
|
|
198
|
-
data(string: :string, integer: :integer, float: :float, size: :size, bool: :bool, time: :time, hash: :hash, array: :array)
|
199
|
+
data(string: :string, integer: :integer, float: :float, size: :size, bool: :bool, time: :time, hash: :hash, array: :array, regexp: :regexp)
|
199
200
|
test 'deny list for non-enum types' do |type|
|
200
201
|
assert_raise ArgumentError.new(":list is valid only for :enum type, but #{type}: arg") do
|
201
202
|
@proxy.config_argument(:arg, type, list: [:a, :b])
|
@@ -205,7 +206,7 @@ module Fluent::Config
|
|
205
206
|
end
|
206
207
|
end
|
207
208
|
|
208
|
-
data(string: :string, integer: :integer, float: :float, size: :size, bool: :bool, time: :time)
|
209
|
+
data(string: :string, integer: :integer, float: :float, size: :size, bool: :bool, time: :time, regexp: :regexp)
|
209
210
|
test 'deny value_type for non-hash/array types' do |type|
|
210
211
|
assert_raise ArgumentError.new(":value_type is valid only for :hash and :array, but #{type}: arg") do
|
211
212
|
@proxy.config_argument(:arg, type, value_type: :string)
|
@@ -215,7 +216,7 @@ module Fluent::Config
|
|
215
216
|
end
|
216
217
|
end
|
217
218
|
|
218
|
-
data(string: :string, integer: :integer, float: :float, size: :size, bool: :bool, time: :time, array: :array)
|
219
|
+
data(string: :string, integer: :integer, float: :float, size: :size, bool: :bool, time: :time, array: :array, regexp: :regexp)
|
219
220
|
test 'deny symbolize_keys for non-hash types' do |type|
|
220
221
|
assert_raise ArgumentError.new(":symbolize_keys is valid only for :hash, but #{type}: arg") do
|
221
222
|
@proxy.config_argument(:arg, type, symbolize_keys: true)
|
data/test/config/test_types.rb
CHANGED
@@ -61,6 +61,26 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
sub_test_case 'Config.regexp_value' do
|
65
|
+
data("empty" => [//, "//"],
|
66
|
+
"plain" => [/regexp/, "/regexp/"],
|
67
|
+
"zero width" => [/^$/, "/^$/"],
|
68
|
+
"character classes" => [/[a-z]/, "/[a-z]/"],
|
69
|
+
"meta charactersx" => [/.+.*?\d\w\s\S/, '/.+.*?\d\w\s\S/'])
|
70
|
+
test 'normal case' do |(expected, str)|
|
71
|
+
assert_equal(expected, Config.regexp_value(str))
|
72
|
+
end
|
73
|
+
|
74
|
+
data("empty" => [//, ""],
|
75
|
+
"plain" => [/regexp/, "regexp"],
|
76
|
+
"zero width" => [/^$/, "^$"],
|
77
|
+
"character classes" => [/[a-z]/, "[a-z]"],
|
78
|
+
"meta charactersx" => [/.+.*?\d\w\s\S/, '.+.*?\d\w\s\S'])
|
79
|
+
test 'w/o slashes' do |(expected, str)|
|
80
|
+
assert_equal(expected, Config.regexp_value(str))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
64
84
|
sub_test_case 'type converters for config_param definitions' do
|
65
85
|
test 'string' do
|
66
86
|
assert_equal 'test', Config::STRING_TYPE.call('test', {})
|
@@ -134,6 +154,15 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
134
154
|
assert_equal 86400, Config::TIME_TYPE.call('1d', {})
|
135
155
|
end
|
136
156
|
|
157
|
+
data("empty" => [//, "//"],
|
158
|
+
"plain" => [/regexp/, "/regexp/"],
|
159
|
+
"zero width" => [/^$/, "/^$/"],
|
160
|
+
"character classes" => [/[a-z]/, "/[a-z]/"],
|
161
|
+
"meta charactersx" => [/.+.*?\d\w\s\S/, '/.+.*?\d\w\s\S/'])
|
162
|
+
test 'regexp' do |(expected, str)|
|
163
|
+
assert_equal(expected, Config::REGEXP_TYPE.call(str, {}))
|
164
|
+
end
|
165
|
+
|
137
166
|
test 'hash' do
|
138
167
|
assert_equal({"x"=>"v","k"=>1}, Config::HASH_TYPE.call('{"x":"v","k":1}', {}))
|
139
168
|
assert_equal({"x"=>"v","k"=>"1"}, Config::HASH_TYPE.call('x:v,k:1', {}))
|
@@ -23,15 +23,15 @@ 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
|
-
d.instance.
|
27
|
-
assert_equal(Regexp.compile(/ foo/), value)
|
26
|
+
d.instance._regexp_and_conditions.each { |value|
|
27
|
+
assert_equal(Regexp.compile(/ foo/), value.pattern)
|
28
28
|
}
|
29
29
|
end
|
30
30
|
|
31
31
|
test "excludeN can contain a space" do
|
32
32
|
d = create_driver(%[exclude1 message foo])
|
33
|
-
d.instance.
|
34
|
-
assert_equal(Regexp.compile(/ foo/), value)
|
33
|
+
d.instance._exclude_or_conditions.each { |value|
|
34
|
+
assert_equal(Regexp.compile(/ foo/), value.pattern)
|
35
35
|
}
|
36
36
|
end
|
37
37
|
|
@@ -72,6 +72,118 @@ class GrepFilterTest < Test::Unit::TestCase
|
|
72
72
|
create_driver(conf)
|
73
73
|
end
|
74
74
|
end
|
75
|
+
|
76
|
+
test "and/regexp" do
|
77
|
+
conf = %[
|
78
|
+
<and>
|
79
|
+
<regexp>
|
80
|
+
key message
|
81
|
+
pattern test
|
82
|
+
</regexp>
|
83
|
+
<regexp>
|
84
|
+
key message
|
85
|
+
pattern test
|
86
|
+
</regexp>
|
87
|
+
</and>
|
88
|
+
]
|
89
|
+
assert_raise(Fluent::ConfigError) do
|
90
|
+
create_driver(conf)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
test "and/regexp, and/regexp" do
|
95
|
+
conf = %[
|
96
|
+
<and>
|
97
|
+
<regexp>
|
98
|
+
key message
|
99
|
+
pattern test
|
100
|
+
</regexp>
|
101
|
+
</and>
|
102
|
+
<and>
|
103
|
+
<regexp>
|
104
|
+
key message
|
105
|
+
pattern test
|
106
|
+
</regexp>
|
107
|
+
</and>
|
108
|
+
]
|
109
|
+
assert_raise(Fluent::ConfigError) do
|
110
|
+
create_driver(conf)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
test "regexp, and/regexp" do
|
115
|
+
conf = %[
|
116
|
+
<regexp>
|
117
|
+
key message
|
118
|
+
pattern test
|
119
|
+
</regexp>
|
120
|
+
<and>
|
121
|
+
<regexp>
|
122
|
+
key message
|
123
|
+
pattern test
|
124
|
+
</regexp>
|
125
|
+
</and>
|
126
|
+
]
|
127
|
+
assert_raise(Fluent::ConfigError) do
|
128
|
+
create_driver(conf)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
test "and/exclude" do
|
133
|
+
conf = %[
|
134
|
+
<and>
|
135
|
+
<exclude>
|
136
|
+
key message
|
137
|
+
pattern test
|
138
|
+
</exclude>
|
139
|
+
<exclude>
|
140
|
+
key message
|
141
|
+
pattern test
|
142
|
+
</exclude>
|
143
|
+
</and>
|
144
|
+
]
|
145
|
+
assert_raise(Fluent::ConfigError) do
|
146
|
+
create_driver(conf)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
test "and/exclude, and/exclude" do
|
151
|
+
conf = %[
|
152
|
+
<and>
|
153
|
+
<exclude>
|
154
|
+
key message
|
155
|
+
pattern test
|
156
|
+
</exclude>
|
157
|
+
</and>
|
158
|
+
<and>
|
159
|
+
<exclude>
|
160
|
+
key message
|
161
|
+
pattern test
|
162
|
+
</exclude>
|
163
|
+
</and>
|
164
|
+
]
|
165
|
+
assert_raise(Fluent::ConfigError) do
|
166
|
+
create_driver(conf)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
test "exclude, or/exclude" do
|
171
|
+
conf = %[
|
172
|
+
<exclude>
|
173
|
+
key message
|
174
|
+
pattern test
|
175
|
+
</exclude>
|
176
|
+
<or>
|
177
|
+
<exclude>
|
178
|
+
key message
|
179
|
+
pattern test
|
180
|
+
</exclude>
|
181
|
+
</or>
|
182
|
+
]
|
183
|
+
assert_raise(Fluent::ConfigError) do
|
184
|
+
create_driver(conf)
|
185
|
+
end
|
186
|
+
end
|
75
187
|
end
|
76
188
|
|
77
189
|
sub_test_case "pattern with slashes" do
|
@@ -91,6 +203,44 @@ class GrepFilterTest < Test::Unit::TestCase
|
|
91
203
|
assert_equal(/[A-Z]test/, d.instance.excludes.first.pattern)
|
92
204
|
end
|
93
205
|
end
|
206
|
+
|
207
|
+
sub_test_case "and/or section" do
|
208
|
+
test "<and> section cannot include both <regexp> and <exclude>" do
|
209
|
+
conf = %[
|
210
|
+
<and>
|
211
|
+
<regexp>
|
212
|
+
key message
|
213
|
+
pattern /test/
|
214
|
+
</regexp>
|
215
|
+
<exclude>
|
216
|
+
key level
|
217
|
+
pattern /debug/
|
218
|
+
</exclude>
|
219
|
+
</and>
|
220
|
+
]
|
221
|
+
assert_raise(Fluent::ConfigError) do
|
222
|
+
create_driver(conf)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
test "<or> section cannot include both <regexp> and <exclude>" do
|
227
|
+
conf = %[
|
228
|
+
<or>
|
229
|
+
<regexp>
|
230
|
+
key message
|
231
|
+
pattern /test/
|
232
|
+
</regexp>
|
233
|
+
<exclude>
|
234
|
+
key level
|
235
|
+
pattern /debug/
|
236
|
+
</exclude>
|
237
|
+
</or>
|
238
|
+
]
|
239
|
+
assert_raise(Fluent::ConfigError) do
|
240
|
+
create_driver(conf)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
94
244
|
end
|
95
245
|
|
96
246
|
sub_test_case 'filter_stream' do
|
@@ -183,6 +333,289 @@ class GrepFilterTest < Test::Unit::TestCase
|
|
183
333
|
}
|
184
334
|
end
|
185
335
|
end
|
336
|
+
|
337
|
+
sub_test_case "and/or section" do
|
338
|
+
def records
|
339
|
+
[
|
340
|
+
{ "time" => "2013/01/13T07:02:11.124202", "level" => "INFO", "method" => "GET", "path" => "/ping" },
|
341
|
+
{ "time" => "2013/01/13T07:02:13.232645", "level" => "WARN", "method" => "POST", "path" => "/auth" },
|
342
|
+
{ "time" => "2013/01/13T07:02:21.542145", "level" => "WARN", "method" => "GET", "path" => "/favicon.ico" },
|
343
|
+
{ "time" => "2013/01/13T07:02:43.632145", "level" => "WARN", "method" => "POST", "path" => "/login" },
|
344
|
+
]
|
345
|
+
end
|
346
|
+
|
347
|
+
def filter(conf, records)
|
348
|
+
d = create_driver(conf)
|
349
|
+
d.run do
|
350
|
+
records.each do |record|
|
351
|
+
d.feed("filter.test", @time, record)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
d.filtered_records
|
355
|
+
end
|
356
|
+
|
357
|
+
test "basic and/regexp" do
|
358
|
+
conf = %[
|
359
|
+
<and>
|
360
|
+
<regexp>
|
361
|
+
key level
|
362
|
+
pattern ^INFO$
|
363
|
+
</regexp>
|
364
|
+
<regexp>
|
365
|
+
key method
|
366
|
+
pattern ^GET$
|
367
|
+
</regexp>
|
368
|
+
</and>
|
369
|
+
]
|
370
|
+
filtered_records = filter(conf, records)
|
371
|
+
assert_equal(records.values_at(0), filtered_records)
|
372
|
+
end
|
373
|
+
|
374
|
+
test "basic or/exclude" do
|
375
|
+
conf = %[
|
376
|
+
<or>
|
377
|
+
<exclude>
|
378
|
+
key level
|
379
|
+
pattern ^INFO$
|
380
|
+
</exclude>
|
381
|
+
<exclude>
|
382
|
+
key method
|
383
|
+
pattern ^GET$
|
384
|
+
</exclude>
|
385
|
+
</or>
|
386
|
+
]
|
387
|
+
filtered_records = filter(conf, records)
|
388
|
+
assert_equal(records.values_at(1, 3), filtered_records)
|
389
|
+
end
|
390
|
+
|
391
|
+
test "basic or/regexp" do
|
392
|
+
conf = %[
|
393
|
+
<or>
|
394
|
+
<regexp>
|
395
|
+
key level
|
396
|
+
pattern ^INFO$
|
397
|
+
</regexp>
|
398
|
+
<regexp>
|
399
|
+
key method
|
400
|
+
pattern ^GET$
|
401
|
+
</regexp>
|
402
|
+
</or>
|
403
|
+
]
|
404
|
+
filtered_records = filter(conf, records)
|
405
|
+
assert_equal(records.values_at(0, 2), filtered_records)
|
406
|
+
end
|
407
|
+
|
408
|
+
test "basic and/exclude" do
|
409
|
+
conf = %[
|
410
|
+
<and>
|
411
|
+
<exclude>
|
412
|
+
key level
|
413
|
+
pattern ^INFO$
|
414
|
+
</exclude>
|
415
|
+
<exclude>
|
416
|
+
key method
|
417
|
+
pattern ^GET$
|
418
|
+
</exclude>
|
419
|
+
</and>
|
420
|
+
]
|
421
|
+
filtered_records = filter(conf, records)
|
422
|
+
assert_equal(records.values_at(1, 2, 3), filtered_records)
|
423
|
+
end
|
424
|
+
|
425
|
+
sub_test_case "and/or combo" do
|
426
|
+
def records
|
427
|
+
[
|
428
|
+
{ "time" => "2013/01/13T07:02:11.124202", "level" => "INFO", "method" => "GET", "path" => "/ping" },
|
429
|
+
{ "time" => "2013/01/13T07:02:13.232645", "level" => "WARN", "method" => "POST", "path" => "/auth" },
|
430
|
+
{ "time" => "2013/01/13T07:02:21.542145", "level" => "WARN", "method" => "GET", "path" => "/favicon.ico" },
|
431
|
+
{ "time" => "2013/01/13T07:02:43.632145", "level" => "WARN", "method" => "POST", "path" => "/login" },
|
432
|
+
{ "time" => "2013/01/13T07:02:44.959307", "level" => "ERROR", "method" => "POST", "path" => "/login" },
|
433
|
+
{ "time" => "2013/01/13T07:02:45.444992", "level" => "ERROR", "method" => "GET", "path" => "/ping" },
|
434
|
+
{ "time" => "2013/01/13T07:02:51.247941", "level" => "WARN", "method" => "GET", "path" => "/info" },
|
435
|
+
{ "time" => "2013/01/13T07:02:53.108366", "level" => "WARN", "method" => "POST", "path" => "/ban" },
|
436
|
+
]
|
437
|
+
end
|
438
|
+
|
439
|
+
test "and/regexp, or/exclude" do
|
440
|
+
conf = %[
|
441
|
+
<and>
|
442
|
+
<regexp>
|
443
|
+
key level
|
444
|
+
pattern ^ERROR|WARN$
|
445
|
+
</regexp>
|
446
|
+
<regexp>
|
447
|
+
key method
|
448
|
+
pattern ^GET|POST$
|
449
|
+
</regexp>
|
450
|
+
</and>
|
451
|
+
<or>
|
452
|
+
<exclude>
|
453
|
+
key level
|
454
|
+
pattern ^WARN$
|
455
|
+
</exclude>
|
456
|
+
<exclude>
|
457
|
+
key method
|
458
|
+
pattern ^GET$
|
459
|
+
</exclude>
|
460
|
+
</or>
|
461
|
+
]
|
462
|
+
filtered_records = filter(conf, records)
|
463
|
+
assert_equal(records.values_at(4), filtered_records)
|
464
|
+
end
|
465
|
+
|
466
|
+
test "and/regexp, and/exclude" do
|
467
|
+
conf = %[
|
468
|
+
<and>
|
469
|
+
<regexp>
|
470
|
+
key level
|
471
|
+
pattern ^ERROR|WARN$
|
472
|
+
</regexp>
|
473
|
+
<regexp>
|
474
|
+
key method
|
475
|
+
pattern ^GET|POST$
|
476
|
+
</regexp>
|
477
|
+
</and>
|
478
|
+
<and>
|
479
|
+
<exclude>
|
480
|
+
key level
|
481
|
+
pattern ^WARN$
|
482
|
+
</exclude>
|
483
|
+
<exclude>
|
484
|
+
key method
|
485
|
+
pattern ^GET$
|
486
|
+
</exclude>
|
487
|
+
</and>
|
488
|
+
]
|
489
|
+
filtered_records = filter(conf, records)
|
490
|
+
assert_equal(records.values_at(1, 3, 4, 5, 7), filtered_records)
|
491
|
+
end
|
492
|
+
|
493
|
+
test "or/regexp, and/exclude" do
|
494
|
+
conf = %[
|
495
|
+
<or>
|
496
|
+
<regexp>
|
497
|
+
key level
|
498
|
+
pattern ^ERROR|WARN$
|
499
|
+
</regexp>
|
500
|
+
<regexp>
|
501
|
+
key method
|
502
|
+
pattern ^GET|POST$
|
503
|
+
</regexp>
|
504
|
+
</or>
|
505
|
+
<and>
|
506
|
+
<exclude>
|
507
|
+
key level
|
508
|
+
pattern ^WARN$
|
509
|
+
</exclude>
|
510
|
+
<exclude>
|
511
|
+
key method
|
512
|
+
pattern ^GET$
|
513
|
+
</exclude>
|
514
|
+
</and>
|
515
|
+
]
|
516
|
+
filtered_records = filter(conf, records)
|
517
|
+
assert_equal(records.values_at(0, 1, 3, 4, 5, 7), filtered_records)
|
518
|
+
end
|
519
|
+
|
520
|
+
test "or/regexp, or/exclude" do
|
521
|
+
conf = %[
|
522
|
+
<or>
|
523
|
+
<regexp>
|
524
|
+
key level
|
525
|
+
pattern ^ERROR|WARN$
|
526
|
+
</regexp>
|
527
|
+
<regexp>
|
528
|
+
key method
|
529
|
+
pattern ^GET|POST$
|
530
|
+
</regexp>
|
531
|
+
</or>
|
532
|
+
<or>
|
533
|
+
<exclude>
|
534
|
+
key level
|
535
|
+
pattern ^WARN$
|
536
|
+
</exclude>
|
537
|
+
<exclude>
|
538
|
+
key method
|
539
|
+
pattern ^GET$
|
540
|
+
</exclude>
|
541
|
+
</or>
|
542
|
+
]
|
543
|
+
filtered_records = filter(conf, records)
|
544
|
+
assert_equal(records.values_at(4), filtered_records)
|
545
|
+
end
|
546
|
+
|
547
|
+
test "regexp, and/regexp" do
|
548
|
+
conf = %[
|
549
|
+
<and>
|
550
|
+
<regexp>
|
551
|
+
key level
|
552
|
+
pattern ^ERROR|WARN$
|
553
|
+
</regexp>
|
554
|
+
<regexp>
|
555
|
+
key method
|
556
|
+
pattern ^GET|POST$
|
557
|
+
</regexp>
|
558
|
+
</and>
|
559
|
+
<regexp>
|
560
|
+
key path
|
561
|
+
pattern ^/login$
|
562
|
+
</regexp>
|
563
|
+
]
|
564
|
+
filtered_records = filter(conf, records)
|
565
|
+
assert_equal(records.values_at(3, 4), filtered_records)
|
566
|
+
end
|
567
|
+
|
568
|
+
test "regexp, or/exclude" do
|
569
|
+
conf = %[
|
570
|
+
<regexp>
|
571
|
+
key level
|
572
|
+
pattern ^ERROR|WARN$
|
573
|
+
</regexp>
|
574
|
+
<regexp>
|
575
|
+
key method
|
576
|
+
pattern ^GET|POST$
|
577
|
+
</regexp>
|
578
|
+
<or>
|
579
|
+
<exclude>
|
580
|
+
key level
|
581
|
+
pattern ^WARN$
|
582
|
+
</exclude>
|
583
|
+
<exclude>
|
584
|
+
key method
|
585
|
+
pattern ^GET$
|
586
|
+
</exclude>
|
587
|
+
</or>
|
588
|
+
]
|
589
|
+
filtered_records = filter(conf, records)
|
590
|
+
assert_equal(records.values_at(4), filtered_records)
|
591
|
+
end
|
592
|
+
|
593
|
+
test "regexp, and/exclude" do
|
594
|
+
conf = %[
|
595
|
+
<regexp>
|
596
|
+
key level
|
597
|
+
pattern ^ERROR|WARN$
|
598
|
+
</regexp>
|
599
|
+
<regexp>
|
600
|
+
key method
|
601
|
+
pattern ^GET|POST$
|
602
|
+
</regexp>
|
603
|
+
<and>
|
604
|
+
<exclude>
|
605
|
+
key level
|
606
|
+
pattern ^WARN$
|
607
|
+
</exclude>
|
608
|
+
<exclude>
|
609
|
+
key method
|
610
|
+
pattern ^GET$
|
611
|
+
</exclude>
|
612
|
+
</and>
|
613
|
+
]
|
614
|
+
filtered_records = filter(conf, records)
|
615
|
+
assert_equal(records.values_at(1, 3, 4, 5, 7), filtered_records)
|
616
|
+
end
|
617
|
+
end
|
618
|
+
end
|
186
619
|
end
|
187
620
|
|
188
621
|
sub_test_case 'nested keys' do
|
data/test/plugin/test_in_exec.rb
CHANGED
@@ -131,9 +131,7 @@ EOC
|
|
131
131
|
d = create_driver REGEXP_CONFIG
|
132
132
|
assert{ d.instance.parser.is_a? Fluent::Plugin::RegexpParser }
|
133
133
|
assert_equal "regex_tag", d.instance.tag
|
134
|
-
expression =
|
135
|
-
(?<time>[^\]]*) (?<message>[^ ]*)
|
136
|
-
EXP
|
134
|
+
expression = /(?<time>[^\]]*) (?<message>[^ ]*)/
|
137
135
|
assert_equal expression, d.instance.parser.expression
|
138
136
|
assert_nil d.instance.extract_config
|
139
137
|
end
|
@@ -194,8 +192,8 @@ EXP
|
|
194
192
|
test 'configure_with_regexp' do
|
195
193
|
d = create_driver REGEXP_CONFIG_COMPAT
|
196
194
|
assert{ d.instance.parser.is_a? Fluent::Plugin::RegexpParser }
|
197
|
-
assert_equal
|
198
|
-
assert_equal
|
195
|
+
assert_equal(/(?<time>[^\]]*) (?<message>[^ ]*)/, d.instance.parser.expression)
|
196
|
+
assert_equal('regex_tag', d.instance.tag)
|
199
197
|
end
|
200
198
|
end
|
201
199
|
|
@@ -16,6 +16,18 @@ class NginxParserTest < ::Test::Unit::TestCase
|
|
16
16
|
'referer' => '-',
|
17
17
|
'agent' => 'Opera/12.0'
|
18
18
|
}
|
19
|
+
@expected_extended = {
|
20
|
+
'remote' => '127.0.0.1',
|
21
|
+
'host' => '192.168.0.1',
|
22
|
+
'user' => '-',
|
23
|
+
'method' => 'GET',
|
24
|
+
'path' => '/',
|
25
|
+
'code' => '200',
|
26
|
+
'size' => '777',
|
27
|
+
'referer' => '-',
|
28
|
+
'agent' => 'Opera/12.0',
|
29
|
+
'http_x_forwarded_for' => '-'
|
30
|
+
}
|
19
31
|
end
|
20
32
|
|
21
33
|
def create_driver
|
@@ -45,4 +57,12 @@ class NginxParserTest < ::Test::Unit::TestCase
|
|
45
57
|
assert_equal(@expected, record)
|
46
58
|
}
|
47
59
|
end
|
60
|
+
|
61
|
+
def test_parse_with_http_x_forwarded_for
|
62
|
+
d = create_driver
|
63
|
+
d.instance.parse('127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" -') { |time, record|
|
64
|
+
assert_equal(event_time('28/Feb/2013:12:00:00 +0900', format: '%d/%b/%Y:%H:%M:%S %z'), time)
|
65
|
+
assert_equal(@expected_extended, record)
|
66
|
+
}
|
67
|
+
end
|
48
68
|
end
|
@@ -160,25 +160,24 @@ class RegexpParserTest < ::Test::Unit::TestCase
|
|
160
160
|
'types' => 'user:string,date:time:%d/%b/%Y:%H:%M:%S %z,flag:bool,path:array,code:float,size:integer'
|
161
161
|
}
|
162
162
|
d = create_driver(conf)
|
163
|
-
regexp = d.instance.
|
163
|
+
regexp = d.instance.expression
|
164
164
|
assert_equal(0, regexp.options)
|
165
165
|
end
|
166
166
|
|
167
167
|
data(
|
168
|
-
ignorecase: [
|
169
|
-
multiline: [
|
170
|
-
ignorecase_multiline: [
|
168
|
+
ignorecase: ["i", Regexp::IGNORECASE],
|
169
|
+
multiline: ["m", Regexp::MULTILINE],
|
170
|
+
ignorecase_multiline: ["im", Regexp::IGNORECASE | Regexp::MULTILINE],
|
171
171
|
)
|
172
172
|
def test_options(data)
|
173
173
|
regexp_option, expected = data
|
174
174
|
conf = {
|
175
|
-
'expression' => %
|
175
|
+
'expression' => %Q!/^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] \[(?<date>[^\]]*)\] "(?<flag>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)$/#{regexp_option}!,
|
176
176
|
'time_format' => "%d/%b/%Y:%H:%M:%S %z",
|
177
177
|
'types' => 'user:string,date:time:%d/%b/%Y:%H:%M:%S %z,flag:bool,path:array,code:float,size:integer'
|
178
178
|
}
|
179
|
-
conf = conf.merge(regexp_option)
|
180
179
|
d = create_driver(conf)
|
181
|
-
regexp = d.instance.
|
180
|
+
regexp = d.instance.expression
|
182
181
|
assert_equal(expected, regexp.options)
|
183
182
|
end
|
184
183
|
end
|
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: 1.
|
4
|
+
version: 1.2.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -329,7 +329,6 @@ files:
|
|
329
329
|
- AUTHORS
|
330
330
|
- CHANGELOG.md
|
331
331
|
- CONTRIBUTING.md
|
332
|
-
- COPYING
|
333
332
|
- GOVERNANCE.md
|
334
333
|
- Gemfile
|
335
334
|
- LICENSE
|
@@ -748,9 +747,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
748
747
|
version: '2.1'
|
749
748
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
750
749
|
requirements:
|
751
|
-
- - "
|
750
|
+
- - ">"
|
752
751
|
- !ruby/object:Gem::Version
|
753
|
-
version:
|
752
|
+
version: 1.3.1
|
754
753
|
requirements: []
|
755
754
|
rubyforge_project:
|
756
755
|
rubygems_version: 2.6.13
|
data/COPYING
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
Copyright (C) 2011 FURUHASHI Sadayuki
|
2
|
-
|
3
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
you may not use this file except in compliance with the License.
|
5
|
-
You may obtain a copy of the License at
|
6
|
-
|
7
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
|
9
|
-
Unless required by applicable law or agreed to in writing, software
|
10
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
See the License for the specific language governing permissions and
|
13
|
-
limitations under the License.
|
14
|
-
|