fluentd 0.10.50 → 0.10.51

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.

@@ -160,34 +160,6 @@ module Fluent
160
160
  end
161
161
  end
162
162
 
163
-
164
- # obsolete
165
- # ForwardInput is backward compatible with TcpInput
166
- #class TcpInput < StreamInput
167
- # Plugin.register_input('tcp', self)
168
- #
169
- # config_param :port, :integer, :default => DEFAULT_LISTEN_PORT
170
- # config_param :bind, :string, :default => '0.0.0.0'
171
- #
172
- # def configure(conf)
173
- # super
174
- # end
175
- #
176
- # def listen
177
- # log.debug "listening fluent socket on #{@bind}:#{@port}"
178
- # Coolio::TCPServer.new(@bind, @port, Handler, method(:on_message))
179
- # end
180
- #end
181
- class TcpInput < ForwardInput
182
- Plugin.register_input('tcp', self)
183
-
184
- def initialize
185
- super
186
- $log.warn "'tcp' input is obsoleted and will be removed soon. Use 'forward' instead."
187
- end
188
- end
189
-
190
-
191
163
  class UnixInput < StreamInput
192
164
  Plugin.register_input('unix', self)
193
165
 
@@ -20,8 +20,6 @@ module Fluent
20
20
  Plugin.register_input('syslog', self)
21
21
 
22
22
  SYSLOG_REGEXP = /^\<([0-9]+)\>(.*)/
23
- SYSLOG_ALL_REGEXP = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: *(?<message>.*)$/
24
- TIME_FORMAT = "%b %d %H:%M:%S"
25
23
 
26
24
  FACILITY_MAP = {
27
25
  0 => 'kern',
@@ -88,17 +86,19 @@ module Fluent
88
86
  if parser.configure(conf, false)
89
87
  @parser = parser
90
88
  else
91
- @parser = nil
92
- @time_parser = TextParser::TimeParser.new(TIME_FORMAT)
89
+ conf['with_priority'] = true
90
+ @parser = TextParser::SyslogParser.new
91
+ @parser.configure(conf)
92
+ @use_default = true
93
93
  end
94
94
  end
95
95
 
96
96
  def start
97
- if @parser
98
- callback = method(:receive_data_parser)
99
- else
100
- callback = method(:receive_data)
101
- end
97
+ callback = if @use_default
98
+ method(:receive_data)
99
+ else
100
+ method(:receive_data_parser)
101
+ end
102
102
 
103
103
  @loop = Coolio::Loop.new
104
104
  @handler = listen(callback)
@@ -122,10 +122,10 @@ module Fluent
122
122
  end
123
123
 
124
124
  protected
125
- def receive_data_parser(data)
125
+ def receive_data_parser(data, addr)
126
126
  m = SYSLOG_REGEXP.match(data)
127
127
  unless m
128
- log.debug "invalid syslog message: #{data.dump}"
128
+ log.warn "invalid syslog message: #{data.dump}"
129
129
  return
130
130
  end
131
131
  pri = m[1].to_i
@@ -139,42 +139,24 @@ module Fluent
139
139
 
140
140
  emit(pri, time, record)
141
141
  }
142
- rescue
143
- log.warn data.dump, :error=>$!.to_s
144
- log.debug_backtrace
142
+ rescue => e
143
+ log.error data.dump, :error => e.to_s
144
+ log.error_backtrace
145
145
  end
146
146
 
147
- def receive_data(data)
148
- m = SYSLOG_ALL_REGEXP.match(data)
149
- unless m
150
- log.debug "invalid syslog message", :data=>data
151
- return
152
- end
153
-
154
- pri = nil
155
- time = nil
156
- record = {}
157
-
158
- m.names.each {|name|
159
- if value = m[name]
160
- case name
161
- when "pri"
162
- pri = value.to_i
163
- when "time"
164
- time = @time_parser.parse(value.gsub(/ +/, ' '))
165
- else
166
- record[name] = value
167
- end
147
+ def receive_data(data, addr)
148
+ @parser.call(data) { |time, record|
149
+ unless time && record
150
+ log.warn "invalid syslog message", :data => data
151
+ return
168
152
  end
169
- }
170
-
171
- time ||= Engine.now
172
-
173
- emit(pri, time, record)
174
153
 
175
- rescue
176
- log.warn data.dump, :error=>$!.to_s
177
- log.debug_backtrace
154
+ pri = record.delete('pri')
155
+ emit(pri, time, record)
156
+ }
157
+ rescue => e
158
+ log.error data.dump, :error => e.to_s
159
+ log.error_backtrace
178
160
  end
179
161
 
180
162
  private
@@ -184,9 +166,10 @@ module Fluent
184
166
  if @protocol_type == :udp
185
167
  @usock = SocketUtil.create_udp_socket(@bind)
186
168
  @usock.bind(@bind, @port)
187
- UdpHandler.new(@usock, callback)
169
+ SocketUtil::UdpHandler.new(@usock, log, 2048, callback)
188
170
  else
189
- Coolio::TCPServer.new(@bind, @port, TcpHandler, log, callback)
171
+ # syslog family add "\n" to each message and this seems only way to split messages in tcp stream
172
+ Coolio::TCPServer.new(@bind, @port, SocketUtil::TcpHandler, log, "\n", callback)
190
173
  end
191
174
  end
192
175
 
@@ -200,60 +183,5 @@ module Fluent
200
183
  rescue => e
201
184
  log.error "syslog failed to emit", :error => e.to_s, :error_class => e.class.to_s, :tag => tag, :record => Yajl.dump(record)
202
185
  end
203
-
204
- class UdpHandler < Coolio::IO
205
- def initialize(io, callback)
206
- super(io)
207
- @io = io
208
- @callback = callback
209
- end
210
-
211
- def on_readable
212
- msg, addr = @io.recvfrom_nonblock(2048)
213
- #host = addr[3]
214
- #port = addr[1]
215
- #@callback.call(host, port, msg)
216
- @callback.call(msg)
217
- rescue
218
- # TODO log?
219
- end
220
- end
221
-
222
- class TcpHandler < Coolio::Socket
223
- def initialize(io, log, on_message)
224
- super(io)
225
- if io.is_a?(TCPSocket)
226
- opt = [1, @timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
227
- io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
228
- end
229
- @on_message = on_message
230
- @log = log
231
- @log.trace { "accepted fluent socket object_id=#{self.object_id}" }
232
- @buffer = "".force_encoding('ASCII-8BIT')
233
- end
234
-
235
- def on_connect
236
- end
237
-
238
- def on_read(data)
239
- @buffer << data
240
- pos = 0
241
-
242
- # syslog family add "\n" to each message and this seems only way to split messages in tcp stream
243
- while i = @buffer.index("\n", pos)
244
- msg = @buffer[pos..i]
245
- @on_message.call(msg)
246
- pos = i + 1
247
- end
248
- @buffer.slice!(0, pos) if pos > 0
249
- rescue => e
250
- @log.error "syslog error", :error => e, :error_class => e.class
251
- close
252
- end
253
-
254
- def on_close
255
- @log.trace { "closed fluent socket object_id=#{self.object_id}" }
256
- end
257
- end
258
186
  end
259
187
  end
@@ -338,7 +338,7 @@ module Fluent
338
338
  end
339
339
 
340
340
  def on_notify
341
- @rotate_handler.on_notify
341
+ @rotate_handler.on_notify if @rotate_handler
342
342
  return unless @io_handler
343
343
  @io_handler.on_notify
344
344
  end
@@ -396,12 +396,13 @@ module Fluent
396
396
  @pe.update(inode, io.pos)
397
397
  io_handler = IOHandler.new(io, @pe, @log, &method(:wrap_receive_lines))
398
398
  @io_handler = io_handler
399
- else
399
+ else # file is rotated and new file found
400
400
  @update_watcher.call(@path, swap_state(@pe))
401
401
  end
402
- else
403
- @io_handler.close
404
- @io_handler = NullIOHandler.new
402
+ else # file is rotated and new file not found
403
+ # Clear RotateHandler to avoid duplicated file watch in same path.
404
+ @rotate_handler = nil
405
+ @update_watcher.call(@path, swap_state(@pe))
405
406
  end
406
407
  end
407
408
 
@@ -0,0 +1,15 @@
1
+ require 'fluent/plugin/socket_util'
2
+
3
+ module Fluent
4
+ class TcpInput < SocketUtil::BaseInput
5
+ Plugin.register_input('tcp', self)
6
+
7
+ config_set_default :port, 5170
8
+ config_param :delimiter, :string, :default => "\n" # syslog family add "\n" to each message and this seems only way to split messages in tcp stream
9
+
10
+ def listen(callback)
11
+ log.debug "listening tcp socket on #{@bind}:#{@port}"
12
+ Coolio::TCPServer.new(@bind, @port, SocketUtil::TcpHandler, log, @delimiter, callback)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'fluent/plugin/socket_util'
2
+
3
+ module Fluent
4
+ class UdpInput < SocketUtil::BaseInput
5
+ Plugin.register_input('udp', self)
6
+
7
+ config_set_default :port, 5160
8
+ config_param :body_size_limit, :size, :default => 4096
9
+
10
+ def listen(callback)
11
+ log.debug "listening udp socket on #{@bind}:#{@port}"
12
+ @usock = SocketUtil.create_udp_socket(@bind)
13
+ @usock.bind(@bind, @port)
14
+ SocketUtil::UdpHandler.new(@usock, log, @body_size_limit, callback)
15
+ end
16
+ end
17
+ end
@@ -1,3 +1,5 @@
1
+ require 'cool.io'
2
+
1
3
  module Fluent
2
4
  module SocketUtil
3
5
  def create_udp_socket(host)
@@ -10,5 +12,122 @@ module Fluent
10
12
  end
11
13
  end
12
14
  module_function :create_udp_socket
15
+
16
+ class UdpHandler < Coolio::IO
17
+ def initialize(io, log, body_size_limit, callback)
18
+ super(io)
19
+ @io = io
20
+ @log = log
21
+ @body_size_limit = body_size_limit
22
+ @callback = callback
23
+ end
24
+
25
+ def on_readable
26
+ msg, addr = @io.recvfrom_nonblock(@body_size_limit)
27
+ msg.chomp!
28
+ @callback.call(msg, addr)
29
+ rescue => e
30
+ @log.error "unexpected error", :error => e, :error_class => e.class
31
+ end
32
+ end
33
+
34
+ class TcpHandler < Coolio::Socket
35
+ PEERADDR_FAILED = ["?", "?", "name resolusion failed", "?"]
36
+
37
+ def initialize(io, log, delimiter, callback)
38
+ super(io)
39
+ if io.is_a?(TCPSocket)
40
+ @addr = (io.peeraddr rescue PEERADDR_FAILED)
41
+
42
+ opt = [1, @timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
43
+ io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
44
+ end
45
+ @delimiter = delimiter
46
+ @callback = callback
47
+ @log = log
48
+ @log.trace { "accepted fluent socket object_id=#{self.object_id}" }
49
+ @buffer = "".force_encoding('ASCII-8BIT')
50
+ end
51
+
52
+ def on_connect
53
+ end
54
+
55
+ def on_read(data)
56
+ @buffer << data
57
+ pos = 0
58
+
59
+ while i = @buffer.index(@delimiter, pos)
60
+ msg = @buffer[pos...i]
61
+ @callback.call(msg, @addr)
62
+ pos = i + @delimiter.length
63
+ end
64
+ @buffer.slice!(0, pos) if pos > 0
65
+ rescue => e
66
+ @log.error "unexpected error", :error => e, :error_class => e.class
67
+ close
68
+ end
69
+
70
+ def on_close
71
+ @log.trace { "closed fluent socket object_id=#{self.object_id}" }
72
+ end
73
+ end
74
+
75
+ class BaseInput < Fluent::Input
76
+ def initialize
77
+ super
78
+ require 'fluent/parser'
79
+ end
80
+
81
+ config_param :tag, :string
82
+ config_param :format, :string
83
+ config_param :port, :integer, :default => 5150
84
+ config_param :bind, :string, :default => '0.0.0.0'
85
+ config_param :source_host_key, :string, :default => nil
86
+
87
+ def configure(conf)
88
+ super
89
+
90
+ @parser = TextParser.new
91
+ @parser.configure(conf)
92
+ end
93
+
94
+ def start
95
+ @loop = Coolio::Loop.new
96
+ @handler = listen(method(:on_message))
97
+ @loop.attach(@handler)
98
+ @thread = Thread.new(&method(:run))
99
+ end
100
+
101
+ def shutdown
102
+ @loop.watchers.each { |w| w.detach }
103
+ @loop.stop
104
+ @handler.close
105
+ @thread.join
106
+ end
107
+
108
+ def run
109
+ @loop.run
110
+ rescue => e
111
+ log.error "unexpected error", :error => e, :error_class => e.class
112
+ log.error_backtrace
113
+ end
114
+
115
+ private
116
+
117
+ def on_message(msg, addr)
118
+ @parser.parse(msg) { |time, record|
119
+ unless time && record
120
+ log.warn "pattern not match: #{msg.inspect}"
121
+ return
122
+ end
123
+
124
+ record[@source_host_key] = addr[3] if @source_host_key
125
+ Engine.emit(@tag, time, record)
126
+ }
127
+ rescue => e
128
+ log.error msg.dump, :error => e, :error_class => e.class, :host => addr[3]
129
+ log.error_backtrace
130
+ end
131
+ end
13
132
  end
14
133
  end
@@ -18,6 +18,7 @@
18
18
 
19
19
  require 'fluent/env'
20
20
  require 'fluent/log'
21
+ require 'fluent/config'
21
22
  require 'etc'
22
23
 
23
24
  module Fluent
@@ -95,19 +96,22 @@ module Fluent
95
96
  end
96
97
 
97
98
  def initialize(opt)
99
+ @daemonize = opt[:daemonize]
98
100
  @config_path = opt[:config_path]
101
+ @inline_config = opt[:inline_config]
102
+ @use_v1_config = opt[:use_v1_config]
99
103
  @log_path = opt[:log_path]
100
- @log_level = opt[:log_level]
101
- @daemonize = opt[:daemonize]
102
- @chgroup = opt[:chgroup]
103
- @chuser = opt[:chuser]
104
+ @dry_run = opt[:dry_run]
104
105
  @libs = opt[:libs]
105
106
  @plugin_dirs = opt[:plugin_dirs]
106
- @inline_config = opt[:inline_config]
107
+ @chgroup = opt[:chgroup]
108
+ @chuser = opt[:chuser]
109
+
110
+ apply_system_config(opt)
111
+
112
+ @log_level = opt[:log_level]
107
113
  @suppress_interval = opt[:suppress_interval]
108
- @dry_run = opt[:dry_run]
109
114
  @suppress_config_dump = opt[:suppress_config_dump]
110
- @use_v1_config = opt[:use_v1_config]
111
115
 
112
116
  log_opts = {:suppress_repeated_stacktrace => opt[:suppress_repeated_stacktrace]}
113
117
  @log = LoggerInitializer.new(@log_path, @log_level, @chuser, @chgroup, log_opts)
@@ -317,8 +321,9 @@ module Fluent
317
321
  end
318
322
  end
319
323
 
320
- def read_config
321
- $log.info "reading config file", :path=>@config_path
324
+ # with_log is for disabling logging before Log#init is called
325
+ def read_config(with_log = true)
326
+ $log.info "reading config file", :path => @config_path if with_log
322
327
  @config_fname = File.basename(@config_path)
323
328
  @config_basedir = File.dirname(@config_path)
324
329
  @config_data = File.read(@config_path)
@@ -329,8 +334,45 @@ module Fluent
329
334
  end
330
335
  end
331
336
 
337
+ class SystemConfig
338
+ include Configurable
339
+
340
+ config_param :log_level, :default => nil do |level|
341
+ Log.str_to_level(level)
342
+ end
343
+ config_param :suppress_repeated_stacktrace, :bool, :default => nil
344
+ config_param :emit_error_log_interval, :time, :default => nil
345
+ config_param :suppress_config_dump, :bool, :default => nil
346
+
347
+ def initialize(conf)
348
+ super()
349
+ configure(conf)
350
+ end
351
+
352
+ def to_opt
353
+ opt = {}
354
+ opt[:log_level] = @log_level unless @log_level.nil?
355
+ opt[:suppress_interval] = @emit_error_log_interval unless @emit_error_log_interval.nil?
356
+ opt[:suppress_config_dump] = @suppress_config_dump unless @suppress_config_dump.nil?
357
+ opt[:suppress_repeated_stacktrace] = @suppress_repeated_stacktrace unless @suppress_repeated_stacktrace.nil?
358
+ opt
359
+ end
360
+ end
361
+
362
+ def apply_system_config(opt)
363
+ read_config(false)
364
+ systems = Fluent::Config.parse(@config_data, @config_fname, @config_basedir, @use_v1_config).elements.select { |e|
365
+ e.name == 'system'
366
+ }
367
+ return if systems.empty?
368
+ raise ConfigError, "<system> is duplicated. <system> should be only one" if systems.size > 1
369
+
370
+ opt.merge!(SystemConfig.new(systems.first).to_opt)
371
+ end
372
+
332
373
  def run_configure
333
- Fluent::Engine.parse_config(@config_data, @config_fname, @config_basedir, @use_v1_config)
374
+ conf = Fluent::Config.parse(@config_data, @config_fname, @config_basedir, @use_v1_config)
375
+ Fluent::Engine.run_configure(conf)
334
376
  end
335
377
 
336
378
  def change_privilege