fluentd 0.10.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.

Files changed (54) hide show
  1. data/AUTHORS +1 -0
  2. data/COPYING +14 -0
  3. data/ChangeLog +178 -0
  4. data/README.rdoc +57 -0
  5. data/Rakefile +62 -0
  6. data/VERSION +1 -0
  7. data/bin/fluent-cat +6 -0
  8. data/bin/fluent-gem +10 -0
  9. data/bin/fluentd +6 -0
  10. data/fluent.conf +78 -0
  11. data/fluentd.gemspec +116 -0
  12. data/lib/fluent/buffer.rb +274 -0
  13. data/lib/fluent/command/cat.rb +299 -0
  14. data/lib/fluent/command/fluentd.rb +245 -0
  15. data/lib/fluent/config.rb +304 -0
  16. data/lib/fluent/engine.rb +224 -0
  17. data/lib/fluent/env.rb +6 -0
  18. data/lib/fluent/event.rb +159 -0
  19. data/lib/fluent/input.rb +41 -0
  20. data/lib/fluent/load.rb +23 -0
  21. data/lib/fluent/log.rb +277 -0
  22. data/lib/fluent/match.rb +189 -0
  23. data/lib/fluent/mixin.rb +170 -0
  24. data/lib/fluent/output.rb +466 -0
  25. data/lib/fluent/parser.rb +115 -0
  26. data/lib/fluent/plugin.rb +145 -0
  27. data/lib/fluent/plugin/buf_file.rb +181 -0
  28. data/lib/fluent/plugin/buf_memory.rb +97 -0
  29. data/lib/fluent/plugin/buf_zfile.rb +84 -0
  30. data/lib/fluent/plugin/in_http.rb +282 -0
  31. data/lib/fluent/plugin/in_stream.rb +187 -0
  32. data/lib/fluent/plugin/in_syslog.rb +174 -0
  33. data/lib/fluent/plugin/in_tail.rb +150 -0
  34. data/lib/fluent/plugin/out_copy.rb +72 -0
  35. data/lib/fluent/plugin/out_file.rb +111 -0
  36. data/lib/fluent/plugin/out_null.rb +44 -0
  37. data/lib/fluent/plugin/out_roundrobin.rb +72 -0
  38. data/lib/fluent/plugin/out_stdout.rb +34 -0
  39. data/lib/fluent/plugin/out_stream.rb +128 -0
  40. data/lib/fluent/plugin/out_test.rb +68 -0
  41. data/lib/fluent/test.rb +8 -0
  42. data/lib/fluent/test/base.rb +63 -0
  43. data/lib/fluent/test/input_test.rb +89 -0
  44. data/lib/fluent/test/output_test.rb +93 -0
  45. data/lib/fluent/version.rb +5 -0
  46. data/test/helper.rb +6 -0
  47. data/test/match.rb +115 -0
  48. data/test/plugin/in_http.rb +84 -0
  49. data/test/plugin/in_stream.rb +136 -0
  50. data/test/plugin/out_copy.rb +55 -0
  51. data/test/plugin/out_file.rb +82 -0
  52. data/test/plugin/out_roundrobin.rb +65 -0
  53. data/test/plugin/out_stream.rb +74 -0
  54. metadata +224 -0
@@ -0,0 +1,245 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'optparse'
20
+ require 'fluent/log'
21
+ require 'fluent/env'
22
+ require 'fluent/version'
23
+
24
+ op = OptionParser.new
25
+ op.version = Fluent::VERSION
26
+
27
+ # default values
28
+ config_path = Fluent::DEFAULT_CONFIG_PATH
29
+ plugin_dirs = [Fluent::DEFAULT_PLUGIN_DIR]
30
+ log_level = Fluent::Log::LEVEL_INFO
31
+ log_file = nil
32
+ daemonize = false
33
+ libs = []
34
+ setup_path = nil
35
+ chuser = nil
36
+ chgroup = nil
37
+
38
+ op.on('-s', "--setup [DIR=#{File.dirname(Fluent::DEFAULT_CONFIG_PATH)}]", "install sample configuration file to the directory") {|s|
39
+ setup_path = s || File.dirname(Fluent::DEFAULT_CONFIG_PATH)
40
+ }
41
+
42
+ op.on('-c', '--config PATH', "config flie path (default: #{config_path})") {|s|
43
+ config_path = s
44
+ }
45
+
46
+ op.on('-p', '--plugin DIR', "add plugin directory") {|s|
47
+ plugin_dirs << s
48
+ }
49
+
50
+ op.on('-I PATH', "add library path") {|s|
51
+ $LOAD_PATH << s
52
+ }
53
+
54
+ op.on('-r NAME', "load library") {|s|
55
+ libs << s
56
+ }
57
+
58
+ op.on('-d', '--daemon PIDFILE', "daemonize fluent process") {|s|
59
+ daemonize = s
60
+ }
61
+
62
+ op.on('--user USER', "change user") {|s|
63
+ chuser = s
64
+ }
65
+
66
+ op.on('--group GROUP', "change group") {|s|
67
+ chgroup = s
68
+ }
69
+
70
+ op.on('-o', '--log PATH', "log file path") {|s|
71
+ log_file = s
72
+ }
73
+
74
+ op.on('-v', '--verbose', "increment verbose level (-v: debug, -vv: trace)", TrueClass) {|b|
75
+ if b
76
+ case log_level
77
+ when Fluent::Log::LEVEL_INFO
78
+ log_level = Fluent::Log::LEVEL_DEBUG
79
+ when Fluent::Log::LEVEL_DEBUG
80
+ log_level = Fluent::Log::LEVEL_TRACE
81
+ end
82
+ end
83
+ }
84
+
85
+ (class<<self;self;end).module_eval do
86
+ define_method(:usage) do |msg|
87
+ puts op.to_s
88
+ puts "error: #{msg}" if msg
89
+ exit 1
90
+ end
91
+ end
92
+
93
+ begin
94
+ op.parse!(ARGV)
95
+
96
+ if ARGV.length != 0
97
+ usage nil
98
+ end
99
+ rescue
100
+ usage $!.to_s
101
+ end
102
+
103
+
104
+ if setup_path
105
+ require 'fileutils'
106
+ FileUtils.mkdir_p File.join(setup_path, "plugin")
107
+ confpath = File.join(setup_path, "fluent.conf")
108
+ if File.exist?(confpath)
109
+ puts "#{confpath} already exists."
110
+ else
111
+ File.open(confpath, "w") {|f|
112
+ conf = File.read File.join(File.dirname(__FILE__), "..", "..", "..", "fluent.conf")
113
+ f.write conf
114
+ }
115
+ puts "Installed #{confpath}."
116
+ end
117
+ exit 0
118
+ end
119
+
120
+
121
+ if log_file && log_file != "-"
122
+ log_out = File.open(log_file, "a")
123
+ else
124
+ log_out = STDOUT
125
+ end
126
+
127
+ $log = Fluent::Log.new(log_out, log_level)
128
+
129
+ $log.enable_color(false) if log_file
130
+ $log.enable_debug if log_level <= Fluent::Log::LEVEL_DEBUG
131
+
132
+
133
+ require 'fluent/load'
134
+
135
+ begin
136
+ #
137
+ # initialize
138
+ #
139
+ Fluent::Engine.init
140
+
141
+ libs.each {|lib|
142
+ require lib
143
+ }
144
+
145
+ plugin_dirs.each {|dir|
146
+ if Dir.exist?(dir)
147
+ dir = File.expand_path(dir)
148
+ Fluent::Engine.load_plugin_dir(dir)
149
+ end
150
+ }
151
+
152
+ Fluent::Engine.read_config(config_path)
153
+
154
+
155
+ #
156
+ # daemonize
157
+ #
158
+ if chgroup
159
+ chgid = chgroup.to_i
160
+ if chgid.to_s != chgroup
161
+ chgid = `id -u #{chgroup}`.to_i
162
+ if $?.to_i != 0
163
+ exit 1
164
+ end
165
+ end
166
+ Process::GID.change_privilege(chgid)
167
+ end
168
+
169
+ if chuser
170
+ chuid = chuser.to_i
171
+ if chuid.to_s != chuser
172
+ chuid = `id -u #{chuser}`.to_i
173
+ if $?.to_i != 0
174
+ exit 1
175
+ end
176
+ end
177
+ Process::UID.change_privilege(chuid)
178
+ end
179
+
180
+ trap :INT do
181
+ Fluent::Engine.stop
182
+ end
183
+
184
+ trap :TERM do
185
+ Fluent::Engine.stop
186
+ end
187
+
188
+ trap :HUP do
189
+ if log_file
190
+ $log.reopen(log_file, "a")
191
+ end
192
+ end
193
+
194
+ trap :USR1 do
195
+ $log.info "force flushing buffered events"
196
+ Fluent::Engine.flush!
197
+ end
198
+
199
+ if daemonize
200
+ exit!(0) if fork
201
+ Process.setsid
202
+ exit!(0) if fork
203
+ File.umask(0)
204
+ STDIN.reopen("/dev/null")
205
+ STDOUT.reopen("/dev/null", "w")
206
+ STDERR.reopen("/dev/null", "w")
207
+ File.open(daemonize, "w") {|f|
208
+ f.write Process.pid.to_s
209
+ }
210
+ end
211
+
212
+
213
+ #
214
+ # run
215
+ #
216
+ $log.info "running fluent-#{Fluent::VERSION}"
217
+ Fluent::Engine.run
218
+
219
+ rescue Fluent::ConfigError
220
+ $log.error "config error", :file=>config_path, :error=>$!.to_s
221
+ $log.debug_backtrace
222
+
223
+ # also STDOUT
224
+ if log_out != STDOUT
225
+ console = Fluent::Log.new(STDOUT, log_level).enable_debug
226
+ console.error "config error", :file=>config_path, :error=>$!.to_s
227
+ console.debug_backtrace
228
+ end
229
+
230
+ exit 1
231
+
232
+ rescue
233
+ $log.error "unexpected error", :error=>$!.to_s
234
+ $log.error_backtrace
235
+
236
+ # also STDOUT
237
+ if log_out != STDOUT
238
+ console = Fluent::Log.new(STDOUT, log_level).enable_debug
239
+ console.error "unexpected error", :error=>$!.to_s
240
+ console.error_backtrace
241
+ end
242
+
243
+ exit 1
244
+ end
245
+
@@ -0,0 +1,304 @@
1
+ #
2
+ # Fluent
3
+ #
4
+ # Copyright (C) 2011 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module Fluent
19
+
20
+
21
+ class ConfigError < StandardError
22
+ end
23
+
24
+ class ConfigParseError < ConfigError
25
+ end
26
+
27
+
28
+ module Config
29
+ class Element < Hash
30
+ def initialize(name, arg, attrs, elements, used=[])
31
+ @name = name
32
+ @arg = arg
33
+ @elements = elements
34
+ super()
35
+ attrs.each {|k,v|
36
+ self[k] = v
37
+ }
38
+ @used = used
39
+ end
40
+
41
+ attr_accessor :name, :arg, :elements, :used
42
+
43
+ def add_element(name, arg='')
44
+ e = Element.new(name, arg, {}, [])
45
+ @elements << e
46
+ e
47
+ end
48
+
49
+ def +(o)
50
+ Element.new(@name.dup, @arg.dup, o.merge(self), @elements+o.elements, @used+o.used)
51
+ end
52
+
53
+ def has_key?(key)
54
+ @used << key
55
+ super
56
+ end
57
+
58
+ def [](key)
59
+ @used << key
60
+ super
61
+ end
62
+
63
+ def check_not_fetched(&block)
64
+ each_key {|key|
65
+ unless @used.include?(key)
66
+ block.call(key, self)
67
+ end
68
+ }
69
+ @elements.each {|e|
70
+ e.check_not_fetched(&block)
71
+ }
72
+ end
73
+
74
+ def to_s(nest = 0)
75
+ indent = " "*nest
76
+ nindent = " "*(nest+1)
77
+ out = ""
78
+ if @arg.empty?
79
+ out << "#{indent}<#{@name}>\n"
80
+ else
81
+ out << "#{indent}<#{@name} #{@name}>\n"
82
+ end
83
+ each_pair {|k,v|
84
+ out << "#{nindent}#{k} #{v}\n"
85
+ }
86
+ @elements.each {|e|
87
+ out << e.to_s(nest+1)
88
+ }
89
+ out << "#{indent}</#{@name}>\n"
90
+ out
91
+ end
92
+ end
93
+
94
+ def self.read(path)
95
+ parse(File.read(path), File.basename(path))
96
+ end
97
+
98
+ def self.parse(str, fname)
99
+ lines = str.split("\n")
100
+ i, attrs, elems = parse_element('end', lines, 0, fname)
101
+ Element.new('ROOT', '', attrs, elems)
102
+ end
103
+
104
+ def self.new(name='')
105
+ Element.new('', '', {}, [])
106
+ end
107
+
108
+ def self.size_value(str)
109
+ case str.to_s
110
+ when /([0-9]+)k/i
111
+ $~[1].to_i * 1024
112
+ when /([0-9]+)m/i
113
+ $~[1].to_i * (1024**2)
114
+ when /([0-9]+)g/i
115
+ $~[1].to_i * (1024**3)
116
+ when /([0-9]+)t/i
117
+ $~[1].to_i * (1024**4)
118
+ else
119
+ str.to_i
120
+ end
121
+ end
122
+
123
+ def self.time_value(str)
124
+ case str.to_s
125
+ when /([0-9]+)s/
126
+ $~[1].to_i
127
+ when /([0-9]+)m/
128
+ $~[1].to_i * 60
129
+ when /([0-9]+)h/
130
+ $~[1].to_i * 60*60
131
+ when /([0-9]+)d/
132
+ $~[1].to_i * 24*60*60
133
+ else
134
+ str.to_f
135
+ end
136
+ end
137
+
138
+ def self.bool_value(str)
139
+ case str.to_s
140
+ when 'true', 'yes'
141
+ true
142
+ when 'false', 'no'
143
+ false
144
+ else
145
+ nil
146
+ end
147
+ end
148
+
149
+ private
150
+ def self.parse_element(name, lines, i, fname)
151
+ attrs = {}
152
+ elems = []
153
+ while i < lines.length
154
+ line = lines[i]
155
+ line.lstrip!
156
+ line.gsub!(/\s*(?:\#.*)?$/,'')
157
+ if line.empty?
158
+ i += 1
159
+ next
160
+ elsif m = /^\<([a-zA-Z0-9_]+)\s*(.+?)?\>$/.match(line)
161
+ e_name = m[1]
162
+ e_arg = m[2] || ""
163
+ i, e_attrs, e_elems = parse_element(e_name, lines, i+1, fname)
164
+ elems << Element.new(e_name, e_arg, e_attrs, e_elems)
165
+ elsif line == "</#{name}>"
166
+ i += 1
167
+ break
168
+ elsif m = /^([a-zA-Z0-9_]+)\s*(.+)?$/.match(line)
169
+ attrs[m[1]] = m[2] || ""
170
+ i += 1
171
+ next
172
+ else
173
+ raise ConfigParseError, "parse error at #{fname}:#{i}"
174
+ end
175
+ end
176
+ return i, attrs, elems
177
+ end
178
+ end
179
+
180
+
181
+ module Configurable
182
+ def self.included(mod)
183
+ mod.extend(ClassMethods)
184
+ end
185
+
186
+ def initialize
187
+ self.class.config_defaults.each_pair {|name,defval|
188
+ varname = :"@#{name}"
189
+ instance_variable_set(varname, defval)
190
+ }
191
+ end
192
+
193
+ def configure(conf)
194
+ self.class.config_params.each_pair {|name,(block,opts)|
195
+ varname = :"@#{name}"
196
+ if val = conf[name.to_s]
197
+ val = self.instance_exec(val, opts, name, &block)
198
+ instance_variable_set(varname, val)
199
+ end
200
+ unless instance_variable_defined?(varname)
201
+ $log.error "config error in:\n#{conf}"
202
+ raise ConfigError, "'#{name}' parameter is required"
203
+ end
204
+ }
205
+ end
206
+
207
+ module ClassMethods
208
+ def config_param(name, *args, &block)
209
+ name = name.to_sym
210
+
211
+ opts = {}
212
+ args.each {|a|
213
+ if a.is_a?(Symbol)
214
+ opts[:type] = a
215
+ elsif a.is_a?(Hash)
216
+ opts.merge!(a)
217
+ else
218
+ raise ArgumentError, "wrong number of arguments (#{1+args.length} for #{block ? 2 : 3})"
219
+ end
220
+ }
221
+
222
+ type = opts[:type]
223
+ if block && type
224
+ raise ArgumentError, "wrong number of arguments (#{1+args.length} for #{block ? 2 : 3})"
225
+ end
226
+
227
+ block ||= case type
228
+ when :string, nil
229
+ Proc.new {|val| val }
230
+ when :integer
231
+ Proc.new {|val| val.to_i }
232
+ when :size
233
+ Proc.new {|val| Config.size_value(val) }
234
+ when :bool
235
+ Proc.new {|val| Config.bool_value(val) }
236
+ when :time
237
+ Proc.new {|val| Config.time_value(val) }
238
+ else
239
+ raise ArgumentError, "unknown config_param type `#{type}'"
240
+ end
241
+
242
+ params = config_params_set
243
+ params.delete(name)
244
+ params[name] = [block, opts]
245
+
246
+ if opts.has_key?(:default)
247
+ config_set_default(name, opts[:default])
248
+ end
249
+
250
+ attr_accessor name
251
+ end
252
+
253
+ def config_set_default(name, defval)
254
+ name = name.to_sym
255
+
256
+ defaults = config_defaults_set
257
+ defaults.delete(name)
258
+ defaults[name] = defval
259
+
260
+ nil
261
+ end
262
+
263
+ def config_params
264
+ singleton_value(:_config_params)
265
+ end
266
+
267
+ def config_defaults
268
+ singleton_value(:_config_defaults)
269
+ end
270
+
271
+ private
272
+ def config_params_set
273
+ singleton_value_set(:_config_params)
274
+ end
275
+
276
+ def config_defaults_set
277
+ singleton_value_set(:_config_defaults)
278
+ end
279
+
280
+ def singleton_value_set(name)
281
+ if methods(false).include?(name)
282
+ __send__(name)
283
+ else
284
+ val = {}
285
+ define_singleton_method(name) { val }
286
+ val
287
+ end
288
+ end
289
+
290
+ def singleton_value(name)
291
+ val = {}
292
+ ancestors.reverse_each {|c|
293
+ if c.methods(false).include?(name)
294
+ val.merge!(c.__send__(name))
295
+ end
296
+ }
297
+ val
298
+ end
299
+ end
300
+ end
301
+
302
+
303
+ end
304
+