fluentd 0.10.57 → 0.10.58
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/.travis.yml +1 -0
- data/ChangeLog +18 -0
- data/fluent.conf +26 -16
- data/fluentd.gemspec +1 -1
- data/lib/fluent/config.rb +1 -8
- data/lib/fluent/config/basic_parser.rb +1 -0
- data/lib/fluent/config/configure_proxy.rb +7 -7
- data/lib/fluent/config/types.rb +1 -0
- data/lib/fluent/config/v1_parser.rb +2 -1
- data/lib/fluent/engine.rb +0 -26
- data/lib/fluent/env.rb +1 -0
- data/lib/fluent/formatter.rb +96 -26
- data/lib/fluent/input.rb +4 -0
- data/lib/fluent/output.rb +7 -2
- data/lib/fluent/parser.rb +82 -88
- data/lib/fluent/plugin.rb +18 -0
- data/lib/fluent/plugin/buf_file.rb +3 -3
- data/lib/fluent/plugin/in_dummy.rb +103 -0
- data/lib/fluent/plugin/in_exec.rb +1 -1
- data/lib/fluent/plugin/in_forward.rb +3 -3
- data/lib/fluent/plugin/in_gc_stat.rb +1 -1
- data/lib/fluent/plugin/in_http.rb +49 -17
- data/lib/fluent/plugin/in_monitor_agent.rb +41 -10
- data/lib/fluent/plugin/in_object_space.rb +1 -1
- data/lib/fluent/plugin/in_status.rb +1 -1
- data/lib/fluent/plugin/in_stream.rb +3 -3
- data/lib/fluent/plugin/in_syslog.rb +5 -5
- data/lib/fluent/plugin/in_tail.rb +6 -6
- data/lib/fluent/plugin/out_copy.rb +1 -1
- data/lib/fluent/plugin/out_exec_filter.rb +1 -1
- data/lib/fluent/plugin/out_file.rb +3 -3
- data/lib/fluent/plugin/out_roundrobin.rb +1 -1
- data/lib/fluent/plugin/socket_util.rb +2 -2
- data/lib/fluent/supervisor.rb +21 -24
- data/lib/fluent/test/base.rb +14 -0
- data/lib/fluent/test/output_test.rb +7 -1
- data/lib/fluent/version.rb +1 -1
- data/test/config/test_config_parser.rb +6 -2
- data/test/config/test_configurable.rb +1 -1
- data/test/config/test_configure_proxy.rb +1 -1
- data/test/config/test_dsl.rb +1 -1
- data/test/config/test_literal_parser.rb +2 -2
- data/test/config/test_section.rb +1 -1
- data/test/config/test_system_config.rb +65 -15
- data/test/config/test_types.rb +63 -0
- data/test/plugin/test_in_dummy.rb +95 -0
- data/test/plugin/test_in_exec.rb +1 -1
- data/test/plugin/test_in_forward.rb +1 -2
- data/test/plugin/test_in_gc_stat.rb +1 -1
- data/test/plugin/test_in_http.rb +77 -2
- data/test/plugin/test_in_object_space.rb +1 -1
- data/test/plugin/test_in_status.rb +1 -1
- data/test/plugin/test_in_stream.rb +1 -2
- data/test/plugin/test_in_syslog.rb +1 -2
- data/test/plugin/test_in_tail.rb +1 -1
- data/test/plugin/test_in_tcp.rb +1 -2
- data/test/plugin/test_in_udp.rb +1 -2
- data/test/plugin/test_out_copy.rb +12 -1
- data/test/plugin/test_out_exec.rb +1 -1
- data/test/plugin/test_out_exec_filter.rb +1 -1
- data/test/plugin/test_out_file.rb +61 -7
- data/test/plugin/test_out_forward.rb +1 -2
- data/test/plugin/test_out_roundrobin.rb +12 -1
- data/test/plugin/test_out_stdout.rb +1 -1
- data/test/plugin/test_out_stream.rb +1 -2
- data/test/scripts/fluent/plugin/formatter_known.rb +4 -1
- data/{lib → test/scripts}/fluent/plugin/out_test.rb +0 -0
- data/test/scripts/fluent/plugin/parser_known.rb +2 -1
- data/test/test_config.rb +1 -1
- data/test/test_configdsl.rb +1 -2
- data/test/test_formatter.rb +172 -3
- data/test/test_input.rb +21 -0
- data/test/test_match.rb +1 -2
- data/test/test_mixin.rb +1 -1
- data/test/test_output.rb +25 -1
- data/test/test_parser.rb +124 -78
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a62e7c7181c7f247c4a76b42638d0a6b4195d8a
|
4
|
+
data.tar.gz: 12ccff6793701f59c0b67c17d66804a3d25ac818
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81a1d182345423ecbb41a94351ccb6666f449126128718187345b9e62c187a3f8ed50fa56cfdee19cd5817ed37620471d10d871ca339cd345ef2111e1da76e29
|
7
|
+
data.tar.gz: 7a61d7bd4b80b28373fb1ed7824add416a085d77a7ace5a229bb34ebb6965fadf7fbcbd5ff4d61ee89ce6166b05a17011b619d5e7d9e9e42ddade2d6828ab8f0
|
data/.travis.yml
CHANGED
data/ChangeLog
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
Release 0.10.58 - 2014/12/14
|
2
|
+
|
3
|
+
* parser/formatter: Add base class and Plugin.new_xxx/Plugin.register_xxx APIs
|
4
|
+
* parser: Fix blank column handling of TSVParser
|
5
|
+
* formatter: Add new CSV formatter
|
6
|
+
* formatter: Add msgpack format to built-in Formatter to dump records
|
7
|
+
* input: Add in_dummy plugin
|
8
|
+
* in_http: Add respond_with_empty_img parameter to return empty gif image
|
9
|
+
* in_http: Add cors_allow_origins parameter to support CORS request
|
10
|
+
* config: Add self.name to configure_proxy error message
|
11
|
+
* config: Fix system config using double memory
|
12
|
+
* config: Fix v1 config to support multiple tag match
|
13
|
+
* config: Fix Config.bool_value regression for nil value
|
14
|
+
* buffer: Prevent an exception with large num_retries
|
15
|
+
* out_file: Don't create world writable directory in daemon mode
|
16
|
+
* add router.emit and router= for compatibility with v0.12
|
17
|
+
* Use router instead of Engine.emit
|
18
|
+
|
1
19
|
Release 0.10.57 - 2014/11/12
|
2
20
|
|
3
21
|
* buffer: Make total_queued_chunk_size thread-safe to avoid race condition with in_monitor_agent
|
data/fluent.conf
CHANGED
@@ -1,26 +1,31 @@
|
|
1
|
+
# In v1 configuration, type and id are @ prefix parameters.
|
2
|
+
# @type and @id are recommended. type and id are still available for backward compatibility
|
1
3
|
|
2
4
|
## built-in TCP input
|
3
5
|
## $ echo <json> | fluent-cat <tag>
|
4
6
|
<source>
|
5
|
-
type forward
|
7
|
+
@type forward
|
8
|
+
@id forward_input
|
6
9
|
</source>
|
7
10
|
|
8
11
|
## built-in UNIX socket input
|
9
12
|
#<source>
|
10
|
-
# type unix
|
13
|
+
# @type unix
|
11
14
|
#</source>
|
12
15
|
|
13
16
|
# HTTP input
|
14
17
|
# http://localhost:8888/<tag>?json=<json>
|
15
18
|
<source>
|
16
|
-
type http
|
19
|
+
@type http
|
20
|
+
@id http_input
|
21
|
+
|
17
22
|
port 8888
|
18
23
|
</source>
|
19
24
|
|
20
25
|
## File input
|
21
26
|
## read apache logs with tag=apache.access
|
22
27
|
#<source>
|
23
|
-
# type tail
|
28
|
+
# @type tail
|
24
29
|
# format apache
|
25
30
|
# path /var/log/httpd-access.log
|
26
31
|
# tag apache.access
|
@@ -31,32 +36,38 @@
|
|
31
36
|
# http://localhost:24220/api/plugins?type=TYPE
|
32
37
|
# http://localhost:24220/api/plugins?tag=MYTAG
|
33
38
|
<source>
|
34
|
-
type monitor_agent
|
39
|
+
@type monitor_agent
|
40
|
+
@id monitor_agent_input
|
41
|
+
|
35
42
|
port 24220
|
36
43
|
</source>
|
37
44
|
|
38
45
|
# Listen DRb for debug
|
39
46
|
<source>
|
40
|
-
type debug_agent
|
47
|
+
@type debug_agent
|
48
|
+
@id debug_agent_input
|
49
|
+
|
41
50
|
bind 127.0.0.1
|
42
51
|
port 24230
|
43
52
|
</source>
|
44
53
|
|
45
|
-
|
46
54
|
## match tag=apache.access and write to file
|
47
55
|
#<match apache.access>
|
48
|
-
# type file
|
56
|
+
# @type file
|
49
57
|
# path /var/log/fluent/access
|
50
58
|
#</match>
|
51
59
|
|
52
60
|
## match tag=debug.** and dump to console
|
53
61
|
<match debug.**>
|
54
|
-
type stdout
|
62
|
+
@type stdout
|
63
|
+
@id stdout_output
|
55
64
|
</match>
|
56
65
|
|
57
66
|
# match tag=system.** and forward to another fluent server
|
58
67
|
<match system.**>
|
59
|
-
type forward
|
68
|
+
@type forward
|
69
|
+
@id forward_output
|
70
|
+
|
60
71
|
<server>
|
61
72
|
host 192.168.0.11
|
62
73
|
</server>
|
@@ -69,9 +80,9 @@
|
|
69
80
|
|
70
81
|
## match tag=myapp.** and forward and write to file
|
71
82
|
#<match myapp.**>
|
72
|
-
# type copy
|
83
|
+
# @type copy
|
73
84
|
# <store>
|
74
|
-
# type forward
|
85
|
+
# @type forward
|
75
86
|
# buffer_type file
|
76
87
|
# buffer_path /var/log/fluent/myapp-forward
|
77
88
|
# retry_limit 50
|
@@ -81,20 +92,19 @@
|
|
81
92
|
# </server>
|
82
93
|
# </store>
|
83
94
|
# <store>
|
84
|
-
# type file
|
95
|
+
# @type file
|
85
96
|
# path /var/log/fluent/myapp
|
86
97
|
# </store>
|
87
98
|
#</match>
|
88
99
|
|
89
100
|
## match fluent's internal events
|
90
101
|
#<match fluent.**>
|
91
|
-
# type null
|
102
|
+
# @type null
|
92
103
|
#</match>
|
93
104
|
|
94
105
|
## match not matched logs and write to file
|
95
106
|
#<match **>
|
96
|
-
# type file
|
107
|
+
# @type file
|
97
108
|
# path /var/log/fluent/else
|
98
109
|
# compress gz
|
99
110
|
#</match>
|
100
|
-
|
data/fluentd.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.require_paths = ["lib"]
|
17
17
|
gem.has_rdoc = false
|
18
18
|
|
19
|
-
gem.required_ruby_version = '>= 1.9.
|
19
|
+
gem.required_ruby_version = '>= 1.9.3'
|
20
20
|
|
21
21
|
gem.add_runtime_dependency("msgpack", [">= 0.4.4", "!= 0.5.0", "!= 0.5.1", "!= 0.5.2", "!= 0.5.3", "< 0.6.0"])
|
22
22
|
gem.add_runtime_dependency("json", [">= 1.4.3"])
|
data/lib/fluent/config.rb
CHANGED
@@ -44,17 +44,10 @@ module Fluent
|
|
44
44
|
|
45
45
|
module PluginId
|
46
46
|
def configure(conf)
|
47
|
-
@id = conf['id']
|
47
|
+
@id = conf['@id'] || conf['id']
|
48
48
|
super
|
49
49
|
end
|
50
50
|
|
51
|
-
def require_id
|
52
|
-
unless @id
|
53
|
-
raise ConfigError, "'id' parameter is required"
|
54
|
-
end
|
55
|
-
@id
|
56
|
-
end
|
57
|
-
|
58
51
|
def plugin_id
|
59
52
|
@id ? @id : "object:#{object_id.to_s(16)}"
|
60
53
|
end
|
@@ -68,13 +68,13 @@ module Fluent
|
|
68
68
|
elsif a.is_a?(Hash)
|
69
69
|
opts.merge!(a)
|
70
70
|
else
|
71
|
-
raise ArgumentError, "wrong number of arguments (#{1 + args.length} for #{block ? 2 : 3})"
|
71
|
+
raise ArgumentError, "#{self.name}: wrong number of arguments (#{1 + args.length} for #{block ? 2 : 3})"
|
72
72
|
end
|
73
73
|
}
|
74
74
|
|
75
75
|
type = opts[:type]
|
76
76
|
if block && type
|
77
|
-
raise ArgumentError, "both of block and type cannot be specified"
|
77
|
+
raise ArgumentError, "#{self.name}: both of block and type cannot be specified"
|
78
78
|
end
|
79
79
|
|
80
80
|
begin
|
@@ -82,7 +82,7 @@ module Fluent
|
|
82
82
|
block ||= Configurable.lookup_type(type)
|
83
83
|
rescue ConfigError
|
84
84
|
# override error message
|
85
|
-
raise ArgumentError, "unknown config_argument type `#{type}'"
|
85
|
+
raise ArgumentError, "#{self.name}: unknown config_argument type `#{type}'"
|
86
86
|
end
|
87
87
|
|
88
88
|
if opts.has_key?(:default)
|
@@ -94,7 +94,7 @@ module Fluent
|
|
94
94
|
|
95
95
|
def config_argument(name, *args, &block)
|
96
96
|
if @argument
|
97
|
-
raise ArgumentError, "config_argument called twice"
|
97
|
+
raise ArgumentError, "#{self.name}: config_argument called twice"
|
98
98
|
end
|
99
99
|
name, block, opts = parameter_configuration(name, *args, &block)
|
100
100
|
|
@@ -114,7 +114,7 @@ module Fluent
|
|
114
114
|
name = name.to_sym
|
115
115
|
|
116
116
|
if @defaults.has_key?(name)
|
117
|
-
raise ArgumentError, "default value specified twice for #{name}"
|
117
|
+
raise ArgumentError, "#{self.name}: default value specified twice for #{name}"
|
118
118
|
end
|
119
119
|
|
120
120
|
@defaults[name] = defval
|
@@ -123,13 +123,13 @@ module Fluent
|
|
123
123
|
|
124
124
|
def config_section(name, *args, &block)
|
125
125
|
unless block_given?
|
126
|
-
raise ArgumentError, "config_section requires block parameter"
|
126
|
+
raise ArgumentError, "#{self.name}: config_section requires block parameter"
|
127
127
|
end
|
128
128
|
name = name.to_sym
|
129
129
|
|
130
130
|
opts = {}
|
131
131
|
unless args.empty? || args.size == 1 && args.first.is_a?(Hash)
|
132
|
-
raise ArgumentError, "unknown config_section arguments: #{args.inspect}"
|
132
|
+
raise ArgumentError, "#{self.name}: unknown config_section arguments: #{args.inspect}"
|
133
133
|
end
|
134
134
|
|
135
135
|
sub_proxy = ConfigureProxy.new(name, *args)
|
data/lib/fluent/config/types.rb
CHANGED
@@ -50,6 +50,7 @@ module Fluent
|
|
50
50
|
end
|
51
51
|
|
52
52
|
ELEM_SYMBOLS = ['match', 'source', 'filter', 'system']
|
53
|
+
RESERVED_PARAMS = %W(@type @id @label)
|
53
54
|
|
54
55
|
def parse_element(root_element, elem_name, attrs = {}, elems = [])
|
55
56
|
while true
|
@@ -78,7 +79,7 @@ module Fluent
|
|
78
79
|
elsif skip(/\</)
|
79
80
|
e_name = scan(ELEMENT_NAME)
|
80
81
|
spacing
|
81
|
-
e_arg = scan_nonquoted_string(/(?:#{
|
82
|
+
e_arg = scan_nonquoted_string(/(?:#{ZERO_OR_MORE_SPACING}\>)/)
|
82
83
|
spacing
|
83
84
|
unless skip(/\>/)
|
84
85
|
parse_error! "expected '>'"
|
data/lib/fluent/engine.rb
CHANGED
@@ -352,30 +352,4 @@ module Fluent
|
|
352
352
|
end
|
353
353
|
|
354
354
|
Engine = EngineClass.new
|
355
|
-
|
356
|
-
|
357
|
-
module Test
|
358
|
-
@@test = false
|
359
|
-
|
360
|
-
def test?
|
361
|
-
@@test
|
362
|
-
end
|
363
|
-
|
364
|
-
def self.setup
|
365
|
-
@@test = true
|
366
|
-
|
367
|
-
Fluent.__send__(:remove_const, :Engine)
|
368
|
-
engine = Fluent.const_set(:Engine, EngineClass.new).init
|
369
|
-
|
370
|
-
engine.define_singleton_method(:now=) {|n|
|
371
|
-
@now = n.to_i
|
372
|
-
}
|
373
|
-
engine.define_singleton_method(:now) {
|
374
|
-
@now || super()
|
375
|
-
}
|
376
|
-
|
377
|
-
nil
|
378
|
-
end
|
379
|
-
end
|
380
355
|
end
|
381
|
-
|
data/lib/fluent/env.rb
CHANGED
data/lib/fluent/formatter.rb
CHANGED
@@ -18,6 +18,18 @@
|
|
18
18
|
module Fluent
|
19
19
|
require 'fluent/registry'
|
20
20
|
|
21
|
+
class Formatter
|
22
|
+
include Configurable
|
23
|
+
|
24
|
+
def configure(conf)
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def format(tag, time, record)
|
29
|
+
raise NotImplementedError, "Implement this method in child class"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
module TextFormatter
|
22
34
|
module HandleTagAndTimeMixin
|
23
35
|
def self.included(klass)
|
@@ -51,8 +63,7 @@ module Fluent
|
|
51
63
|
end
|
52
64
|
end
|
53
65
|
|
54
|
-
class OutFileFormatter
|
55
|
-
include Configurable
|
66
|
+
class OutFileFormatter < Formatter
|
56
67
|
include HandleTagAndTimeMixin
|
57
68
|
|
58
69
|
config_param :output_time, :bool, :default => true
|
@@ -65,10 +76,6 @@ module Fluent
|
|
65
76
|
end
|
66
77
|
end
|
67
78
|
|
68
|
-
def configure(conf)
|
69
|
-
super
|
70
|
-
end
|
71
|
-
|
72
79
|
def format(tag, time, record)
|
73
80
|
filter_record(tag, time, record)
|
74
81
|
header = ''
|
@@ -78,11 +85,12 @@ module Fluent
|
|
78
85
|
end
|
79
86
|
end
|
80
87
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
88
|
+
module StructuredFormatMixin
|
89
|
+
def self.included(klass)
|
90
|
+
klass.instance_eval {
|
91
|
+
config_param :time_as_epoch, :bool, :default => false
|
92
|
+
}
|
93
|
+
end
|
86
94
|
|
87
95
|
def configure(conf)
|
88
96
|
super
|
@@ -100,12 +108,29 @@ module Fluent
|
|
100
108
|
def format(tag, time, record)
|
101
109
|
filter_record(tag, time, record)
|
102
110
|
record[@time_key] = time if @time_as_epoch
|
111
|
+
format_record(record)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class JSONFormatter < Formatter
|
116
|
+
include HandleTagAndTimeMixin
|
117
|
+
include StructuredFormatMixin
|
118
|
+
|
119
|
+
def format_record(record)
|
103
120
|
"#{Yajl.dump(record)}\n"
|
104
121
|
end
|
105
122
|
end
|
106
123
|
|
107
|
-
class
|
108
|
-
include
|
124
|
+
class MessagePackFormatter < Formatter
|
125
|
+
include HandleTagAndTimeMixin
|
126
|
+
include StructuredFormatMixin
|
127
|
+
|
128
|
+
def format_record(record)
|
129
|
+
record.to_msgpack
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class LabeledTSVFormatter < Formatter
|
109
134
|
include HandleTagAndTimeMixin
|
110
135
|
|
111
136
|
config_param :delimiter, :string, :default => "\t"
|
@@ -122,9 +147,37 @@ module Fluent
|
|
122
147
|
end
|
123
148
|
end
|
124
149
|
|
125
|
-
class
|
126
|
-
include
|
150
|
+
class CsvFormatter < Formatter
|
151
|
+
include HandleTagAndTimeMixin
|
152
|
+
|
153
|
+
config_param :delimiter, :default => ',' do |val|
|
154
|
+
['\t', 'TAB'].include?(val) ? "\t" : val
|
155
|
+
end
|
156
|
+
config_param :force_quotes, :bool, :default => true
|
157
|
+
config_param :fields, :default => [] do |val|
|
158
|
+
val.split(',').map do |f|
|
159
|
+
f.strip!
|
160
|
+
f.size > 0 ? f : nil
|
161
|
+
end.compact
|
162
|
+
end
|
163
|
+
|
164
|
+
def initialize
|
165
|
+
super
|
166
|
+
require 'csv'
|
167
|
+
end
|
168
|
+
|
169
|
+
def format(tag, time, record)
|
170
|
+
filter_record(tag, time, record)
|
171
|
+
row = @fields.inject([]) do |memo, key|
|
172
|
+
memo << record[key]
|
173
|
+
memo
|
174
|
+
end
|
175
|
+
CSV.generate_line(row, :col_sep => @delimiter,
|
176
|
+
:force_quotes => @force_quotes)
|
177
|
+
end
|
178
|
+
end
|
127
179
|
|
180
|
+
class SingleValueFormatter < Formatter
|
128
181
|
config_param :message_key, :string, :default => 'message'
|
129
182
|
config_param :add_newline, :bool, :default => true
|
130
183
|
|
@@ -135,41 +188,58 @@ module Fluent
|
|
135
188
|
end
|
136
189
|
end
|
137
190
|
|
191
|
+
class ProcWrappedFormatter < Formatter
|
192
|
+
def initialize(proc)
|
193
|
+
@proc = proc
|
194
|
+
end
|
195
|
+
|
196
|
+
def configure(conf)
|
197
|
+
end
|
198
|
+
|
199
|
+
def format(tag, time, record)
|
200
|
+
@proc.call(tag, time, record)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
138
204
|
TEMPLATE_REGISTRY = Registry.new(:formatter_type, 'fluent/plugin/formatter_')
|
139
205
|
{
|
140
206
|
'out_file' => Proc.new { OutFileFormatter.new },
|
141
207
|
'json' => Proc.new { JSONFormatter.new },
|
208
|
+
'msgpack' => Proc.new { MessagePackFormatter.new },
|
142
209
|
'ltsv' => Proc.new { LabeledTSVFormatter.new },
|
210
|
+
'csv' => Proc.new { CsvFormatter.new },
|
143
211
|
'single_value' => Proc.new { SingleValueFormatter.new },
|
144
212
|
}.each { |name, factory|
|
145
213
|
TEMPLATE_REGISTRY.register(name, factory)
|
146
214
|
}
|
147
215
|
|
148
216
|
def self.register_template(name, factory_or_proc)
|
149
|
-
factory = if factory_or_proc.
|
150
|
-
Proc.new { factory_or_proc }
|
151
|
-
|
217
|
+
factory = if factory_or_proc.is_a?(Class) # XXXFormatter
|
218
|
+
Proc.new { factory_or_proc.new }
|
219
|
+
elsif factory_or_proc.arity == 3 # Proc.new { |tag, time, record| }
|
220
|
+
Proc.new { ProcWrappedFormatter.new(factory_or_proc) }
|
221
|
+
else # Proc.new { XXXFormatter.new }
|
152
222
|
factory_or_proc
|
153
223
|
end
|
154
224
|
|
155
225
|
TEMPLATE_REGISTRY.register(name, factory)
|
156
226
|
end
|
157
227
|
|
228
|
+
def self.lookup(format)
|
229
|
+
TEMPLATE_REGISTRY.lookup(format).call
|
230
|
+
end
|
231
|
+
|
232
|
+
# Keep backward-compatibility
|
158
233
|
def self.create(conf)
|
159
234
|
format = conf['format']
|
160
235
|
if format.nil?
|
161
236
|
raise ConfigError, "'format' parameter is required"
|
162
237
|
end
|
163
238
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
rescue ConfigError => e
|
168
|
-
raise ConfigError, "unknown format: '#{format}'"
|
239
|
+
formatter = lookup(format)
|
240
|
+
if formatter.respond_to?(:configure)
|
241
|
+
formatter.configure(conf)
|
169
242
|
end
|
170
|
-
|
171
|
-
formatter = factory.call
|
172
|
-
formatter.configure(conf)
|
173
243
|
formatter
|
174
244
|
end
|
175
245
|
end
|