fluentd 1.3.0 → 1.3.1
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 +23 -0
- data/lib/fluent/command/cat.rb +25 -14
- data/lib/fluent/config/types.rb +3 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +1 -1
- data/lib/fluent/plugin/out_forward.rb +35 -2
- data/lib/fluent/plugin/parser_nginx.rb +1 -1
- data/lib/fluent/plugin_helper/record_accessor.rb +8 -2
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_types.rb +8 -0
- data/test/plugin/test_out_forward.rb +146 -0
- data/test/plugin/test_parser_nginx.rb +20 -0
- data/test/plugin_helper/test_record_accessor.rb +13 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab82be7292539aa23259062e0a5fb6fbe9d6a5ee
|
4
|
+
data.tar.gz: f2114ce7960c197f57693e8c84e377cb2ee2edb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4cffdc9ff288294bf1ed8f93dac35045f488309b8d303765fdce93434077e820f10c326f9af4437ba26b63b7f1c1636677b03c1514fa61c0a20dcb3d3f69361
|
7
|
+
data.tar.gz: d7fa53ec4203b5b818d4bffea29102f295824c7120ce50217ec45d473f225e152647f6d0ed20049dd0e0a58f79e626012a48724620b203cb8b2aed54f27a06b5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# v1.3
|
2
2
|
|
3
|
+
## Release v1.3.1 - 2018/11/27
|
4
|
+
|
5
|
+
### Enhancements
|
6
|
+
|
7
|
+
* out_forward: Separate parameter names for certificate
|
8
|
+
https://github.com/fluent/fluentd/pull/2181
|
9
|
+
https://github.com/fluent/fluentd/pull/2190
|
10
|
+
* out_forward: Add `verify_connection_at_startup` parameter to check connection setting at startup phase
|
11
|
+
https://github.com/fluent/fluentd/pull/2184
|
12
|
+
* config: Check right slash position in regexp type
|
13
|
+
https://github.com/fluent/fluentd/pull/2176
|
14
|
+
* parser_nginx: Support multiple IPs in `http_x_forwarded_for` field
|
15
|
+
https://github.com/fluent/fluentd/pull/2171
|
16
|
+
|
17
|
+
### Bug fixes
|
18
|
+
|
19
|
+
* fluent-cat: Fix retry limit handling
|
20
|
+
https://github.com/fluent/fluentd/pull/2193
|
21
|
+
* record_accessor helper: Delete top level field with bracket style
|
22
|
+
https://github.com/fluent/fluentd/pull/2192
|
23
|
+
* filter_record_transformer: Keep `class` methond to avoid undefined method error
|
24
|
+
https://github.com/fluent/fluentd/pull/2186
|
25
|
+
|
3
26
|
## Release v1.3.0 - 2018/11/10
|
4
27
|
|
5
28
|
### New features
|
data/lib/fluent/command/cat.rb
CHANGED
@@ -34,6 +34,7 @@ config_path = Fluent::DEFAULT_CONFIG_PATH
|
|
34
34
|
format = 'json'
|
35
35
|
message_key = 'message'
|
36
36
|
time_as_integer = false
|
37
|
+
retry_limit = 5
|
37
38
|
|
38
39
|
op.on('-p', '--port PORT', "fluent tcp port (default: #{port})", Integer) {|i|
|
39
40
|
port = i
|
@@ -75,6 +76,10 @@ op.on('--time-as-integer', "Send time as integer for v0.12 or earlier", TrueClas
|
|
75
76
|
time_as_integer = true
|
76
77
|
}
|
77
78
|
|
79
|
+
op.on('--retry-limit N', "Specify the number of retry limit (default: #{retry_limit})", Integer) {|n|
|
80
|
+
retry_limit = n
|
81
|
+
}
|
82
|
+
|
78
83
|
singleton_class.module_eval do
|
79
84
|
define_method(:usage) do |msg|
|
80
85
|
puts op.to_s
|
@@ -107,6 +112,8 @@ require 'msgpack'
|
|
107
112
|
class Writer
|
108
113
|
include MonitorMixin
|
109
114
|
|
115
|
+
RetryLimitError = Class.new(StandardError)
|
116
|
+
|
110
117
|
class TimerThread
|
111
118
|
def initialize(writer)
|
112
119
|
@writer = writer
|
@@ -130,7 +137,7 @@ class Writer
|
|
130
137
|
end
|
131
138
|
end
|
132
139
|
|
133
|
-
def initialize(tag, connector, time_as_integer: false)
|
140
|
+
def initialize(tag, connector, time_as_integer: false, retry_limit: 5)
|
134
141
|
@tag = tag
|
135
142
|
@connector = connector
|
136
143
|
@socket = false
|
@@ -142,7 +149,7 @@ class Writer
|
|
142
149
|
@pending = []
|
143
150
|
@pending_limit = 1024 # TODO
|
144
151
|
@retry_wait = 1
|
145
|
-
@retry_limit =
|
152
|
+
@retry_limit = retry_limit
|
146
153
|
@time_as_integer = time_as_integer
|
147
154
|
|
148
155
|
super()
|
@@ -236,21 +243,24 @@ class Writer
|
|
236
243
|
end
|
237
244
|
|
238
245
|
def try_connect
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
+
begin
|
247
|
+
now = Time.now.to_i
|
248
|
+
|
249
|
+
unless @error_history.empty?
|
250
|
+
# wait before re-connecting
|
251
|
+
wait = 1 #@retry_wait * (2 ** (@error_history.size-1))
|
252
|
+
if now <= @socket_time + wait
|
253
|
+
sleep(wait)
|
254
|
+
try_connect
|
255
|
+
end
|
246
256
|
end
|
247
|
-
end
|
248
257
|
|
249
|
-
begin
|
250
258
|
@socket = @connector.call
|
251
259
|
@error_history.clear
|
252
260
|
return true
|
253
261
|
|
262
|
+
rescue RetryLimitError => ex
|
263
|
+
raise ex
|
254
264
|
rescue
|
255
265
|
$stderr.puts "connect failed: #{$!}"
|
256
266
|
@error_history << $!
|
@@ -263,9 +273,10 @@ class Writer
|
|
263
273
|
}
|
264
274
|
@pending.clear
|
265
275
|
@error_history.clear
|
276
|
+
raise RetryLimitError, "exceed retry limit"
|
277
|
+
else
|
278
|
+
retry
|
266
279
|
end
|
267
|
-
|
268
|
-
return false
|
269
280
|
end
|
270
281
|
end
|
271
282
|
|
@@ -285,7 +296,7 @@ else
|
|
285
296
|
}
|
286
297
|
end
|
287
298
|
|
288
|
-
w = Writer.new(tag, connector, time_as_integer: time_as_integer)
|
299
|
+
w = Writer.new(tag, connector, time_as_integer: time_as_integer, retry_limit: retry_limit)
|
289
300
|
w.start
|
290
301
|
|
291
302
|
case format
|
data/lib/fluent/config/types.rb
CHANGED
@@ -74,6 +74,9 @@ module Fluent
|
|
74
74
|
return nil unless str
|
75
75
|
return Regexp.compile(str) unless str.start_with?("/")
|
76
76
|
right_slash_position = str.rindex("/")
|
77
|
+
if right_slash_position < str.size - 3
|
78
|
+
raise Fluent::ConfigError, "invalid regexp: missing right slash: #{str}"
|
79
|
+
end
|
77
80
|
options = str[(right_slash_position + 1)..-1]
|
78
81
|
option = 0
|
79
82
|
option |= Regexp::IGNORECASE if options.include?("i")
|
@@ -316,7 +316,7 @@ module Fluent::Plugin
|
|
316
316
|
end
|
317
317
|
|
318
318
|
(Object.instance_methods).each do |m|
|
319
|
-
undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member
|
319
|
+
undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member|^class$/
|
320
320
|
end
|
321
321
|
end
|
322
322
|
end
|
@@ -77,6 +77,9 @@ module Fluent::Plugin
|
|
77
77
|
desc 'Ignore DNS resolution and errors at startup time.'
|
78
78
|
config_param :ignore_network_errors_at_startup, :bool, default: false
|
79
79
|
|
80
|
+
desc 'Verify that a connection can be made with one of out_forward nodes at the time of startup.'
|
81
|
+
config_param :verify_connection_at_startup, :bool, default: false
|
82
|
+
|
80
83
|
desc 'Compress buffered data.'
|
81
84
|
config_param :compress, :enum, list: [:text, :gzip], default: :text
|
82
85
|
|
@@ -91,6 +94,8 @@ module Fluent::Plugin
|
|
91
94
|
desc 'Verify hostname of servers and certificates or not in TLS transport.'
|
92
95
|
config_param :tls_verify_hostname, :bool, default: true
|
93
96
|
desc 'The additional CA certificate path for TLS.'
|
97
|
+
config_param :tls_ca_cert_path, :array, value_type: :string, default: nil
|
98
|
+
desc 'The additional certificate path for TLS.'
|
94
99
|
config_param :tls_cert_path, :array, value_type: :string, default: nil
|
95
100
|
|
96
101
|
config_section :security, required: false, multi: false do
|
@@ -166,8 +171,12 @@ module Fluent::Plugin
|
|
166
171
|
end
|
167
172
|
|
168
173
|
if @transport == :tls
|
174
|
+
# socket helper adds CA cert or signed certificate to same cert store internally so unify it in this place.
|
169
175
|
if @tls_cert_path && !@tls_cert_path.empty?
|
170
|
-
@
|
176
|
+
@tls_ca_cert_path = @tls_cert_path
|
177
|
+
end
|
178
|
+
if @tls_ca_cert_path && !@tls_ca_cert_path.empty?
|
179
|
+
@tls_ca_cert_path.each do |path|
|
171
180
|
raise Fluent::ConfigError, "specified cert path does not exist:#{path}" unless File.exist?(path)
|
172
181
|
raise Fluent::ConfigError, "specified cert path is not readable:#{path}" unless File.readable?(path)
|
173
182
|
end
|
@@ -253,6 +262,17 @@ module Fluent::Plugin
|
|
253
262
|
@sock_ack_waiting = []
|
254
263
|
thread_create(:out_forward_receiving_ack, &method(:ack_reader))
|
255
264
|
end
|
265
|
+
|
266
|
+
if @verify_connection_at_startup
|
267
|
+
@nodes.each do |node|
|
268
|
+
begin
|
269
|
+
node.verify_connection
|
270
|
+
rescue StandardError => e
|
271
|
+
log.fatal "forward's connection setting error: #{e.message}"
|
272
|
+
raise Fluent::UnrecoverableError, e.message
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
256
276
|
end
|
257
277
|
|
258
278
|
def close
|
@@ -324,7 +344,7 @@ module Fluent::Plugin
|
|
324
344
|
verify_fqdn: @tls_verify_hostname,
|
325
345
|
fqdn: hostname,
|
326
346
|
allow_self_signed_cert: @tls_allow_self_signed_cert,
|
327
|
-
cert_paths: @
|
347
|
+
cert_paths: @tls_ca_cert_path,
|
328
348
|
linger_timeout: @send_timeout,
|
329
349
|
send_timeout: @send_timeout,
|
330
350
|
recv_timeout: @ack_response_timeout,
|
@@ -568,6 +588,19 @@ module Fluent::Plugin
|
|
568
588
|
@standby
|
569
589
|
end
|
570
590
|
|
591
|
+
def verify_connection
|
592
|
+
sock = @sender.create_transfer_socket(resolved_host, port, @hostname)
|
593
|
+
begin
|
594
|
+
ri = RequestInfo.new(@sender.security ? :helo : :established)
|
595
|
+
if ri.state != :established
|
596
|
+
establish_connection(sock, ri)
|
597
|
+
raise if ri.state != :established
|
598
|
+
end
|
599
|
+
ensure
|
600
|
+
sock.close
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
571
604
|
def establish_connection(sock, ri)
|
572
605
|
while available? && ri.state != :established
|
573
606
|
begin
|
@@ -21,7 +21,7 @@ module Fluent
|
|
21
21
|
class NginxParser < RegexpParser
|
22
22
|
Plugin.register_parser("nginx", self)
|
23
23
|
|
24
|
-
config_set_default :expression, /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?:\s
|
24
|
+
config_set_default :expression, /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?:\s+\"?(?<http_x_forwarded_for>[^\"]*)\"?)?)?$/
|
25
25
|
config_set_default :time_format, "%d/%b/%Y:%H:%M:%S %z"
|
26
26
|
end
|
27
27
|
end
|
@@ -40,8 +40,14 @@ module Fluent
|
|
40
40
|
if @keys.is_a?(Array)
|
41
41
|
@last_key = @keys.last
|
42
42
|
@dig_keys = @keys[0..-2]
|
43
|
-
|
44
|
-
|
43
|
+
if @dig_keys.empty?
|
44
|
+
@keys = @keys.first
|
45
|
+
mcall = method(:call_index)
|
46
|
+
mdelete = method(:delete_top)
|
47
|
+
else
|
48
|
+
mcall = method(:call_dig)
|
49
|
+
mdelete = method(:delete_nest)
|
50
|
+
end
|
45
51
|
else
|
46
52
|
# Call [] for single key to reduce dig overhead
|
47
53
|
mcall = method(:call_index)
|
data/lib/fluent/version.rb
CHANGED
data/test/config/test_types.rb
CHANGED
@@ -79,6 +79,14 @@ class TestConfigTypes < ::Test::Unit::TestCase
|
|
79
79
|
test 'w/o slashes' do |(expected, str)|
|
80
80
|
assert_equal(expected, Config.regexp_value(str))
|
81
81
|
end
|
82
|
+
|
83
|
+
data("missing right slash" => "/regexp",
|
84
|
+
"too many options" => "/regexp/imx",)
|
85
|
+
test 'invalid regexp' do |(str)|
|
86
|
+
assert_raise(Fluent::ConfigError.new("invalid regexp: missing right slash: #{str}")) do
|
87
|
+
Config.regexp_value(str)
|
88
|
+
end
|
89
|
+
end
|
82
90
|
end
|
83
91
|
|
84
92
|
sub_test_case 'type converters for config_param definitions' do
|
@@ -9,6 +9,8 @@ require 'fluent/plugin/in_forward'
|
|
9
9
|
class ForwardOutputTest < Test::Unit::TestCase
|
10
10
|
def setup
|
11
11
|
Fluent::Test.setup
|
12
|
+
FileUtils.rm_rf(TMP_DIR)
|
13
|
+
FileUtils.mkdir_p(TMP_DIR)
|
12
14
|
@d = nil
|
13
15
|
end
|
14
16
|
|
@@ -16,6 +18,8 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
16
18
|
@d.instance_shutdown if @d
|
17
19
|
end
|
18
20
|
|
21
|
+
TMP_DIR = File.join(__dir__, "../tmp/out_forward#{ENV['TEST_ENV_NUMBER']}")
|
22
|
+
|
19
23
|
TARGET_HOST = '127.0.0.1'
|
20
24
|
TARGET_PORT = unused_port
|
21
25
|
CONFIG = %[
|
@@ -153,6 +157,27 @@ EOL
|
|
153
157
|
assert{ logs.any?{|log| log.include?(expected_log) && log.include?(expected_detail) } }
|
154
158
|
end
|
155
159
|
|
160
|
+
data('CA cert' => 'tls_ca_cert_path',
|
161
|
+
'non CA cert' => 'tls_cert_path')
|
162
|
+
test 'configure tls_cert_path/tls_ca_cert_path' do |param|
|
163
|
+
dummy_cert_path = File.join(TMP_DIR, "dummy_cert.pem")
|
164
|
+
FileUtils.touch(dummy_cert_path)
|
165
|
+
conf = %[
|
166
|
+
send_timeout 5
|
167
|
+
transport tls
|
168
|
+
tls_insecure_mode true
|
169
|
+
#{param} #{dummy_cert_path}
|
170
|
+
<server>
|
171
|
+
host #{TARGET_HOST}
|
172
|
+
port #{TARGET_PORT}
|
173
|
+
</server>
|
174
|
+
]
|
175
|
+
|
176
|
+
@d = d = create_driver(conf)
|
177
|
+
# In the plugin, tls_ca_cert_path is used for both cases
|
178
|
+
assert_equal([dummy_cert_path], d.instance.tls_ca_cert_path)
|
179
|
+
end
|
180
|
+
|
156
181
|
test 'compress_default_value' do
|
157
182
|
@d = d = create_driver
|
158
183
|
assert_equal :text, d.instance.compress
|
@@ -217,6 +242,18 @@ EOL
|
|
217
242
|
assert_equal 2, d.instance.ack_response_timeout
|
218
243
|
end
|
219
244
|
|
245
|
+
test 'verify_connection_at_startup is disabled in default' do
|
246
|
+
@d = d = create_driver(CONFIG)
|
247
|
+
assert_false d.instance.verify_connection_at_startup
|
248
|
+
end
|
249
|
+
|
250
|
+
test 'verify_connection_at_startup can be enabled' do
|
251
|
+
@d = d = create_driver(CONFIG + %[
|
252
|
+
verify_connection_at_startup true
|
253
|
+
])
|
254
|
+
assert_true d.instance.verify_connection_at_startup
|
255
|
+
end
|
256
|
+
|
220
257
|
test 'send tags in str (utf-8 strings)' do
|
221
258
|
target_input_driver = create_target_input_driver
|
222
259
|
|
@@ -774,4 +811,113 @@ EOL
|
|
774
811
|
i.configure(conf)
|
775
812
|
end
|
776
813
|
end
|
814
|
+
|
815
|
+
sub_test_case 'verify_connection_at_startup' do
|
816
|
+
test 'nodes are not available' do
|
817
|
+
@d = d = create_driver(CONFIG + %[
|
818
|
+
verify_connection_at_startup true
|
819
|
+
<buffer tag>
|
820
|
+
flush_mode immediate
|
821
|
+
retry_type periodic
|
822
|
+
retry_wait 30s
|
823
|
+
flush_at_shutdown false # suppress errors in d.instance_shutdown
|
824
|
+
</buffer>
|
825
|
+
])
|
826
|
+
assert_raise Fluent::UnrecoverableError do
|
827
|
+
d.instance_start
|
828
|
+
end
|
829
|
+
d.instance_shutdown
|
830
|
+
end
|
831
|
+
|
832
|
+
test 'nodes_shared_key_miss_match' do
|
833
|
+
input_conf = TARGET_CONFIG + %[
|
834
|
+
<security>
|
835
|
+
self_hostname in.localhost
|
836
|
+
shared_key fluentd-sharedkey
|
837
|
+
</security>
|
838
|
+
]
|
839
|
+
target_input_driver = create_target_input_driver(conf: input_conf)
|
840
|
+
output_conf = %[
|
841
|
+
send_timeout 30
|
842
|
+
heartbeat_type transport
|
843
|
+
transport tls
|
844
|
+
tls_verify_hostname false
|
845
|
+
verify_connection_at_startup true
|
846
|
+
require_ack_response true
|
847
|
+
ack_response_timeout 5s
|
848
|
+
<security>
|
849
|
+
self_hostname localhost
|
850
|
+
shared_key key_miss_match
|
851
|
+
</security>
|
852
|
+
<buffer tag>
|
853
|
+
flush_mode immediate
|
854
|
+
retry_type periodic
|
855
|
+
retry_wait 30s
|
856
|
+
flush_at_shutdown false # suppress errors in d.instance_shutdown
|
857
|
+
flush_thread_interval 31s
|
858
|
+
</buffer>
|
859
|
+
|
860
|
+
<server>
|
861
|
+
host #{TARGET_HOST}
|
862
|
+
port #{TARGET_PORT}
|
863
|
+
</server>
|
864
|
+
]
|
865
|
+
@d = d = create_driver(output_conf)
|
866
|
+
|
867
|
+
target_input_driver.run(expect_records: 1, timeout: 15) do
|
868
|
+
assert_raise Fluent::UnrecoverableError do
|
869
|
+
d.instance_start
|
870
|
+
end
|
871
|
+
d.instance_shutdown
|
872
|
+
end
|
873
|
+
end
|
874
|
+
|
875
|
+
test 'nodes_shared_key_match' do
|
876
|
+
input_conf = TARGET_CONFIG + %[
|
877
|
+
<security>
|
878
|
+
self_hostname in.localhost
|
879
|
+
shared_key fluentd-sharedkey
|
880
|
+
<client>
|
881
|
+
host 127.0.0.1
|
882
|
+
</client>
|
883
|
+
</security>
|
884
|
+
]
|
885
|
+
target_input_driver = create_target_input_driver(conf: input_conf)
|
886
|
+
|
887
|
+
output_conf = %[
|
888
|
+
send_timeout 51
|
889
|
+
verify_connection_at_startup true
|
890
|
+
<security>
|
891
|
+
self_hostname localhost
|
892
|
+
shared_key fluentd-sharedkey
|
893
|
+
</security>
|
894
|
+
<server>
|
895
|
+
name test
|
896
|
+
host #{TARGET_HOST}
|
897
|
+
port #{TARGET_PORT}
|
898
|
+
shared_key fluentd-sharedkey
|
899
|
+
</server>
|
900
|
+
]
|
901
|
+
@d = d = create_driver(output_conf)
|
902
|
+
|
903
|
+
time = event_time("2011-01-02 13:14:15 UTC")
|
904
|
+
records = [
|
905
|
+
{"a" => 1},
|
906
|
+
{"a" => 2}
|
907
|
+
]
|
908
|
+
|
909
|
+
target_input_driver.run(expect_records: 2, timeout: 15) do
|
910
|
+
d.run(default_tag: 'test') do
|
911
|
+
records.each do |record|
|
912
|
+
d.feed(time, record)
|
913
|
+
end
|
914
|
+
end
|
915
|
+
end
|
916
|
+
|
917
|
+
events = target_input_driver.events
|
918
|
+
assert{ events != [] }
|
919
|
+
assert_equal(['test', time, records[0]], events[0])
|
920
|
+
assert_equal(['test', time, records[1]], events[1])
|
921
|
+
end
|
922
|
+
end
|
777
923
|
end
|
@@ -28,6 +28,18 @@ class NginxParserTest < ::Test::Unit::TestCase
|
|
28
28
|
'agent' => 'Opera/12.0',
|
29
29
|
'http_x_forwarded_for' => '-'
|
30
30
|
}
|
31
|
+
@expected_extended_multiple_ip = {
|
32
|
+
'remote' => '127.0.0.1',
|
33
|
+
'host' => '192.168.0.1',
|
34
|
+
'user' => '-',
|
35
|
+
'method' => 'GET',
|
36
|
+
'path' => '/',
|
37
|
+
'code' => '200',
|
38
|
+
'size' => '777',
|
39
|
+
'referer' => '-',
|
40
|
+
'agent' => 'Opera/12.0',
|
41
|
+
'http_x_forwarded_for' => '127.0.0.1, 192.168.0.1'
|
42
|
+
}
|
31
43
|
end
|
32
44
|
|
33
45
|
def create_driver
|
@@ -65,4 +77,12 @@ class NginxParserTest < ::Test::Unit::TestCase
|
|
65
77
|
assert_equal(@expected_extended, record)
|
66
78
|
}
|
67
79
|
end
|
80
|
+
|
81
|
+
def test_parse_with_http_x_forwarded_for_multiple_ip
|
82
|
+
d = create_driver
|
83
|
+
d.instance.parse('127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" "127.0.0.1, 192.168.0.1"') { |time, record|
|
84
|
+
assert_equal(event_time('28/Feb/2013:12:00:00 +0900', format: '%d/%b/%Y:%H:%M:%S %z'), time)
|
85
|
+
assert_equal(@expected_extended_multiple_ip, record)
|
86
|
+
}
|
87
|
+
end
|
68
88
|
end
|
@@ -110,6 +110,12 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
|
|
110
110
|
assert_equal r[param], accessor.call(r)
|
111
111
|
end
|
112
112
|
|
113
|
+
test "access single dot key using bracket style" do
|
114
|
+
r = {'key1' => 'v1', 'ke y2' => 'v2', 'this.is.key3' => 'v3'}
|
115
|
+
accessor = @d.record_accessor_create('$["this.is.key3"]')
|
116
|
+
assert_equal 'v3', accessor.call(r)
|
117
|
+
end
|
118
|
+
|
113
119
|
test "nested bracket keys with dot" do
|
114
120
|
r = {'key1' => {'this.is.key3' => 'value'}}
|
115
121
|
accessor = @d.record_accessor_create("$['key1']['this.is.key3']")
|
@@ -164,6 +170,13 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
|
|
164
170
|
assert_not_include(r, param)
|
165
171
|
end
|
166
172
|
|
173
|
+
test "delete top key using bracket style" do
|
174
|
+
r = {'key1' => 'v1', 'ke y2' => 'v2', 'this.is.key3' => 'v3'}
|
175
|
+
accessor = @d.record_accessor_create('$["this.is.key3"]')
|
176
|
+
accessor.delete(r)
|
177
|
+
assert_not_include(r, 'this.is.key3')
|
178
|
+
end
|
179
|
+
|
167
180
|
data('bracket' => "$['key1'][0]['ke y2']",
|
168
181
|
'bracket w/ double quotes' => '$["key1"][0]["ke y2"]')
|
169
182
|
test "delete nested keys ['key1', 0, 'ke y2']" do |param|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluentd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|