fluentd 0.10.35 → 0.10.36
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.
- data/.travis.yml +13 -0
- data/ChangeLog +9 -0
- data/fluentd.gemspec +1 -1
- data/lib/fluent/buffer.rb +210 -214
- data/lib/fluent/command/fluentd.rb +4 -0
- data/lib/fluent/config.rb +1 -0
- data/lib/fluent/engine.rb +10 -10
- data/lib/fluent/output.rb +404 -406
- data/lib/fluent/plugin/buf_file.rb +146 -151
- data/lib/fluent/plugin/buf_memory.rb +62 -67
- data/lib/fluent/plugin/in_debug_agent.rb +27 -31
- data/lib/fluent/plugin/in_exec.rb +86 -90
- data/lib/fluent/plugin/in_forward.rb +171 -171
- data/lib/fluent/plugin/in_gc_stat.rb +43 -47
- data/lib/fluent/plugin/in_http.rb +214 -216
- data/lib/fluent/plugin/in_monitor_agent.rb +212 -214
- data/lib/fluent/plugin/in_object_space.rb +75 -79
- data/lib/fluent/plugin/in_status.rb +44 -50
- data/lib/fluent/plugin/in_stream.rb +159 -160
- data/lib/fluent/plugin/in_syslog.rb +149 -153
- data/lib/fluent/plugin/in_tail.rb +382 -387
- data/lib/fluent/plugin/out_copy.rb +40 -45
- data/lib/fluent/plugin/out_exec.rb +52 -57
- data/lib/fluent/plugin/out_exec_filter.rb +327 -331
- data/lib/fluent/plugin/out_file.rb +78 -74
- data/lib/fluent/plugin/out_forward.rb +410 -414
- data/lib/fluent/plugin/out_null.rb +15 -19
- data/lib/fluent/plugin/out_roundrobin.rb +63 -68
- data/lib/fluent/plugin/out_stdout.rb +9 -14
- data/lib/fluent/plugin/out_stream.rb +83 -90
- data/lib/fluent/plugin/out_test.rb +42 -46
- data/lib/fluent/supervisor.rb +15 -0
- data/lib/fluent/version.rb +1 -1
- data/test/plugin/in_stream.rb +2 -0
- data/test/plugin/out_file.rb +19 -1
- metadata +6 -5
@@ -16,63 +16,59 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
module Fluent
|
19
|
+
class GCStatInput < Input
|
20
|
+
Plugin.register_input('gc_stat', self)
|
19
21
|
|
22
|
+
def initialize
|
23
|
+
super
|
24
|
+
end
|
20
25
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
def initialize
|
25
|
-
super
|
26
|
-
end
|
26
|
+
config_param :emit_interval, :time, :default => 60
|
27
|
+
config_param :tag, :string
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
class TimerWatcher < Coolio::TimerWatcher
|
30
|
+
def initialize(interval, repeat, &callback)
|
31
|
+
@callback = callback
|
32
|
+
super(interval, repeat)
|
33
|
+
end
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
def on_timer
|
36
|
+
@callback.call
|
37
|
+
rescue
|
38
|
+
# TODO log?
|
39
|
+
$log.error $!.to_s
|
40
|
+
$log.error_backtrace
|
41
|
+
end
|
35
42
|
end
|
36
43
|
|
37
|
-
def
|
38
|
-
|
39
|
-
rescue
|
40
|
-
# TODO log?
|
41
|
-
$log.error $!.to_s
|
42
|
-
$log.error_backtrace
|
44
|
+
def configure(conf)
|
45
|
+
super
|
43
46
|
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def configure(conf)
|
47
|
-
super
|
48
|
-
end
|
49
47
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
def start
|
49
|
+
@loop = Coolio::Loop.new
|
50
|
+
@timer = TimerWatcher.new(@emit_interval, true, &method(:on_timer))
|
51
|
+
@loop.attach(@timer)
|
52
|
+
@thread = Thread.new(&method(:run))
|
53
|
+
end
|
56
54
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
def shutdown
|
56
|
+
@loop.watchers.each {|w| w.detach }
|
57
|
+
@loop.stop
|
58
|
+
@thread.join
|
59
|
+
end
|
62
60
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
61
|
+
def run
|
62
|
+
@loop.run
|
63
|
+
rescue
|
64
|
+
$log.error "unexpected error", :error=>$!.to_s
|
65
|
+
$log.error_backtrace
|
66
|
+
end
|
69
67
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
def on_timer
|
69
|
+
now = Engine.now
|
70
|
+
record = GC.stat
|
71
|
+
Engine.emit(@tag, now, record)
|
72
|
+
end
|
74
73
|
end
|
75
74
|
end
|
76
|
-
|
77
|
-
|
78
|
-
end
|
@@ -16,285 +16,283 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
module Fluent
|
19
|
+
class HttpInput < Input
|
20
|
+
Plugin.register_input('http', self)
|
19
21
|
|
22
|
+
include DetachMultiProcessMixin
|
20
23
|
|
21
|
-
|
22
|
-
Plugin.register_input('http', self)
|
24
|
+
require 'http/parser'
|
23
25
|
|
24
|
-
|
26
|
+
def initialize
|
27
|
+
require 'webrick/httputils'
|
28
|
+
super
|
29
|
+
end
|
25
30
|
|
26
|
-
|
31
|
+
config_param :port, :integer, :default => 9880
|
32
|
+
config_param :bind, :string, :default => '0.0.0.0'
|
33
|
+
config_param :body_size_limit, :size, :default => 32*1024*1024 # TODO default
|
34
|
+
config_param :keepalive_timeout, :time, :default => 10 # TODO default
|
35
|
+
config_param :backlog, :integer, :default => nil
|
27
36
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
37
|
+
def configure(conf)
|
38
|
+
super
|
39
|
+
end
|
32
40
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
41
|
+
class KeepaliveManager < Coolio::TimerWatcher
|
42
|
+
class TimerValue
|
43
|
+
def initialize
|
44
|
+
@value = 0
|
45
|
+
end
|
46
|
+
attr_accessor :value
|
47
|
+
end
|
37
48
|
|
38
|
-
|
39
|
-
|
40
|
-
|
49
|
+
def initialize(timeout)
|
50
|
+
super(1, true)
|
51
|
+
@cons = {}
|
52
|
+
@timeout = timeout.to_i
|
53
|
+
end
|
41
54
|
|
42
|
-
|
43
|
-
|
44
|
-
def initialize
|
45
|
-
@value = 0
|
55
|
+
def add(sock)
|
56
|
+
@cons[sock] = sock
|
46
57
|
end
|
47
|
-
attr_accessor :value
|
48
|
-
end
|
49
58
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
@timeout = timeout.to_i
|
54
|
-
end
|
59
|
+
def delete(sock)
|
60
|
+
@cons.delete(sock)
|
61
|
+
end
|
55
62
|
|
56
|
-
|
57
|
-
|
63
|
+
def on_timer
|
64
|
+
@cons.each_pair {|sock,val|
|
65
|
+
if sock.step_idle > @timeout
|
66
|
+
sock.close
|
67
|
+
end
|
68
|
+
}
|
69
|
+
end
|
58
70
|
end
|
59
71
|
|
60
|
-
def
|
61
|
-
@
|
62
|
-
|
72
|
+
def start
|
73
|
+
$log.debug "listening http on #{@bind}:#{@port}"
|
74
|
+
lsock = TCPServer.new(@bind, @port)
|
63
75
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
76
|
+
detach_multi_process do
|
77
|
+
super
|
78
|
+
@km = KeepaliveManager.new(@keepalive_timeout)
|
79
|
+
#@lsock = Coolio::TCPServer.new(@bind, @port, Handler, @km, method(:on_request), @body_size_limit)
|
80
|
+
@lsock = Coolio::TCPServer.new(lsock, nil, Handler, @km, method(:on_request), @body_size_limit)
|
81
|
+
@lsock.listen(@backlog) unless @backlog.nil?
|
72
82
|
|
73
|
-
|
74
|
-
|
75
|
-
|
83
|
+
@loop = Coolio::Loop.new
|
84
|
+
@loop.attach(@km)
|
85
|
+
@loop.attach(@lsock)
|
76
86
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
#@lsock = Coolio::TCPServer.new(@bind, @port, Handler, @km, method(:on_request), @body_size_limit)
|
81
|
-
@lsock = Coolio::TCPServer.new(lsock, nil, Handler, @km, method(:on_request), @body_size_limit)
|
87
|
+
@thread = Thread.new(&method(:run))
|
88
|
+
end
|
89
|
+
end
|
82
90
|
|
83
|
-
|
84
|
-
@loop.
|
85
|
-
@loop.
|
91
|
+
def shutdown
|
92
|
+
@loop.watchers.each {|w| w.detach }
|
93
|
+
@loop.stop
|
94
|
+
@lsock.close
|
95
|
+
@thread.join
|
96
|
+
end
|
86
97
|
|
87
|
-
|
98
|
+
def run
|
99
|
+
@loop.run
|
100
|
+
rescue
|
101
|
+
$log.error "unexpected error", :error=>$!.to_s
|
102
|
+
$log.error_backtrace
|
88
103
|
end
|
89
|
-
end
|
90
104
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
@thread.join
|
96
|
-
end
|
105
|
+
def on_request(path_info, params)
|
106
|
+
begin
|
107
|
+
path = path_info[1..-1] # remove /
|
108
|
+
tag = path.split('/').join('.')
|
97
109
|
|
98
|
-
|
99
|
-
|
100
|
-
rescue
|
101
|
-
$log.error "unexpected error", :error=>$!.to_s
|
102
|
-
$log.error_backtrace
|
103
|
-
end
|
110
|
+
if msgpack = params['msgpack']
|
111
|
+
record = MessagePack.unpack(msgpack)
|
104
112
|
|
105
|
-
|
106
|
-
|
107
|
-
path = path_info[1..-1] # remove /
|
108
|
-
tag = path.split('/').join('.')
|
113
|
+
elsif js = params['json']
|
114
|
+
record = JSON.parse(js)
|
109
115
|
|
110
|
-
|
111
|
-
|
116
|
+
else
|
117
|
+
raise "'json' or 'msgpack' parameter is required"
|
118
|
+
end
|
112
119
|
|
113
|
-
|
114
|
-
|
120
|
+
time = params['time']
|
121
|
+
time = time.to_i
|
122
|
+
if time == 0
|
123
|
+
time = Engine.now
|
124
|
+
end
|
115
125
|
|
116
|
-
|
117
|
-
|
126
|
+
rescue
|
127
|
+
return ["400 Bad Request", {'Content-type'=>'text/plain'}, "400 Bad Request\n#{$!}\n"]
|
118
128
|
end
|
119
129
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
130
|
+
# TODO server error
|
131
|
+
begin
|
132
|
+
Engine.emit(tag, time, record)
|
133
|
+
rescue
|
134
|
+
return ["500 Internal Server Error", {'Content-type'=>'text/plain'}, "500 Internal Server Error\n#{$!}\n"]
|
124
135
|
end
|
125
136
|
|
126
|
-
|
127
|
-
return ["400 Bad Request", {'Content-type'=>'text/plain'}, "400 Bad Request\n#{$!}\n"]
|
137
|
+
return ["200 OK", {'Content-type'=>'text/plain'}, ""]
|
128
138
|
end
|
129
139
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
139
|
-
|
140
|
-
class Handler < Coolio::Socket
|
141
|
-
def initialize(io, km, callback, body_size_limit)
|
142
|
-
super(io)
|
143
|
-
@km = km
|
144
|
-
@callback = callback
|
145
|
-
@body_size_limit = body_size_limit
|
146
|
-
@content_type = ""
|
147
|
-
@next_close = false
|
140
|
+
class Handler < Coolio::Socket
|
141
|
+
def initialize(io, km, callback, body_size_limit)
|
142
|
+
super(io)
|
143
|
+
@km = km
|
144
|
+
@callback = callback
|
145
|
+
@body_size_limit = body_size_limit
|
146
|
+
@content_type = ""
|
147
|
+
@next_close = false
|
148
148
|
|
149
|
-
|
150
|
-
|
149
|
+
@idle = 0
|
150
|
+
@km.add(self)
|
151
151
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
def step_idle
|
156
|
-
@idle += 1
|
157
|
-
end
|
152
|
+
@remote_port, @remote_addr = *Socket.unpack_sockaddr_in(io.getpeername)
|
153
|
+
end
|
158
154
|
|
159
|
-
|
160
|
-
|
161
|
-
|
155
|
+
def step_idle
|
156
|
+
@idle += 1
|
157
|
+
end
|
162
158
|
|
163
|
-
|
164
|
-
|
165
|
-
|
159
|
+
def on_close
|
160
|
+
@km.delete(self)
|
161
|
+
end
|
166
162
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
rescue
|
171
|
-
$log.warn "unexpected error", :error=>$!.to_s
|
172
|
-
$log.warn_backtrace
|
173
|
-
close
|
174
|
-
end
|
163
|
+
def on_connect
|
164
|
+
@parser = Http::Parser.new(self)
|
165
|
+
end
|
175
166
|
|
176
|
-
|
177
|
-
|
178
|
-
|
167
|
+
def on_read(data)
|
168
|
+
@idle = 0
|
169
|
+
@parser << data
|
170
|
+
rescue
|
171
|
+
$log.warn "unexpected error", :error=>$!.to_s
|
172
|
+
$log.warn_backtrace
|
173
|
+
close
|
174
|
+
end
|
179
175
|
|
180
|
-
|
181
|
-
|
182
|
-
size = nil
|
183
|
-
if @parser.http_version == [1, 1]
|
184
|
-
@keep_alive = true
|
185
|
-
else
|
186
|
-
@keep_alive = false
|
176
|
+
def on_message_begin
|
177
|
+
@body = ''
|
187
178
|
end
|
188
|
-
|
189
|
-
headers
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
when /Content-Type/i
|
197
|
-
@content_type = v
|
198
|
-
when /Connection/i
|
199
|
-
if v =~ /close/i
|
200
|
-
@keep_alive = false
|
201
|
-
elsif v =~ /Keep-alive/i
|
202
|
-
@keep_alive = true
|
203
|
-
end
|
179
|
+
|
180
|
+
def on_headers_complete(headers)
|
181
|
+
expect = nil
|
182
|
+
size = nil
|
183
|
+
if @parser.http_version == [1, 1]
|
184
|
+
@keep_alive = true
|
185
|
+
else
|
186
|
+
@keep_alive = false
|
204
187
|
end
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
188
|
+
@env = {}
|
189
|
+
headers.each_pair {|k,v|
|
190
|
+
@env["HTTP_#{k.gsub('-','_').upcase}"] = v
|
191
|
+
case k
|
192
|
+
when /Expect/i
|
193
|
+
expect = v
|
194
|
+
when /Content-Length/i
|
195
|
+
size = v.to_i
|
196
|
+
when /Content-Type/i
|
197
|
+
@content_type = v
|
198
|
+
when /Connection/i
|
199
|
+
if v =~ /close/i
|
200
|
+
@keep_alive = false
|
201
|
+
elsif v =~ /Keep-alive/i
|
202
|
+
@keep_alive = true
|
203
|
+
end
|
204
|
+
end
|
205
|
+
}
|
206
|
+
if expect
|
207
|
+
if expect == '100-continue'
|
208
|
+
if !size || size < @body_size_limit
|
209
|
+
send_response_nobody("100 Continue", {})
|
210
|
+
else
|
211
|
+
send_response_and_close("413 Request Entity Too Large", {}, "Too large")
|
212
|
+
end
|
210
213
|
else
|
211
|
-
send_response_and_close("
|
214
|
+
send_response_and_close("417 Expectation Failed", {}, "")
|
212
215
|
end
|
213
|
-
else
|
214
|
-
send_response_and_close("417 Expectation Failed", {}, "")
|
215
216
|
end
|
216
217
|
end
|
217
|
-
end
|
218
218
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
219
|
+
def on_body(chunk)
|
220
|
+
if @body.bytesize + chunk.bytesize > @body_size_limit
|
221
|
+
unless closing?
|
222
|
+
send_response_and_close("413 Request Entity Too Large", {}, "Too large")
|
223
|
+
end
|
224
|
+
return
|
223
225
|
end
|
224
|
-
|
226
|
+
@body << chunk
|
225
227
|
end
|
226
|
-
@body << chunk
|
227
|
-
end
|
228
228
|
|
229
|
-
|
230
|
-
|
229
|
+
def on_message_complete
|
230
|
+
return if closing?
|
231
231
|
|
232
|
-
|
232
|
+
@env['REMOTE_ADDR'] = @remote_addr
|
233
233
|
|
234
|
-
|
234
|
+
params = WEBrick::HTTPUtils.parse_query(@parser.query_string)
|
235
235
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
236
|
+
if @content_type =~ /^application\/x-www-form-urlencoded/
|
237
|
+
params.update WEBrick::HTTPUtils.parse_query(@body)
|
238
|
+
elsif @content_type =~ /^multipart\/form-data; boundary=(.+)/
|
239
|
+
boundary = WEBrick::HTTPUtils.dequote($1)
|
240
|
+
params.update WEBrick::HTTPUtils.parse_form_data(@body, boundary)
|
241
|
+
elsif @content_type =~ /^application\/json/
|
242
|
+
params['json'] = @body
|
243
|
+
end
|
244
|
+
path_info = @parser.request_path
|
245
245
|
|
246
|
-
|
247
|
-
|
246
|
+
params.merge!(@env)
|
247
|
+
@env.clear
|
248
248
|
|
249
|
-
|
250
|
-
|
249
|
+
code, header, body = *@callback.call(path_info, params)
|
250
|
+
body = body.to_s
|
251
251
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
252
|
+
if @keep_alive
|
253
|
+
header['Connection'] = 'Keep-Alive'
|
254
|
+
send_response(code, header, body)
|
255
|
+
else
|
256
|
+
send_response_and_close(code, header, body)
|
257
|
+
end
|
257
258
|
end
|
258
|
-
end
|
259
259
|
|
260
|
-
|
261
|
-
|
262
|
-
|
260
|
+
def on_write_complete
|
261
|
+
close if @next_close
|
262
|
+
end
|
263
263
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
264
|
+
def send_response_and_close(code, header, body)
|
265
|
+
send_response(code, header, body)
|
266
|
+
@next_close = true
|
267
|
+
end
|
268
268
|
|
269
|
-
|
270
|
-
|
271
|
-
|
269
|
+
def closing?
|
270
|
+
@next_close
|
271
|
+
end
|
272
272
|
|
273
|
-
|
274
|
-
|
275
|
-
|
273
|
+
def send_response(code, header, body)
|
274
|
+
header['Content-length'] ||= body.bytesize
|
275
|
+
header['Content-type'] ||= 'text/plain'
|
276
276
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
277
|
+
data = %[HTTP/1.1 #{code}\r\n]
|
278
|
+
header.each_pair {|k,v|
|
279
|
+
data << "#{k}: #{v}\r\n"
|
280
|
+
}
|
281
|
+
data << "\r\n"
|
282
|
+
write data
|
283
283
|
|
284
|
-
|
285
|
-
|
284
|
+
write body
|
285
|
+
end
|
286
286
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
287
|
+
def send_response_nobody(code, header)
|
288
|
+
data = %[HTTP/1.1 #{code}\r\n]
|
289
|
+
header.each_pair {|k,v|
|
290
|
+
data << "#{k}: #{v}\r\n"
|
291
|
+
}
|
292
|
+
data << "\r\n"
|
293
|
+
write data
|
294
|
+
end
|
294
295
|
end
|
295
296
|
end
|
296
297
|
end
|
297
298
|
|
298
|
-
|
299
|
-
end
|
300
|
-
|