fluentd 0.10.55 → 0.10.56
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 +7 -0
- data/fluentd.gemspec +2 -0
- data/lib/fluent/config/section.rb +2 -0
- data/lib/fluent/formatter.rb +2 -1
- data/lib/fluent/mixin.rb +22 -7
- data/lib/fluent/output.rb +17 -8
- data/lib/fluent/plugin/in_exec.rb +6 -0
- data/lib/fluent/plugin/out_exec.rb +1 -1
- data/lib/fluent/plugin/out_exec_filter.rb +8 -1
- data/lib/fluent/plugin/out_forward.rb +1 -1
- data/lib/fluent/timezone.rb +131 -0
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_section.rb +10 -0
- data/test/plugin/test_out_file.rb +35 -0
- data/test/test_formatter.rb +223 -0
- data/test/test_mixin.rb +74 -2
- metadata +31 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15aab20b26be1dd37d9f185c97971a38767f30a6
|
4
|
+
data.tar.gz: 782800a38871c60c45a69a36e96f8577488809fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed67bd0d60ed78502d18d10920343db5f78cd8b99ba012b1547d3eef1550e49d1bf0456f88cf5ede4e066a03867821007ef1dd65a19a10ddce5f9e4f8478a7d8
|
7
|
+
data.tar.gz: 359d689bc9ec1b8f158759a1b8a876f5b14858d845263a8b2fd32dff39c7edafb408003875dd4089c6a29d1c6bf58be38843c99e17bba1a7ff15d1ccdd90c3c9
|
data/ChangeLog
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
Release 0.10.56 - 2014/10/30
|
2
|
+
|
3
|
+
* config: Add Fluent::Config::Section#object_id to avoid NoMethodError by object dump tools
|
4
|
+
* mixin: Fix SetTagKeyMixin and SetTimeKeyMixin which ignores config_set_default since 0.10.53
|
5
|
+
* input/output: Support 'timezone' configuration parameter (e.g. "+09:00" for JST).
|
6
|
+
* log: Use plugin_id instead of object_id in log message for consistency with in_monitor_agent
|
7
|
+
|
1
8
|
Release 0.10.55 - 2014/10/17
|
2
9
|
|
3
10
|
* config: Relax '@' handling in the plugin configuration for backward compatibility
|
data/fluentd.gemspec
CHANGED
@@ -24,6 +24,8 @@ Gem::Specification.new do |gem|
|
|
24
24
|
gem.add_runtime_dependency("cool.io", [">= 1.1.1", "!= 1.2.0", "< 2.0.0"])
|
25
25
|
gem.add_runtime_dependency("http_parser.rb", [">= 0.5.1", "< 0.7.0"])
|
26
26
|
gem.add_runtime_dependency("sigdump", ["~> 0.2.2"])
|
27
|
+
gem.add_runtime_dependency("tzinfo", [">= 1.0.0"])
|
28
|
+
gem.add_runtime_dependency("tzinfo-data", [">= 1.0.0"])
|
27
29
|
|
28
30
|
gem.add_development_dependency("rake", [">= 0.9.2"])
|
29
31
|
gem.add_development_dependency("flexmock")
|
data/lib/fluent/formatter.rb
CHANGED
@@ -28,6 +28,7 @@ module Fluent
|
|
28
28
|
config_param :include_tag_key, :bool, :default => false
|
29
29
|
config_param :tag_key, :string, :default => 'tag'
|
30
30
|
config_param :localtime, :bool, :default => true
|
31
|
+
config_param :timezone, :string, :default => nil
|
31
32
|
}
|
32
33
|
end
|
33
34
|
|
@@ -37,7 +38,7 @@ module Fluent
|
|
37
38
|
if conf['utc']
|
38
39
|
@localtime = false
|
39
40
|
end
|
40
|
-
@timef = TimeFormatter.new(@time_format, @localtime)
|
41
|
+
@timef = TimeFormatter.new(@time_format, @localtime, @timezone)
|
41
42
|
end
|
42
43
|
|
43
44
|
def filter_record(tag, time, record)
|
data/lib/fluent/mixin.rb
CHANGED
@@ -17,12 +17,21 @@
|
|
17
17
|
#
|
18
18
|
module Fluent
|
19
19
|
class TimeFormatter
|
20
|
-
|
20
|
+
require 'fluent/timezone'
|
21
|
+
|
22
|
+
def initialize(format, localtime, timezone = nil)
|
21
23
|
@tc1 = 0
|
22
24
|
@tc1_str = nil
|
23
25
|
@tc2 = 0
|
24
26
|
@tc2_str = nil
|
25
27
|
|
28
|
+
if formatter = Fluent::Timezone.formatter(timezone, format)
|
29
|
+
define_singleton_method(:format_nocache) {|time|
|
30
|
+
formatter.call(time)
|
31
|
+
}
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
26
35
|
if format
|
27
36
|
if localtime
|
28
37
|
define_singleton_method(:format_nocache) {|time|
|
@@ -113,15 +122,16 @@ module Fluent
|
|
113
122
|
end
|
114
123
|
|
115
124
|
module SetTimeKeyMixin
|
125
|
+
require 'fluent/timezone'
|
116
126
|
include RecordFilterMixin
|
117
127
|
|
118
|
-
attr_accessor :include_time_key, :time_key, :localtime
|
128
|
+
attr_accessor :include_time_key, :time_key, :localtime, :timezone
|
119
129
|
|
120
130
|
def configure(conf)
|
121
|
-
super
|
122
|
-
|
123
131
|
@include_time_key = false
|
124
132
|
|
133
|
+
super
|
134
|
+
|
125
135
|
if s = conf['include_time_key']
|
126
136
|
include_time_key = Config.bool_value(s)
|
127
137
|
raise ConfigError, "Invalid boolean expression '#{s}' for include_time_key parameter" if include_time_key.nil?
|
@@ -139,7 +149,12 @@ module Fluent
|
|
139
149
|
@localtime = false
|
140
150
|
end
|
141
151
|
|
142
|
-
|
152
|
+
if conf['timezone']
|
153
|
+
@timezone = conf['timezone']
|
154
|
+
Fluent::Timezone.validate!(@timezone)
|
155
|
+
end
|
156
|
+
|
157
|
+
@timef = TimeFormatter.new(@time_format, @localtime, @timezone)
|
143
158
|
end
|
144
159
|
end
|
145
160
|
|
@@ -156,10 +171,10 @@ module Fluent
|
|
156
171
|
attr_accessor :include_tag_key, :tag_key
|
157
172
|
|
158
173
|
def configure(conf)
|
159
|
-
super
|
160
|
-
|
161
174
|
@include_tag_key = false
|
162
175
|
|
176
|
+
super
|
177
|
+
|
163
178
|
if s = conf['include_tag_key']
|
164
179
|
include_tag_key = Config.bool_value(s)
|
165
180
|
raise ConfigError, "Invalid boolean expression '#{s}' for include_tag_key parameter" if include_tag_key.nil?
|
data/lib/fluent/output.rb
CHANGED
@@ -316,7 +316,7 @@ module Fluent
|
|
316
316
|
@num_errors = 0
|
317
317
|
# Note: don't notify to other threads to prevent
|
318
318
|
# burst to recovered server
|
319
|
-
$log.warn "retry succeeded.", :
|
319
|
+
$log.warn "retry succeeded.", :plugin_id=>plugin_id
|
320
320
|
end
|
321
321
|
|
322
322
|
if has_next
|
@@ -341,20 +341,20 @@ module Fluent
|
|
341
341
|
end
|
342
342
|
|
343
343
|
if @disable_retry_limit || error_count < @retry_limit
|
344
|
-
$log.warn "temporarily failed to flush the buffer.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :
|
344
|
+
$log.warn "temporarily failed to flush the buffer.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
345
345
|
$log.warn_backtrace e.backtrace
|
346
346
|
|
347
347
|
elsif @secondary
|
348
348
|
if error_count == @retry_limit
|
349
|
-
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :
|
349
|
+
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
350
350
|
$log.warn "retry count exceededs limit. falling back to secondary output."
|
351
351
|
$log.warn_backtrace e.backtrace
|
352
352
|
retry # retry immediately
|
353
353
|
elsif error_count <= @retry_limit + @secondary_limit
|
354
|
-
$log.warn "failed to flush the buffer, next retry will be with secondary output.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :
|
354
|
+
$log.warn "failed to flush the buffer, next retry will be with secondary output.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
355
355
|
$log.warn_backtrace e.backtrace
|
356
356
|
else
|
357
|
-
$log.warn "failed to flush the buffer.", :error_class=>e.class, :error=>e.to_s, :
|
357
|
+
$log.warn "failed to flush the buffer.", :error_class=>e.class, :error=>e.to_s, :plugin_id=>plugin_id
|
358
358
|
$log.warn "secondary retry count exceededs limit."
|
359
359
|
$log.warn_backtrace e.backtrace
|
360
360
|
write_abort
|
@@ -362,7 +362,7 @@ module Fluent
|
|
362
362
|
end
|
363
363
|
|
364
364
|
else
|
365
|
-
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :
|
365
|
+
$log.warn "failed to flush the buffer.", :error_class=>e.class.to_s, :error=>e.to_s, :plugin_id=>plugin_id
|
366
366
|
$log.warn "retry count exceededs limit."
|
367
367
|
$log.warn_backtrace e.backtrace
|
368
368
|
write_abort
|
@@ -453,6 +453,8 @@ module Fluent
|
|
453
453
|
|
454
454
|
|
455
455
|
class TimeSlicedOutput < BufferedOutput
|
456
|
+
require 'fluent/timezone'
|
457
|
+
|
456
458
|
def initialize
|
457
459
|
super
|
458
460
|
@localtime = true
|
@@ -461,6 +463,7 @@ module Fluent
|
|
461
463
|
|
462
464
|
config_param :time_slice_format, :string, :default => '%Y%m%d'
|
463
465
|
config_param :time_slice_wait, :time, :default => 10*60
|
466
|
+
config_param :timezone, :string, :default => nil
|
464
467
|
config_set_default :buffer_type, 'file' # overwrite default buffer_type
|
465
468
|
config_set_default :buffer_chunk_limit, 256*1024*1024 # overwrite default buffer_chunk_limit
|
466
469
|
config_set_default :flush_interval, nil
|
@@ -470,14 +473,20 @@ module Fluent
|
|
470
473
|
def configure(conf)
|
471
474
|
super
|
472
475
|
|
473
|
-
# TODO timezone
|
474
476
|
if conf['utc']
|
475
477
|
@localtime = false
|
476
478
|
elsif conf['localtime']
|
477
479
|
@localtime = true
|
478
480
|
end
|
479
481
|
|
480
|
-
if
|
482
|
+
if conf['timezone']
|
483
|
+
@timezone = conf['timezone']
|
484
|
+
Fluent::Timezone.validate!(@timezone)
|
485
|
+
end
|
486
|
+
|
487
|
+
if @timezone
|
488
|
+
@time_slicer = Timezone.formatter(@timezone, @time_slice_format)
|
489
|
+
elsif @localtime
|
481
490
|
@time_slicer = Proc.new {|time|
|
482
491
|
Time.at(time).strftime(@time_slice_format)
|
483
492
|
}
|
@@ -22,6 +22,7 @@ module Fluent
|
|
22
22
|
def initialize
|
23
23
|
super
|
24
24
|
require 'fluent/plugin/exec_util'
|
25
|
+
require 'fluent/timezone'
|
25
26
|
end
|
26
27
|
|
27
28
|
SUPPORTED_FORMAT = {
|
@@ -54,6 +55,11 @@ module Fluent
|
|
54
55
|
@localtime = false
|
55
56
|
end
|
56
57
|
|
58
|
+
if conf['timezone']
|
59
|
+
@timezone = conf['timezone']
|
60
|
+
Fluent::Timezone.validate!(@timezone)
|
61
|
+
end
|
62
|
+
|
57
63
|
if !@tag && !@tag_key
|
58
64
|
raise ConfigError, "'tag' or 'tag_key' option is required on exec input"
|
59
65
|
end
|
@@ -58,7 +58,7 @@ module Fluent
|
|
58
58
|
|
59
59
|
if @time_key
|
60
60
|
if @time_format
|
61
|
-
tf = TimeFormatter.new(@time_format, @localtime)
|
61
|
+
tf = TimeFormatter.new(@time_format, @localtime, @timezone)
|
62
62
|
@time_format_proc = tf.method(:format)
|
63
63
|
else
|
64
64
|
@time_format_proc = Proc.new { |time| time.to_s }
|
@@ -24,6 +24,7 @@ module Fluent
|
|
24
24
|
|
25
25
|
def initialize
|
26
26
|
super
|
27
|
+
require 'fluent/timezone'
|
27
28
|
end
|
28
29
|
|
29
30
|
config_param :command, :string
|
@@ -61,6 +62,7 @@ module Fluent
|
|
61
62
|
config_param :time_format, :string, :default => nil
|
62
63
|
|
63
64
|
config_param :localtime, :bool, :default => true
|
65
|
+
config_param :timezone, :string, :default => nil
|
64
66
|
config_param :num_children, :integer, :default => 1
|
65
67
|
|
66
68
|
# nil, 'none' or 0: no respawn, 'inf' or -1: infinite times, positive integer: try to respawn specified times only
|
@@ -98,13 +100,18 @@ module Fluent
|
|
98
100
|
@localtime = false
|
99
101
|
end
|
100
102
|
|
103
|
+
if conf['timezone']
|
104
|
+
@timezone = conf['timezone']
|
105
|
+
Fluent::Timezone.validate!(@timezone)
|
106
|
+
end
|
107
|
+
|
101
108
|
if !@tag && !@out_tag_key
|
102
109
|
raise ConfigError, "'tag' or 'out_tag_key' option is required on exec_filter output"
|
103
110
|
end
|
104
111
|
|
105
112
|
if @in_time_key
|
106
113
|
if f = @in_time_format
|
107
|
-
tf = TimeFormatter.new(f, @localtime)
|
114
|
+
tf = TimeFormatter.new(f, @localtime, @timezone)
|
108
115
|
@time_format_proc = tf.method(:format)
|
109
116
|
else
|
110
117
|
@time_format_proc = Proc.new {|time| time.to_s }
|
@@ -87,7 +87,7 @@ module Fluent
|
|
87
87
|
node_conf = NodeConfig.new(name, host, port, weight, standby, failure,
|
88
88
|
@phi_threshold, recover_sample_size, @expire_dns_cache, @phi_failure_detector)
|
89
89
|
@nodes << Node.new(log, node_conf)
|
90
|
-
log.info "adding forwarding server '#{name}'", :host=>host, :port=>port, :weight=>weight
|
90
|
+
log.info "adding forwarding server '#{name}'", :host=>host, :port=>port, :weight=>weight, :plugin_id=>plugin_id
|
91
91
|
}
|
92
92
|
end
|
93
93
|
|
@@ -0,0 +1,131 @@
|
|
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 'tzinfo'
|
18
|
+
|
19
|
+
module Fluent
|
20
|
+
class Timezone
|
21
|
+
# [+-]HH:MM, [+-]HHMM, [+-]HH
|
22
|
+
NUMERIC_PATTERN = %r{\A[+-]\d\d(:?\d\d)?\z}
|
23
|
+
|
24
|
+
# Region/Zone, Region/Zone/Zone
|
25
|
+
NAME_PATTERN = %r{\A[^/]+/[^/]+(/[^/]+)?\z}
|
26
|
+
|
27
|
+
# Validate the format of the specified timezone.
|
28
|
+
#
|
29
|
+
# Valid formats are as follows. Note that timezone abbreviations
|
30
|
+
# such as PST and JST are not supported intentionally.
|
31
|
+
#
|
32
|
+
# 1. [+-]HH:MM (e.g. "+09:00")
|
33
|
+
# 2. [+-]HHMM (e.g. "+0900")
|
34
|
+
# 3. [+-]HH (e.g. "+09")
|
35
|
+
# 4. Region/Zone (e.g. "Asia/Tokyo")
|
36
|
+
# 5. Region/Zone/Zone (e.g. "America/Argentina/Buenos_Aires")
|
37
|
+
#
|
38
|
+
# In the 4th and 5th cases, it is checked whether the specified
|
39
|
+
# timezone exists in the timezone database.
|
40
|
+
#
|
41
|
+
# When the given timezone is valid, true is returned. Otherwise,
|
42
|
+
# false is returned. When nil is given, false is returned.
|
43
|
+
def self.validate(timezone)
|
44
|
+
# If the specified timezone is nil.
|
45
|
+
if timezone.nil?
|
46
|
+
# Invalid.
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
# [+-]HH:MM, [+-]HHMM, [+-]HH
|
51
|
+
if NUMERIC_PATTERN === timezone
|
52
|
+
# Valid. It can be parsed by Time.zone_offset method.
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
|
56
|
+
# Region/Zone, Region/Zone/Zone
|
57
|
+
if NAME_PATTERN === timezone
|
58
|
+
begin
|
59
|
+
# Get a Timezone instance for the specified timezone.
|
60
|
+
TZInfo::Timezone.get(timezone)
|
61
|
+
rescue
|
62
|
+
# Invalid. The string does not exist in the timezone database.
|
63
|
+
return false
|
64
|
+
else
|
65
|
+
# Valid. The string was found in the timezone database.
|
66
|
+
return true
|
67
|
+
end
|
68
|
+
else
|
69
|
+
# Invalid. Timezone abbreviations are not supported.
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Validate the format of the specified timezone.
|
75
|
+
#
|
76
|
+
# The implementation of this method calls validate(timezone) method
|
77
|
+
# to check whether the given timezone is valid. When invalid, this
|
78
|
+
# method raises a ConfigError.
|
79
|
+
def self.validate!(timezone)
|
80
|
+
unless validate(timezone)
|
81
|
+
raise ConfigError, "Unsupported timezone '#{timezone}'"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Create a formatter for a timezone and optionally a format.
|
86
|
+
#
|
87
|
+
# An Proc object is returned. If the given timezone is invalid,
|
88
|
+
# nil is returned.
|
89
|
+
def self.formatter(timezone, format = nil)
|
90
|
+
if timezone.nil?
|
91
|
+
return nil
|
92
|
+
end
|
93
|
+
|
94
|
+
# [+-]HH:MM, [+-]HHMM, [+-]HH
|
95
|
+
if NUMERIC_PATTERN === timezone
|
96
|
+
offset = Time.zone_offset(timezone)
|
97
|
+
|
98
|
+
if format
|
99
|
+
return Proc.new {|time|
|
100
|
+
Time.at(time).localtime(offset).strftime(format)
|
101
|
+
}
|
102
|
+
else
|
103
|
+
return Proc.new {|time|
|
104
|
+
Time.at(time).localtime(offset).iso8601
|
105
|
+
}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Region/Zone, Region/Zone/Zone
|
110
|
+
if NAME_PATTERN === timezone
|
111
|
+
begin
|
112
|
+
tz = TZInfo::Timezone.get(timezone)
|
113
|
+
rescue
|
114
|
+
return nil
|
115
|
+
end
|
116
|
+
|
117
|
+
if format
|
118
|
+
return Proc.new {|time|
|
119
|
+
Time.at(time).localtime(tz.period_for_utc(time).utc_total_offset).strftime(format)
|
120
|
+
}
|
121
|
+
else
|
122
|
+
return Proc.new {|time|
|
123
|
+
Time.at(time).localtime(tz.period_for_utc(time).utc_total_offset).iso8601
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
return nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/fluent/version.rb
CHANGED
data/test/config/test_section.rb
CHANGED
@@ -45,6 +45,16 @@ module Fluent::Config
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
sub_test_case '#object_id' do
|
49
|
+
test 'returns its object id' do
|
50
|
+
s1 = Fluent::Config::Section.new({})
|
51
|
+
assert s1.object_id
|
52
|
+
s2 = Fluent::Config::Section.new({})
|
53
|
+
assert s2.object_id
|
54
|
+
assert_not_equal s1.object_id, s2.object_id
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
48
58
|
sub_test_case '#to_h' do
|
49
59
|
test 'returns internal hash itself' do
|
50
60
|
hash = {
|
@@ -63,6 +63,41 @@ class FileOutputTest < Test::Unit::TestCase
|
|
63
63
|
d.run
|
64
64
|
end
|
65
65
|
|
66
|
+
def test_timezone_1
|
67
|
+
d = create_driver %[
|
68
|
+
path #{TMP_DIR}/out_file_test
|
69
|
+
timezone Asia/Taipei
|
70
|
+
]
|
71
|
+
|
72
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
73
|
+
|
74
|
+
d.emit({"a"=>1}, time)
|
75
|
+
d.expect_format %[2011-01-02T21:14:15+08:00\ttest\t{"a":1}\n]
|
76
|
+
d.run
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_timezone_2
|
80
|
+
d = create_driver %[
|
81
|
+
path #{TMP_DIR}/out_file_test
|
82
|
+
timezone -03:30
|
83
|
+
]
|
84
|
+
|
85
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
86
|
+
|
87
|
+
d.emit({"a"=>1}, time)
|
88
|
+
d.expect_format %[2011-01-02T09:44:15-03:30\ttest\t{"a":1}\n]
|
89
|
+
d.run
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_timezone_invalid
|
93
|
+
assert_raise(Fluent::ConfigError) do
|
94
|
+
create_driver %[
|
95
|
+
path #{TMP_DIR}/out_file_test
|
96
|
+
timezone Invalid/Invalid
|
97
|
+
]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
66
101
|
def check_gzipped_result(path, expect)
|
67
102
|
# Zlib::GzipReader has a bug of concatenated file: https://bugs.ruby-lang.org/issues/9790
|
68
103
|
# Following code from https://www.ruby-forum.com/topic/971591#979520
|
data/test/test_formatter.rb
CHANGED
@@ -29,6 +29,13 @@ module FormatterTest
|
|
29
29
|
{'message' => 'awesome'}
|
30
30
|
end
|
31
31
|
|
32
|
+
def with_timezone(tz)
|
33
|
+
oldtz, ENV['TZ'] = ENV['TZ'], tz
|
34
|
+
yield
|
35
|
+
ensure
|
36
|
+
ENV['TZ'] = oldtz
|
37
|
+
end
|
38
|
+
|
32
39
|
class OutFileFormatterTest < ::Test::Unit::TestCase
|
33
40
|
include FormatterTest
|
34
41
|
|
@@ -216,4 +223,220 @@ module FormatterTest
|
|
216
223
|
end
|
217
224
|
end
|
218
225
|
end
|
226
|
+
|
227
|
+
class TimeFormatterTest < ::Test::Unit::TestCase
|
228
|
+
include FormatterTest
|
229
|
+
|
230
|
+
def setup
|
231
|
+
@time = Time.new(2014, 9, 27, 0, 0, 0, 0).to_i
|
232
|
+
@fmt = "%Y%m%d %H%M%z" # YYYYMMDD HHMM[+-]HHMM
|
233
|
+
end
|
234
|
+
|
235
|
+
def format(format, localtime, timezone)
|
236
|
+
formatter = Fluent::TimeFormatter.new(format, localtime, timezone)
|
237
|
+
formatter.format(@time)
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_default_utc_nil
|
241
|
+
assert_equal("2014-09-27T00:00:00Z", format(nil, false, nil))
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_default_utc_pHH_MM
|
245
|
+
assert_equal("2014-09-27T01:30:00+01:30", format(nil, false, "+01:30"))
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_default_utc_nHH_MM
|
249
|
+
assert_equal("2014-09-26T22:30:00-01:30", format(nil, false, "-01:30"))
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_default_utc_pHHMM
|
253
|
+
assert_equal("2014-09-27T02:30:00+02:30", format(nil, false, "+0230"))
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_default_utc_nHHMM
|
257
|
+
assert_equal("2014-09-26T21:30:00-02:30", format(nil, false, "-0230"))
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_default_utc_pHH
|
261
|
+
assert_equal("2014-09-27T03:00:00+03:00", format(nil, false, "+03"))
|
262
|
+
end
|
263
|
+
|
264
|
+
def test_default_utc_nHH
|
265
|
+
assert_equal("2014-09-26T21:00:00-03:00", format(nil, false, "-03"))
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_default_utc_timezone_1
|
269
|
+
# Asia/Tokyo (+09:00) does not have daylight saving time.
|
270
|
+
assert_equal("2014-09-27T09:00:00+09:00", format(nil, false, "Asia/Tokyo"))
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_default_utc_timezone_2
|
274
|
+
# Pacific/Honolulu (-10:00) does not have daylight saving time.
|
275
|
+
assert_equal("2014-09-26T14:00:00-10:00", format(nil, false, "Pacific/Honolulu"))
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_default_utc_timezone_3
|
279
|
+
# America/Argentina/Buenos_Aires (-03:00) does not have daylight saving time.
|
280
|
+
assert_equal("2014-09-26T21:00:00-03:00", format(nil, false, "America/Argentina/Buenos_Aires"))
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_default_utc_timezone_4
|
284
|
+
# Europe/Paris has daylight saving time. Its UTC offset is +01:00 and its
|
285
|
+
# UTC offset in DST is +02:00. In September, Europe/Paris is in DST.
|
286
|
+
assert_equal("2014-09-27T02:00:00+02:00", format(nil, false, "Europe/Paris"))
|
287
|
+
end
|
288
|
+
|
289
|
+
def test_default_utc_timezone_5
|
290
|
+
# Europe/Paris has daylight saving time. Its UTC offset is +01:00 and its
|
291
|
+
# UTC offset in DST is +02:00. In January, Europe/Paris is not in DST.
|
292
|
+
@time = Time.new(2014, 1, 24, 0, 0, 0, 0).to_i
|
293
|
+
assert_equal("2014-01-24T01:00:00+01:00", format(nil, false, "Europe/Paris"))
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_default_utc_invalid
|
297
|
+
assert_equal("2014-09-27T00:00:00Z", format(nil, false, "Invalid"))
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_default_localtime_nil_1
|
301
|
+
with_timezone("UTC-04") do
|
302
|
+
assert_equal("2014-09-27T04:00:00+04:00", format(nil, true, nil))
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_default_localtime_nil_2
|
307
|
+
with_timezone("UTC+05") do
|
308
|
+
assert_equal("2014-09-26T19:00:00-05:00", format(nil, true, nil))
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_default_localtime_timezone
|
313
|
+
# 'timezone' takes precedence over 'localtime'.
|
314
|
+
with_timezone("UTC-06") do
|
315
|
+
assert_equal("2014-09-27T07:00:00+07:00", format(nil, true, "+07"))
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def test_specific_utc_nil
|
320
|
+
assert_equal("20140927 0000+0000", format(@fmt, false, nil))
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_specific_utc_pHH_MM
|
324
|
+
assert_equal("20140927 0830+0830", format(@fmt, false, "+08:30"))
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_specific_utc_nHH_MM
|
328
|
+
assert_equal("20140926 1430-0930", format(@fmt, false, "-09:30"))
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_specific_utc_pHHMM
|
332
|
+
assert_equal("20140927 1030+1030", format(@fmt, false, "+1030"))
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_specific_utc_nHHMM
|
336
|
+
assert_equal("20140926 1230-1130", format(@fmt, false, "-1130"))
|
337
|
+
end
|
338
|
+
|
339
|
+
def test_specific_utc_pHH
|
340
|
+
assert_equal("20140927 1200+1200", format(@fmt, false, "+12"))
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_specific_utc_nHH
|
344
|
+
assert_equal("20140926 1100-1300", format(@fmt, false, "-13"))
|
345
|
+
end
|
346
|
+
|
347
|
+
def test_specific_utc_timezone_1
|
348
|
+
# Europe/Moscow (+04:00) does not have daylight saving time.
|
349
|
+
assert_equal("20140927 0400+0400", format(@fmt, false, "Europe/Moscow"))
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_specific_utc_timezone_2
|
353
|
+
# Pacific/Galapagos (-06:00) does not have daylight saving time.
|
354
|
+
assert_equal("20140926 1800-0600", format(@fmt, false, "Pacific/Galapagos"))
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_specific_utc_timezone_3
|
358
|
+
# America/Argentina/Buenos_Aires (-03:00) does not have daylight saving time.
|
359
|
+
assert_equal("20140926 2100-0300", format(@fmt, false, "America/Argentina/Buenos_Aires"))
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_specific_utc_timezone_4
|
363
|
+
# America/Los_Angeles has daylight saving time. Its UTC offset is -08:00 and its
|
364
|
+
# UTC offset in DST is -07:00. In September, America/Los_Angeles is in DST.
|
365
|
+
assert_equal("20140926 1700-0700", format(@fmt, false, "America/Los_Angeles"))
|
366
|
+
end
|
367
|
+
|
368
|
+
def test_specific_utc_timezone_5
|
369
|
+
# America/Los_Angeles has daylight saving time. Its UTC offset is -08:00 and its
|
370
|
+
# UTC offset in DST is -07:00. In January, America/Los_Angeles is not in DST.
|
371
|
+
@time = Time.new(2014, 1, 24, 0, 0, 0, 0).to_i
|
372
|
+
assert_equal("20140123 1600-0800", format(@fmt, false, "America/Los_Angeles"))
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_specific_utc_invalid
|
376
|
+
assert_equal("20140927 0000+0000", format(@fmt, false, "Invalid"))
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_specific_localtime_nil_1
|
380
|
+
with_timezone("UTC-07") do
|
381
|
+
assert_equal("20140927 0700+0700", format(@fmt, true, nil))
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def test_specific_localtime_nil_2
|
386
|
+
with_timezone("UTC+08") do
|
387
|
+
assert_equal("20140926 1600-0800", format(@fmt, true, nil))
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_specific_localtime_timezone
|
392
|
+
# 'timezone' takes precedence over 'localtime'.
|
393
|
+
with_timezone("UTC-09") do
|
394
|
+
assert_equal("20140926 1400-1000", format(@fmt, true, "-10"))
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
class TimeConfigTest < ::Test::Unit::TestCase
|
400
|
+
include FormatterTest
|
401
|
+
|
402
|
+
def setup
|
403
|
+
@formatter = TextFormatter::LabeledTSVFormatter.new
|
404
|
+
@time = Time.new(2014, 9, 27, 0, 0, 0, 0).to_i
|
405
|
+
end
|
406
|
+
|
407
|
+
def format(conf)
|
408
|
+
@formatter.configure({'include_time_key' => true}.merge(conf))
|
409
|
+
formatted = @formatter.format("tag", @time, {})
|
410
|
+
# Drop the leading "time:" and the trailing "\n".
|
411
|
+
formatted[5..-2]
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_none
|
415
|
+
with_timezone("UTC-01") do
|
416
|
+
# 'localtime' is true by default.
|
417
|
+
assert_equal("2014-09-27T01:00:00+01:00", format({}))
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
def test_utc
|
422
|
+
with_timezone("UTC-01") do
|
423
|
+
# 'utc' takes precedence over 'localtime'.
|
424
|
+
assert_equal("2014-09-27T00:00:00Z", format("utc" => true))
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_timezone
|
429
|
+
with_timezone("UTC-01") do
|
430
|
+
# 'timezone' takes precedence over 'localtime'.
|
431
|
+
assert_equal("2014-09-27T02:00:00+02:00", format("timezone" => "+02"))
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_utc_timezone
|
436
|
+
with_timezone("UTC-01") do
|
437
|
+
# 'timezone' takes precedence over 'utc'.
|
438
|
+
assert_equal("2014-09-27T09:00:00+09:00", format("utc" => true, "timezone" => "Asia/Tokyo"))
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
219
442
|
end
|
data/test/test_mixin.rb
CHANGED
@@ -27,15 +27,17 @@ module MixinTest
|
|
27
27
|
end
|
28
28
|
|
29
29
|
@@num = 0
|
30
|
+
|
30
31
|
def create_register_output_name
|
31
|
-
|
32
|
+
@@num += 1
|
33
|
+
"mixin_text_#{@@num}"
|
32
34
|
end
|
33
35
|
|
34
36
|
def format_check(hash, tagname = 'test')
|
35
37
|
mock(Checker).format_check(tagname, @time.to_i, hash)
|
36
38
|
end
|
37
39
|
|
38
|
-
def create_driver(include_klass, conf = '', tag = "test")
|
40
|
+
def create_driver(include_klass, conf = '', tag = "test", &block)
|
39
41
|
register_output_name = create_register_output_name
|
40
42
|
include_klasses = [include_klass].flatten
|
41
43
|
|
@@ -51,6 +53,11 @@ module MixinTest
|
|
51
53
|
def write(chunk); end
|
52
54
|
}
|
53
55
|
|
56
|
+
if block
|
57
|
+
Utils.const_set("MixinTestClass#{@@num}", klass)
|
58
|
+
klass.module_eval(&block)
|
59
|
+
end
|
60
|
+
|
54
61
|
Fluent::Test::BufferedOutputTestDriver.new(klass, tag) {
|
55
62
|
}.configure("type #{register_output_name}" + conf)
|
56
63
|
end
|
@@ -110,6 +117,19 @@ module MixinTest
|
|
110
117
|
d.emit({'a' => 1})
|
111
118
|
d.run
|
112
119
|
end
|
120
|
+
|
121
|
+
sub_test_case "mixin" do
|
122
|
+
data(
|
123
|
+
'true' => true,
|
124
|
+
'false' => false)
|
125
|
+
test 'include_tag_key' do |param|
|
126
|
+
d = create_driver(Fluent::SetTagKeyMixin) {
|
127
|
+
config_set_default :include_tag_key, param
|
128
|
+
}
|
129
|
+
|
130
|
+
assert_equal(param, d.instance.include_tag_key)
|
131
|
+
end
|
132
|
+
end
|
113
133
|
end
|
114
134
|
|
115
135
|
class SetTimeKeyMixinText < Test::Unit::TestCase
|
@@ -155,6 +175,58 @@ module MixinTest
|
|
155
175
|
d.emit({'a' => 1})
|
156
176
|
d.run
|
157
177
|
end
|
178
|
+
|
179
|
+
def test_timezone_1
|
180
|
+
format_check({
|
181
|
+
'time' => "2010-05-03T17:02:01-10:00",
|
182
|
+
'a' => 1
|
183
|
+
})
|
184
|
+
|
185
|
+
d = create_driver(Fluent::SetTimeKeyMixin, %[
|
186
|
+
include_time_key true
|
187
|
+
timezone Pacific/Honolulu
|
188
|
+
])
|
189
|
+
|
190
|
+
d.emit({'a' => 1})
|
191
|
+
d.run
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_timezone_2
|
195
|
+
format_check({
|
196
|
+
'time' => "2010-05-04T08:32:01+05:30",
|
197
|
+
'a' => 1
|
198
|
+
})
|
199
|
+
|
200
|
+
d = create_driver(Fluent::SetTimeKeyMixin, %[
|
201
|
+
include_time_key true
|
202
|
+
timezone +05:30
|
203
|
+
])
|
204
|
+
|
205
|
+
d.emit({'a' => 1})
|
206
|
+
d.run
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_timezone_invalid
|
210
|
+
assert_raise(Fluent::ConfigError) do
|
211
|
+
d = create_driver(Fluent::SetTimeKeyMixin, %[
|
212
|
+
include_time_key true
|
213
|
+
timezone Invalid/Invalid
|
214
|
+
])
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
sub_test_case "mixin" do
|
219
|
+
data(
|
220
|
+
'true' => true,
|
221
|
+
'false' => false)
|
222
|
+
test 'include_time_key' do |param|
|
223
|
+
d = create_driver(Fluent::SetTimeKeyMixin) {
|
224
|
+
config_set_default :include_time_key, param
|
225
|
+
}
|
226
|
+
|
227
|
+
assert_equal(param, d.instance.include_time_key)
|
228
|
+
end
|
229
|
+
end
|
158
230
|
end
|
159
231
|
|
160
232
|
class HandleTagMixinTest < Test::Unit::TestCase
|
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: 0.10.
|
4
|
+
version: 0.10.56
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -142,6 +142,34 @@ dependencies:
|
|
142
142
|
- - "~>"
|
143
143
|
- !ruby/object:Gem::Version
|
144
144
|
version: 0.2.2
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: tzinfo
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: 1.0.0
|
152
|
+
type: :runtime
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: 1.0.0
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: tzinfo-data
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 1.0.0
|
166
|
+
type: :runtime
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: 1.0.0
|
145
173
|
- !ruby/object:Gem::Dependency
|
146
174
|
name: rake
|
147
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -333,6 +361,7 @@ files:
|
|
333
361
|
- lib/fluent/test/base.rb
|
334
362
|
- lib/fluent/test/input_test.rb
|
335
363
|
- lib/fluent/test/output_test.rb
|
364
|
+
- lib/fluent/timezone.rb
|
336
365
|
- lib/fluent/version.rb
|
337
366
|
- spec/spec_helper.rb
|
338
367
|
- test/config/assertions.rb
|