sml-log4r 1.0.6

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 (77) hide show
  1. data/doc/content/contact.html +22 -0
  2. data/doc/content/contribute.html +21 -0
  3. data/doc/content/index.html +90 -0
  4. data/doc/content/license.html +56 -0
  5. data/doc/content/manual.html +449 -0
  6. data/doc/dev/README.developers +40 -0
  7. data/doc/dev/checklist +14 -0
  8. data/doc/dev/things-to-do +2 -0
  9. data/doc/images/crush/logo2.png +0 -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/old/manual.html +348 -0
  14. data/doc/templates/main.html +147 -0
  15. data/examples/README +19 -0
  16. data/examples/customlevels.rb +34 -0
  17. data/examples/fileroll.rb +40 -0
  18. data/examples/log4r_yaml.yaml +0 -0
  19. data/examples/logclient.rb +25 -0
  20. data/examples/logserver.rb +18 -0
  21. data/examples/moderate.xml +29 -0
  22. data/examples/moderateconfig.rb +66 -0
  23. data/examples/myformatter.rb +23 -0
  24. data/examples/outofthebox.rb +21 -0
  25. data/examples/rrconfig.xml +63 -0
  26. data/examples/rrsetup.rb +42 -0
  27. data/examples/simpleconfig.rb +39 -0
  28. data/examples/xmlconfig.rb +25 -0
  29. data/examples/yaml.rb +30 -0
  30. data/src/log4r.rb +17 -0
  31. data/src/log4r/base.rb +74 -0
  32. data/src/log4r/config.rb +9 -0
  33. data/src/log4r/configurator.rb +224 -0
  34. data/src/log4r/formatter/formatter.rb +105 -0
  35. data/src/log4r/formatter/patternformatter.rb +108 -0
  36. data/src/log4r/lib/drbloader.rb +52 -0
  37. data/src/log4r/lib/xmlloader.rb +24 -0
  38. data/src/log4r/logevent.rb +28 -0
  39. data/src/log4r/logger.rb +194 -0
  40. data/src/log4r/loggerfactory.rb +89 -0
  41. data/src/log4r/logserver.rb +28 -0
  42. data/src/log4r/outputter/consoleoutputters.rb +18 -0
  43. data/src/log4r/outputter/datefileoutputter.rb +110 -0
  44. data/src/log4r/outputter/emailoutputter.rb +115 -0
  45. data/src/log4r/outputter/fileoutputter.rb +49 -0
  46. data/src/log4r/outputter/iooutputter.rb +55 -0
  47. data/src/log4r/outputter/outputter.rb +132 -0
  48. data/src/log4r/outputter/outputterfactory.rb +59 -0
  49. data/src/log4r/outputter/remoteoutputter.rb +40 -0
  50. data/src/log4r/outputter/rollingfileoutputter.rb +126 -0
  51. data/src/log4r/outputter/staticoutputter.rb +30 -0
  52. data/src/log4r/outputter/syslogoutputter.rb +75 -0
  53. data/src/log4r/rdoc/configurator +243 -0
  54. data/src/log4r/rdoc/emailoutputter +103 -0
  55. data/src/log4r/rdoc/formatter +39 -0
  56. data/src/log4r/rdoc/log4r +89 -0
  57. data/src/log4r/rdoc/logger +175 -0
  58. data/src/log4r/rdoc/logserver +85 -0
  59. data/src/log4r/rdoc/outputter +108 -0
  60. data/src/log4r/rdoc/patternformatter +128 -0
  61. data/src/log4r/rdoc/syslogoutputter +29 -0
  62. data/src/log4r/rdoc/yamlconfigurator +20 -0
  63. data/src/log4r/repository.rb +65 -0
  64. data/src/log4r/staticlogger.rb +49 -0
  65. data/src/log4r/yamlconfigurator.rb +0 -0
  66. data/tests/include.rb +7 -0
  67. data/tests/runtest.rb +6 -0
  68. data/tests/testbase.rb +45 -0
  69. data/tests/testcustom.rb +33 -0
  70. data/tests/testdefault.rb +25 -0
  71. data/tests/testformatter.rb +29 -0
  72. data/tests/testlogger.rb +198 -0
  73. data/tests/testoutputter.rb +112 -0
  74. data/tests/testpatternformatter.rb +26 -0
  75. data/tests/testxmlconf.rb +51 -0
  76. data/tests/xml/testconf.xml +37 -0
  77. metadata +140 -0
@@ -0,0 +1,105 @@
1
+ # :include: ../rdoc/formatter
2
+ #
3
+ # Version:: $Id: formatter.rb,v 1.7 2003/09/01 22:33:20 cepheus Exp $
4
+
5
+ require "singleton"
6
+
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
+ if obj.kind_of? Exception
72
+ return "Caught #{obj.class}: #{obj.message}\n\t" +\
73
+ obj.backtrace[0...@depth].join("\n\t")
74
+ elsif obj.kind_of? String
75
+ return obj
76
+ else # inspect the object
77
+ return "#{obj.class}: #{obj.inspect}"
78
+ end
79
+ end
80
+ end
81
+
82
+ # Formats objects the same way irb does:
83
+ #
84
+ # loggername:foo.rb in 12>
85
+ # [1, 3, 4]
86
+ # loggername:foo.rb in 13>
87
+ # {1=>"1"}
88
+ #
89
+ # Strings don't get inspected. just printed. The trace is optional.
90
+
91
+ class ObjectFormatter < Formatter
92
+ def format(event)
93
+ buff = event.logger.name
94
+ buff += (event.tracer.nil? ? "" : ":#{event.tracer[0]}") + ">\n"
95
+ buff += (event.data.kind_of?(String) ? event.data : event.data.inspect)
96
+ buff += "\n"
97
+ end
98
+ end
99
+
100
+ # Outputters that don't define a Formatter will get this, which
101
+ # is currently BasicFormatter
102
+ class DefaultFormatter < BasicFormatter
103
+ end
104
+
105
+ end
@@ -0,0 +1,108 @@
1
+ # :include: ../rdoc/patternformatter
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id: patternformatter.rb,v 1.2 2002/01/28 16:05:05 cepheus Exp $
6
+ # Author:: Leon Torres <leon@ugcs.caltech.edu>
7
+
8
+ require "log4r/formatter/formatter"
9
+
10
+ module Log4r
11
+ # See log4r/formatter/patternformatter.rb
12
+ class PatternFormatter < BasicFormatter
13
+
14
+ # Arguments to sprintf keyed to directive letters
15
+ DirectiveTable = {
16
+ "c" => 'event.name',
17
+ "C" => 'event.fullname',
18
+ "d" => 'format_date',
19
+ "t" => 'event.tracer[0]',
20
+ "m" => 'event.data',
21
+ "M" => 'format_object(event.data)',
22
+ "l" => 'LNAMES[event.level]',
23
+ "%" => '"%"'
24
+ }
25
+
26
+ # Matches the first directive encountered and the stuff around it.
27
+ #
28
+ # * $1 is the stuff before directive or "" if not applicable
29
+ # * $2 is the directive group or nil if there's none
30
+ # * $3 is the %#.# match within directive group
31
+ # * $4 is the .# match which we don't use (it's there to match properly)
32
+ # * $5 is the directive letter
33
+ # * $6 is the stuff after the directive or "" if not applicable
34
+
35
+ DirectiveRegexp = /([^%]*)((%-?\d*(\.\d+)?)([cCdtmMl%]))?(.*)/
36
+
37
+ # default date format
38
+ ISO8601 = "%Y-%m-%d %H:%M:%S"
39
+
40
+ attr_reader :pattern, :date_pattern, :date_method
41
+
42
+ # Accepts the following hash arguments (either a string or a symbol):
43
+ #
44
+ # [<tt>pattern</tt>] A pattern format string.
45
+ # [<tt>date_pattern</tt>] A Time#strftime format string. See the
46
+ # Ruby Time class for details.
47
+ # [+date_method+]
48
+ # As an option to date_pattern, specify which
49
+ # Time.now method to call. For
50
+ # example, +usec+ or +to_s+.
51
+ # Specify it as a String or Symbol.
52
+ #
53
+ # The default date format is ISO8601, which looks like this:
54
+ #
55
+ # yyyy-mm-dd hh:mm:ss => 2001-01-12 13:15:50
56
+
57
+ def initialize(hash={})
58
+ super(hash)
59
+ @pattern = (hash['pattern'] or hash[:pattern] or nil)
60
+ @date_pattern = (hash['date_pattern'] or hash[:date_pattern] or nil)
61
+ @date_method = (hash['date_method'] or hash[:date_method] or nil)
62
+ @date_pattern = ISO8601 if @date_pattern.nil? and @date_method.nil?
63
+ PatternFormatter.create_format_methods(self)
64
+ end
65
+
66
+ # PatternFormatter works by dynamically defining a <tt>format</tt> method
67
+ # based on the supplied pattern format. This method contains a call to
68
+ # Kernel#sptrintf with arguments containing the data requested in
69
+ # the pattern format.
70
+ #
71
+ # How is this magic accomplished? First, we visit each directive
72
+ # and change the %#.# component to %#.#s. The directive letter is then
73
+ # used to cull an appropriate entry from the DirectiveTable for the
74
+ # sprintf argument list. After assembling the method definition, we
75
+ # run module_eval on it, and voila.
76
+
77
+ def PatternFormatter.create_format_methods(pf) #:nodoc:
78
+ # first, define the format_date method
79
+ if pf.date_method
80
+ module_eval "def pf.format_date; Time.now.#{pf.date_method}; end"
81
+ else
82
+ module_eval <<-EOS
83
+ def pf.format_date
84
+ Time.now.strftime "#{pf.date_pattern}"
85
+ end
86
+ EOS
87
+ end
88
+ # and now the main format method
89
+ ebuff = "def pf.format(event)\n sprintf(\""
90
+ _pattern = pf.pattern.dup
91
+ args = [] # the args to sprintf which we'll append to ebuff lastly
92
+ while true # work on each match in turn
93
+ match = DirectiveRegexp.match _pattern
94
+ ebuff += match[1] unless match[1].empty?
95
+ break if match[2].nil?
96
+ # deal with the directive by inserting a %#.#s where %#.# is copied
97
+ # directy from the match
98
+ ebuff += match[3] + "s"
99
+ args << DirectiveTable[match[5]] # cull the data for our argument list
100
+ break if match[6].empty?
101
+ _pattern = match[6]
102
+ end
103
+ ebuff += '\n", ' + args.join(', ') + ")\n"
104
+ ebuff += "end\n"
105
+ module_eval ebuff
106
+ end
107
+ end
108
+ 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
@@ -0,0 +1,194 @@
1
+ # :include: rdoc/logger
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id: logger.rb,v 1.24 2004/03/17 19:13:07 fando Exp $
6
+ # Author:: Leon Torres <leon(at)ugcs.caltech.edu>
7
+
8
+ require "log4r/outputter/outputter"
9
+ require "log4r/repository"
10
+ require "log4r/loggerfactory"
11
+ require "log4r/staticlogger"
12
+
13
+ module Log4r
14
+
15
+ # See log4r/logger.rb
16
+ class Logger
17
+ attr_reader :name, :fullname, :path, :level, :parent
18
+ attr_reader :additive, :trace, :outputters
19
+
20
+ # Logger requires a name. The last 3 parameters are:
21
+ #
22
+ # level:: Do I have a level? (Otherwise, I'll inherit my parent's)
23
+ # additive:: Am I additive?
24
+ # trace:: Do I record the execution trace? (slows things a wee bit)
25
+
26
+ def initialize(_fullname, _level=nil, _additive=true, _trace=false)
27
+ # validation
28
+ raise ArgumentError, "Logger must have a name", caller if _fullname.nil?
29
+ Log4rTools.validate_level(_level) unless _level.nil?
30
+ validate_name(_fullname)
31
+
32
+ # create the logger
33
+ @fullname = _fullname
34
+ @outputters = []
35
+ @additive = _additive
36
+ deal_with_inheritance(_level)
37
+ LoggerFactory.define_methods(self)
38
+ self.trace = _trace
39
+ Repository[@fullname] = self
40
+ end
41
+
42
+ def validate_name(_fullname)
43
+ parts = _fullname.split Log4rConfig::LoggerPathDelimiter
44
+ for part in parts
45
+ raise ArgumentError, "Malformed path", caller[1..-1] if part.empty?
46
+ end
47
+ end
48
+ private :validate_name
49
+
50
+ # Parses name for location in heiarchy, sets the parent, and
51
+ # deals with level inheritance
52
+
53
+ def deal_with_inheritance(_level)
54
+ mypath = @fullname.split Log4rConfig::LoggerPathDelimiter
55
+ @name = mypath.pop
56
+ if mypath.empty? # then root is my daddy
57
+ @path = ""
58
+ # This is one of the guarantees that RootLogger gets created
59
+ @parent = Logger.root
60
+ else
61
+ @path = mypath.join(Log4rConfig::LoggerPathDelimiter)
62
+ @parent = Repository.find_ancestor(@path)
63
+ @parent = Logger.root if @parent.nil?
64
+ end
65
+ # inherit the level if no level defined
66
+ if _level.nil? then @level = @parent.level
67
+ else @level = _level end
68
+ Repository.reassign_any_children(self)
69
+ end
70
+ private :deal_with_inheritance
71
+
72
+ # Set the logger level dynamically. Does not affect children.
73
+ def level=(_level)
74
+ Log4rTools.validate_level(_level)
75
+ @level = _level
76
+ LoggerFactory.define_methods(self)
77
+ Logger.log_internal {"Logger '#{@fullname}' set to #{LNAMES[@level]}"}
78
+ @level
79
+ end
80
+
81
+ # Set the additivity of the logger dynamically. True or false.
82
+ def additive=(_additive)
83
+ @additive = _additive
84
+ LoggerFactory.define_methods(self)
85
+ Logger.log_internal {"Logger '#{@fullname}' is additive"}
86
+ @additive
87
+ end
88
+
89
+ # Set whether the logger traces. Can be set dynamically. Defaults
90
+ # to false and understands the strings 'true' and 'false'.
91
+ def trace=(_trace)
92
+ @trace =
93
+ case _trace
94
+ when "true", true then true
95
+ else false end
96
+ LoggerFactory.define_methods(self)
97
+ Logger.log_internal {"Logger '#{@fullname}' is tracing"} if @trace
98
+ @trace
99
+ end
100
+
101
+ # Please don't reset the parent
102
+ def parent=(parent)
103
+ @parent = parent
104
+ end
105
+
106
+ # Set the Outputters dynamically by name or reference. Can be done any
107
+ # time.
108
+ def outputters=(_outputters)
109
+ @outputters.clear
110
+ add(*_outputters)
111
+ end
112
+
113
+ # Add outputters by name or by reference. Can be done any time.
114
+ def add(*_outputters)
115
+ for thing in _outputters
116
+ o = (thing.kind_of?(Outputter) ? thing : Outputter[thing])
117
+ # some basic validation
118
+ if not o.kind_of?(Outputter)
119
+ raise TypeError, "Expected kind of Outputter, got #{o.class}", caller
120
+ elsif o.nil?
121
+ raise TypeError, "Couldn't find Outputter '#{thing}'", caller
122
+ end
123
+ @outputters.push o
124
+ Logger.log_internal {"Added outputter '#{o.name}' to '#{@fullname}'"}
125
+ end
126
+ @outputters
127
+ end
128
+
129
+ # Remove outputters from this logger by name only. Can be done any time.
130
+ def remove(*_outputters)
131
+ for name in _outputters
132
+ o = Outputter[name]
133
+ @outputters.delete o
134
+ Logger.log_internal {"Removed outputter '#{o.name}' from '#{@fullname}'"}
135
+ end
136
+ end
137
+
138
+ def is_root?; false end
139
+
140
+ def ==(other)
141
+ return true if object_id == other.object_id
142
+ end
143
+ end
144
+
145
+
146
+ # RootLogger should be retrieved with Logger.root or Logger.global.
147
+ # It's supposed to be transparent.
148
+ #--
149
+ # We must guarantee the creation of RootLogger before any other Logger
150
+ # or Outputter gets their logging methods defined. There are two
151
+ # guarantees in the code:
152
+ #
153
+ # * Logger#deal_with_inheritance - calls RootLogger.instance when
154
+ # a new Logger is created without a parent. Parents must exist, therefore
155
+ # RootLogger is forced to be created.
156
+ #
157
+ # * OutputterFactory.create_methods - Calls Logger.root first. So if
158
+ # an Outputter is created, RootLogger is also created.
159
+ #
160
+ # When RootLogger is created, it calls
161
+ # Log4r.define_levels(*Log4rConfig::LogLevels). This ensures that the
162
+ # default levels are loaded if no custom ones are.
163
+
164
+ class RootLogger < Logger
165
+ include Singleton
166
+
167
+ def initialize
168
+ Log4r.define_levels(*Log4rConfig::LogLevels) # ensure levels are loaded
169
+ @level = ALL
170
+ @outputters = []
171
+ Repository['root'] = self
172
+ Repository['global'] = self
173
+ LoggerFactory.undefine_methods(self)
174
+ end
175
+
176
+ def is_root?; true end
177
+
178
+ # Set the global level. Any loggers defined thereafter will
179
+ # not log below the global level regardless of their levels.
180
+
181
+ def level=(alevel); @level = alevel end
182
+
183
+ # Does nothing
184
+ def outputters=(foo); end
185
+ # Does nothing
186
+ def trace=(foo); end
187
+ # Does nothing
188
+ def additive=(foo); end
189
+ # Does nothing
190
+ def add(*foo); end
191
+ # Does nothing
192
+ def remove(*foo); end
193
+ end
194
+ end