fluentd 1.10.2-x64-mingw32 → 1.11.2-x64-mingw32
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/CHANGELOG.md +102 -1
- data/CONTRIBUTING.md +1 -1
- data/example/copy_roundrobin.conf +3 -3
- data/example/counter.conf +1 -1
- data/example/filter_stdout.conf +2 -2
- data/example/{in_dummy_blocks.conf → in_sample_blocks.conf} +4 -4
- data/example/{in_dummy_with_compression.conf → in_sample_with_compression.conf} +3 -3
- data/example/logevents.conf +5 -5
- data/example/multi_filters.conf +1 -1
- data/example/out_exec_filter.conf +2 -2
- data/example/out_forward.conf +1 -1
- data/example/out_forward_buf_file.conf +1 -1
- data/example/out_forward_client.conf +5 -5
- data/example/out_forward_heartbeat_none.conf +1 -1
- data/example/out_forward_sd.conf +1 -1
- data/example/out_forward_shared_key.conf +2 -2
- data/example/out_forward_tls.conf +1 -1
- data/example/out_forward_users.conf +3 -3
- data/example/out_null.conf +4 -4
- data/example/secondary_file.conf +1 -1
- data/lib/fluent/command/fluentd.rb +11 -0
- data/lib/fluent/config.rb +1 -0
- data/lib/fluent/match.rb +10 -1
- data/lib/fluent/plugin/buffer.rb +24 -4
- data/lib/fluent/plugin/in_dummy.rb +2 -123
- data/lib/fluent/plugin/in_forward.rb +2 -2
- data/lib/fluent/plugin/in_gc_stat.rb +16 -0
- data/lib/fluent/plugin/in_http.rb +148 -77
- data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
- data/lib/fluent/plugin/in_sample.rb +141 -0
- data/lib/fluent/plugin/in_tail.rb +4 -4
- data/lib/fluent/plugin/in_unix.rb +77 -77
- data/lib/fluent/plugin/out_file.rb +1 -1
- data/lib/fluent/plugin/out_forward.rb +7 -2
- data/lib/fluent/plugin/out_forward/load_balancer.rb +1 -1
- data/lib/fluent/plugin/out_http.rb +15 -2
- data/lib/fluent/plugin/parser_multiline.rb +1 -1
- data/lib/fluent/plugin/parser_syslog.rb +215 -54
- data/lib/fluent/plugin_helper/cert_option.rb +5 -8
- data/lib/fluent/plugin_helper/child_process.rb +3 -2
- data/lib/fluent/plugin_helper/record_accessor.rb +14 -0
- data/lib/fluent/plugin_helper/service_discovery.rb +7 -0
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +8 -0
- data/lib/fluent/plugin_helper/socket.rb +1 -1
- data/lib/fluent/plugin_helper/socket_option.rb +2 -2
- data/lib/fluent/supervisor.rb +6 -3
- data/lib/fluent/test/filter_test.rb +2 -2
- data/lib/fluent/test/output_test.rb +3 -3
- data/lib/fluent/version.rb +1 -1
- data/test/plugin/out_forward/test_load_balancer.rb +46 -0
- data/test/plugin/test_in_gc_stat.rb +24 -1
- data/test/plugin/test_in_http.rb +57 -0
- data/test/plugin/{test_in_dummy.rb → test_in_sample.rb} +25 -25
- data/test/plugin/test_in_tail.rb +17 -0
- data/test/plugin/test_in_unix.rb +128 -73
- data/test/plugin/test_out_http.rb +38 -0
- data/test/plugin/test_parser_syslog.rb +66 -29
- data/test/plugin_helper/data/cert/empty.pem +0 -0
- data/test/plugin_helper/test_cert_option.rb +7 -0
- data/test/plugin_helper/test_child_process.rb +15 -0
- data/test/plugin_helper/test_record_accessor.rb +41 -0
- data/test/plugin_helper/test_server.rb +34 -0
- data/test/plugin_helper/test_service_discovery.rb +37 -4
- data/test/plugin_helper/test_socket.rb +8 -0
- data/test/test_match.rb +11 -0
- data/test/test_static_config_analysis.rb +2 -2
- metadata +9 -6
@@ -223,7 +223,7 @@ module Fluent::Plugin
|
|
223
223
|
opts = {with_config: false, with_retry: false}
|
224
224
|
timer_execute(:in_monitor_agent_emit, @emit_interval, repeat: true) {
|
225
225
|
es = Fluent::MultiEventStream.new
|
226
|
-
now = Fluent::
|
226
|
+
now = Fluent::EventTime.now
|
227
227
|
plugins_info_all(opts).each { |record|
|
228
228
|
es.add(now, record)
|
229
229
|
}
|
@@ -0,0 +1,141 @@
|
|
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 'json'
|
18
|
+
|
19
|
+
require 'fluent/plugin/input'
|
20
|
+
require 'fluent/config/error'
|
21
|
+
|
22
|
+
module Fluent::Plugin
|
23
|
+
class SampleInput < Input
|
24
|
+
Fluent::Plugin.register_input('sample', self)
|
25
|
+
Fluent::Plugin.register_input('dummy', self)
|
26
|
+
|
27
|
+
helpers :thread, :storage
|
28
|
+
|
29
|
+
BIN_NUM = 10
|
30
|
+
DEFAULT_STORAGE_TYPE = 'local'
|
31
|
+
|
32
|
+
desc "The value is the tag assigned to the generated events."
|
33
|
+
config_param :tag, :string
|
34
|
+
desc "The number of events in event stream of each emits."
|
35
|
+
config_param :size, :integer, default: 1
|
36
|
+
desc "It configures how many events to generate per second."
|
37
|
+
config_param :rate, :integer, default: 1
|
38
|
+
desc "If specified, each generated event has an auto-incremented key field."
|
39
|
+
config_param :auto_increment_key, :string, default: nil
|
40
|
+
desc "The boolean to suspend-and-resume incremental value after restart"
|
41
|
+
config_param :suspend, :bool, default: false,deprecated: 'This parameters is ignored'
|
42
|
+
desc "The sample data to be generated. An array of JSON hashes or a single JSON hash."
|
43
|
+
config_param :sample, alias: :dummy, default: [{"message" => "sample"}] do |val|
|
44
|
+
begin
|
45
|
+
parsed = JSON.parse(val)
|
46
|
+
rescue JSON::ParserError => ex
|
47
|
+
# Fluent::ConfigParseError, "got incomplete JSON" will be raised
|
48
|
+
# at literal_parser.rb with --use-v1-config, but I had to
|
49
|
+
# take care at here for the case of --use-v0-config.
|
50
|
+
raise Fluent::ConfigError, "#{ex.class}: #{ex.message}"
|
51
|
+
end
|
52
|
+
sample = parsed.is_a?(Array) ? parsed : [parsed]
|
53
|
+
sample.each_with_index do |e, i|
|
54
|
+
raise Fluent::ConfigError, "#{i}th element of sample, #{e}, is not a hash" unless e.is_a?(Hash)
|
55
|
+
end
|
56
|
+
sample
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize
|
60
|
+
super
|
61
|
+
@storage = nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def configure(conf)
|
65
|
+
super
|
66
|
+
@sample_index = 0
|
67
|
+
config = conf.elements.select{|e| e.name == 'storage' }.first
|
68
|
+
@storage = storage_create(usage: 'suspend', conf: config, default_type: DEFAULT_STORAGE_TYPE)
|
69
|
+
end
|
70
|
+
|
71
|
+
def multi_workers_ready?
|
72
|
+
true
|
73
|
+
end
|
74
|
+
|
75
|
+
def start
|
76
|
+
super
|
77
|
+
|
78
|
+
@storage.put(:increment_value, 0) unless @storage.get(:increment_value)
|
79
|
+
# keep 'dummy' to avoid breaking changes for existing environment. Change it in fluentd v2
|
80
|
+
@storage.put(:dummy_index, 0) unless @storage.get(:dummy_index)
|
81
|
+
|
82
|
+
if @auto_increment_key && !@storage.get(:auto_increment_value)
|
83
|
+
@storage.put(:auto_increment_value, -1)
|
84
|
+
end
|
85
|
+
|
86
|
+
thread_create(:sample_input, &method(:run))
|
87
|
+
end
|
88
|
+
|
89
|
+
def run
|
90
|
+
batch_num = (@rate / BIN_NUM).to_i
|
91
|
+
residual_num = (@rate % BIN_NUM)
|
92
|
+
while thread_current_running?
|
93
|
+
current_time = Time.now.to_i
|
94
|
+
BIN_NUM.times do
|
95
|
+
break unless (thread_current_running? && Time.now.to_i <= current_time)
|
96
|
+
wait(0.1) { emit(batch_num) }
|
97
|
+
end
|
98
|
+
emit(residual_num) if thread_current_running?
|
99
|
+
# wait for next second
|
100
|
+
while thread_current_running? && Time.now.to_i <= current_time
|
101
|
+
sleep 0.01
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def emit(num)
|
107
|
+
begin
|
108
|
+
if @size > 1
|
109
|
+
num.times do
|
110
|
+
router.emit_array(@tag, Array.new(@size) { [Fluent::EventTime.now, generate] })
|
111
|
+
end
|
112
|
+
else
|
113
|
+
num.times { router.emit(@tag, Fluent::EventTime.now, generate) }
|
114
|
+
end
|
115
|
+
rescue => _
|
116
|
+
# ignore all errors not to stop emits by emit errors
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def generate
|
121
|
+
d = @sample[@sample_index]
|
122
|
+
unless d
|
123
|
+
@sample_index = 0
|
124
|
+
d = @sample[@sample_index]
|
125
|
+
end
|
126
|
+
@sample_index += 1
|
127
|
+
if @auto_increment_key
|
128
|
+
d = d.dup
|
129
|
+
d[@auto_increment_key] = @storage.update(:auto_increment_value){|v| v + 1 }
|
130
|
+
end
|
131
|
+
d
|
132
|
+
end
|
133
|
+
|
134
|
+
def wait(time)
|
135
|
+
start_time = Time.now
|
136
|
+
yield
|
137
|
+
sleep_time = time - (Time.now - start_time)
|
138
|
+
sleep sleep_time if sleep_time > 0
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -136,7 +136,7 @@ module Fluent::Plugin
|
|
136
136
|
raise Fluent::ConfigError, "#{rc} are reserved words: #{@path_delimiter}"
|
137
137
|
end
|
138
138
|
|
139
|
-
@paths = @path.split(@path_delimiter).map(&:strip)
|
139
|
+
@paths = @path.split(@path_delimiter).map(&:strip).uniq
|
140
140
|
if @paths.empty?
|
141
141
|
raise Fluent::ConfigError, "tail: 'path' parameter is required on tail input"
|
142
142
|
end
|
@@ -271,9 +271,9 @@ module Fluent::Plugin
|
|
271
271
|
end
|
272
272
|
else
|
273
273
|
if is_file
|
274
|
-
unless @ignore_list.include?(
|
274
|
+
unless @ignore_list.include?(p)
|
275
275
|
log.warn "#{p} unreadable. It is excluded and would be examined next time."
|
276
|
-
@ignore_list <<
|
276
|
+
@ignore_list << p if @ignore_repeated_permission_error
|
277
277
|
end
|
278
278
|
end
|
279
279
|
false
|
@@ -296,7 +296,7 @@ module Fluent::Plugin
|
|
296
296
|
end
|
297
297
|
path.include?('*') ? Dir.glob(path) : path
|
298
298
|
}.flatten.uniq
|
299
|
-
paths - excluded
|
299
|
+
paths.uniq - excluded
|
300
300
|
end
|
301
301
|
|
302
302
|
# in_tail with '*' path doesn't check rotation file equality at refresh phase.
|
@@ -14,50 +14,68 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
require '
|
18
|
-
require '
|
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
|
-
|
24
|
-
|
36
|
+
@lsock = nil
|
37
|
+
end
|
25
38
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
config_param :
|
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
|
-
|
37
|
-
@thread = Thread.new(&method(:run))
|
54
|
+
event_loop_attach(@lsock)
|
38
55
|
end
|
39
56
|
|
40
57
|
def shutdown
|
41
|
-
@
|
42
|
-
|
43
|
-
|
44
|
-
|
58
|
+
if @lsock
|
59
|
+
event_loop_detach(@lsock)
|
60
|
+
@lsock.close
|
61
|
+
end
|
45
62
|
|
46
63
|
super
|
47
64
|
end
|
48
65
|
|
49
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
83
|
-
|
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
|
-
|
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
|
-
|
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 ||= Engine.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 = Engine.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
|
-
|
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
|
-
@
|
137
|
-
@
|
161
|
+
@parser = Yajl::Parser.new
|
162
|
+
@parser.on_parse_complete = @on_message
|
138
163
|
else
|
139
164
|
m = method(:on_read_msgpack)
|
140
|
-
@
|
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
|
-
@
|
151
|
-
rescue
|
152
|
-
@log.error "unexpected error", error:
|
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
|
-
@
|
159
|
-
rescue
|
160
|
-
@log.error "unexpected error", error:
|
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
|
@@ -155,7 +155,7 @@ module Fluent::Plugin
|
|
155
155
|
dummy_record_keys = get_placeholders_keys(@path_template) || ['message']
|
156
156
|
dummy_record = Hash[dummy_record_keys.zip(['data'] * dummy_record_keys.size)]
|
157
157
|
|
158
|
-
test_chunk1 = chunk_for_test(dummy_tag, Fluent::
|
158
|
+
test_chunk1 = chunk_for_test(dummy_tag, Fluent::EventTime.now, dummy_record)
|
159
159
|
test_path = extract_placeholders(@path_template, test_chunk1)
|
160
160
|
unless ::Fluent::FileUtil.writable_p?(test_path)
|
161
161
|
raise Fluent::ConfigError, "out_file: `#{test_path}` is not writable"
|
@@ -382,7 +382,12 @@ module Fluent::Plugin
|
|
382
382
|
cert_logical_store_name: @tls_cert_logical_store_name,
|
383
383
|
cert_use_enterprise_store: @tls_cert_use_enterprise_store,
|
384
384
|
|
385
|
-
|
385
|
+
# Enabling SO_LINGER causes tcp port exhaustion on Windows.
|
386
|
+
# This is because dynamic ports are only 16384 (from 49152 to 65535) and
|
387
|
+
# expiring SO_LINGER enabled ports should wait 4 minutes
|
388
|
+
# where set by TcpTimeDelay. Its default value is 4 minutes.
|
389
|
+
# So, we should disable SO_LINGER on Windows to prevent flood of waiting ports.
|
390
|
+
linger_timeout: Fluent.windows? ? nil : @send_timeout,
|
386
391
|
send_timeout: @send_timeout,
|
387
392
|
recv_timeout: @ack_response_timeout,
|
388
393
|
connect_timeout: @connect_timeout,
|
@@ -704,7 +709,7 @@ module Fluent::Plugin
|
|
704
709
|
@resolved_host ||= resolve_dns!
|
705
710
|
|
706
711
|
else
|
707
|
-
now = Fluent::
|
712
|
+
now = Fluent::EventTime.now
|
708
713
|
rh = @resolved_host
|
709
714
|
if !rh || now - @resolved_time >= @sender.expire_dns_cache
|
710
715
|
rh = @resolved_host = resolve_dns!
|