log4rails 1.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.bsd +12 -0
  3. data/README.md +37 -0
  4. data/lib/log4r/GDC.rb +41 -0
  5. data/lib/log4r/MDC.rb +59 -0
  6. data/lib/log4r/NDC.rb +86 -0
  7. data/lib/log4r/base.rb +74 -0
  8. data/lib/log4r/config.rb +9 -0
  9. data/lib/log4r/configurator.rb +224 -0
  10. data/lib/log4r/formatter/formatter.rb +105 -0
  11. data/lib/log4r/formatter/log4jxmlformatter.rb +65 -0
  12. data/lib/log4r/formatter/patternformatter.rb +145 -0
  13. data/lib/log4r/lib/drbloader.rb +52 -0
  14. data/lib/log4r/lib/xmlloader.rb +24 -0
  15. data/lib/log4r/log4r-rails.yaml +60 -0
  16. data/lib/log4r/logevent.rb +28 -0
  17. data/lib/log4r/logger.rb +206 -0
  18. data/lib/log4r/loggerfactory.rb +89 -0
  19. data/lib/log4r/logserver.rb +28 -0
  20. data/lib/log4r/outputter/bufferedsyslogoutputter.rb +47 -0
  21. data/lib/log4r/outputter/consoleoutputters.rb +18 -0
  22. data/lib/log4r/outputter/datefileoutputter.rb +117 -0
  23. data/lib/log4r/outputter/emailoutputter.rb +143 -0
  24. data/lib/log4r/outputter/fileoutputter.rb +57 -0
  25. data/lib/log4r/outputter/iooutputter.rb +55 -0
  26. data/lib/log4r/outputter/outputter.rb +134 -0
  27. data/lib/log4r/outputter/outputterfactory.rb +60 -0
  28. data/lib/log4r/outputter/remoteoutputter.rb +40 -0
  29. data/lib/log4r/outputter/rollingfileoutputter.rb +234 -0
  30. data/lib/log4r/outputter/scribeoutputter.rb +37 -0
  31. data/lib/log4r/outputter/staticoutputter.rb +30 -0
  32. data/lib/log4r/outputter/syslogoutputter.rb +126 -0
  33. data/lib/log4r/outputter/udpoutputter.rb +53 -0
  34. data/lib/log4r/railtie.rb +211 -0
  35. data/lib/log4r/rdoc/GDC +14 -0
  36. data/lib/log4r/rdoc/MDC +16 -0
  37. data/lib/log4r/rdoc/NDC +41 -0
  38. data/lib/log4r/rdoc/configurator +243 -0
  39. data/lib/log4r/rdoc/emailoutputter +103 -0
  40. data/lib/log4r/rdoc/formatter +39 -0
  41. data/lib/log4r/rdoc/log4jxmlformatter +21 -0
  42. data/lib/log4r/rdoc/log4r +89 -0
  43. data/lib/log4r/rdoc/logger +175 -0
  44. data/lib/log4r/rdoc/logserver +85 -0
  45. data/lib/log4r/rdoc/outputter +108 -0
  46. data/lib/log4r/rdoc/patternformatter +128 -0
  47. data/lib/log4r/rdoc/scribeoutputter +16 -0
  48. data/lib/log4r/rdoc/syslogoutputter +29 -0
  49. data/lib/log4r/rdoc/win32eventoutputter +7 -0
  50. data/lib/log4r/rdoc/yamlconfigurator +20 -0
  51. data/lib/log4r/repository.rb +88 -0
  52. data/lib/log4r/staticlogger.rb +49 -0
  53. data/lib/log4r/version.rb +4 -0
  54. data/lib/log4r/yamlconfigurator.rb +198 -0
  55. data/lib/log4rails.rb +22 -0
  56. metadata +97 -0
@@ -0,0 +1,53 @@
1
+ # :include: ../rdoc/outputter
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id$
6
+ # Author:: Leon Torres <leon@ugcs.caltech.edu>
7
+
8
+ require "log4r/outputter/outputter"
9
+ require 'log4r/staticlogger'
10
+ require "socket"
11
+
12
+ module Log4r
13
+
14
+ class UDPOutputter < Outputter
15
+ attr_reader :host, :port
16
+ attr_accessor :udpsock
17
+
18
+ def initialize(_name, hash={})
19
+ super(_name, hash)
20
+ @host = (hash[:hostname] or hash["hostname"])
21
+ @port = (hash[:port] or hash["port"])
22
+
23
+ begin
24
+ Logger.log_internal {
25
+ "UDPOutputter will send to #{@host}:#{@port}"
26
+ }
27
+ @udpsock = UDPSocket.new
28
+ @udpsock.connect( @host, @port )
29
+ rescue Exception => e
30
+ Logger.log_internal(ERROR) {
31
+ "UDPOutputter failed to create UDP socket: #{e}"
32
+ }
33
+ Logger.log_internal {e}
34
+ self.level = OFF
35
+ raise e
36
+ end
37
+ end
38
+
39
+ #######
40
+ private
41
+ #######
42
+
43
+ def write(data)
44
+ @udpsock.send(data, 0)
45
+ rescue Exception => e
46
+ Logger.log_internal(ERROR) {
47
+ "UDPOutputter failed to send data to #{@host}:#{@port}, #{e}"
48
+ }
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,211 @@
1
+ # :nodoc:
2
+ # Version:: $Id$
3
+ # Author:: Mike Ho <i(at)bestmike007.com>
4
+ # How to configure log4r for rails in application.rb:
5
+ # config.log4rails.<option> = <value>
6
+ # config.log4rails.enabled = true # enable log4r integration
7
+ # config.log4rails.action_mht = 500 # maximum action handling time to log with level INFO, default: 500ms.
8
+ # config.log4rails.auto_reload = true # auto-reload log4r configuration file from config/log4r.yaml (or config/log4r-production.yaml in production environment)
9
+
10
+ require 'rails'
11
+ require 'log4r/yamlconfigurator'
12
+
13
+ module Log4r
14
+
15
+ class Railtie < Rails::Railtie
16
+
17
+ config.log4rails = ActiveSupport::OrderedOptions.new
18
+ # default values
19
+ config.log4rails.enabled = false
20
+ config.log4rails.action_mht = 500
21
+ config.log4rails.auto_reload = true
22
+
23
+ initializer "log4rails.pre_init", :before => :initialize_logger do |app|
24
+ if app.config.log4rails.enabled
25
+ Log4r::Railtie.load_config
26
+ Log4r::Railtie.pre_init(app, {:root => Rails.root.to_s, :env => Rails.env}.merge(app.config.log4rails))
27
+ end
28
+ end
29
+
30
+ initializer "log4rails.post_init", :after => :initialize_logger do |app|
31
+ if app.config.log4rails.enabled
32
+ Log4r::Railtie.post_init
33
+ end
34
+ end
35
+
36
+ initializer "log4rails.cache_logger", :after => :initialize_cache do |app|
37
+ if app.config.log4rails.enabled
38
+ class << Rails.cache
39
+ def logger
40
+ Log4r::Logger['rails::cache'] || Log4r::Logger.root
41
+ end
42
+ def logger=(l)
43
+ (l || logger).debug "Log4r is preventing set of logger for cache."
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ class << self
50
+
51
+ # remove rails default log subscriptions
52
+ # [ActiveRecord::LogSubscriber, ActionController::LogSubscriber, ActionView::LogSubscriber, ActionMailer::LogSubscriber]
53
+ unsubscribe = lambda { |component, subscriber|
54
+ events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
55
+ events.each do |event|
56
+ ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
57
+ if listener.instance_variable_get('@delegate') == subscriber
58
+ ActiveSupport::Notifications.unsubscribe listener
59
+ end
60
+ end
61
+ end
62
+ }
63
+ remove_existing_log_subscriptions = lambda {
64
+ ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
65
+ case subscriber
66
+ when ActionView::LogSubscriber
67
+ unsubscribe.call(:action_view, subscriber)
68
+ when ActionController::LogSubscriber
69
+ unsubscribe.call(:action_controller, subscriber)
70
+ when ActiveRecord::LogSubscriber
71
+ unsubscribe.call(:active_record, subscriber)
72
+ when ActionMailer::LogSubscriber
73
+ unsubscribe.call(:action_mailler, subscriber)
74
+ end
75
+ end
76
+ }
77
+
78
+ config_time = Time.new 0
79
+ config_next_check = Time.now
80
+ config_path = nil
81
+ options = nil
82
+
83
+ define_method(:options) { options }
84
+
85
+ # load or reload config from RAILS_ROOT/config/log4r.yaml or RAILS_ROOT/config/log4r-production.yaml
86
+ define_method :load_config do
87
+ # auto reload config every 30 seconds.
88
+ return if Time.now < config_next_check
89
+ config_next_check = Time.now + 30
90
+ return if !config_path.nil? && (!File.file?(config_path) || File.mtime(config_path) == config_time)
91
+ config_path = File.join Rails.root, "config", "log4r.yaml"
92
+ begin
93
+ if Rails.env == 'production'
94
+ production_config = File.join Rails.root, "config", "log4r-production.yaml"
95
+ config_path = production_config if File.file?(production_config)
96
+ end
97
+ if File.file? config_path
98
+ YamlConfigurator.load_yaml_file config_path
99
+ config_path = config_path
100
+ config_time = File.mtime(config_path)
101
+ return
102
+ end
103
+ puts "Log4r Warning: Unable to find log4r config file for rails, using default config."
104
+ rescue Log4r::ConfigError => e
105
+ puts "Log4r Error: Unable to load config #{config_path}, error: #{e}. Using default config."
106
+ end
107
+ config_path = File.join File.dirname(__FILE__), 'log4r-rails.yaml'
108
+ YamlConfigurator.load_yaml_file config_path
109
+ end
110
+
111
+ define_method :pre_init do |app, opts|
112
+ options = opts
113
+ # silence default rails logger
114
+ app.config.log_level = :unknown
115
+ # define global logger
116
+ setup_logger Object, "root"
117
+ # define rails controller logger names
118
+ setup_logger ActionController::Base, "rails::controllers"
119
+ setup_logger ActiveRecord::Base, "rails::models"
120
+ setup_logger ActionMailer::Base, "rails::mailers"
121
+
122
+ remove_existing_log_subscriptions.call
123
+
124
+ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, start, finish, id, payload|
125
+ Log4r::Railtie.load_config if Log4r::Railtie.options[:auto_reload]
126
+ Log4r::Railtie.controller_log({ duration: ((finish - start).to_f * 100000).round / 100.0 }.merge(payload))
127
+ end
128
+
129
+ ActiveSupport::Notifications.subscribe "sql.active_record" do |name, start, finish, id, payload|
130
+ Log4r::Railtie.load_config if Log4r::Railtie.options[:auto_reload]
131
+ logger = Log4r::Logger["rails::db"] || Log4r::Logger.root
132
+ logger.debug { "(#{((finish - start).to_f * 100000).round / 100.0 }) #{payload[:sql]}" }
133
+ end
134
+ end
135
+
136
+ def post_init
137
+ setup_logger Rails, "rails"
138
+ # disable rack development output, e.g. Started GET "/session/new" for 127.0.0.1 at 2012-09-26 14:51:42 -0700
139
+ if Rails.const_defined?(:Rack) && Rails::Rack.const_defined?(:Logger)
140
+ setup_logger Rails::Rack::Logger, "root"
141
+ end
142
+ # override DebugExceptions output
143
+ ActionDispatch::DebugExceptions.module_eval %-
144
+ def log_error(env, wrapper)
145
+ logger = Rails.logger
146
+ exception = wrapper.exception
147
+ # trace = wrapper.application_trace
148
+ # trace = wrapper.framework_trace if trace.empty?
149
+ logger.info "ActionDispatch Exception: \#{exception.class} (\#{exception.message})"
150
+ end
151
+ private :log_error
152
+ -
153
+ end
154
+
155
+ def controller_log(payload)
156
+ logger = Rails.logger
157
+ params_logger = Log4r::Logger["rails::params"] || Log4r::Logger.root
158
+
159
+ duration = payload[:duration]
160
+ unless payload[:exception].nil?
161
+ logger.warn {
162
+ db = (payload[:db_runtime] * 100).round/100.0 rescue "-"
163
+ view = (payload[:view_runtime] * 100).round/100.0 rescue "-"
164
+ "#{payload[:method]} #{payload[:path]} (TIMING[ms]: sum:#{duration} db:#{db} view:#{view}) EXCEPTION: #{payload[:exception]}"
165
+ }
166
+ params_logger.info { "request params: " + payload[:params].to_json }
167
+ return
168
+ end
169
+ if duration >= Log4r::Railtie.options[:action_mht]
170
+ logger.warn {
171
+ db = (payload[:db_runtime] * 100).round/100.0 rescue "-"
172
+ view = (payload[:view_runtime] * 100).round/100.0 rescue "-"
173
+ "#{payload[:method]} #{payload[:path]} (TIMING[ms]: sum:#{duration} db:#{db} view:#{view})"
174
+ }
175
+ else
176
+ logger.info {
177
+ db = (payload[:db_runtime] * 100).round/100.0 rescue "-"
178
+ view = (payload[:view_runtime] * 100).round/100.0 rescue "-"
179
+ "#{payload[:method]} #{payload[:path]} (TIMING[ms]: sum:#{duration} db:#{db} view:#{view})"
180
+ }
181
+ end
182
+ params_logger.info { "request params: " + payload[:params].to_json }
183
+ end
184
+
185
+ # convenient static method to setup logger for class and descendants.
186
+ def setup_logger(clazz, logger_name)
187
+ clazz.module_eval %(
188
+ class << self
189
+ custom_logger = nil
190
+ define_method :logger do
191
+ custom_logger || Log4r::Logger['#{logger_name}'] || Log4r::Logger.root
192
+ end
193
+ define_method :logger= do |l|
194
+ (l || custom_logger).debug "Log4rails is preventing set of logger. Use #custom_logger= if you really want it set."
195
+ end
196
+ define_method :custom_logger= do |l|
197
+ custom_logger = l
198
+ end
199
+ end
200
+
201
+ def logger
202
+ #{clazz.name}.logger
203
+ end
204
+ )
205
+ end
206
+
207
+ end
208
+
209
+ end # class Railtie
210
+
211
+ end # module Log4r
@@ -0,0 +1,14 @@
1
+ = GDC
2
+
3
+ The GDC class implements a copy of the Global Diagnostic Context, which
4
+ is not part of the Apache Log4j library, as of this writing (10 Jan 2009).
5
+
6
+ The GDC is like the NDC and MDC classes, only it is global to the
7
+ application (see NDC and MDC for details on those classes).
8
+
9
+ The GDC is local to the main thread, and any new threads will return
10
+ the value of the current GDC set in the main thread.
11
+
12
+ Only the main thread can set the GDC, any other threads that
13
+ attempt to will raise an exception.
14
+
@@ -0,0 +1,16 @@
1
+ = MDC
2
+
3
+ The MDC class implements a copy of the Mapped Diagnostic Context, which
4
+ is part of the Apache Log4j library. See the NDC documentation for
5
+ more details. MDCs are much like NDCs, but instead of a stack context
6
+ it uses a map for holding this information.
7
+
8
+ This allows for selection of information out of the map when
9
+ the log message is being created.
10
+
11
+ MDCs are thread safe, and are unique to each thread.
12
+
13
+ An important difference between MDCs in Log4r vs Log4j is that they
14
+ only inherit from the main thread. Ruby treats all new threads as
15
+ being the children of the main thread, even if they are started
16
+ from a thread that is not main.
@@ -0,0 +1,41 @@
1
+ = NDC
2
+
3
+ The NDC class implements a copy of the Nested Diagnostic Context, which
4
+ is part of the Apache Log4j library. Nested Diagnostic Contexts were
5
+ derived from Neil Harrison's article on "Patterns for Logging
6
+ Diagnostic Messages", part of the book "Pattern Languages of Program
7
+ Design 3" edited by Martin et al.
8
+
9
+ NDCs in Log4r are thread safe.
10
+
11
+ NDCs in log4r are close enough to NDCs in Log4j that I include its
12
+ documentation directly:
13
+
14
+ ...
15
+ A Nested Diagnostic Context, or NDC in short, is an instrument to
16
+ distinguish interleaved log output from different sources. Log output
17
+ is typically interleaved when a server handles multiple clients
18
+ near-simultaneously.
19
+
20
+ Interleaved log output can still be meaningful if each log entry from
21
+ different contexts had a distinctive stamp. This is where NDCs come into
22
+ play.
23
+
24
+ Note that NDCs are managed on a per thread basis. NDC operations such as
25
+ push, pop(), clear(), getDepth() and setMaxDepth(int) affect the NDC of
26
+ the current thread only. NDCs of other threads remain unaffected.
27
+ ...
28
+
29
+ An important difference between NDCs in Log4r vs Log4j is that you
30
+ do not have to called NDC.remove() when exiting a thread.
31
+
32
+ This class will automatically create Thread specific storage for the
33
+ current thread on the first call to any of its methods, i.e.
34
+
35
+ NDC.push( "client accept" );
36
+
37
+ New threads may inherit the NDC of the parent thread by making use of
38
+ the clone_stack() and inherit() methods. By default, the NDC is not
39
+ inherited automatically. This is unlike MDCs, which will inherit from
40
+ the main thread.
41
+
@@ -0,0 +1,243 @@
1
+ = Configuring Log4r with Log4r::Configurator
2
+
3
+ The Configurator class allows one to set up Log4r via XML.
4
+ Additionally, Configurator contains methods to configure any Log4r
5
+ defaults. In particular, Configurator provides a method to
6
+ customize the logging levels.
7
+
8
+ Log4r is also configurable using YAML. For that, there is
9
+ a class similar to Configurator called Log4r::YamlConfigurator. Please see
10
+ log4r/yamlconfigurator.rb for details.
11
+
12
+ REXML is required for XML configuration. Get REXML at
13
+ http://www.ruby-lang.org/en/raa-list.rhtml?name=REXML
14
+
15
+ To use the Configurator class,
16
+
17
+ require 'log4r/configurator'
18
+
19
+ == Custom Levels
20
+
21
+ Suppose you want the following levels and ranks:
22
+
23
+ Foo < Bar < Baz
24
+
25
+ This is easily accomplished:
26
+
27
+ Configurator.custom_levels('Foo', 'Bar', :Baz)
28
+
29
+ The method accepts strings or symbols. However, custom levels must have names
30
+ that are valid for Ruby constants. Also, custom levels should be set before
31
+ anything else is done with Log4r, otherwise the default levels will be loaded.
32
+
33
+ You can set custom levels in XML. That's covered in the following section.
34
+
35
+ == XML Configuration
36
+
37
+ If you have REXML, you can configure Log4r with XML.
38
+ To do this, first write an XML configuration (which you can learn by
39
+ studying this document and the examples provided in the distribution)
40
+ and then load up the XML from within your program as follows:
41
+
42
+ Configurator.load_xml_file('/path/to/file.xml')
43
+
44
+ The Log4r XML configuration system is very flexible and powerful. In fact,
45
+ it is somewhat preferable to configuring Log4r in Ruby. In order to take
46
+ full advantage of this feature, there are several concepts one must know.
47
+ They are covered in the following three sections.
48
+
49
+ === Concept: XML Directives
50
+
51
+ The expressive power of Ruby has enabled a feature I call
52
+ <i>XML directives</i>. An XML directive is a name-value pair belonging to
53
+ some element. It
54
+ may be represented as an attribute (name="value") of the element, or
55
+ as a child (<name>value</name>) of the element. Therefore, you are
56
+ free to specify information about an object as either an attribute
57
+ or an element. An example should clarify:
58
+
59
+ <object data="value"/>
60
+
61
+ Is equivalent to:
62
+
63
+ <object>
64
+ <data>value</data>
65
+ </object>
66
+
67
+ You can assume this behavior except where noted elsewhere in the API.
68
+
69
+ === Concept: XML Parameters
70
+
71
+ A scheme which I call <i>XML parameters</i> enables one to utilize the XML
72
+ configuratin system for custom Outputters and Formatters.
73
+ This requires <b>no</b> extra work on your part, so long as your objects
74
+ are set up using hash arguments and can decode string values. That is, once
75
+ you've written a custom Outputter, it is automatically configurable in XML
76
+ without having to write any extra code.
77
+
78
+ An XML parameter is analogous to a hash argument to some object's <tt>new</tt>
79
+ method. Consider these hash arguments to FileOutputter:
80
+
81
+ :filename => '/path/to/logs/my.log'
82
+ :trunc => 'true'
83
+
84
+ We can specify them in XML like this:
85
+
86
+ <outputter type="FileOutputter" trunc="true">
87
+ <filename>/path/to/logs/my.log</filename>
88
+ ...
89
+
90
+ The name of the element/attribute is just the name of the parameter. Note that
91
+ the input will be a string, thus it's wise to convert the data in from
92
+ strings in any custom classes (to_i for integers, etc). Now let's suppose you
93
+ have defined a custom Outputter named MyOutputter with the following
94
+ additional hash args:
95
+
96
+ :myarg1 => 'foo'
97
+ :myarg2 => 123
98
+
99
+ Automagically, you can configure your Outputter like so:
100
+
101
+ <outputter type="MyOutputter" myarg2="123">
102
+ <myarg1>foo</myarg1>
103
+ ...
104
+
105
+ Isn't that nice? <tt>:-)</tt>
106
+
107
+ === Concept: Variable Substitution
108
+
109
+ To kill the need for preprocessors, Configurator provides a means of variable
110
+ substitution for XML parameters at runtime. If you specify
111
+ <tt>#{foo}</tt> in an XML parameter value, Configurator will replace it with
112
+ the value of 'foo' in its parameter hashtable. The primary idea is that you
113
+ can figure stuff out in your program,
114
+ say the log path, and relay that information to the XML while it's being
115
+ loaded. Secondarily, it is a way to have aliases within an XML document.
116
+
117
+ There are two ways to tell Configurator about these variables. The first
118
+ method we'll cover is done within a Ruby program with Configurator[].
119
+
120
+ Configurator['logpath'] = '/path/to/logs'
121
+
122
+ Thereafter, any occurence of <tt>#{logpath}</tt> in each and every XML
123
+ parameter will be substituted with '/path/to/logs'. For example:
124
+
125
+ <filename>#{logpath}/mylog.log</filename>
126
+
127
+ Becomes,
128
+
129
+ <filename>/path/to/logs/mylog.log</filename>
130
+
131
+ Aside from Configurator[], another way to define XML parameter variables
132
+ is to define <tt>parameters</tt> under the <tt><pre_config></tt> element
133
+ of an XML configuration:
134
+
135
+ <pre_config>
136
+ <parameter name="logpath" value="/path/to/logs'/>
137
+ <parameter name="other" value="somethingelse'/>
138
+ ...
139
+ </pre_config>
140
+
141
+ Alternatively,
142
+
143
+ <pre_config>
144
+ <parameters>
145
+ <logpath>/path/to/logs</logpath>
146
+ <other>somethingelse</other>
147
+ ...
148
+ </parameters>
149
+ ...
150
+
151
+ The end result is the same as using Configurator[]. However, this method
152
+ is not dynamic. Configurator[] should be used when you want to set variables
153
+ from within Ruby.
154
+
155
+ = XML Grammar
156
+
157
+ And now, here's the XML grammar we use to configure Log4r.
158
+
159
+ == Root Element
160
+
161
+ The root element is <tt><log4r_config></tt>. It can be embedded as a node of
162
+ any other element in an XML file. For instance:
163
+
164
+ <my-xml-thing>
165
+ <customize-libraries>
166
+ <log4r_config>
167
+ <!-- log4r configuratin goes here -->
168
+ </log4r_config>
169
+ ...
170
+
171
+ == Pre-config element
172
+
173
+ The pre_config element is a child of log4r_config and contains:
174
+
175
+ * 'custom_levels' element
176
+ * 'global' element
177
+ * 'parameters' element
178
+ * any number of 'parameter' elements
179
+
180
+ === Pre_config: Custom Levels
181
+
182
+ The custom_levels element is not an <i>XML directive</i> of pre_config. It
183
+ <b>must</b> be specified like this:
184
+
185
+ <custom_levels>Foo, Bar, Baz</custom_levels>
186
+
187
+ And <b>not</b> like this:
188
+
189
+ <!-- NOT SUPPORTED -->
190
+ <custom_levels levels="Foo, Bar, Baz"/>
191
+
192
+ === Pre_config: Global Level
193
+
194
+ <global level="DEBUG"/>
195
+
196
+ or
197
+
198
+ <global><level>DEBUG</level></global>
199
+
200
+ Here, level is an XML directive of global.
201
+
202
+ === Pre_config: Parameters
203
+
204
+ Parameters are variables that will be substituted later on. Please
205
+ see the <b>Concept: Variable Substitution</b> section above. Parameters
206
+ are <i>XML Directives</i>, which means they can be expressed using elements
207
+ or attributes. Here is an example:
208
+
209
+ <parameter name="param name 1" value="param value 1">
210
+ <parameter name="param name 2" value="param value 2">
211
+ ...
212
+ <parameters>
213
+ <param3>value3</param3>
214
+ <param4>value3</param4>
215
+ ...
216
+
217
+ === Pre_config: Complete Example
218
+
219
+ <log4r_config>
220
+
221
+ <pre_config>
222
+ <custom_levels>
223
+ Foo,Bar, Baz
224
+ </custom_levels>
225
+ <global level="Bar"/>
226
+ <parameters>
227
+ <logpath>/var/log/foo</logpath>
228
+ <mypattern>%l [%d] %m</mypattern>
229
+ </parameters>
230
+ </pre_config>
231
+
232
+ <!-- define some outputters and loggers -->
233
+
234
+ </log4r_config>
235
+
236
+ == Configuring Log4r Objects
237
+
238
+ The XML configuration grammar for Loggers, Outputters and the like are
239
+ covered in the usage guidelines for those classes.
240
+
241
+ == Order Doesn't Matter
242
+
243
+ You can (it is hoped) define any of the XML objects in any order desired.