fluentd 0.10.62 → 0.12.0.pre.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.

Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -2
  3. data/.travis.yml +0 -4
  4. data/ChangeLog +0 -72
  5. data/Gemfile +0 -6
  6. data/Rakefile +12 -3
  7. data/example/in_http.conf +14 -0
  8. data/example/in_syslog.conf +15 -0
  9. data/example/in_tail.conf +14 -0
  10. data/example/in_tcp.conf +13 -0
  11. data/example/in_udp.conf +13 -0
  12. data/example/out_copy.conf +20 -0
  13. data/example/out_file.conf +13 -0
  14. data/example/out_forward.conf +30 -0
  15. data/fluent.conf +2 -12
  16. data/fluentd.gemspec +8 -11
  17. data/lib/fluent/agent.rb +180 -0
  18. data/lib/fluent/buffer.rb +6 -12
  19. data/lib/fluent/command/cat.rb +1 -3
  20. data/lib/fluent/command/debug.rb +1 -3
  21. data/lib/fluent/command/fluentd.rb +0 -10
  22. data/lib/fluent/config.rb +9 -3
  23. data/lib/fluent/config/basic_parser.rb +1 -6
  24. data/lib/fluent/config/configure_proxy.rb +25 -61
  25. data/lib/fluent/config/dsl.rb +16 -0
  26. data/lib/fluent/config/element.rb +21 -2
  27. data/lib/fluent/config/error.rb +16 -0
  28. data/lib/fluent/config/literal_parser.rb +9 -27
  29. data/lib/fluent/config/parser.rb +16 -0
  30. data/lib/fluent/config/section.rb +16 -2
  31. data/lib/fluent/config/types.rb +16 -1
  32. data/lib/fluent/config/v1_parser.rb +4 -12
  33. data/lib/fluent/configurable.rb +16 -0
  34. data/lib/fluent/engine.rb +43 -163
  35. data/lib/fluent/env.rb +16 -1
  36. data/lib/fluent/event.rb +20 -48
  37. data/lib/fluent/event_router.rb +187 -0
  38. data/lib/fluent/filter.rb +32 -0
  39. data/lib/fluent/formatter.rb +29 -101
  40. data/lib/fluent/input.rb +6 -4
  41. data/lib/fluent/label.rb +18 -0
  42. data/lib/fluent/load.rb +1 -3
  43. data/lib/fluent/log.rb +1 -3
  44. data/lib/fluent/match.rb +12 -19
  45. data/lib/fluent/mixin.rb +9 -25
  46. data/lib/fluent/output.rb +27 -45
  47. data/lib/fluent/parser.rb +93 -99
  48. data/lib/fluent/plugin.rb +22 -48
  49. data/lib/fluent/plugin/buf_file.rb +10 -7
  50. data/lib/fluent/plugin/buf_memory.rb +2 -3
  51. data/lib/fluent/plugin/buf_zfile.rb +75 -0
  52. data/lib/fluent/plugin/exec_util.rb +16 -0
  53. data/lib/fluent/plugin/in_debug_agent.rb +2 -3
  54. data/lib/fluent/plugin/in_exec.rb +2 -9
  55. data/lib/fluent/plugin/in_forward.rb +4 -22
  56. data/lib/fluent/plugin/in_gc_stat.rb +2 -3
  57. data/lib/fluent/plugin/in_http.rb +19 -59
  58. data/lib/fluent/plugin/in_monitor_agent.rb +21 -47
  59. data/lib/fluent/plugin/in_object_space.rb +2 -3
  60. data/lib/fluent/plugin/in_status.rb +2 -3
  61. data/lib/fluent/plugin/in_stream.rb +6 -16
  62. data/lib/fluent/plugin/in_syslog.rb +8 -17
  63. data/lib/fluent/plugin/in_tail.rb +17 -24
  64. data/lib/fluent/plugin/in_tcp.rb +16 -0
  65. data/lib/fluent/plugin/in_udp.rb +16 -0
  66. data/lib/fluent/plugin/out_copy.rb +3 -4
  67. data/lib/fluent/plugin/out_exec.rb +2 -4
  68. data/lib/fluent/plugin/out_exec_filter.rb +2 -13
  69. data/lib/fluent/plugin/out_file.rb +5 -6
  70. data/lib/fluent/plugin/out_forward.rb +4 -5
  71. data/lib/fluent/plugin/out_null.rb +2 -3
  72. data/lib/fluent/plugin/out_relabel.rb +26 -0
  73. data/lib/fluent/plugin/out_roundrobin.rb +3 -4
  74. data/lib/fluent/plugin/out_stdout.rb +2 -3
  75. data/lib/fluent/plugin/out_stream.rb +2 -3
  76. data/{test/scripts → lib}/fluent/plugin/out_test.rb +2 -3
  77. data/lib/fluent/plugin/socket_util.rb +19 -10
  78. data/lib/fluent/process.rb +4 -6
  79. data/lib/fluent/registry.rb +16 -0
  80. data/lib/fluent/root_agent.rb +212 -0
  81. data/lib/fluent/status.rb +2 -3
  82. data/lib/fluent/supervisor.rb +33 -54
  83. data/lib/fluent/test.rb +16 -0
  84. data/lib/fluent/test/base.rb +3 -17
  85. data/lib/fluent/test/input_test.rb +52 -7
  86. data/lib/fluent/test/output_test.rb +4 -20
  87. data/lib/fluent/version.rb +17 -1
  88. data/spec/config/config_parser_spec.rb +314 -0
  89. data/spec/config/configurable_spec.rb +524 -0
  90. data/spec/config/configure_proxy_spec.rb +96 -0
  91. data/spec/config/dsl_spec.rb +239 -0
  92. data/spec/config/helper.rb +49 -0
  93. data/spec/config/literal_parser_spec.rb +222 -0
  94. data/spec/config/section_spec.rb +97 -0
  95. data/spec/config/system_config_spec.rb +49 -0
  96. data/test/helper.rb +0 -25
  97. data/test/plugin/test_in_exec.rb +1 -1
  98. data/test/plugin/test_in_forward.rb +2 -1
  99. data/test/plugin/test_in_gc_stat.rb +1 -1
  100. data/test/plugin/test_in_http.rb +3 -78
  101. data/test/plugin/test_in_object_space.rb +1 -1
  102. data/test/plugin/test_in_status.rb +1 -1
  103. data/test/plugin/test_in_stream.rb +2 -1
  104. data/test/plugin/test_in_syslog.rb +2 -1
  105. data/test/plugin/test_in_tail.rb +6 -11
  106. data/test/plugin/test_in_tcp.rb +2 -1
  107. data/test/plugin/test_in_udp.rb +2 -1
  108. data/test/plugin/test_out_copy.rb +1 -12
  109. data/test/plugin/test_out_exec.rb +1 -1
  110. data/test/plugin/test_out_exec_filter.rb +1 -1
  111. data/test/plugin/test_out_file.rb +7 -96
  112. data/test/plugin/test_out_forward.rb +2 -1
  113. data/test/plugin/test_out_roundrobin.rb +1 -12
  114. data/test/plugin/test_out_stdout.rb +1 -1
  115. data/test/plugin/test_out_stream.rb +2 -1
  116. data/test/scripts/fluent/plugin/formatter_known.rb +1 -4
  117. data/test/scripts/fluent/plugin/parser_known.rb +1 -2
  118. data/test/test_config.rb +1 -1
  119. data/test/test_configdsl.rb +2 -1
  120. data/test/test_formatter.rb +3 -395
  121. data/test/test_match.rb +2 -1
  122. data/test/test_mixin.rb +3 -75
  123. data/test/test_output.rb +1 -112
  124. data/test/test_parser.rb +85 -152
  125. metadata +58 -167
  126. data/example/v1_literal_example.conf +0 -36
  127. data/lib/fluent/plugin/in_dummy.rb +0 -103
  128. data/lib/fluent/timezone.rb +0 -131
  129. data/test/config/assertions.rb +0 -42
  130. data/test/config/test_config_parser.rb +0 -389
  131. data/test/config/test_configurable.rb +0 -652
  132. data/test/config/test_configure_proxy.rb +0 -99
  133. data/test/config/test_dsl.rb +0 -237
  134. data/test/config/test_literal_parser.rb +0 -295
  135. data/test/config/test_section.rb +0 -112
  136. data/test/config/test_system_config.rb +0 -99
  137. data/test/config/test_types.rb +0 -63
  138. data/test/plugin/test_in_dummy.rb +0 -95
  139. data/test/test_event.rb +0 -168
  140. data/test/test_input.rb +0 -21
data/lib/fluent/event.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  #
2
- # Fluent
3
- #
4
- # Copyright (C) 2011 FURUHASHI Sadayuki
2
+ # Fluentd
5
3
  #
6
4
  # Licensed under the Apache License, Version 2.0 (the "License");
7
5
  # you may not use this file except in compliance with the License.
@@ -15,6 +13,7 @@
15
13
  # See the License for the specific language governing permissions and
16
14
  # limitations under the License.
17
15
  #
16
+
18
17
  module Fluent
19
18
  class EventStream
20
19
  include Enumerable
@@ -28,11 +27,11 @@ module Fluent
28
27
  end
29
28
 
30
29
  def to_msgpack_stream
31
- out = $use_msgpack_5 ? MessagePack::Buffer.new : ''.force_encoding('ASCII-8BIT')
30
+ out = ''
32
31
  each {|time,record|
33
32
  [time,record].to_msgpack(out)
34
33
  }
35
- out.to_s
34
+ out
36
35
  end
37
36
  end
38
37
 
@@ -67,7 +66,7 @@ module Fluent
67
66
  end
68
67
 
69
68
  def dup
70
- entries = @entries.map { |entry| entry.dup } # @entries.map(:dup) doesn't work by ArgumentError
69
+ entries = @entries.map(:dup)
71
70
  ArrayEventStream.new(entries)
72
71
  end
73
72
 
@@ -132,53 +131,26 @@ module Fluent
132
131
  end
133
132
  end
134
133
 
135
- if $use_msgpack_5
136
-
137
- class MessagePackEventStream < EventStream
138
- def initialize(data, cached_unpacker=nil)
139
- @data = data
140
- end
141
-
142
- def repeatable?
143
- true
144
- end
145
-
146
- def each(&block)
147
- # TODO format check
148
- unpacker = MessagePack::Unpacker.new
149
- unpacker.feed_each(@data, &block)
150
- nil
151
- end
152
-
153
- def to_msgpack_stream
154
- @data
155
- end
134
+ class MessagePackEventStream < EventStream
135
+ # Keep cached_unpacker argument for existence plugins
136
+ def initialize(data, cached_unpacker = nil)
137
+ @data = data
156
138
  end
157
139
 
158
- else # for 0.4.x. Will be removed after 0.5.x is stable
159
-
160
- class MessagePackEventStream < EventStream
161
- def initialize(data, cached_unpacker=nil)
162
- @data = data
163
- @unpacker = cached_unpacker || MessagePack::Unpacker.new
164
- end
165
-
166
- def repeatable?
167
- true
168
- end
169
-
170
- def each(&block)
171
- @unpacker.reset
172
- # TODO format check
173
- @unpacker.feed_each(@data, &block)
174
- nil
175
- end
140
+ def repeatable?
141
+ true
142
+ end
176
143
 
177
- def to_msgpack_stream
178
- @data
179
- end
144
+ def each(&block)
145
+ # TODO format check
146
+ unpacker = MessagePack::Unpacker.new
147
+ unpacker.feed_each(@data, &block)
148
+ nil
180
149
  end
181
150
 
151
+ def to_msgpack_stream
152
+ @data
153
+ end
182
154
  end
183
155
  end
184
156
 
@@ -0,0 +1,187 @@
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
+ module Fluent
17
+ require 'fluent/match'
18
+
19
+ #
20
+ # EventRouter is responsible to route events to a collector.
21
+ #
22
+ # It has a list of MatchPattern and Collector pairs:
23
+ #
24
+ # +----------------+ +-----------------+
25
+ # | MatchPattern | | Collector |
26
+ # +----------------+ +-----------------+
27
+ # | access.** ---------> type forward |
28
+ # | logs.** ---------> type copy |
29
+ # | archive.** ---------> type s3 |
30
+ # +----------------+ +-----------------+
31
+ #
32
+ # EventRouter does:
33
+ #
34
+ # 1) receive an event at `#emit` methods
35
+ # 2) match the event's tag with the MatchPatterns
36
+ # 3) forward the event to the corresponding Collector
37
+ #
38
+ # Collector is either of Output, Filter or other EventRouter.
39
+ #
40
+ class EventRouter
41
+ def initialize(emit_error_handler, default_collector)
42
+ @match_rules = []
43
+ @match_cache = MatchCache.new
44
+ @default_collector = default_collector
45
+ @emit_error_handler = emit_error_handler || RaiseEmitErrorHandler.new
46
+ @chain = NullOutputChain.instance
47
+ end
48
+
49
+ # Agent implements EmitErrorHandler. See 'fluentd/agent.rb'
50
+ class RaiseEmitErrorHandler
51
+ def handle_emits_error(tag, es, error)
52
+ raise error
53
+ end
54
+ end
55
+
56
+ attr_accessor :default_collector
57
+ attr_accessor :emit_error_handler
58
+
59
+ class Rule
60
+ def initialize(pattern, collector)
61
+ patterns = pattern.split(/\s+/).map { |str| MatchPattern.create(str) }
62
+ @pattern = if patterns.length == 1
63
+ patterns[0]
64
+ else
65
+ OrMatchPattern.new(patterns)
66
+ end
67
+ @pattern_str = pattern
68
+ @collector = collector
69
+ end
70
+
71
+ def match?(tag)
72
+ @pattern.match(tag)
73
+ end
74
+
75
+ attr_reader :collector
76
+ attr_reader :patatern_str
77
+ end
78
+
79
+ # called by Agent to add new match pattern and collector
80
+ def add_rule(pattern, collector)
81
+ @match_rules << Rule.new(pattern, collector)
82
+ end
83
+
84
+ def emit(tag, time, record)
85
+ unless record.nil?
86
+ emit_stream(tag, OneEventStream.new(time, record))
87
+ end
88
+ end
89
+
90
+ def emit_array(tag, array)
91
+ emit_stream(tag, ArrayEventStream.new(array))
92
+ end
93
+
94
+ def emit_stream(tag, es)
95
+ match(tag).emit(tag, es, @chain)
96
+ rescue => e
97
+ @emit_error_handler.handle_emits_error(tag, es, e)
98
+ end
99
+
100
+ def match?(tag)
101
+ !!find(tag)
102
+ end
103
+
104
+ def match(tag)
105
+ collector = @match_cache.get(tag) {
106
+ c = find(tag) || @default_collector
107
+ }
108
+ collector
109
+ end
110
+
111
+ class MatchCache
112
+ MATCH_CACHE_SIZE = 1024
113
+
114
+ def initialize
115
+ super
116
+ @map = {}
117
+ @keys = []
118
+ end
119
+
120
+ def get(key)
121
+ if collector = @map[key]
122
+ return collector
123
+ end
124
+ collector = @map[key] = yield
125
+ if @keys.size >= MATCH_CACHE_SIZE
126
+ # expire the oldest key
127
+ @map.delete @keys.shift
128
+ end
129
+ @keys << key
130
+ collector
131
+ end
132
+ end
133
+
134
+ private
135
+
136
+ class Pipeline
137
+ def initialize
138
+ @filters = []
139
+ @output = nil
140
+ end
141
+
142
+ def add_filter(filter)
143
+ @filters << filter
144
+ end
145
+
146
+ def set_output(output)
147
+ @output = output
148
+ end
149
+
150
+ def emit(tag, es, chain)
151
+ processed = es
152
+ @filters.each { |filter|
153
+ processed = filter.filter_stream(tag, processed)
154
+ }
155
+ @output.emit(tag, processed, chain)
156
+ end
157
+ end
158
+
159
+ def find(tag)
160
+ pipeline = nil
161
+ @match_rules.each_with_index { |rule, i|
162
+ if rule.match?(tag)
163
+ if rule.collector.is_a?(Filter)
164
+ pipeline ||= Pipeline.new
165
+ pipeline.add_filter(rule.collector)
166
+ else
167
+ if pipeline
168
+ pipeline.set_output(rule.collector)
169
+ else
170
+ # Use Output directly when filter is not matched
171
+ pipeline = rule.collector
172
+ end
173
+ return pipeline
174
+ end
175
+ end
176
+ }
177
+
178
+ if pipeline
179
+ # filter is matched but no match
180
+ pipeline.set_output(@default_collector)
181
+ pipeline
182
+ else
183
+ nil
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,32 @@
1
+ module Fluent
2
+ class Filter
3
+ include Configurable
4
+ include PluginId
5
+ include PluginLoggerMixin
6
+
7
+ def initialize
8
+ super
9
+ end
10
+
11
+ def configure(conf)
12
+ super
13
+ end
14
+
15
+ def start
16
+ end
17
+
18
+ def shutdown
19
+ end
20
+
21
+ def filter(tag, time, record)
22
+ end
23
+
24
+ def filter_stream(tag, es)
25
+ new_es = MultiEventStream.new
26
+ es.each { |time, record|
27
+ new_es.add(time, filter(tag, time, record))
28
+ }
29
+ new_es
30
+ end
31
+ end
32
+ end
@@ -1,7 +1,5 @@
1
1
  #
2
- # Fluent
3
- #
4
- # Copyright (C) 2014 Fluentd project
2
+ # Fluentd
5
3
  #
6
4
  # Licensed under the Apache License, Version 2.0 (the "License");
7
5
  # you may not use this file except in compliance with the License.
@@ -15,21 +13,10 @@
15
13
  # See the License for the specific language governing permissions and
16
14
  # limitations under the License.
17
15
  #
16
+
18
17
  module Fluent
19
18
  require 'fluent/registry'
20
19
 
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
-
33
20
  module TextFormatter
34
21
  module HandleTagAndTimeMixin
35
22
  def self.included(klass)
@@ -40,7 +27,6 @@ module Fluent
40
27
  config_param :include_tag_key, :bool, :default => false
41
28
  config_param :tag_key, :string, :default => 'tag'
42
29
  config_param :localtime, :bool, :default => true
43
- config_param :timezone, :string, :default => nil
44
30
  }
45
31
  end
46
32
 
@@ -50,7 +36,7 @@ module Fluent
50
36
  if conf['utc']
51
37
  @localtime = false
52
38
  end
53
- @timef = TimeFormatter.new(@time_format, @localtime, @timezone)
39
+ @timef = TimeFormatter.new(@time_format, @localtime)
54
40
  end
55
41
 
56
42
  def filter_record(tag, time, record)
@@ -63,7 +49,8 @@ module Fluent
63
49
  end
64
50
  end
65
51
 
66
- class OutFileFormatter < Formatter
52
+ class OutFileFormatter
53
+ include Configurable
67
54
  include HandleTagAndTimeMixin
68
55
 
69
56
  config_param :output_time, :bool, :default => true
@@ -76,6 +63,10 @@ module Fluent
76
63
  end
77
64
  end
78
65
 
66
+ def configure(conf)
67
+ super
68
+ end
69
+
79
70
  def format(tag, time, record)
80
71
  filter_record(tag, time, record)
81
72
  header = ''
@@ -85,12 +76,11 @@ module Fluent
85
76
  end
86
77
  end
87
78
 
88
- module StructuredFormatMixin
89
- def self.included(klass)
90
- klass.instance_eval {
91
- config_param :time_as_epoch, :bool, :default => false
92
- }
93
- end
79
+ class JSONFormatter
80
+ include Configurable
81
+ include HandleTagAndTimeMixin
82
+
83
+ config_param :time_as_epoch, :bool, :default => false
94
84
 
95
85
  def configure(conf)
96
86
  super
@@ -108,29 +98,12 @@ module Fluent
108
98
  def format(tag, time, record)
109
99
  filter_record(tag, time, record)
110
100
  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)
120
101
  "#{Yajl.dump(record)}\n"
121
102
  end
122
103
  end
123
104
 
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
105
+ class LabeledTSVFormatter
106
+ include Configurable
134
107
  include HandleTagAndTimeMixin
135
108
 
136
109
  config_param :delimiter, :string, :default => "\t"
@@ -147,37 +120,9 @@ module Fluent
147
120
  end
148
121
  end
149
122
 
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
123
+ class SingleValueFormatter
124
+ include Configurable
179
125
 
180
- class SingleValueFormatter < Formatter
181
126
  config_param :message_key, :string, :default => 'message'
182
127
  config_param :add_newline, :bool, :default => true
183
128
 
@@ -188,58 +133,41 @@ module Fluent
188
133
  end
189
134
  end
190
135
 
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
-
204
136
  TEMPLATE_REGISTRY = Registry.new(:formatter_type, 'fluent/plugin/formatter_')
205
137
  {
206
138
  'out_file' => Proc.new { OutFileFormatter.new },
207
139
  'json' => Proc.new { JSONFormatter.new },
208
- 'msgpack' => Proc.new { MessagePackFormatter.new },
209
140
  'ltsv' => Proc.new { LabeledTSVFormatter.new },
210
- 'csv' => Proc.new { CsvFormatter.new },
211
141
  'single_value' => Proc.new { SingleValueFormatter.new },
212
142
  }.each { |name, factory|
213
143
  TEMPLATE_REGISTRY.register(name, factory)
214
144
  }
215
145
 
216
146
  def self.register_template(name, factory_or_proc)
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 }
147
+ factory = if factory_or_proc.arity == 3
148
+ Proc.new { factory_or_proc }
149
+ else
222
150
  factory_or_proc
223
151
  end
224
152
 
225
153
  TEMPLATE_REGISTRY.register(name, factory)
226
154
  end
227
155
 
228
- def self.lookup(format)
229
- TEMPLATE_REGISTRY.lookup(format).call
230
- end
231
-
232
- # Keep backward-compatibility
233
156
  def self.create(conf)
234
157
  format = conf['format']
235
158
  if format.nil?
236
159
  raise ConfigError, "'format' parameter is required"
237
160
  end
238
161
 
239
- formatter = lookup(format)
240
- if formatter.respond_to?(:configure)
241
- formatter.configure(conf)
162
+ # built-in template
163
+ begin
164
+ factory = TEMPLATE_REGISTRY.lookup(format)
165
+ rescue ConfigError => e
166
+ raise ConfigError, "unknown format: '#{format}'"
242
167
  end
168
+
169
+ formatter = factory.call
170
+ formatter.configure(conf)
243
171
  formatter
244
172
  end
245
173
  end