/
configurator.rb
188 lines (155 loc) · 4.91 KB
/
configurator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
module Logging::Config
# The Configurator class is used to configure the Logging framework
# using information found in a block of Ruby code. This block is evaluated
# in the context of the configurator's DSL.
#
class Configurator
class Error < StandardError; end # :nodoc:
# call-seq:
# Configurator.process( &block )
#
def self.process( &block )
new.load(&block)
end
# call-seq:
# load { block }
#
# Loads the configuration from the _block_ and configures the Logging
# gem.
#
def load( &block )
raise Error, "missing configuration block" unless block
dsl = TopLevelDSL.new
dsl.instance_eval(&block)
pre_config dsl.__pre_config
::Logging::Logger[:root] # ensures the log levels are defined
appenders dsl.__appenders
loggers dsl.__loggers
end
# call-seq:
# pre_config( config )
#
# Configures the logging levels, object format style, and root logging
# level.
#
def pre_config( config )
if config.nil?
::Logging.init unless ::Logging.const_defined? 'MAX_LEVEL_LENGTH'
return
end
# define levels
levels = config[:levels]
::Logging.init(levels) unless levels.nil?
# format as
format = config[:format_as]
::Logging.format_as(format) unless format.nil?
# backtrace
value = config[:backtrace]
::Logging.backtrace(value) unless value.nil?
end
# call-seq:
# appenders( ary )
#
# Given an array of Appender configurations, this method will iterate
# over each and create the Appender(s).
#
def appenders( ary )
ary.each {|name, config| appender(name, config)}
end
# call-seq:
# loggers( ary )
#
# Given an array of Logger configurations, this method will iterate over
# each and create the Logger(s).
#
def loggers( ary )
ary.each do |name, config|
l = Logging::Logger[name]
l.level = config[:level] if config[:level]
l.additive = config[:additive] if l.respond_to? :additive=
l.trace = config[:trace]
l.appenders = Array(config[:appenders]).
map {|nm| ::Logging::Appenders[nm]}
end
end
# call-seq:
# appender( name, config )
#
# Creates a new Appender based on the given _config_ options (a hash).
# The type of Appender created is determined by the 'type' option in the
# config. The remaining config options are passed to the Appender
# initializer.
#
# The config options can also contain a 'layout' option. This should be
# another set of options used to create a Layout for this Appender.
#
def appender( name, config )
type = config.delete(:type)
raise Error, "appender type not given for #{name.inspect}" if type.nil?
config[:layout] = layout(config[:layout]) if config.has_key? :layout
clazz = ::Logging::Appenders.const_get type
clazz.new(name, config)
rescue NameError => err
raise Error, "unknown appender class Logging::Appenders::#{type}"
end
# call-seq:
# layout( config )
#
# Creates a new Layout based on the given _config_ options (a hash).
# The type of Layout created is determined by the 'type' option in the
# config. The remaining config options are passed to the Layout
# initializer.
#
def layout( config )
return ::Logging::Layouts::Basic.new if config.nil?
type = config.delete(:type)
raise Error, 'layout type not given' if type.nil?
clazz = ::Logging::Layouts.const_get type
clazz.new config
rescue NameError => err
raise Error, "unknown layout class Logging::Layouts::#{type}"
end
class DSL
instance_methods.each do |m|
undef_method m unless m[%r/^(__|object_id|instance_eval)/]
end
def self.process( &block )
dsl = new
dsl.instance_eval(&block)
dsl.__hash
end
def __hash
@hash ||= Hash.new
end
def method_missing( method, *args, &block )
args << DSL.process(&block) if block
key = method.to_sym
value = (1 == args.length ? args.first : args)
__store(key, value)
end
def __store( key, value )
__hash[key] = value
end
end
class TopLevelDSL < DSL
undef_method :method_missing
def initialize
@loggers = []
@appenders = []
end
def pre_config( &block )
__store(:preconfig, DSL.process(&block))
end
def logger( name, &block )
@loggers << [name, DSL.process(&block)]
end
def appender( name, &block )
@appenders << [name, DSL.process(&block)]
end
def __pre_config() __hash[:preconfig]; end
def __loggers() @loggers; end
def __appenders() @appenders; end
end
end # class Configurator
end # module Logging::Config
# EOF