fluentd 1.10.4 → 1.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 578798388cf4aa5c2628456764505f249ee7c5c50b6cf3c45cfd48bfccc5a62e
4
- data.tar.gz: 172bf6a9caf7b38ae9274c3a1ada15b828655d79c4186a27c90c5de6882707f6
3
+ metadata.gz: 269cadf10ed4159e0c5279177cde46de14d563637b38ccadc71da090a098a22e
4
+ data.tar.gz: 9bf1dca5f46b1f3b245231c0e08b3b709add909840c3241bf29401952e02f27a
5
5
  SHA512:
6
- metadata.gz: 8056b113c52d327fc314166e0cc4fda3765afe0dd41614e644e423a5504ff164297c01ab03f90c605f43fce84e902b226de7847c9b7f41d40ad8b462b7f86d43
7
- data.tar.gz: 4ac3f7fb124ab42e21df67901b7435d4040cea3ad20e58b60515aa3b198755bb763c3415e48760aab7ebe12c895ff827e47487209de26ad06bccd46594742907
6
+ metadata.gz: 115e9f075e91136de66003ced2eda6076c1cff31c1e8edae5bb063f4c97420e4f832bcf6539a1ac4ee50bbe28d2050a6782840e88c951fa8fcbb52c66a889569
7
+ data.tar.gz: 25ebff981ebc41c4b6c0de4a6710350a07653be263019a138bb7be62d97dd6593bff67b7dd4d6ca4d37d0f84427b05d4c9b06f56cc9bc344fa46e0cfa82a7d68
@@ -1,3 +1,26 @@
1
+ # v1.11
2
+
3
+ ## Release v1.11.0 - 2020/06/04
4
+
5
+ ### New feature
6
+
7
+ * in_unix: Use v1 API
8
+ https://github.com/fluent/fluentd/pull/2992
9
+
10
+ ### Enhancement
11
+
12
+ * parser_syslog: Support any `time_format` for RFC3164 string parser
13
+ https://github.com/fluent/fluentd/pull/2988
14
+ * parser_syslog: Add new parser for RFC5424
15
+ https://github.com/fluent/fluentd/pull/3015
16
+ * Refactoring code
17
+ https://github.com/fluent/fluentd/pull/3019
18
+
19
+ ### Bug fix
20
+
21
+ * in_gc_stat: Add `use_symbol_keys` parameter to emit string key record
22
+ https://github.com/fluent/fluentd/pull/3008
23
+
1
24
  # v1.10
2
25
 
3
26
  ## Release v1.10.4 - 2020/05/12
@@ -24,13 +24,22 @@ module Fluent::Plugin
24
24
 
25
25
  def initialize
26
26
  super
27
+ @key_map = nil
27
28
  end
28
29
 
29
30
  config_param :emit_interval, :time, default: 60
31
+ config_param :use_symbol_keys, :bool, default: true
30
32
  config_param :tag, :string
31
33
 
32
34
  def configure(conf)
33
35
  super
36
+
37
+ unless @use_symbol_keys
38
+ @key_map = {}
39
+ GC.stat.each_key { |key|
40
+ @key_map[key] = key.to_s
41
+ }
42
+ end
34
43
  end
35
44
 
36
45
  def multi_workers_ready?
@@ -50,6 +59,13 @@ module Fluent::Plugin
50
59
  def on_timer
51
60
  now = Fluent::EventTime.now
52
61
  record = GC.stat
62
+ unless @use_symbol_keys
63
+ new_record = {}
64
+ record.each_pair { |k, v|
65
+ new_record[@key_map[k]] = v
66
+ }
67
+ record = new_record
68
+ end
53
69
  router.emit(@tag, now, record)
54
70
  end
55
71
  end
@@ -14,50 +14,68 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fileutils'
18
- require 'socket'
17
+ require 'fluent/env'
18
+ require 'fluent/plugin/input'
19
+ require 'fluent/msgpack_factory'
19
20
 
20
21
  require 'cool.io'
21
22
  require 'yajl'
23
+ require 'fileutils'
24
+ require 'socket'
25
+
26
+ module Fluent::Plugin
27
+ # TODO: This plugin will be 3rd party plugin
28
+ class UnixInput < Input
29
+ Fluent::Plugin.register_input('unix', self)
30
+
31
+ helpers :event_loop
32
+
33
+ def initialize
34
+ super
22
35
 
23
- require 'fluent/input'
24
- require 'fluent/event'
36
+ @lsock = nil
37
+ end
25
38
 
26
- module Fluent
27
- # obsolete
28
- class StreamInput < Input
29
- config_param :blocking_timeout, :time, default: 0.5
39
+ desc 'The path to your Unix Domain Socket.'
40
+ config_param :path, :string, default: Fluent::DEFAULT_SOCKET_PATH
41
+ desc 'The backlog of Unix Domain Socket.'
42
+ config_param :backlog, :integer, default: nil
43
+ desc "New tag instead of incoming tag"
44
+ config_param :tag, :string, default: nil
45
+
46
+ def configure(conf)
47
+ super
48
+ end
30
49
 
31
50
  def start
32
51
  super
33
52
 
34
- @loop = Coolio::Loop.new
35
53
  @lsock = listen
36
- @loop.attach(@lsock)
37
- @thread = Thread.new(&method(:run))
54
+ event_loop_attach(@lsock)
38
55
  end
39
56
 
40
57
  def shutdown
41
- @loop.watchers.each {|w| w.detach }
42
- @loop.stop
43
- @lsock.close
44
- @thread.join
58
+ if @lsock
59
+ event_loop_detach(@lsock)
60
+ @lsock.close
61
+ end
45
62
 
46
63
  super
47
64
  end
48
65
 
49
- #def listen
50
- #end
66
+ def listen
67
+ if File.exist?(@path)
68
+ log.warn "Found existing '#{@path}'. Remove this file for in_unix plugin"
69
+ File.unlink(@path)
70
+ end
71
+ FileUtils.mkdir_p(File.dirname(@path))
51
72
 
52
- def run
53
- @loop.run(@blocking_timeout)
54
- rescue
55
- log.error "unexpected error", error: $!.to_s
56
- log.error_backtrace
73
+ log.info "listening fluent socket on #{@path}"
74
+ s = Coolio::UNIXServer.new(@path, Handler, log, method(:on_message))
75
+ s.listen(@backlog) unless @backlog.nil?
76
+ s
57
77
  end
58
78
 
59
- private
60
-
61
79
  # message Entry {
62
80
  # 1: long time
63
81
  # 2: object record
@@ -79,23 +97,27 @@ module Fluent
79
97
  # 3: object record
80
98
  # }
81
99
  def on_message(msg)
82
- # TODO format error
83
- tag = msg[0].to_s
100
+ unless msg.is_a?(Array)
101
+ log.warn "incoming data is broken:", msg: msg
102
+ return
103
+ end
104
+
105
+ tag = @tag || (msg[0].to_s)
84
106
  entries = msg[1]
85
107
 
86
- if entries.class == String
108
+ case entries
109
+ when String
87
110
  # PackedForward
88
- es = MessagePackEventStream.new(entries)
111
+ es = Fluent::MessagePackEventStream.new(entries)
89
112
  router.emit_stream(tag, es)
90
113
 
91
- elsif entries.class == Array
114
+ when Array
92
115
  # Forward
93
- es = MultiEventStream.new
116
+ es = Fluent::MultiEventStream.new
94
117
  entries.each {|e|
95
118
  record = e[1]
96
119
  next if record.nil?
97
- time = e[0]
98
- time = (now ||= EventTime.now) if time.to_i == 0
120
+ time = convert_time(e[0])
99
121
  es.add(time, record)
100
122
  }
101
123
  router.emit_stream(tag, es)
@@ -105,25 +127,28 @@ module Fluent
105
127
  record = msg[2]
106
128
  return if record.nil?
107
129
 
108
- time = msg[1]
109
- time = EventTime.now if time.to_i == 0
130
+ time = convert_time(msg[1])
110
131
  router.emit(tag, time, record)
111
132
  end
112
133
  end
113
134
 
135
+ def convert_time(time)
136
+ case time
137
+ when nil, 0
138
+ Fluent::EventTime.now
139
+ when Fluent::EventTime
140
+ time
141
+ else
142
+ Fluent::EventTime.from_time(Time.at(time))
143
+ end
144
+ end
145
+
114
146
  class Handler < Coolio::Socket
115
147
  def initialize(io, log, on_message)
116
148
  super(io)
117
- if io.is_a?(TCPSocket)
118
- opt = [1, @timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
119
- io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
120
- end
149
+
121
150
  @on_message = on_message
122
151
  @log = log
123
- @log.trace {
124
- remote_port, remote_addr = *Socket.unpack_sockaddr_in(@_io.getpeername) rescue nil
125
- "accepted fluent socket from '#{remote_addr}:#{remote_port}': object_id=#{self.object_id}"
126
- }
127
152
  end
128
153
 
129
154
  def on_connect
@@ -131,13 +156,13 @@ module Fluent
131
156
 
132
157
  def on_read(data)
133
158
  first = data[0]
134
- if first == '{' || first == '['
159
+ if first == '{'.freeze || first == '['.freeze
135
160
  m = method(:on_read_json)
136
- @y = Yajl::Parser.new
137
- @y.on_parse_complete = @on_message
161
+ @parser = Yajl::Parser.new
162
+ @parser.on_parse_complete = @on_message
138
163
  else
139
164
  m = method(:on_read_msgpack)
140
- @u = Fluent::MessagePackFactory.msgpack_unpacker
165
+ @parser = Fluent::MessagePackFactory.msgpack_unpacker
141
166
  end
142
167
 
143
168
  singleton_class.module_eval do
@@ -147,17 +172,17 @@ module Fluent
147
172
  end
148
173
 
149
174
  def on_read_json(data)
150
- @y << data
151
- rescue
152
- @log.error "unexpected error", error: $!.to_s
175
+ @parser << data
176
+ rescue => e
177
+ @log.error "unexpected error in json payload", error: e.to_s
153
178
  @log.error_backtrace
154
179
  close
155
180
  end
156
181
 
157
182
  def on_read_msgpack(data)
158
- @u.feed_each(data, &@on_message)
159
- rescue
160
- @log.error "unexpected error", error: $!.to_s
183
+ @parser.feed_each(data, &@on_message)
184
+ rescue => e
185
+ @log.error "unexpected error in msgpack payload", error: e.to_s
161
186
  @log.error_backtrace
162
187
  close
163
188
  end
@@ -167,29 +192,4 @@ module Fluent
167
192
  end
168
193
  end
169
194
  end
170
-
171
- class UnixInput < StreamInput
172
- Plugin.register_input('unix', self)
173
-
174
- desc 'The path to your Unix Domain Socket.'
175
- config_param :path, :string, default: DEFAULT_SOCKET_PATH
176
- desc 'The backlog of Unix Domain Socket.'
177
- config_param :backlog, :integer, default: nil
178
-
179
- def configure(conf)
180
- super
181
- #log.warn "'unix' input is obsoleted and will be removed. Use 'forward' instead."
182
- end
183
-
184
- def listen
185
- if File.exist?(@path)
186
- File.unlink(@path)
187
- end
188
- FileUtils.mkdir_p File.dirname(@path)
189
- log.info "listening fluent socket on #{@path}"
190
- s = Coolio::UNIXServer.new(@path, Handler, log, method(:on_message))
191
- s.listen(@backlog) unless @backlog.nil?
192
- s
193
- end
194
- end
195
195
  end
@@ -63,16 +63,22 @@ module Fluent
63
63
  def initialize
64
64
  super
65
65
  @mutex = Mutex.new
66
- @space_count = nil
66
+ @regexp = nil
67
+ @regexp3164 = nil
68
+ @regexp5424 = nil
69
+ @regexp_parser = nil
70
+ @time_parser_rfc3164 = nil
71
+ @time_parser_rfc5424 = nil
72
+ @space_count_rfc3164 = nil
67
73
  @space_count_rfc5424 = nil
74
+ @skip_space_count_rfc3164 = false
75
+ @skip_space_count_rfc5424 = false
76
+ @time_parser_rfc5424_without_subseconds = nil
68
77
  end
69
78
 
70
79
  def configure(conf)
71
80
  super
72
81
 
73
- @time_parser_rfc3164 = @time_parser_rfc5424 = nil
74
- @time_parser_rfc5424_without_subseconds = nil
75
- @support_rfc5424_without_subseconds = false
76
82
  @regexp_parser = @parser_type == :regexp
77
83
  @regexp = case @message_format
78
84
  when :rfc3164
@@ -85,27 +91,49 @@ module Fluent
85
91
  alias_method :parse, :parse_rfc3164
86
92
  end
87
93
  end
94
+ setup_time_parser_3164(@time_format)
88
95
  RFC3164_WITHOUT_TIME_AND_PRI_REGEXP
89
96
  when :rfc5424
90
- class << self
91
- alias_method :parse, :parse_rfc5424_regex
97
+ if @regexp_parser
98
+ class << self
99
+ alias_method :parse, :parse_rfc5424_regex
100
+ end
101
+ else
102
+ class << self
103
+ alias_method :parse, :parse_rfc5424
104
+ end
92
105
  end
93
106
  @time_format = @rfc5424_time_format unless conf.has_key?('time_format')
94
- @support_rfc5424_without_subseconds = true
107
+ setup_time_parser_5424(@time_format)
95
108
  RFC5424_WITHOUT_TIME_AND_PRI_REGEXP
96
109
  when :auto
97
110
  class << self
98
111
  alias_method :parse, :parse_auto
99
112
  end
100
- @time_parser_rfc3164 = time_parser_create(format: @time_format)
101
- @time_parser_rfc5424 = time_parser_create(format: @rfc5424_time_format)
113
+ setup_time_parser_3164(@time_format)
114
+ setup_time_parser_5424(@rfc5424_time_format)
102
115
  nil
103
116
  end
104
117
 
105
- @space_count = @time_format.squeeze(' ').count(' ') + 1
106
- @space_count_rfc5424 = @rfc5424_time_format.squeeze(' ').count(' ') + 1
107
- @time_parser = time_parser_create
118
+ if @regexp_parser
119
+ @regexp3164 = RFC3164_WITHOUT_TIME_AND_PRI_REGEXP
120
+ @regexp5424 = RFC5424_WITHOUT_TIME_AND_PRI_REGEXP
121
+ end
122
+ end
123
+
124
+ def setup_time_parser_3164(time_fmt)
125
+ @time_parser_rfc3164 = time_parser_create(format: time_fmt)
126
+ if ['%b %d %H:%M:%S', '%b %d %H:%M:%S.%N'].include?(time_fmt)
127
+ @skip_space_count_rfc3164 = true
128
+ end
129
+ @space_count_rfc3164 = time_fmt.squeeze(' ').count(' ') + 1
130
+ end
131
+
132
+ def setup_time_parser_5424(time_fmt)
133
+ @time_parser_rfc5424 = time_parser_create(format: time_fmt)
108
134
  @time_parser_rfc5424_without_subseconds = time_parser_create(format: "%Y-%m-%dT%H:%M:%S%z")
135
+ @skip_space_count_rfc5424 = time_fmt.count(' ').zero?
136
+ @space_count_rfc5424 = time_fmt.squeeze(' ').count(' ') + 1
109
137
  end
110
138
 
111
139
  # this method is for tests
@@ -118,14 +146,13 @@ module Fluent
118
146
  end
119
147
 
120
148
  def parse_auto(text, &block)
121
- if REGEXP_DETECT_RFC5424.match(text)
122
- @regexp = RFC5424_WITHOUT_TIME_AND_PRI_REGEXP
123
- @time_parser = @time_parser_rfc5424
124
- @support_rfc5424_without_subseconds = true
125
- parse_rfc5424_regex(text, &block)
149
+ if REGEXP_DETECT_RFC5424.match?(text)
150
+ if @regexp_parser
151
+ parse_rfc5424_regex(text, &block)
152
+ else
153
+ parse_rfc5424(text, &block)
154
+ end
126
155
  else
127
- @regexp = RFC3164_WITHOUT_TIME_AND_PRI_REGEXP
128
- @time_parser = @time_parser_rfc3164
129
156
  if @regexp_parser
130
157
  parse_rfc3164_regex(text, &block)
131
158
  else
@@ -134,6 +161,8 @@ module Fluent
134
161
  end
135
162
  end
136
163
 
164
+ SPLIT_CHAR = ' '.freeze
165
+
137
166
  def parse_rfc3164_regex(text, &block)
138
167
  idx = 0
139
168
  record = {}
@@ -151,22 +180,22 @@ module Fluent
151
180
 
152
181
  i = idx - 1
153
182
  sq = false
154
- @space_count.times do
155
- while text[i + 1] == ' '.freeze
183
+ @space_count_rfc3164.times do
184
+ while text[i + 1] == SPLIT_CHAR
156
185
  sq = true
157
186
  i += 1
158
187
  end
159
188
 
160
- i = text.index(' '.freeze, i + 1)
189
+ i = text.index(SPLIT_CHAR, i + 1)
161
190
  end
162
191
 
163
- time_str = sq ? text.slice(idx, i - idx).squeeze(' ') : text.slice(idx, i - idx)
164
- time = @mutex.synchronize { @time_parser.parse(time_str) }
192
+ time_str = sq ? text.slice(idx, i - idx).squeeze(SPLIT_CHAR) : text.slice(idx, i - idx)
193
+ time = @mutex.synchronize { @time_parser_rfc3164.parse(time_str) }
165
194
  if @keep_time_key
166
195
  record['time'] = time_str
167
196
  end
168
197
 
169
- parse_plain(time, text, i + 1, record, RFC3164_CAPTURES, &block)
198
+ parse_plain(@regexp3164, time, text, i + 1, record, RFC3164_CAPTURES, &block)
170
199
  end
171
200
 
172
201
  def parse_rfc5424_regex(text, &block)
@@ -186,40 +215,36 @@ module Fluent
186
215
  i = idx - 1
187
216
  sq = false
188
217
  @space_count_rfc5424.times {
189
- while text[i + 1] == ' '.freeze
218
+ while text[i + 1] == SPLIT_CHAR
190
219
  sq = true
191
220
  i += 1
192
221
  end
193
222
 
194
- i = text.index(' '.freeze, i + 1)
223
+ i = text.index(SPLIT_CHAR, i + 1)
195
224
  }
196
225
 
197
- time_str = sq ? text.slice(idx, i - idx).squeeze(' '.freeze) : text.slice(idx, i - idx)
226
+ time_str = sq ? text.slice(idx, i - idx).squeeze(SPLIT_CHAR) : text.slice(idx, i - idx)
198
227
  time = @mutex.synchronize do
199
228
  begin
200
- @time_parser.parse(time_str)
229
+ @time_parser_rfc5424.parse(time_str)
201
230
  rescue Fluent::TimeParser::TimeParseError => e
202
- if @support_rfc5424_without_subseconds
203
- log.trace(e)
204
- @time_parser_rfc5424_without_subseconds.parse(time_str)
205
- else
206
- raise
207
- end
231
+ log.trace(e)
232
+ @time_parser_rfc5424_without_subseconds.parse(time_str)
208
233
  end
209
234
  end
210
235
 
211
236
  if @keep_time_key
212
237
  record['time'] = time_str
213
238
  end
214
- parse_plain(time, text, i + 1, record, RFC5424_CAPTURES, &block)
239
+ parse_plain(@regexp5424, time, text, i + 1, record, RFC5424_CAPTURES, &block)
215
240
  end
216
241
 
217
242
  # @param time [EventTime]
218
243
  # @param idx [Integer] note: this argument is needed to avoid string creation
219
244
  # @param record [Hash]
220
245
  # @param capture_list [Array] for performance
221
- def parse_plain(time, text, idx, record, capture_list, &block)
222
- m = @regexp.match(text, idx)
246
+ def parse_plain(re, time, text, idx, record, capture_list, &block)
247
+ m = re.match(text, idx)
223
248
  if m.nil?
224
249
  yield nil, nil
225
250
  return
@@ -244,8 +269,6 @@ module Fluent
244
269
  yield time, record
245
270
  end
246
271
 
247
- SPLIT_CHAR = ' '.freeze
248
-
249
272
  def parse_rfc3164(text, &block)
250
273
  pri = nil
251
274
  cursor = 0
@@ -264,20 +287,35 @@ module Fluent
264
287
  end
265
288
  end
266
289
 
267
- # header part
268
- time_size = 15 # skip Mmm dd hh:mm:ss
269
- time_end = text[cursor + time_size]
270
- if time_end == SPLIT_CHAR
271
- time_str = text.slice(cursor, time_size)
272
- cursor += 16 # time + ' '
273
- elsif time_end == '.'.freeze
274
- # support subsecond time
275
- i = text.index(SPLIT_CHAR, time_size)
276
- time_str = text.slice(cursor, i - cursor)
277
- cursor = i + 1
290
+ if @skip_space_count_rfc3164
291
+ # header part
292
+ time_size = 15 # skip Mmm dd hh:mm:ss
293
+ time_end = text[cursor + time_size]
294
+ if time_end == SPLIT_CHAR
295
+ time_str = text.slice(cursor, time_size)
296
+ cursor += 16 # time + ' '
297
+ elsif time_end == '.'.freeze
298
+ # support subsecond time
299
+ i = text.index(SPLIT_CHAR, time_size)
300
+ time_str = text.slice(cursor, i - cursor)
301
+ cursor = i + 1
302
+ else
303
+ yield nil, nil
304
+ return
305
+ end
278
306
  else
279
- yield nil, nil
280
- return
307
+ i = cursor - 1
308
+ sq = false
309
+ @space_count_rfc3164.times do
310
+ while text[i + 1] == SPLIT_CHAR
311
+ sq = true
312
+ i += 1
313
+ end
314
+ i = text.index(SPLIT_CHAR, i + 1)
315
+ end
316
+
317
+ time_str = sq ? text.slice(idx, i - cursor).squeeze(SPLIT_CHAR) : text.slice(cursor, i - cursor)
318
+ cursor = i + 1
281
319
  end
282
320
 
283
321
  i = text.index(SPLIT_CHAR, cursor)
@@ -325,7 +363,130 @@ module Fluent
325
363
  msg.chomp!
326
364
  record['message'] = msg
327
365
 
328
- time = @time_parser.parse(time_str)
366
+ time = @time_parser_rfc3164.parse(time_str)
367
+ record['time'] = time_str if @keep_time_key
368
+
369
+ yield time, record
370
+ end
371
+
372
+ NILVALUE = '-'.freeze
373
+
374
+ def parse_rfc5424(text, &block)
375
+ pri = nil
376
+ cursor = 0
377
+ if @with_priority
378
+ if text.start_with?('<'.freeze)
379
+ i = text.index('>'.freeze, 1)
380
+ if i < 2
381
+ yield nil, nil
382
+ return
383
+ end
384
+ pri = text.slice(1, i - 1).to_i
385
+ i = text.index(SPLIT_CHAR, i)
386
+ cursor = i + 1
387
+ else
388
+ yield nil, nil
389
+ return
390
+ end
391
+ end
392
+
393
+ # timestamp part
394
+ if @skip_space_count_rfc5424
395
+ i = text.index(SPLIT_CHAR, cursor)
396
+ time_str = text.slice(cursor, i - cursor)
397
+ cursor = i + 1
398
+ else
399
+ i = cursor - 1
400
+ sq = false
401
+ @space_count_rfc5424.times do
402
+ while text[i + 1] == SPLIT_CHAR
403
+ sq = true
404
+ i += 1
405
+ end
406
+ i = text.index(SPLIT_CHAR, i + 1)
407
+ end
408
+
409
+ time_str = sq ? text.slice(idx, i - cursor).squeeze(SPLIT_CHAR) : text.slice(cursor, i - cursor)
410
+ cursor = i + 1
411
+ end
412
+
413
+ # Repeat same code for the performance
414
+
415
+ # host part
416
+ i = text.index(SPLIT_CHAR, cursor)
417
+ unless i
418
+ yield nil, nil
419
+ return
420
+ end
421
+ slice_size = i - cursor
422
+ host = text.slice(cursor, slice_size)
423
+ cursor += slice_size + 1
424
+
425
+ # ident part
426
+ i = text.index(SPLIT_CHAR, cursor)
427
+ unless i
428
+ yield nil, nil
429
+ return
430
+ end
431
+ slice_size = i - cursor
432
+ ident = text.slice(cursor, slice_size)
433
+ cursor += slice_size + 1
434
+
435
+ # pid part
436
+ i = text.index(SPLIT_CHAR, cursor)
437
+ unless i
438
+ yield nil, nil
439
+ return
440
+ end
441
+ slice_size = i - cursor
442
+ pid = text.slice(cursor, slice_size)
443
+ cursor += slice_size + 1
444
+
445
+ # msgid part
446
+ i = text.index(SPLIT_CHAR, cursor)
447
+ unless i
448
+ yield nil, nil
449
+ return
450
+ end
451
+ slice_size = i - cursor
452
+ msgid = text.slice(cursor, slice_size)
453
+ cursor += slice_size + 1
454
+
455
+ record = {'host' => host, 'ident' => ident, 'pid' => pid, 'msgid' => msgid}
456
+ record['pri'] = pri if pri
457
+
458
+ # extradata part
459
+ ed_start = text[cursor]
460
+ if ed_start == NILVALUE
461
+ record['extradata'] = NILVALUE
462
+ cursor += 1
463
+ else
464
+ start = cursor
465
+ i = text.index('] '.freeze, cursor)
466
+ extradata = if i
467
+ diff = i + 1 - start # calculate ']' position
468
+ cursor += diff
469
+ text.slice(start, diff)
470
+ else # No message part case
471
+ cursor = text.bytesize
472
+ text.slice(start, cursor)
473
+ end
474
+ extradata.tr!("\\".freeze, ''.freeze)
475
+ record['extradata'] = extradata
476
+ end
477
+
478
+ # message part
479
+ if cursor != text.bytesize
480
+ msg = text.slice(cursor + 1, text.bytesize)
481
+ msg.chomp!
482
+ record['message'] = msg
483
+ end
484
+
485
+ time = begin
486
+ @time_parser_rfc5424.parse(time_str)
487
+ rescue Fluent::TimeParser::TimeParseError => e
488
+ @time_parser_rfc5424_without_subseconds.parse(time_str)
489
+ end
329
490
  record['time'] = time_str if @keep_time_key
330
491
 
331
492
  yield time, record