log4rails 1.1.11

Sign up to get free protection for your applications and to get access to all the features.
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,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,206 @@
1
+ # :include: rdoc/logger
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id$
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
+ # Return array of defined levels.
82
+ def levels
83
+ LNAMES
84
+ end
85
+
86
+ # Set the additivity of the logger dynamically. True or false.
87
+ def additive=(_additive)
88
+ @additive = _additive
89
+ LoggerFactory.define_methods(self)
90
+ Logger.log_internal {"Logger '#{@fullname}' is additive"}
91
+ @additive
92
+ end
93
+
94
+ # Set whether the logger traces. Can be set dynamically. Defaults
95
+ # to false and understands the strings 'true' and 'false'.
96
+ def trace=(_trace)
97
+ @trace =
98
+ case _trace
99
+ when "true", true then true
100
+ else false end
101
+ LoggerFactory.define_methods(self)
102
+ Logger.log_internal {"Logger '#{@fullname}' is tracing"} if @trace
103
+ @trace
104
+ end
105
+
106
+ # Please don't reset the parent
107
+ def parent=(parent)
108
+ @parent = parent
109
+ end
110
+
111
+ # Set the Outputters dynamically by name or reference. Can be done any
112
+ # time.
113
+ def outputters=(_outputters)
114
+ @outputters.clear
115
+ add(*_outputters)
116
+ end
117
+
118
+ # Add outputters by name or by reference. Can be done any time.
119
+ def add(*_outputters)
120
+ for thing in _outputters
121
+ o = (thing.kind_of?(Outputter) ? thing : Outputter[thing])
122
+ # some basic validation
123
+ if not o.kind_of?(Outputter)
124
+ raise TypeError, "Expected kind of Outputter, got #{o.class}", caller
125
+ elsif o.nil?
126
+ raise TypeError, "Couldn't find Outputter '#{thing}'", caller
127
+ end
128
+ @outputters.push o
129
+ Logger.log_internal {"Added outputter '#{o.name}' to '#{@fullname}'"}
130
+ end
131
+ @outputters
132
+ end
133
+
134
+ # Remove outputters from this logger by name only. Can be done any time.
135
+ def remove(*_outputters)
136
+ for name in _outputters
137
+ o = Outputter[name]
138
+ @outputters.delete o
139
+ Logger.log_internal {"Removed outputter '#{o.name}' from '#{@fullname}'"}
140
+ end
141
+ end
142
+
143
+ def is_root?; false end
144
+
145
+ def ==(other)
146
+ return true if self.object_id == other.object_id
147
+ end
148
+
149
+ # fix for rails 4+
150
+ # <tk>
151
+ def formatter
152
+ nil
153
+ end
154
+ # </tk>
155
+ end
156
+
157
+
158
+ # RootLogger should be retrieved with Logger.root or Logger.global.
159
+ # It's supposed to be transparent.
160
+ #--
161
+ # We must guarantee the creation of RootLogger before any other Logger
162
+ # or Outputter gets their logging methods defined. There are two
163
+ # guarantees in the code:
164
+ #
165
+ # * Logger#deal_with_inheritance - calls RootLogger.instance when
166
+ # a new Logger is created without a parent. Parents must exist, therefore
167
+ # RootLogger is forced to be created.
168
+ #
169
+ # * OutputterFactory.create_methods - Calls Logger.root first. So if
170
+ # an Outputter is created, RootLogger is also created.
171
+ #
172
+ # When RootLogger is created, it calls
173
+ # Log4r.define_levels(*Log4rConfig::LogLevels). This ensures that the
174
+ # default levels are loaded if no custom ones are.
175
+
176
+ class RootLogger < Logger
177
+ include Singleton
178
+
179
+ def initialize
180
+ Log4r.define_levels(*Log4rConfig::LogLevels) # ensure levels are loaded
181
+ @level = ALL
182
+ @outputters = []
183
+ Repository['root'] = self
184
+ Repository['global'] = self
185
+ LoggerFactory.undefine_methods(self)
186
+ end
187
+
188
+ def is_root?; true end
189
+
190
+ # Set the global level. Any loggers defined thereafter will
191
+ # not log below the global level regardless of their levels.
192
+
193
+ def level=(alevel); @level = alevel end
194
+
195
+ # Does nothing
196
+ def outputters=(foo); end
197
+ # Does nothing
198
+ def trace=(foo); end
199
+ # Does nothing
200
+ def additive=(foo); end
201
+ # Does nothing
202
+ def add(*foo); end
203
+ # Does nothing
204
+ def remove(*foo); end
205
+ end
206
+ end
@@ -0,0 +1,89 @@
1
+ # :nodoc:
2
+ # Version:: $Id$
3
+
4
+ require "log4r/base"
5
+ require "log4r/repository"
6
+ require 'log4r/logevent'
7
+
8
+ module Log4r
9
+ class Logger
10
+ class LoggerFactory #:nodoc:
11
+
12
+ # we want to log iff root.lev <= lev && logger.lev <= lev
13
+ # BTW, root is guaranteed to be defined by this point
14
+ def self.define_methods(logger)
15
+ return if logger.is_root?
16
+ undefine_methods(logger)
17
+ globlev = Repository['root'].level
18
+ return if logger.level == OFF or globlev == OFF
19
+ toggle_methods(globlev, logger)
20
+ end
21
+
22
+ # set logging methods to null defaults
23
+ def self.undefine_methods(logger)
24
+ for lname in LNAMES
25
+ next if lname == 'OFF'|| lname == 'ALL'
26
+ unset_log(logger, lname)
27
+ set_false(logger, lname)
28
+ end
29
+ set_false(logger, 'all')
30
+ set_true(logger, 'off')
31
+ end
32
+
33
+ # toggle methods >= globlev that are also >= level
34
+ def self.toggle_methods(globlev, logger)
35
+ for lev in globlev...LEVELS # satisfies >= globlev
36
+ next if lev < logger.level # satisfies >= level
37
+ next if LNAMES[lev] == 'OFF'
38
+ next if LNAMES[lev] == 'ALL'
39
+ set_log(logger, LNAMES[lev])
40
+ set_true(logger, LNAMES[lev])
41
+ end
42
+ if logger.level == ALL
43
+ set_true(logger, 'all')
44
+ end
45
+ if logger.level != OFF && globlev != OFF
46
+ set_false(logger, 'off')
47
+ end
48
+ end
49
+
50
+ # And now, the weird dynamic method definitions! :)
51
+
52
+ def self.unset_log(logger, lname)
53
+ mstr="def logger.#{lname.downcase}(data=nil, propagated=false); end"
54
+ module_eval mstr
55
+ end
56
+
57
+ # Logger logging methods are defined here.
58
+ def self.set_log(logger, lname)
59
+ # invoke caller iff the logger invoked is tracing
60
+ tracercall = (logger.trace ? "caller" : "nil")
61
+ # maybe pass parent a logevent. second arg is the switch
62
+ if logger.additive && !logger.parent.is_root?
63
+ parentcall = "@parent.#{lname.downcase}(event, true)"
64
+ end
65
+ mstr = %-
66
+ def logger.#{lname.downcase}(data=nil, propagated=false)
67
+ if propagated then event = data
68
+ else
69
+ data = yield if block_given?
70
+ event = LogEvent.new(#{lname}, self, #{tracercall}, data)
71
+ end
72
+ @outputters.each {|o| o.#{lname.downcase}(event) }
73
+ #{parentcall}
74
+ end
75
+ -
76
+ module_eval mstr
77
+ end
78
+
79
+ def self.set_false(logger, lname)
80
+ module_eval "def logger.#{lname.downcase}?; false end"
81
+ end
82
+
83
+ def self.set_true(logger, lname)
84
+ module_eval "def logger.#{lname.downcase}?; true end"
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,28 @@
1
+ # :include: rdoc/logserver
2
+
3
+ require 'log4r/logger'
4
+ require 'log4r/lib/drbloader'
5
+
6
+ module Log4r
7
+ # See log4r/logserver.rb
8
+ class LogServer < Logger
9
+ attr_reader :uri
10
+
11
+ # A valid ROMP uri must be specified.
12
+ def initialize(_fullname, _uri, _level=nil,
13
+ _additive=true, _trace=false, &accept)
14
+ super(_fullname, _level, _additive, _trace)
15
+ @uri = _uri
16
+ start_server(_uri, accept)
17
+ Logger.log_internal {"LogServer started at #{@uri}"}
18
+ end
19
+
20
+ if HAVE_ROMP
21
+ include ROMPServer
22
+ else
23
+ def initialize(*args)
24
+ raise RuntimeError, "LogServer not supported. ROMP is required", caller
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ require 'log4r/outputter/syslogoutputter'
2
+
3
+ module Log4r
4
+ class BufferedSyslogOutputter < SyslogOutputter
5
+
6
+ def initialize(*args)
7
+ super
8
+ @buff = {}
9
+ end
10
+
11
+ def flush
12
+ synch do
13
+ begin
14
+ @buff.each do |pri, message|
15
+ Syslog.open(@ident, @logopt, @facility) do |s|
16
+ s.log(pri, '%s', message.join("\t"))
17
+ end
18
+ end
19
+ ensure
20
+ @buff.clear
21
+ end
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def canonical_log(logevent)
28
+ begin
29
+ pri = SYSLOG_LEVELS_MAP[@levels_map[LNAMES[logevent.level]]]
30
+ rescue
31
+ pri = LOG_INFO
32
+ end
33
+
34
+ return if logevent.data.empty?
35
+
36
+ o = format(logevent)
37
+ msg = if o.is_a? Exception
38
+ "#{o.class} at (#{o.backtrace[0]}): #{o.message}"
39
+ elsif o.respond_to?(:to_str)
40
+ o.to_str
41
+ else
42
+ o.inspect
43
+ end
44
+ synch { @buff.has_key?(pri) ? @buff[pri].push(msg) : @buff[pri] = [msg] }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ # :nodoc:
2
+ require "log4r/outputter/iooutputter"
3
+
4
+ module Log4r
5
+ # Same as IOOutputter(name, $stdout)
6
+ class StdoutOutputter < IOOutputter
7
+ def initialize(_name, hash={})
8
+ super(_name, $stdout, hash)
9
+ end
10
+ end
11
+
12
+ # Same as IOOutputter(name, $stderr)
13
+ class StderrOutputter < IOOutputter
14
+ def initialize(_name, hash={})
15
+ super(_name, $stderr, hash)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,117 @@
1
+ # = DateFileOutputter
2
+ #
3
+ # Subclass of FileOutputter that changes the log file daily. When a new
4
+ # day begins, a new file is created with the date included in the name.
5
+ #
6
+ # == Usage
7
+ #
8
+ # df_out = DateFileOutputter.new('name',
9
+ # :dirname="/tmp", :date_pattern=>"%m-%d"
10
+ # )
11
+ #
12
+ # == Rate of Change
13
+ #
14
+ # A new logfile is created whenever the current time as formatted by the date
15
+ # pattern no longer matches the previous time. (This is a simple String
16
+ # comparison.) So, in order to change the frequency of the rollover, just
17
+ # alter the date pattern to match how fast the files should be generated.
18
+ # For instance, to generate files by the minute,
19
+ #
20
+ # df_out.date_pattern = "%M"
21
+ #
22
+ # This causes the following files to show up one minute apart, asuming the
23
+ # script starts at the 4th minute of the hour:
24
+ #
25
+ # file_04.rb
26
+ # file_05.rb
27
+ # file_06.rb
28
+ # ...
29
+ #
30
+ # The only limitation of this approach is that the precise time cannot be
31
+ # recorded as the smallest time interval equals the rollover period for this
32
+ # system.
33
+
34
+ require "log4r/outputter/fileoutputter"
35
+ require "log4r/staticlogger"
36
+
37
+ module Log4r
38
+
39
+ # Additional hash arguments are:
40
+ #
41
+ # [<tt>:dirname</tt>] Directory of the log file
42
+ # [<tt>:date_pattern</tt>] Time.strftime format string (default is "%Y-%m-%d")
43
+
44
+ class DateFileOutputter < FileOutputter
45
+ DEFAULT_DATE_FMT = "%Y-%m-%d"
46
+
47
+ def initialize(_name, hash={})
48
+ @DatePattern = (hash[:date_pattern] or hash['date_pattern'] or
49
+ DEFAULT_DATE_FMT)
50
+ @DateStamp = Time.now.strftime( @DatePattern);
51
+ _dirname = (hash[:dirname] or hash['dirname'])
52
+ # hash[:dirname] masks hash[:filename]
53
+ if _dirname
54
+ if not FileTest.directory?( _dirname)
55
+ raise StandardError, "'#{_dirname}' must be a valid directory", caller
56
+ end
57
+ end
58
+
59
+ _filename = (hash[:filename] or hash['filename'])
60
+ if _filename.nil?
61
+ @filebase = File.basename( $0, '.rb') + ".log"
62
+ else
63
+ @filebase = File.basename((hash[:filename] or hash['filename'] or ""))
64
+ end
65
+
66
+ # Get rid of the 'nil' in the path
67
+ path = [_dirname, @filebase.sub(/(\.\w*)$/, "_#{@DateStamp}" + '\1')].compact
68
+ hash[:filename] = hash['filename'] = File.join(path)
69
+
70
+ super(_name, hash)
71
+ end
72
+
73
+ #######
74
+ private
75
+ #######
76
+
77
+ # perform the write
78
+ def write(data)
79
+ change if requiresChange
80
+ super
81
+ end
82
+
83
+ # construct a new filename from the DateStamp
84
+ def makeNewFilename
85
+ @DateStamp = Time.now.strftime( @DatePattern);
86
+ @filename = File.join(File.dirname(@filename),
87
+ @filebase.sub(/(\.\w*)$/, "_#{@DateStamp}" + '\1'))
88
+ end
89
+
90
+ # does the file require a change?
91
+ def requiresChange
92
+ _DateStamp = Time.now.strftime( @DatePattern);
93
+ if not _DateStamp == @DateStamp
94
+ @DateStamp = _DateStamp
95
+ return true
96
+ end
97
+ false
98
+ end
99
+
100
+ # change the file
101
+ def change
102
+ begin
103
+ @out.close
104
+ rescue
105
+ Logger.log_internal {
106
+ "DateFileOutputter '#{@name}' could not close #{@filename}"
107
+ }
108
+ end
109
+ makeNewFilename
110
+ @out = File.new(@filename, (@trunc ? "wb" : "ab"))
111
+ Logger.log_internal {
112
+ "DateFileOutputter '#{@name}' now writing to #{@filename}"
113
+ }
114
+ end
115
+ end
116
+
117
+ end