fluentd 0.12.40 → 0.14.0
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/.github/ISSUE_TEMPLATE.md +6 -0
- data/.gitignore +2 -0
- data/.travis.yml +33 -21
- data/CONTRIBUTING.md +1 -0
- data/ChangeLog +810 -237
- data/README.md +0 -25
- data/Rakefile +2 -1
- data/Vagrantfile +17 -0
- data/appveyor.yml +35 -0
- data/example/filter_stdout.conf +5 -5
- data/example/in_forward.conf +2 -2
- data/example/in_http.conf +2 -2
- data/example/in_out_forward.conf +17 -0
- data/example/in_syslog.conf +2 -2
- data/example/in_tail.conf +2 -2
- data/example/in_tcp.conf +2 -2
- data/example/in_udp.conf +2 -2
- data/example/out_copy.conf +4 -4
- data/example/out_file.conf +2 -2
- data/example/out_forward.conf +2 -2
- data/example/out_forward_buf_file.conf +23 -0
- data/example/v0_12_filter.conf +8 -8
- data/fluent.conf +29 -0
- data/fluentd.gemspec +18 -11
- data/lib/fluent/agent.rb +60 -58
- data/lib/fluent/command/cat.rb +1 -1
- data/lib/fluent/command/debug.rb +7 -5
- data/lib/fluent/command/fluentd.rb +97 -2
- data/lib/fluent/compat/call_super_mixin.rb +67 -0
- data/lib/fluent/compat/filter.rb +50 -0
- data/lib/fluent/compat/formatter.rb +109 -0
- data/lib/fluent/compat/input.rb +50 -0
- data/lib/fluent/compat/output.rb +617 -0
- data/lib/fluent/compat/output_chain.rb +60 -0
- data/lib/fluent/compat/parser.rb +163 -0
- data/lib/fluent/compat/propagate_default.rb +62 -0
- data/lib/fluent/config.rb +23 -20
- data/lib/fluent/config/configure_proxy.rb +119 -70
- data/lib/fluent/config/dsl.rb +5 -18
- data/lib/fluent/config/element.rb +72 -8
- data/lib/fluent/config/error.rb +0 -3
- data/lib/fluent/config/literal_parser.rb +0 -2
- data/lib/fluent/config/parser.rb +4 -4
- data/lib/fluent/config/section.rb +39 -28
- data/lib/fluent/config/types.rb +2 -13
- data/lib/fluent/config/v1_parser.rb +1 -3
- data/lib/fluent/configurable.rb +48 -16
- data/lib/fluent/daemon.rb +15 -0
- data/lib/fluent/engine.rb +26 -52
- data/lib/fluent/env.rb +6 -4
- data/lib/fluent/event.rb +58 -11
- data/lib/fluent/event_router.rb +5 -5
- data/lib/fluent/filter.rb +2 -50
- data/lib/fluent/formatter.rb +4 -293
- data/lib/fluent/input.rb +2 -32
- data/lib/fluent/label.rb +2 -2
- data/lib/fluent/load.rb +3 -2
- data/lib/fluent/log.rb +107 -38
- data/lib/fluent/match.rb +0 -36
- data/lib/fluent/mixin.rb +117 -7
- data/lib/fluent/msgpack_factory.rb +62 -0
- data/lib/fluent/output.rb +7 -612
- data/lib/fluent/output_chain.rb +23 -0
- data/lib/fluent/parser.rb +4 -800
- data/lib/fluent/plugin.rb +100 -121
- data/lib/fluent/plugin/bare_output.rb +63 -0
- data/lib/fluent/plugin/base.rb +121 -0
- data/lib/fluent/plugin/buf_file.rb +101 -182
- data/lib/fluent/plugin/buf_memory.rb +9 -92
- data/lib/fluent/plugin/buffer.rb +473 -0
- data/lib/fluent/plugin/buffer/chunk.rb +135 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +339 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +100 -0
- data/lib/fluent/plugin/exec_util.rb +80 -75
- data/lib/fluent/plugin/file_util.rb +33 -28
- data/lib/fluent/plugin/file_wrapper.rb +120 -0
- data/lib/fluent/plugin/filter.rb +51 -0
- data/lib/fluent/plugin/filter_grep.rb +13 -40
- data/lib/fluent/plugin/filter_record_transformer.rb +22 -18
- data/lib/fluent/plugin/formatter.rb +93 -0
- data/lib/fluent/plugin/formatter_csv.rb +48 -0
- data/lib/fluent/plugin/formatter_hash.rb +32 -0
- data/lib/fluent/plugin/formatter_json.rb +47 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +32 -0
- data/lib/fluent/plugin/formatter_out_file.rb +45 -0
- data/lib/fluent/plugin/formatter_single_value.rb +34 -0
- data/lib/fluent/plugin/formatter_stdout.rb +39 -0
- data/lib/fluent/plugin/in_debug_agent.rb +4 -0
- data/lib/fluent/plugin/in_dummy.rb +22 -18
- data/lib/fluent/plugin/in_exec.rb +18 -8
- data/lib/fluent/plugin/in_forward.rb +36 -79
- data/lib/fluent/plugin/in_gc_stat.rb +4 -0
- data/lib/fluent/plugin/in_http.rb +21 -18
- data/lib/fluent/plugin/in_monitor_agent.rb +15 -48
- data/lib/fluent/plugin/in_object_space.rb +6 -1
- data/lib/fluent/plugin/in_stream.rb +7 -3
- data/lib/fluent/plugin/in_syslog.rb +46 -95
- data/lib/fluent/plugin/in_tail.rb +51 -595
- data/lib/fluent/plugin/in_tcp.rb +8 -1
- data/lib/fluent/plugin/in_udp.rb +8 -14
- data/lib/fluent/plugin/input.rb +33 -0
- data/lib/fluent/plugin/multi_output.rb +95 -0
- data/lib/fluent/plugin/out_buffered_null.rb +59 -0
- data/lib/fluent/plugin/out_copy.rb +11 -7
- data/lib/fluent/plugin/out_exec.rb +15 -11
- data/lib/fluent/plugin/out_exec_filter.rb +18 -10
- data/lib/fluent/plugin/out_file.rb +34 -5
- data/lib/fluent/plugin/out_forward.rb +19 -9
- data/lib/fluent/plugin/out_null.rb +0 -14
- data/lib/fluent/plugin/out_roundrobin.rb +11 -7
- data/lib/fluent/plugin/out_stdout.rb +5 -7
- data/lib/fluent/plugin/out_stream.rb +3 -1
- data/lib/fluent/plugin/output.rb +979 -0
- data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
- data/lib/fluent/plugin/parser.rb +244 -0
- data/lib/fluent/plugin/parser_apache.rb +24 -0
- data/lib/fluent/plugin/parser_apache2.rb +84 -0
- data/lib/fluent/plugin/parser_apache_error.rb +21 -0
- data/lib/fluent/plugin/parser_csv.rb +31 -0
- data/lib/fluent/plugin/parser_json.rb +79 -0
- data/lib/fluent/plugin/parser_ltsv.rb +50 -0
- data/lib/fluent/plugin/parser_multiline.rb +102 -0
- data/lib/fluent/plugin/parser_nginx.rb +24 -0
- data/lib/fluent/plugin/parser_none.rb +36 -0
- data/lib/fluent/plugin/parser_syslog.rb +82 -0
- data/lib/fluent/plugin/parser_tsv.rb +37 -0
- data/lib/fluent/plugin/socket_util.rb +120 -114
- data/lib/fluent/plugin/storage.rb +84 -0
- data/lib/fluent/plugin/storage_local.rb +116 -0
- data/lib/fluent/plugin/string_util.rb +16 -13
- data/lib/fluent/plugin_helper.rb +39 -0
- data/lib/fluent/plugin_helper/child_process.rb +298 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +99 -0
- data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
- data/lib/fluent/plugin_helper/event_loop.rb +118 -0
- data/lib/fluent/plugin_helper/retry_state.rb +177 -0
- data/lib/fluent/plugin_helper/storage.rb +308 -0
- data/lib/fluent/plugin_helper/thread.rb +147 -0
- data/lib/fluent/plugin_helper/timer.rb +85 -0
- data/lib/fluent/plugin_id.rb +63 -0
- data/lib/fluent/process.rb +21 -30
- data/lib/fluent/registry.rb +21 -9
- data/lib/fluent/root_agent.rb +115 -40
- data/lib/fluent/supervisor.rb +330 -320
- data/lib/fluent/system_config.rb +42 -18
- data/lib/fluent/test.rb +6 -1
- data/lib/fluent/test/base.rb +23 -3
- data/lib/fluent/test/driver/base.rb +247 -0
- data/lib/fluent/test/driver/event_feeder.rb +98 -0
- data/lib/fluent/test/driver/filter.rb +35 -0
- data/lib/fluent/test/driver/input.rb +31 -0
- data/lib/fluent/test/driver/output.rb +78 -0
- data/lib/fluent/test/driver/test_event_router.rb +45 -0
- data/lib/fluent/test/filter_test.rb +0 -1
- data/lib/fluent/test/formatter_test.rb +2 -1
- data/lib/fluent/test/input_test.rb +23 -17
- data/lib/fluent/test/output_test.rb +28 -39
- data/lib/fluent/test/parser_test.rb +1 -1
- data/lib/fluent/time.rb +104 -1
- data/lib/fluent/{status.rb → unique_id.rb} +15 -24
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +72 -0
- data/test/compat/test_calls_super.rb +164 -0
- data/test/config/test_config_parser.rb +83 -0
- data/test/config/test_configurable.rb +547 -274
- data/test/config/test_configure_proxy.rb +146 -29
- data/test/config/test_dsl.rb +3 -181
- data/test/config/test_element.rb +274 -0
- data/test/config/test_literal_parser.rb +1 -1
- data/test/config/test_section.rb +79 -7
- data/test/config/test_system_config.rb +21 -0
- data/test/config/test_types.rb +3 -26
- data/test/helper.rb +78 -8
- data/test/plugin/test_bare_output.rb +118 -0
- data/test/plugin/test_base.rb +75 -0
- data/test/plugin/test_buf_file.rb +420 -521
- data/test/plugin/test_buf_memory.rb +32 -194
- data/test/plugin/test_buffer.rb +981 -0
- data/test/plugin/test_buffer_chunk.rb +110 -0
- data/test/plugin/test_buffer_file_chunk.rb +770 -0
- data/test/plugin/test_buffer_memory_chunk.rb +265 -0
- data/test/plugin/test_filter.rb +255 -0
- data/test/plugin/test_filter_grep.rb +2 -73
- data/test/plugin/test_filter_record_transformer.rb +24 -68
- data/test/plugin/test_filter_stdout.rb +6 -6
- data/test/plugin/test_in_debug_agent.rb +2 -0
- data/test/plugin/test_in_dummy.rb +11 -17
- data/test/plugin/test_in_exec.rb +6 -25
- data/test/plugin/test_in_forward.rb +112 -151
- data/test/plugin/test_in_gc_stat.rb +2 -0
- data/test/plugin/test_in_http.rb +106 -157
- data/test/plugin/test_in_object_space.rb +21 -5
- data/test/plugin/test_in_stream.rb +14 -13
- data/test/plugin/test_in_syslog.rb +30 -275
- data/test/plugin/test_in_tail.rb +95 -234
- data/test/plugin/test_in_tcp.rb +14 -0
- data/test/plugin/test_in_udp.rb +21 -13
- data/test/plugin/test_input.rb +122 -0
- data/test/plugin/test_multi_output.rb +180 -0
- data/test/plugin/test_out_buffered_null.rb +79 -0
- data/test/plugin/test_out_copy.rb +15 -2
- data/test/plugin/test_out_exec.rb +75 -25
- data/test/plugin/test_out_exec_filter.rb +74 -8
- data/test/plugin/test_out_file.rb +61 -7
- data/test/plugin/test_out_forward.rb +92 -15
- data/test/plugin/test_out_roundrobin.rb +1 -0
- data/test/plugin/test_out_stdout.rb +22 -13
- data/test/plugin/test_out_stream.rb +18 -0
- data/test/plugin/test_output.rb +515 -0
- data/test/plugin/test_output_as_buffered.rb +1540 -0
- data/test/plugin/test_output_as_buffered_overflow.rb +247 -0
- data/test/plugin/test_output_as_buffered_retries.rb +808 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +776 -0
- data/test/plugin/test_output_as_standard.rb +362 -0
- data/test/plugin/test_owned_by.rb +35 -0
- data/test/plugin/test_storage.rb +167 -0
- data/test/plugin/test_storage_local.rb +8 -0
- data/test/plugin_helper/test_child_process.rb +599 -0
- data/test/plugin_helper/test_compat_parameters.rb +175 -0
- data/test/plugin_helper/test_event_emitter.rb +51 -0
- data/test/plugin_helper/test_event_loop.rb +52 -0
- data/test/plugin_helper/test_retry_state.rb +399 -0
- data/test/plugin_helper/test_storage.rb +411 -0
- data/test/plugin_helper/test_thread.rb +164 -0
- data/test/plugin_helper/test_timer.rb +100 -0
- data/test/scripts/exec_script.rb +0 -6
- data/test/scripts/fluent/plugin/out_test.rb +3 -0
- data/test/test_config.rb +13 -4
- data/test/test_event.rb +24 -13
- data/test/test_event_router.rb +8 -7
- data/test/test_event_time.rb +187 -0
- data/test/test_formatter.rb +13 -51
- data/test/test_input.rb +1 -1
- data/test/test_log.rb +239 -16
- data/test/test_mixin.rb +1 -1
- data/test/test_output.rb +53 -66
- data/test/test_parser.rb +105 -323
- data/test/test_plugin_helper.rb +81 -0
- data/test/test_root_agent.rb +4 -52
- data/test/test_supervisor.rb +272 -0
- data/test/test_unique_id.rb +47 -0
- metadata +180 -54
- data/lib/fluent/buffer.rb +0 -365
- data/lib/fluent/plugin/filter_parser.rb +0 -107
- data/lib/fluent/plugin/in_status.rb +0 -76
- data/lib/fluent/test/helpers.rb +0 -86
- data/test/plugin/data/log/foo/bar2 +0 -0
- data/test/plugin/test_filter_parser.rb +0 -744
- data/test/plugin/test_in_status.rb +0 -38
- data/test/test_buffer.rb +0 -624
@@ -0,0 +1,23 @@
|
|
1
|
+
#
|
2
|
+
# Fluentd
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'fluent/compat/output_chain'
|
18
|
+
|
19
|
+
module Fluent
|
20
|
+
OutputChain = Fluent::Compat::OutputChain
|
21
|
+
CopyOutputChain = Fluent::Compat::CopyOutputChain
|
22
|
+
NullOutputChain = Fluent::Compat::NullOutputChain
|
23
|
+
end
|
data/lib/fluent/parser.rb
CHANGED
@@ -14,806 +14,10 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
require '
|
18
|
-
require 'json'
|
19
|
-
|
20
|
-
require 'yajl'
|
21
|
-
|
22
|
-
require 'fluent/config/error'
|
23
|
-
require 'fluent/config/element'
|
24
|
-
require 'fluent/configurable'
|
25
|
-
require 'fluent/env'
|
26
|
-
require 'fluent/engine'
|
27
|
-
require 'fluent/registry'
|
28
|
-
require 'fluent/time'
|
17
|
+
require 'fluent/compat/parser'
|
29
18
|
|
30
19
|
module Fluent
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
class Parser
|
35
|
-
include Configurable
|
36
|
-
|
37
|
-
# SET false BEFORE CONFIGURE, to return nil when time not parsed
|
38
|
-
# 'configure()' may raise errors for unexpected configurations
|
39
|
-
attr_accessor :estimate_current_event
|
40
|
-
|
41
|
-
config_param :keep_time_key, :bool, default: false
|
42
|
-
|
43
|
-
def initialize
|
44
|
-
super
|
45
|
-
@estimate_current_event = true
|
46
|
-
end
|
47
|
-
|
48
|
-
def configure(conf)
|
49
|
-
super
|
50
|
-
end
|
51
|
-
|
52
|
-
def parse(text)
|
53
|
-
raise NotImplementedError, "Implement this method in child class"
|
54
|
-
end
|
55
|
-
|
56
|
-
# Keep backward compatibility for existing plugins
|
57
|
-
def call(*a, &b)
|
58
|
-
parse(*a, &b)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
class TextParser
|
63
|
-
# Keep backward compatibility for existing plugins
|
64
|
-
ParserError = ::Fluent::ParserError
|
65
|
-
|
66
|
-
class TimeParser
|
67
|
-
def initialize(time_format)
|
68
|
-
@cache1_key = nil
|
69
|
-
@cache1_time = nil
|
70
|
-
@cache2_key = nil
|
71
|
-
@cache2_time = nil
|
72
|
-
@parser =
|
73
|
-
if time_format
|
74
|
-
if time_format == '%iso8601'
|
75
|
-
Proc.new { |value| Time.iso8601(value) }
|
76
|
-
else
|
77
|
-
Proc.new { |value| Time.strptime(value, time_format) }
|
78
|
-
end
|
79
|
-
else
|
80
|
-
Time.method(:parse)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def parse(value)
|
85
|
-
unless value.is_a?(String)
|
86
|
-
raise ParserError, "value must be string: #{value}"
|
87
|
-
end
|
88
|
-
|
89
|
-
if @cache1_key == value
|
90
|
-
return @cache1_time
|
91
|
-
elsif @cache2_key == value
|
92
|
-
return @cache2_time
|
93
|
-
else
|
94
|
-
begin
|
95
|
-
time = @parser.call(value).to_i
|
96
|
-
rescue => e
|
97
|
-
raise ParserError, "invalid time format: value = #{value}, error_class = #{e.class.name}, error = #{e.message}"
|
98
|
-
end
|
99
|
-
@cache1_key = @cache2_key
|
100
|
-
@cache1_time = @cache2_time
|
101
|
-
@cache2_key = value
|
102
|
-
@cache2_time = time
|
103
|
-
return time
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
module TypeConverter
|
109
|
-
Converters = {
|
110
|
-
'string' => lambda { |v| v.to_s },
|
111
|
-
'integer' => lambda { |v| v.to_i },
|
112
|
-
'float' => lambda { |v| v.to_f },
|
113
|
-
'bool' => lambda { |v|
|
114
|
-
case v.downcase
|
115
|
-
when 'true', 'yes', '1'
|
116
|
-
true
|
117
|
-
else
|
118
|
-
false
|
119
|
-
end
|
120
|
-
},
|
121
|
-
'time' => lambda { |v, time_parser|
|
122
|
-
time_parser.parse(v)
|
123
|
-
},
|
124
|
-
'array' => lambda { |v, delimiter|
|
125
|
-
v.to_s.split(delimiter)
|
126
|
-
}
|
127
|
-
}
|
128
|
-
|
129
|
-
def self.included(klass)
|
130
|
-
klass.instance_eval {
|
131
|
-
config_param :types, :string, default: nil
|
132
|
-
config_param :types_delimiter, :string, default: ','
|
133
|
-
config_param :types_label_delimiter, :string, default: ':'
|
134
|
-
}
|
135
|
-
end
|
136
|
-
|
137
|
-
def configure(conf)
|
138
|
-
super
|
139
|
-
|
140
|
-
@type_converters = parse_types_parameter unless @types.nil?
|
141
|
-
end
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
def convert_type(name, value)
|
146
|
-
converter = @type_converters[name]
|
147
|
-
converter.nil? ? value : converter.call(value)
|
148
|
-
end
|
149
|
-
|
150
|
-
def parse_types_parameter
|
151
|
-
converters = {}
|
152
|
-
|
153
|
-
@types.split(@types_delimiter).each { |pattern_name|
|
154
|
-
name, type, format = pattern_name.split(@types_label_delimiter, 3)
|
155
|
-
raise ConfigError, "Type is needed" if type.nil?
|
156
|
-
|
157
|
-
case type
|
158
|
-
when 'time'
|
159
|
-
t_parser = TimeParser.new(format)
|
160
|
-
converters[name] = lambda { |v|
|
161
|
-
Converters[type].call(v, t_parser)
|
162
|
-
}
|
163
|
-
when 'array'
|
164
|
-
delimiter = format || ','
|
165
|
-
converters[name] = lambda { |v|
|
166
|
-
Converters[type].call(v, delimiter)
|
167
|
-
}
|
168
|
-
else
|
169
|
-
converters[name] = Converters[type]
|
170
|
-
end
|
171
|
-
}
|
172
|
-
|
173
|
-
converters
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
class RegexpParser < Parser
|
178
|
-
include TypeConverter
|
179
|
-
|
180
|
-
config_param :time_key, :string, default: 'time'
|
181
|
-
config_param :time_format, :string, default: nil
|
182
|
-
|
183
|
-
def initialize(regexp, conf={})
|
184
|
-
super()
|
185
|
-
@regexp = regexp
|
186
|
-
unless conf.empty?
|
187
|
-
conf = Config::Element.new('default_regexp_conf', '', conf, []) unless conf.is_a?(Config::Element)
|
188
|
-
configure(conf)
|
189
|
-
end
|
190
|
-
|
191
|
-
@time_parser = TimeParser.new(@time_format)
|
192
|
-
@mutex = Mutex.new
|
193
|
-
end
|
194
|
-
|
195
|
-
def configure(conf)
|
196
|
-
super
|
197
|
-
@time_parser = TimeParser.new(@time_format)
|
198
|
-
end
|
199
|
-
|
200
|
-
def patterns
|
201
|
-
{'format' => @regexp, 'time_format' => @time_format}
|
202
|
-
end
|
203
|
-
|
204
|
-
def parse(text)
|
205
|
-
m = @regexp.match(text)
|
206
|
-
unless m
|
207
|
-
if block_given?
|
208
|
-
yield nil, nil
|
209
|
-
return
|
210
|
-
else
|
211
|
-
return nil, nil
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
time = nil
|
216
|
-
record = {}
|
217
|
-
|
218
|
-
m.names.each {|name|
|
219
|
-
if value = m[name]
|
220
|
-
case name
|
221
|
-
when @time_key
|
222
|
-
time = @mutex.synchronize { @time_parser.parse(value) }
|
223
|
-
if @keep_time_key
|
224
|
-
record[name] = if @type_converters.nil?
|
225
|
-
value
|
226
|
-
else
|
227
|
-
convert_type(name, value)
|
228
|
-
end
|
229
|
-
end
|
230
|
-
else
|
231
|
-
record[name] = if @type_converters.nil?
|
232
|
-
value
|
233
|
-
else
|
234
|
-
convert_type(name, value)
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
}
|
239
|
-
|
240
|
-
if @estimate_current_event
|
241
|
-
time ||= Engine.now
|
242
|
-
end
|
243
|
-
|
244
|
-
if block_given?
|
245
|
-
yield time, record
|
246
|
-
else # keep backward compatibility. will be removed at v1
|
247
|
-
return time, record
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
class JSONParser < Parser
|
253
|
-
config_param :time_key, :string, default: 'time'
|
254
|
-
config_param :time_format, :string, default: nil
|
255
|
-
config_param :json_parser, :string, default: 'oj'
|
256
|
-
|
257
|
-
def configure(conf)
|
258
|
-
super
|
259
|
-
|
260
|
-
unless @time_format.nil?
|
261
|
-
@time_parser = TimeParser.new(@time_format)
|
262
|
-
@mutex = Mutex.new
|
263
|
-
end
|
264
|
-
|
265
|
-
begin
|
266
|
-
raise LoadError unless @json_parser == 'oj'
|
267
|
-
require 'oj'
|
268
|
-
Oj.default_options = Fluent::DEFAULT_OJ_OPTIONS
|
269
|
-
@load_proc = Oj.method(:load)
|
270
|
-
@error_class = Oj::ParseError
|
271
|
-
rescue LoadError
|
272
|
-
@load_proc = Yajl.method(:load)
|
273
|
-
@error_class = Yajl::ParseError
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def parse(text)
|
278
|
-
record = @load_proc.call(text)
|
279
|
-
|
280
|
-
value = @keep_time_key ? record[@time_key] : record.delete(@time_key)
|
281
|
-
if value
|
282
|
-
if @time_format
|
283
|
-
time = @mutex.synchronize { @time_parser.parse(value) }
|
284
|
-
else
|
285
|
-
begin
|
286
|
-
time = value.to_i
|
287
|
-
rescue => e
|
288
|
-
raise ParserError, "invalid time value: value = #{value}, error_class = #{e.class.name}, error = #{e.message}"
|
289
|
-
end
|
290
|
-
end
|
291
|
-
else
|
292
|
-
if @estimate_current_event
|
293
|
-
time = Engine.now
|
294
|
-
else
|
295
|
-
time = nil
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
if block_given?
|
300
|
-
yield time, record
|
301
|
-
else
|
302
|
-
return time, record
|
303
|
-
end
|
304
|
-
rescue @error_class
|
305
|
-
if block_given?
|
306
|
-
yield nil, nil
|
307
|
-
else
|
308
|
-
return nil, nil
|
309
|
-
end
|
310
|
-
end
|
311
|
-
end
|
312
|
-
|
313
|
-
class ValuesParser < Parser
|
314
|
-
include TypeConverter
|
315
|
-
|
316
|
-
config_param :keys, default: [] do |val|
|
317
|
-
if val.start_with?('[') # This check is enough because keys parameter is simple. No '[' started column name.
|
318
|
-
JSON.load(val)
|
319
|
-
else
|
320
|
-
val.split(",")
|
321
|
-
end
|
322
|
-
end
|
323
|
-
config_param :time_key, :string, default: nil
|
324
|
-
config_param :time_format, :string, default: nil
|
325
|
-
config_param :null_value_pattern, :string, default: nil
|
326
|
-
config_param :null_empty_string, :bool, default: false
|
327
|
-
|
328
|
-
def configure(conf)
|
329
|
-
super
|
330
|
-
|
331
|
-
if @time_key && !@keys.include?(@time_key) && @estimate_current_event
|
332
|
-
raise ConfigError, "time_key (#{@time_key.inspect}) is not included in keys (#{@keys.inspect})"
|
333
|
-
end
|
334
|
-
|
335
|
-
if @time_format && !@time_key
|
336
|
-
raise ConfigError, "time_format parameter is ignored because time_key parameter is not set. at #{conf.inspect}"
|
337
|
-
end
|
338
|
-
|
339
|
-
@time_parser = TimeParser.new(@time_format)
|
340
|
-
|
341
|
-
if @null_value_pattern
|
342
|
-
@null_value_pattern = Regexp.new(@null_value_pattern)
|
343
|
-
end
|
344
|
-
|
345
|
-
@mutex = Mutex.new
|
346
|
-
end
|
347
|
-
|
348
|
-
def values_map(values)
|
349
|
-
record = Hash[keys.zip(values.map { |value| convert_value_to_nil(value) })]
|
350
|
-
|
351
|
-
if @time_key
|
352
|
-
value = @keep_time_key ? record[@time_key] : record.delete(@time_key)
|
353
|
-
time = if value.nil?
|
354
|
-
if @estimate_current_event
|
355
|
-
Engine.now
|
356
|
-
else
|
357
|
-
nil
|
358
|
-
end
|
359
|
-
else
|
360
|
-
@mutex.synchronize { @time_parser.parse(value) }
|
361
|
-
end
|
362
|
-
elsif @estimate_current_event
|
363
|
-
time = Engine.now
|
364
|
-
else
|
365
|
-
time = nil
|
366
|
-
end
|
367
|
-
|
368
|
-
convert_field_type!(record) if @type_converters
|
369
|
-
|
370
|
-
return time, record
|
371
|
-
end
|
372
|
-
|
373
|
-
private
|
374
|
-
|
375
|
-
def convert_field_type!(record)
|
376
|
-
@type_converters.each_key { |key|
|
377
|
-
if value = record[key]
|
378
|
-
record[key] = convert_type(key, value)
|
379
|
-
end
|
380
|
-
}
|
381
|
-
end
|
382
|
-
|
383
|
-
def convert_value_to_nil(value)
|
384
|
-
if value and @null_empty_string
|
385
|
-
value = (value == '') ? nil : value
|
386
|
-
end
|
387
|
-
if value and @null_value_pattern
|
388
|
-
value = ::Fluent::StringUtil.match_regexp(@null_value_pattern, value) ? nil : value
|
389
|
-
end
|
390
|
-
value
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
class TSVParser < ValuesParser
|
395
|
-
config_param :delimiter, :string, default: "\t"
|
396
|
-
|
397
|
-
def configure(conf)
|
398
|
-
super
|
399
|
-
@key_num = @keys.length
|
400
|
-
end
|
401
|
-
|
402
|
-
def parse(text)
|
403
|
-
if block_given?
|
404
|
-
yield values_map(text.split(@delimiter, @key_num))
|
405
|
-
else
|
406
|
-
return values_map(text.split(@delimiter, @key_num))
|
407
|
-
end
|
408
|
-
end
|
409
|
-
end
|
410
|
-
|
411
|
-
class LabeledTSVParser < ValuesParser
|
412
|
-
config_param :delimiter, :string, default: "\t"
|
413
|
-
config_param :label_delimiter, :string, default: ":"
|
414
|
-
config_param :time_key, :string, default: "time"
|
415
|
-
|
416
|
-
def configure(conf)
|
417
|
-
conf['keys'] = conf['time_key'] || 'time'
|
418
|
-
super(conf)
|
419
|
-
end
|
420
|
-
|
421
|
-
def parse(text)
|
422
|
-
@keys = []
|
423
|
-
values = []
|
424
|
-
|
425
|
-
text.split(delimiter).each do |pair|
|
426
|
-
key, value = pair.split(label_delimiter, 2)
|
427
|
-
@keys.push(key)
|
428
|
-
values.push(value)
|
429
|
-
end
|
430
|
-
|
431
|
-
if block_given?
|
432
|
-
yield values_map(values)
|
433
|
-
else
|
434
|
-
return values_map(values)
|
435
|
-
end
|
436
|
-
end
|
437
|
-
end
|
438
|
-
|
439
|
-
class CSVParser < ValuesParser
|
440
|
-
def initialize
|
441
|
-
super
|
442
|
-
require 'csv'
|
443
|
-
end
|
444
|
-
|
445
|
-
def parse(text)
|
446
|
-
if block_given?
|
447
|
-
yield values_map(CSV.parse_line(text))
|
448
|
-
else
|
449
|
-
return values_map(CSV.parse_line(text))
|
450
|
-
end
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
class NoneParser < Parser
|
455
|
-
config_param :message_key, :string, default: 'message'
|
456
|
-
|
457
|
-
def parse(text)
|
458
|
-
record = {}
|
459
|
-
record[@message_key] = text
|
460
|
-
time = @estimate_current_event ? Engine.now : nil
|
461
|
-
if block_given?
|
462
|
-
yield time, record
|
463
|
-
else
|
464
|
-
return time, record
|
465
|
-
end
|
466
|
-
end
|
467
|
-
end
|
468
|
-
|
469
|
-
class ApacheParser < Parser
|
470
|
-
REGEXP = /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>(?:[^\"]|\\.)*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>(?:[^\"]|\\.)*)" "(?<agent>(?:[^\"]|\\.)*)")?$/
|
471
|
-
TIME_FORMAT = "%d/%b/%Y:%H:%M:%S %z"
|
472
|
-
|
473
|
-
def initialize
|
474
|
-
super
|
475
|
-
@time_parser = TimeParser.new(TIME_FORMAT)
|
476
|
-
@mutex = Mutex.new
|
477
|
-
end
|
478
|
-
|
479
|
-
def patterns
|
480
|
-
{'format' => REGEXP, 'time_format' => TIME_FORMAT}
|
481
|
-
end
|
482
|
-
|
483
|
-
def parse(text)
|
484
|
-
m = REGEXP.match(text)
|
485
|
-
unless m
|
486
|
-
if block_given?
|
487
|
-
yield nil, nil
|
488
|
-
return
|
489
|
-
else
|
490
|
-
return nil, nil
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
host = m['host']
|
495
|
-
host = (host == '-') ? nil : host
|
496
|
-
|
497
|
-
user = m['user']
|
498
|
-
user = (user == '-') ? nil : user
|
499
|
-
|
500
|
-
time = m['time']
|
501
|
-
time = @mutex.synchronize { @time_parser.parse(time) }
|
502
|
-
|
503
|
-
method = m['method']
|
504
|
-
path = m['path']
|
505
|
-
|
506
|
-
code = m['code'].to_i
|
507
|
-
code = nil if code == 0
|
508
|
-
|
509
|
-
size = m['size']
|
510
|
-
size = (size == '-') ? nil : size.to_i
|
511
|
-
|
512
|
-
referer = m['referer']
|
513
|
-
referer = (referer == '-') ? nil : referer
|
514
|
-
|
515
|
-
agent = m['agent']
|
516
|
-
agent = (agent == '-') ? nil : agent
|
517
|
-
|
518
|
-
record = {
|
519
|
-
"host" => host,
|
520
|
-
"user" => user,
|
521
|
-
"method" => method,
|
522
|
-
"path" => path,
|
523
|
-
"code" => code,
|
524
|
-
"size" => size,
|
525
|
-
"referer" => referer,
|
526
|
-
"agent" => agent,
|
527
|
-
}
|
528
|
-
record["time"] = m['time'] if @keep_time_key
|
529
|
-
|
530
|
-
if block_given?
|
531
|
-
yield time, record
|
532
|
-
else
|
533
|
-
return time, record
|
534
|
-
end
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
class SyslogParser < Parser
|
539
|
-
# From existence TextParser pattern
|
540
|
-
REGEXP = /^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[^ :\[]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
|
541
|
-
# From in_syslog default pattern
|
542
|
-
REGEXP_WITH_PRI = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[^ :\[]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
|
543
|
-
REGEXP_RFC5424 = /\A^(?<time>[^ ]+) (?<host>[^ ]+) (?<ident>[^ ]+) (?<pid>[-0-9]+) (?<msgid>[^ ]+) (?<extradata>(\[(.*)\]|[^ ])) (?<message>.+)$\z/
|
544
|
-
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/
|
545
|
-
REGEXP_DETECT_RFC5424 = /^\<.*\>[1-9]\d{0,2}/
|
546
|
-
|
547
|
-
config_param :time_format, :string, default: "%b %d %H:%M:%S"
|
548
|
-
config_param :with_priority, :bool, default: false
|
549
|
-
config_param :message_format, :enum, list: [:rfc3164, :rfc5424, :auto], default: :rfc3164
|
550
|
-
config_param :rfc5424_time_format, :string, default: "%Y-%m-%dT%H:%M:%S.%L%z"
|
551
|
-
|
552
|
-
def initialize
|
553
|
-
super
|
554
|
-
@mutex = Mutex.new
|
555
|
-
end
|
556
|
-
|
557
|
-
def configure(conf)
|
558
|
-
super
|
559
|
-
|
560
|
-
@time_parser_rfc3164 = @time_parser_rfc5424 = nil
|
561
|
-
@regexp = case @message_format
|
562
|
-
when :rfc3164
|
563
|
-
class << self
|
564
|
-
alias_method :parse, :parse_plain
|
565
|
-
end
|
566
|
-
@with_priority ? REGEXP_WITH_PRI : REGEXP
|
567
|
-
when :rfc5424
|
568
|
-
class << self
|
569
|
-
alias_method :parse, :parse_plain
|
570
|
-
end
|
571
|
-
@time_format = @rfc5424_time_format unless conf.has_key?('time_format')
|
572
|
-
@with_priority ? REGEXP_RFC5424_WITH_PRI : REGEXP_RFC5424
|
573
|
-
when :auto
|
574
|
-
class << self
|
575
|
-
alias_method :parse, :parse_auto
|
576
|
-
end
|
577
|
-
@time_parser_rfc3164 = TextParser::TimeParser.new(@time_format)
|
578
|
-
@time_parser_rfc5424 = TextParser::TimeParser.new(@rfc5424_time_format)
|
579
|
-
nil
|
580
|
-
end
|
581
|
-
@time_parser = TextParser::TimeParser.new(@time_format)
|
582
|
-
end
|
583
|
-
|
584
|
-
def patterns
|
585
|
-
{'format' => @regexp, 'time_format' => @time_format}
|
586
|
-
end
|
587
|
-
|
588
|
-
def parse(text)
|
589
|
-
# This is overwritten in configure
|
590
|
-
end
|
591
|
-
|
592
|
-
def parse_auto(text, &block)
|
593
|
-
if REGEXP_DETECT_RFC5424.match(text)
|
594
|
-
@regexp = @with_priority ? REGEXP_RFC5424_WITH_PRI : REGEXP_RFC5424
|
595
|
-
@time_parser = @time_parser_rfc5424
|
596
|
-
else
|
597
|
-
@regexp = @with_priority ? REGEXP_WITH_PRI : REGEXP
|
598
|
-
@time_parser = @time_parser_rfc3164
|
599
|
-
end
|
600
|
-
parse_plain(text, &block)
|
601
|
-
end
|
602
|
-
|
603
|
-
def parse_plain(text, &block)
|
604
|
-
m = @regexp.match(text)
|
605
|
-
unless m
|
606
|
-
if block_given?
|
607
|
-
yield nil, nil
|
608
|
-
return
|
609
|
-
else
|
610
|
-
return nil, nil
|
611
|
-
end
|
612
|
-
end
|
613
|
-
|
614
|
-
time = nil
|
615
|
-
record = {}
|
616
|
-
|
617
|
-
m.names.each { |name|
|
618
|
-
if value = m[name]
|
619
|
-
case name
|
620
|
-
when "pri"
|
621
|
-
record['pri'] = value.to_i
|
622
|
-
when "time"
|
623
|
-
time = @mutex.synchronize { @time_parser.parse(value.gsub(/ +/, ' ')) }
|
624
|
-
record[name] = value if @keep_time_key
|
625
|
-
else
|
626
|
-
record[name] = value
|
627
|
-
end
|
628
|
-
end
|
629
|
-
}
|
630
|
-
|
631
|
-
if @estimate_current_event
|
632
|
-
time ||= Engine.now
|
633
|
-
end
|
634
|
-
|
635
|
-
if block_given?
|
636
|
-
yield time, record
|
637
|
-
else
|
638
|
-
return time, record
|
639
|
-
end
|
640
|
-
end
|
641
|
-
end
|
642
|
-
|
643
|
-
class MultilineParser < Parser
|
644
|
-
config_param :format_firstline, :string, default: nil
|
645
|
-
|
646
|
-
FORMAT_MAX_NUM = 20
|
647
|
-
|
648
|
-
def configure(conf)
|
649
|
-
super
|
650
|
-
|
651
|
-
formats = parse_formats(conf).compact.map { |f| f[1..-2] }.join
|
652
|
-
begin
|
653
|
-
@regex = Regexp.new(formats, Regexp::MULTILINE)
|
654
|
-
if @regex.named_captures.empty?
|
655
|
-
raise "No named captures"
|
656
|
-
end
|
657
|
-
@parser = RegexpParser.new(@regex, conf)
|
658
|
-
rescue => e
|
659
|
-
raise ConfigError, "Invalid regexp '#{formats}': #{e}"
|
660
|
-
end
|
661
|
-
|
662
|
-
if @format_firstline
|
663
|
-
check_format_regexp(@format_firstline, 'format_firstline')
|
664
|
-
@firstline_regex = Regexp.new(@format_firstline[1..-2])
|
665
|
-
end
|
666
|
-
end
|
667
|
-
|
668
|
-
def parse(text, &block)
|
669
|
-
if block
|
670
|
-
@parser.call(text, &block)
|
671
|
-
else
|
672
|
-
@parser.call(text)
|
673
|
-
end
|
674
|
-
end
|
675
|
-
|
676
|
-
def has_firstline?
|
677
|
-
!!@format_firstline
|
678
|
-
end
|
679
|
-
|
680
|
-
def firstline?(text)
|
681
|
-
@firstline_regex.match(text)
|
682
|
-
end
|
683
|
-
|
684
|
-
private
|
685
|
-
|
686
|
-
def parse_formats(conf)
|
687
|
-
check_format_range(conf)
|
688
|
-
|
689
|
-
prev_format = nil
|
690
|
-
(1..FORMAT_MAX_NUM).map { |i|
|
691
|
-
format = conf["format#{i}"]
|
692
|
-
if (i > 1) && prev_format.nil? && !format.nil?
|
693
|
-
raise ConfigError, "Jump of format index found. format#{i - 1} is missing."
|
694
|
-
end
|
695
|
-
prev_format = format
|
696
|
-
next if format.nil?
|
697
|
-
|
698
|
-
check_format_regexp(format, "format#{i}")
|
699
|
-
format
|
700
|
-
}
|
701
|
-
end
|
702
|
-
|
703
|
-
def check_format_range(conf)
|
704
|
-
invalid_formats = conf.keys.select { |k|
|
705
|
-
m = k.match(/^format(\d+)$/)
|
706
|
-
m ? !((1..FORMAT_MAX_NUM).include?(m[1].to_i)) : false
|
707
|
-
}
|
708
|
-
unless invalid_formats.empty?
|
709
|
-
raise ConfigError, "Invalid formatN found. N should be 1 - #{FORMAT_MAX_NUM}: " + invalid_formats.join(",")
|
710
|
-
end
|
711
|
-
end
|
712
|
-
|
713
|
-
def check_format_regexp(format, key)
|
714
|
-
if format[0] == '/' && format[-1] == '/'
|
715
|
-
begin
|
716
|
-
Regexp.new(format[1..-2], Regexp::MULTILINE)
|
717
|
-
rescue => e
|
718
|
-
raise ConfigError, "Invalid regexp in #{key}: #{e}"
|
719
|
-
end
|
720
|
-
else
|
721
|
-
raise ConfigError, "format should be Regexp, need //, in #{key}: '#{format}'"
|
722
|
-
end
|
723
|
-
end
|
724
|
-
end
|
725
|
-
|
726
|
-
TEMPLATE_REGISTRY = Registry.new(:config_type, 'fluent/plugin/parser_')
|
727
|
-
{
|
728
|
-
'apache' => Proc.new { RegexpParser.new(/^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/, {'time_format'=>"%d/%b/%Y:%H:%M:%S %z"}) },
|
729
|
-
'apache_error' => Proc.new { RegexpParser.new(/^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])?( \[client (?<client>[^\]]*)\])? (?<message>.*)$/) },
|
730
|
-
'apache2' => Proc.new { ApacheParser.new },
|
731
|
-
'syslog' => Proc.new { SyslogParser.new },
|
732
|
-
'json' => Proc.new { JSONParser.new },
|
733
|
-
'tsv' => Proc.new { TSVParser.new },
|
734
|
-
'ltsv' => Proc.new { LabeledTSVParser.new },
|
735
|
-
'csv' => Proc.new { CSVParser.new },
|
736
|
-
'nginx' => Proc.new { RegexpParser.new(/^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/, {'time_format'=>"%d/%b/%Y:%H:%M:%S %z"}) },
|
737
|
-
'none' => Proc.new { NoneParser.new },
|
738
|
-
'multiline' => Proc.new { MultilineParser.new },
|
739
|
-
}.each { |name, factory|
|
740
|
-
TEMPLATE_REGISTRY.register(name, factory)
|
741
|
-
}
|
742
|
-
|
743
|
-
def self.register_template(name, regexp_or_proc, time_format=nil)
|
744
|
-
if regexp_or_proc.is_a?(Class)
|
745
|
-
factory = Proc.new { regexp_or_proc.new }
|
746
|
-
elsif regexp_or_proc.is_a?(Regexp)
|
747
|
-
regexp = regexp_or_proc
|
748
|
-
factory = Proc.new { RegexpParser.new(regexp, {'time_format'=>time_format}) }
|
749
|
-
else
|
750
|
-
factory = regexp_or_proc
|
751
|
-
end
|
752
|
-
|
753
|
-
TEMPLATE_REGISTRY.register(name, factory)
|
754
|
-
end
|
755
|
-
|
756
|
-
def self.lookup(format)
|
757
|
-
if format.nil?
|
758
|
-
raise ConfigError, "'format' parameter is required"
|
759
|
-
end
|
760
|
-
|
761
|
-
if format[0] == ?/ && format[format.length-1] == ?/
|
762
|
-
# regexp
|
763
|
-
begin
|
764
|
-
regexp = Regexp.new(format[1..-2])
|
765
|
-
if regexp.named_captures.empty?
|
766
|
-
raise "No named captures"
|
767
|
-
end
|
768
|
-
rescue
|
769
|
-
raise ConfigError, "Invalid regexp '#{format[1..-2]}': #{$!}"
|
770
|
-
end
|
771
|
-
|
772
|
-
RegexpParser.new(regexp)
|
773
|
-
else
|
774
|
-
# built-in template
|
775
|
-
begin
|
776
|
-
factory = TEMPLATE_REGISTRY.lookup(format)
|
777
|
-
rescue ConfigError => e # keep same error message
|
778
|
-
raise ConfigError, "Unknown format template '#{format}'"
|
779
|
-
end
|
780
|
-
|
781
|
-
factory.call
|
782
|
-
end
|
783
|
-
end
|
784
|
-
|
785
|
-
def initialize
|
786
|
-
@parser = nil
|
787
|
-
@estimate_current_event = nil
|
788
|
-
end
|
789
|
-
|
790
|
-
attr_reader :parser
|
791
|
-
|
792
|
-
# SET false BEFORE CONFIGURE, to return nil when time not parsed
|
793
|
-
# 'configure()' may raise errors for unexpected configurations
|
794
|
-
attr_accessor :estimate_current_event
|
795
|
-
|
796
|
-
def configure(conf, required=true)
|
797
|
-
format = conf['format']
|
798
|
-
|
799
|
-
@parser = TextParser.lookup(format)
|
800
|
-
if ! @estimate_current_event.nil? && @parser.respond_to?(:'estimate_current_event=')
|
801
|
-
@parser.estimate_current_event = @estimate_current_event
|
802
|
-
end
|
803
|
-
|
804
|
-
if @parser.respond_to?(:configure)
|
805
|
-
@parser.configure(conf)
|
806
|
-
end
|
807
|
-
|
808
|
-
return true
|
809
|
-
end
|
810
|
-
|
811
|
-
def parse(text, &block)
|
812
|
-
if block
|
813
|
-
@parser.parse(text, &block)
|
814
|
-
else # keep backward compatibility. Will be removed at v1
|
815
|
-
return @parser.parse(text)
|
816
|
-
end
|
817
|
-
end
|
818
|
-
end
|
20
|
+
ParserError = Fluent::Compat::Parser::ParserError
|
21
|
+
Parser = Fluent::Compat::Parser
|
22
|
+
TextParser = Fluent::Compat::TextParser
|
819
23
|
end
|