mtn_log4r 1.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +15 -0
  2. data/doc/content/contact.html +22 -0
  3. data/doc/content/contribute.html +21 -0
  4. data/doc/content/index.html +90 -0
  5. data/doc/content/license.html +56 -0
  6. data/doc/content/manual.html +449 -0
  7. data/doc/dev/README.developers +55 -0
  8. data/doc/dev/checklist +23 -0
  9. data/doc/dev/things-to-do +5 -0
  10. data/doc/images/log4r-logo.png +0 -0
  11. data/doc/images/logo2.png +0 -0
  12. data/doc/log4r.css +111 -0
  13. data/doc/rdoc-log4r.css +696 -0
  14. data/doc/templates/main.html +147 -0
  15. data/examples/README +19 -0
  16. data/examples/ancestors.rb +53 -0
  17. data/examples/chainsaw_settings.xml +7 -0
  18. data/examples/customlevels.rb +34 -0
  19. data/examples/filelog.rb +25 -0
  20. data/examples/fileroll.rb +40 -0
  21. data/examples/gmail.rb +30 -0
  22. data/examples/gmail.yaml +95 -0
  23. data/examples/log4r_yaml.yaml +0 -0
  24. data/examples/logclient.rb +25 -0
  25. data/examples/logserver.rb +18 -0
  26. data/examples/moderate.xml +29 -0
  27. data/examples/moderateconfig.rb +66 -0
  28. data/examples/myformatter.rb +23 -0
  29. data/examples/outofthebox.rb +21 -0
  30. data/examples/rdoc-gen +2 -0
  31. data/examples/rrconfig.xml +63 -0
  32. data/examples/rrsetup.rb +42 -0
  33. data/examples/simpleconfig.rb +39 -0
  34. data/examples/syslogcustom.rb +52 -0
  35. data/examples/xmlconfig.rb +25 -0
  36. data/examples/yaml.rb +30 -0
  37. data/lib/log4r/GDC.rb +41 -0
  38. data/lib/log4r/MDC.rb +59 -0
  39. data/lib/log4r/NDC.rb +86 -0
  40. data/lib/log4r/base.rb +74 -0
  41. data/lib/log4r/config.rb +9 -0
  42. data/lib/log4r/configurator.rb +224 -0
  43. data/lib/log4r/formatter/formatter.rb +109 -0
  44. data/lib/log4r/formatter/log4jxmlformatter.rb +65 -0
  45. data/lib/log4r/formatter/patternformatter.rb +145 -0
  46. data/lib/log4r/lib/drbloader.rb +52 -0
  47. data/lib/log4r/lib/xmlloader.rb +24 -0
  48. data/lib/log4r/logevent.rb +28 -0
  49. data/lib/log4r/logger.rb +199 -0
  50. data/lib/log4r/loggerfactory.rb +89 -0
  51. data/lib/log4r/logserver.rb +28 -0
  52. data/lib/log4r/outputter/consoleoutputters.rb +18 -0
  53. data/lib/log4r/outputter/datefileoutputter.rb +117 -0
  54. data/lib/log4r/outputter/emailoutputter.rb +143 -0
  55. data/lib/log4r/outputter/fileoutputter.rb +56 -0
  56. data/lib/log4r/outputter/iooutputter.rb +55 -0
  57. data/lib/log4r/outputter/outputter.rb +134 -0
  58. data/lib/log4r/outputter/outputterfactory.rb +61 -0
  59. data/lib/log4r/outputter/rabbitoutputter.rb +70 -0
  60. data/lib/log4r/outputter/remoteoutputter.rb +40 -0
  61. data/lib/log4r/outputter/rollingfileoutputter.rb +234 -0
  62. data/lib/log4r/outputter/scribeoutputter.rb +37 -0
  63. data/lib/log4r/outputter/staticoutputter.rb +30 -0
  64. data/lib/log4r/outputter/syslogoutputter.rb +130 -0
  65. data/lib/log4r/outputter/udpoutputter.rb +53 -0
  66. data/lib/log4r/rdoc/GDC +14 -0
  67. data/lib/log4r/rdoc/MDC +16 -0
  68. data/lib/log4r/rdoc/NDC +41 -0
  69. data/lib/log4r/rdoc/configurator +243 -0
  70. data/lib/log4r/rdoc/emailoutputter +103 -0
  71. data/lib/log4r/rdoc/formatter +39 -0
  72. data/lib/log4r/rdoc/log4jxmlformatter +21 -0
  73. data/lib/log4r/rdoc/log4r +89 -0
  74. data/lib/log4r/rdoc/logger +175 -0
  75. data/lib/log4r/rdoc/logserver +85 -0
  76. data/lib/log4r/rdoc/outputter +108 -0
  77. data/lib/log4r/rdoc/patternformatter +128 -0
  78. data/lib/log4r/rdoc/scribeoutputter +16 -0
  79. data/lib/log4r/rdoc/syslogoutputter +29 -0
  80. data/lib/log4r/rdoc/win32eventoutputter +7 -0
  81. data/lib/log4r/rdoc/yamlconfigurator +20 -0
  82. data/lib/log4r/repository.rb +88 -0
  83. data/lib/log4r/staticlogger.rb +49 -0
  84. data/lib/log4r/version.rb +4 -0
  85. data/lib/log4r/yamlconfigurator.rb +198 -0
  86. data/lib/log4r.rb +18 -0
  87. data/tests/README +10 -0
  88. data/tests/testGDC.rb +24 -0
  89. data/tests/testMDC.rb +40 -0
  90. data/tests/testNDC.rb +25 -0
  91. data/tests/test_helper.rb +12 -0
  92. data/tests/testall.rb +6 -0
  93. data/tests/testbase.rb +48 -0
  94. data/tests/testchainsaw.rb +42 -0
  95. data/tests/testconf.xml +37 -0
  96. data/tests/testcustom.rb +30 -0
  97. data/tests/testformatter.rb +31 -0
  98. data/tests/testlogger.rb +200 -0
  99. data/tests/testoutputter.rb +143 -0
  100. data/tests/testpatternformatter.rb +76 -0
  101. data/tests/testthreads.rb +31 -0
  102. data/tests/testxmlconf.rb +48 -0
  103. data/tests/testyaml.rb +39 -0
  104. data/tests/testyaml_arrays.yaml +25 -0
  105. data/tests/testyaml_injection.yaml +22 -0
  106. metadata +193 -0
@@ -0,0 +1,224 @@
1
+ # :include: rdoc/configurator
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id$
6
+
7
+ require "log4r/logger"
8
+ require "log4r/outputter/staticoutputter"
9
+ require "log4r/lib/xmlloader"
10
+ require "log4r/logserver"
11
+ require "log4r/outputter/remoteoutputter"
12
+
13
+ # TODO: catch unparsed parameters #{FOO} and die
14
+ module Log4r
15
+ # Gets raised when Configurator encounters bad XML.
16
+ class ConfigError < Exception
17
+ end
18
+
19
+ # See log4r/configurator.rb
20
+ class Configurator
21
+ include REXML if HAVE_REXML
22
+ @@params = Hash.new
23
+
24
+ # Get a parameter's value
25
+ def self.[](param); @@params[param] end
26
+ # Define a parameter with a value
27
+ def self.[]=(param, value); @@params[param] = value end
28
+
29
+ # Sets the custom levels. This method accepts symbols or strings.
30
+ #
31
+ # Configurator.custom_levels('My', 'Custom', :Levels)
32
+ #
33
+ # Alternatively, you can specify custom levels in XML:
34
+ #
35
+ # <log4r_config>
36
+ # <pre_config>
37
+ # <custom_levels>
38
+ # My, Custom, Levels
39
+ # </custom_levels>
40
+ # ...
41
+
42
+ def self.custom_levels(*levels)
43
+ return Logger.root if levels.size == 0
44
+ for i in 0...levels.size
45
+ name = levels[i].to_s
46
+ if name =~ /\s/ or name !~ /^[A-Z]/
47
+ raise TypeError, "#{name} is not a valid Ruby Constant name", caller
48
+ end
49
+ end
50
+ Log4r.define_levels *levels
51
+ end
52
+
53
+ # Given a filename, loads the XML configuration for Log4r.
54
+ def self.load_xml_file(filename)
55
+ detect_rexml
56
+ actual_load Document.new(File.new(filename))
57
+ end
58
+
59
+ # You can load a String XML configuration instead of a file.
60
+ def self.load_xml_string(string)
61
+ detect_rexml
62
+ actual_load Document.new(string)
63
+ end
64
+
65
+ #######
66
+ private
67
+ #######
68
+
69
+ def self.detect_rexml
70
+ unless HAVE_REXML
71
+ raise LoadError,
72
+ "Need REXML to load XML configuration", caller[1..-1]
73
+ end
74
+ end
75
+
76
+ def self.actual_load(doc)
77
+ confignode = doc.elements['//log4r_config']
78
+ if confignode.nil?
79
+ raise ConfigError,
80
+ "<log4r_config> element not defined", caller[1..-1]
81
+ end
82
+ decode_xml(confignode)
83
+ end
84
+
85
+ def self.decode_xml(doc)
86
+ decode_pre_config(doc.elements['pre_config'])
87
+ doc.elements.each('outputter') {|e| decode_outputter(e)}
88
+ doc.elements.each('logger') {|e| decode_logger(e)}
89
+ doc.elements.each('logserver') {|e| decode_logserver(e)}
90
+ end
91
+
92
+ def self.decode_pre_config(e)
93
+ return Logger.root if e.nil?
94
+ decode_custom_levels(e.elements['custom_levels'])
95
+ global_config(e.elements['global'])
96
+ global_config(e.elements['root'])
97
+ decode_parameters(e.elements['parameters'])
98
+ e.elements.each('parameter') {|p| decode_parameter(p)}
99
+ end
100
+
101
+ def self.decode_custom_levels(e)
102
+ return Logger.root if e.nil? or e.text.nil?
103
+ begin custom_levels *Log4rTools.comma_split(e.text)
104
+ rescue TypeError => te
105
+ raise ConfigError, te.message, caller[1..-4]
106
+ end
107
+ end
108
+
109
+ def self.global_config(e)
110
+ return if e.nil?
111
+ globlev = e.value_of 'level'
112
+ return if globlev.nil?
113
+ lev = LNAMES.index(globlev) # find value in LNAMES
114
+ Log4rTools.validate_level(lev, 4) # choke on bad level
115
+ Logger.global.level = lev
116
+ end
117
+
118
+ def self.decode_parameters(e)
119
+ e.elements.each{|p| @@params[p.name] = p.text} unless e.nil?
120
+ end
121
+
122
+ def self.decode_parameter(e)
123
+ @@params[e.value_of('name')] = e.value_of 'value'
124
+ end
125
+
126
+ def self.decode_outputter(e)
127
+ # fields
128
+ name = e.value_of 'name'
129
+ type = e.value_of 'type'
130
+ level = e.value_of 'level'
131
+ only_at = e.value_of 'only_at'
132
+ # validation
133
+ raise ConfigError, "Outputter missing name", caller[1..-3] if name.nil?
134
+ raise ConfigError, "Outputter missing type", caller[1..-3] if type.nil?
135
+ Log4rTools.validate_level(LNAMES.index(level)) unless level.nil?
136
+ only_levels = []
137
+ unless only_at.nil?
138
+ for lev in Log4rTools.comma_split(only_at)
139
+ alev = LNAMES.index(lev)
140
+ Log4rTools.validate_level(alev, 3)
141
+ only_levels.push alev
142
+ end
143
+ end
144
+ formatter = decode_formatter(e.elements['formatter'])
145
+ # build the eval string
146
+ buff = "Outputter[name] = #{type}.new name"
147
+ buff += ",:level=>#{LNAMES.index(level)}" unless level.nil?
148
+ buff += ",:formatter=>formatter" unless formatter.nil?
149
+ params = decode_hash_params(e)
150
+ buff += "," + params.join(',') if params.size > 0
151
+ begin eval buff
152
+ rescue Exception => ae
153
+ raise ConfigError,
154
+ "Problem creating outputter: #{ae.message}", caller[1..-3]
155
+ end
156
+ Outputter[name].only_at *only_levels if only_levels.size > 0
157
+ Outputter[name]
158
+ end
159
+
160
+ def self.decode_formatter(e)
161
+ return nil if e.nil?
162
+ type = e.value_of 'type'
163
+ raise ConfigError, "Formatter missing type", caller[1..-4] if type.nil?
164
+ buff = "#{type}.new " + decode_hash_params(e).join(',')
165
+ begin return eval(buff)
166
+ rescue Exception => ae
167
+ raise ConfigError,
168
+ "Problem creating outputter: #{ae.message}", caller[1..-4]
169
+ end
170
+ end
171
+
172
+ ExcludeParams = %w{formatter level name type}
173
+
174
+ # Does the fancy parameter to hash argument transformation
175
+ def self.decode_hash_params(e)
176
+ buff = []
177
+ e.attributes.each_attribute {|p|
178
+ next if ExcludeParams.include? p.name
179
+ buff << ":" + p.name + "=>" + paramsub(p.value)
180
+ }
181
+ e.elements.each {|p|
182
+ next if ExcludeParams.include? p.name
183
+ buff << ":" + p.name + "=>" + paramsub(p.text)
184
+ }
185
+ buff
186
+ end
187
+
188
+ # Substitues any #{foo} in the XML with Parameter['foo']
189
+ def self.paramsub(str)
190
+ return nil if str.nil?
191
+ @@params.each {|param, value| str.sub! '#{'+param+'}', value}
192
+ "'" + str + "'"
193
+ end
194
+
195
+ def self.decode_logger(e)
196
+ l = Logger.new e.value_of('name')
197
+ decode_logger_common(l, e)
198
+ end
199
+
200
+ def self.decode_logserver(e)
201
+ return unless HAVE_REXML
202
+ name = e.value_of 'name'
203
+ uri = e.value_of 'uri'
204
+ l = LogServer.new name, uri
205
+ decode_logger_common(l, e)
206
+ end
207
+
208
+ def self.decode_logger_common(l, e)
209
+ level = e.value_of 'level'
210
+ additive = e.value_of 'additive'
211
+ trace = e.value_of 'trace'
212
+ l.level = LNAMES.index(level) unless level.nil?
213
+ l.additive = additive unless additive.nil?
214
+ l.trace = trace unless trace.nil?
215
+ # and now for outputters
216
+ outs = e.value_of 'outputters'
217
+ Log4rTools.comma_split(outs).each {|n| l.add n.strip} unless outs.nil?
218
+ e.elements.each('outputter') {|e|
219
+ name = (e.value_of 'name' or e.text)
220
+ l.add Outputter[name]
221
+ }
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,109 @@
1
+ # :include: ../rdoc/formatter
2
+ #
3
+ # Version:: $Id$
4
+
5
+ require "singleton"
6
+ require 'json'
7
+ require "log4r/base"
8
+
9
+ module Log4r
10
+
11
+ # Formatter is an abstract class and a null object
12
+ class Formatter
13
+ def initialize(hash={})
14
+ end
15
+ # Define this method in a subclass to format data.
16
+ def format(logevent)
17
+ end
18
+ end
19
+
20
+ # SimpleFormatter produces output like this:
21
+ #
22
+ # WARN loggername> Danger, Will Robinson, danger!
23
+ #
24
+ # Does not write traces and does not inspect objects.
25
+
26
+ class SimpleFormatter < Formatter
27
+ def format(event)
28
+ sprintf("%*s %s> %s\n", MaxLevelLength, LNAMES[event.level],
29
+ event.name, event.data)
30
+ end
31
+ end
32
+
33
+ # BasicFormatter produces output like this:
34
+ #
35
+ # WARN loggername: I dropped my Wookie!
36
+ #
37
+ # Or like this if trace is on:
38
+ #
39
+ # WARN loggername(file.rb at 12): Hot potato!
40
+ #
41
+ # Also, it will pretty-print any Exception it gets and
42
+ # +inspect+ everything else.
43
+ #
44
+ # Hash arguments include:
45
+ #
46
+ # +depth+:: How many lines of the stacktrace to display.
47
+
48
+ class BasicFormatter < SimpleFormatter
49
+ @@basicformat = "%*s %s"
50
+
51
+ def initialize(hash={})
52
+ @depth = (hash[:depth] or hash['depth'] or 7).to_i
53
+ end
54
+
55
+ def format(event)
56
+ buff = sprintf(@@basicformat, MaxLevelLength, LNAMES[event.level],
57
+ event.name)
58
+ buff << (event.tracer.nil? ? "" : "(#{event.tracer[0]})") + ": "
59
+ buff << format_object(event.data) + "\n"
60
+ buff
61
+ end
62
+
63
+ # Formats data according to its class:
64
+ #
65
+ # String:: Prints it out as normal.
66
+ # Exception:: Produces output similar to command-line exceptions.
67
+ # Object:: Prints the type of object, then the output of
68
+ # +inspect+. An example -- Array: [1, 2, 3]
69
+
70
+ def format_object(obj)
71
+ klass = obj.class
72
+ case
73
+ when klass == Exception
74
+ return "Caught #{obj.class}: #{obj.message}\n\t" +\
75
+ (obj.backtrace.nil? ? [] : obj.backtrace[0...@depth]).join("\n\t").gsub('"','\\\\"')
76
+ when klass == Hash
77
+ return obj.to_json.gsub('"','\\\\"')
78
+ when klass == String
79
+ return obj.gsub('"','\\\\"')
80
+ else # inspect the object
81
+ return "#{obj.class}: #{obj.inspect}".gsub('"','\\\\"')
82
+ end
83
+ end
84
+ end
85
+
86
+ # Formats objects the same way irb does:
87
+ #
88
+ # loggername:foo.rb in 12>
89
+ # [1, 3, 4]
90
+ # loggername:foo.rb in 13>
91
+ # {1=>"1"}
92
+ #
93
+ # Strings don't get inspected. just printed. The trace is optional.
94
+
95
+ class ObjectFormatter < Formatter
96
+ def format(event)
97
+ buff = event.logger.name
98
+ buff << (event.tracer.nil? ? "" : ":#{event.tracer[0]}") + ">\n"
99
+ buff << (event.data.kind_of?(String) ? event.data : event.data.inspect)
100
+ buff << "\n"
101
+ end
102
+ end
103
+
104
+ # Outputters that don't define a Formatter will get this, which
105
+ # is currently BasicFormatter
106
+ class DefaultFormatter < BasicFormatter
107
+ end
108
+
109
+ end
@@ -0,0 +1,65 @@
1
+ # :include: ../rdoc/log4jxmlformatter
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id$
6
+
7
+ require "log4r/formatter/formatter"
8
+
9
+ require "rubygems"
10
+ begin
11
+ require "builder"
12
+ rescue LoadError
13
+ puts "builder gem is required to use log4jxmlformatter, i.e. gem install builder"
14
+ end
15
+
16
+ module Log4r
17
+
18
+ class Log4jXmlFormatter < BasicFormatter
19
+
20
+ def format(logevent)
21
+ logger = logevent.fullname.gsub('::', '.')
22
+ timestamp = (Time.now.to_f * 1000).to_i
23
+ level = LNAMES[logevent.level]
24
+ message = format_object(logevent.data)
25
+ exception = message if logevent.data.kind_of? Exception
26
+ file, line, method = parse_caller(logevent.tracer[0]) if logevent.tracer
27
+
28
+ builder = Builder::XmlMarkup.new
29
+ xml = builder.log4j :event, :logger => logger,
30
+ :timestamp => timestamp,
31
+ :level => level,
32
+ :thread => '' do |e|
33
+ e.log4j :NDC, NDC.get
34
+ e.log4j :message, message
35
+ e.log4j :throwable, exception if exception
36
+ e.log4j :locationInfo, :class => '',
37
+ :method => method,
38
+ :file => file,
39
+ :line => line
40
+ e.log4j :properties do |p|
41
+ MDC.get_context.each do |key, value|
42
+ p.log4j :data, :name => key, :value => value
43
+ end
44
+ end
45
+ end
46
+ xml
47
+ end
48
+
49
+ #######
50
+ private
51
+ #######
52
+
53
+ def parse_caller(line)
54
+ if /^(.+?):(\d+)(?::in `(.*)')?/ =~ line
55
+ file = Regexp.last_match[1]
56
+ line = Regexp.last_match[2].to_i
57
+ method = Regexp.last_match[3]
58
+ [file, line, method]
59
+ else
60
+ []
61
+ end
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,145 @@
1
+ # :include: ../rdoc/patternformatter
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id$
6
+
7
+ require "log4r/formatter/formatter"
8
+ require "log4r/GDC"
9
+ require "log4r/MDC"
10
+ require "log4r/NDC"
11
+
12
+ module Log4r
13
+ # See log4r/formatter/patternformatter.rb
14
+ class PatternFormatter < BasicFormatter
15
+
16
+ # Arguments to sprintf keyed to directive letters<br>
17
+ # %c - event short name<br>
18
+ # %C - event fullname<br>
19
+ # %d - date<br>
20
+ # %g - Global Diagnostic Context (GDC)<br>
21
+ # %t - trace<br>
22
+ # %m - message<br>
23
+ # %h - thread name<br>
24
+ # %p - process ID aka PID<br>
25
+ # %M - formatted message<br>
26
+ # %l - Level in string form<br>
27
+ # %x - Nested Diagnostic Context (NDC)<br>
28
+ # %X - Mapped Diagnostic Context (MDC), syntax is "%X{key}"<br>
29
+ # %% - Insert a %<br>
30
+ DirectiveTable = {
31
+ "c" => 'event.name',
32
+ "C" => 'event.fullname',
33
+ "d" => 'format_date',
34
+ "g" => 'Log4r::GDC.get()',
35
+ "t" => '(event.tracer.nil? ? "no trace" : event.tracer[0])',
36
+ "T" => '(event.tracer.nil? ? "no trace" : event.tracer[0].split(File::SEPARATOR)[-1])',
37
+ "m" => 'event.data',
38
+ "h" => '(Thread.current[:name] or Thread.current.to_s)',
39
+ "p" => 'Process.pid.to_s',
40
+ "M" => 'format_object(event.data)',
41
+ "l" => 'LNAMES[event.level]',
42
+ "x" => 'Log4r::NDC.get()',
43
+ "X" => 'Log4r::MDC.get("DTR_REPLACE")',
44
+ "%" => '"%"'
45
+ }
46
+
47
+ # Matches the first directive encountered and the stuff around it.
48
+ #
49
+ # * $1 is the stuff before directive or "" if not applicable
50
+ # * $2 is the directive group or nil if there's none
51
+ # * $3 is the %#.# match within directive group
52
+ # * $4 is the .# match which we don't use (it's there to match properly)
53
+ # * $5 is the directive letter
54
+ # * $6 is the stuff after the directive or "" if not applicable
55
+ # * $7 is the remainder
56
+
57
+ DirectiveRegexp = /([^%]*)((%-?\d*(\.\d+)?)([cCdgtTmhpMlxX%]))?(\{.+?\})?(.*)/
58
+
59
+ # default date format
60
+ ISO8601 = "%Y-%m-%d %H:%M:%S"
61
+
62
+ attr_reader :pattern, :date_pattern, :date_method
63
+
64
+ # Accepts the following hash arguments (either a string or a symbol):
65
+ #
66
+ # [<tt>pattern</tt>] A pattern format string.
67
+ # [<tt>date_pattern</tt>] A Time#strftime format string. See the
68
+ # Ruby Time class for details.
69
+ # [+date_method+]
70
+ # As an option to date_pattern, specify which
71
+ # Time.now method to call. For
72
+ # example, +usec+ or +to_s+.
73
+ # Specify it as a String or Symbol.
74
+ #
75
+ # The default date format is ISO8601, which looks like this:
76
+ #
77
+ # yyyy-mm-dd hh:mm:ss => 2001-01-12 13:15:50
78
+
79
+ def initialize(hash={})
80
+ super(hash)
81
+ @pattern = (hash['pattern'] or hash[:pattern] or nil)
82
+ @date_pattern = (hash['date_pattern'] or hash[:date_pattern] or nil)
83
+ @date_method = (hash['date_method'] or hash[:date_method] or nil)
84
+ @date_pattern = ISO8601 if @date_pattern.nil? and @date_method.nil?
85
+ PatternFormatter.create_format_methods(self)
86
+ end
87
+
88
+ # PatternFormatter works by dynamically defining a <tt>format</tt> method
89
+ # based on the supplied pattern format. This method contains a call to
90
+ # Kernel#sptrintf with arguments containing the data requested in
91
+ # the pattern format.
92
+ #
93
+ # How is this magic accomplished? First, we visit each directive
94
+ # and change the %#.# component to %#.#s. The directive letter is then
95
+ # used to cull an appropriate entry from the DirectiveTable for the
96
+ # sprintf argument list. After assembling the method definition, we
97
+ # run module_eval on it, and voila.
98
+
99
+ def PatternFormatter.create_format_methods(pf) #:nodoc:
100
+ # first, define the format_date method
101
+ if pf.date_method
102
+ module_eval "def pf.format_date; Time.now.#{pf.date_method}; end"
103
+ else
104
+ module_eval <<-EOS
105
+ def pf.format_date
106
+ Time.now.strftime "#{pf.date_pattern}"
107
+ end
108
+ EOS
109
+ end
110
+ # and now the main format method
111
+ ebuff = "def pf.format(event)\n sprintf(\""
112
+ _pattern = pf.pattern.dup
113
+ args = [] # the args to sprintf which we'll append to ebuff lastly
114
+ while true # work on each match in turn
115
+ match = DirectiveRegexp.match _pattern
116
+ ebuff << match[1] unless match[1].empty?
117
+ break if match[2].nil?
118
+ # deal with the directive by inserting a %#.#s where %#.# is copied
119
+ # directy from the match
120
+ ebuff << match[3] + "s"
121
+
122
+ if ( match[5] == 'X' && match[6] != nil ) then
123
+
124
+ # MDC matches, need to be able to handle String, Symbol or Number
125
+ match6sub = /[\{\}\"]/
126
+ mdcmatches = match[6].match /\{(:?)(\d*)(.*)\}/
127
+
128
+ if ( mdcmatches[1] == "" && mdcmatches[2] == "" )
129
+ match6sub = /[\{\}]/ # don't remove surrounding "'s if String
130
+ end
131
+
132
+ args <<
133
+ DirectiveTable[match[5]].gsub("DTR_REPLACE", match[6]).gsub(match6sub,'')
134
+ else
135
+ args << DirectiveTable[match[5]] # cull the data for our argument list
136
+ end
137
+ break if match[7].empty?
138
+ _pattern = match[7]
139
+ end
140
+ ebuff << '\n", ' + args.join(', ') + ")\n"
141
+ ebuff << "end\n"
142
+ module_eval ebuff
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,52 @@
1
+ #:nodoc:
2
+ module Log4r
3
+ begin
4
+ require 'romp'
5
+ HAVE_ROMP = true
6
+ rescue LoadError
7
+ HAVE_ROMP = false
8
+ end
9
+
10
+ if HAVE_ROMP
11
+
12
+ module ROMPServer #:nodoc:
13
+ private
14
+ def start_server(_uri, accept)
15
+ @server = ROMP::Server.new(_uri, accept) # what if accept is nil?
16
+ @server.bind(self, "Log4r::LogServer")
17
+ end
18
+ end
19
+
20
+ module ROMPClient #:nodoc:
21
+ private
22
+ def connect
23
+ begin
24
+ @client = ROMP::Client.new(@uri, false)
25
+ @remote_logger = @client.resolve("Log4r::LogServer")
26
+ rescue Exception => e
27
+ Logger.log_internal(-2) {
28
+ "RemoteOutputter '#{@name}' failed to connect to #{@uri}!"
29
+ }
30
+ Logger.log_internal {e}
31
+ self.level = OFF
32
+ end
33
+ end
34
+ # we use propagated = true
35
+ def send_buffer
36
+ begin
37
+ @buff.each {|levent|
38
+ lname = LNAMES[levent.level].downcase
39
+ @remote_logger.oneway(lname, levent, true)
40
+ }
41
+ rescue Exception => e
42
+ Logger.log_internal(-2) {"RemoteOutputter '#{@name}' can't log!"}
43
+ Logger.log_internal {e}
44
+ self.level = OFF
45
+ ensure @buff.clear
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,24 @@
1
+ #:nodoc:
2
+ module Log4r
3
+ begin
4
+ require 'rexml/document'
5
+ HAVE_REXML = true
6
+ rescue LoadError
7
+ HAVE_REXML = false
8
+ end
9
+ end
10
+
11
+ if Log4r::HAVE_REXML
12
+ module REXML #:nodoc: all
13
+ class Element
14
+ def value_of(elmt)
15
+ val = attributes[elmt]
16
+ if val.nil?
17
+ sub = elements[elmt]
18
+ val = sub.text unless sub.nil?
19
+ end
20
+ val
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ # :nodoc:
2
+ module Log4r
3
+
4
+ ##
5
+ # LogEvent wraps up all the miscellaneous data associated with a logging
6
+ # statement. It gets passed around to the varied components of Log4r and
7
+ # should be of interest to those creating extensions.
8
+ #
9
+ # Data contained:
10
+ #
11
+ # [level] The integer level of the log event. Use LNAMES[level]
12
+ # to get the actual level name.
13
+ # [tracer] The execution stack returned by <tt>caller</tt> at the
14
+ # log event. It is nil if the invoked Logger's trace is false.
15
+ # [data] The object that was passed into the logging method.
16
+ # [name] The name of the logger that was invoked.
17
+ # [fullname] The fully qualified name of the logger that was invoked.
18
+ #
19
+ # Note that creating timestamps is a task left to formatters.
20
+
21
+ class LogEvent
22
+ attr_reader :level, :tracer, :data, :name, :fullname
23
+ def initialize(level, logger, tracer, data)
24
+ @level, @tracer, @data = level, tracer, data
25
+ @name, @fullname = logger.name, logger.fullname
26
+ end
27
+ end
28
+ end