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,143 @@
1
+ # :include: ../rdoc/emailoutputter
2
+
3
+ require 'log4r/outputter/outputter'
4
+ require 'log4r/staticlogger'
5
+ require 'net/smtp'
6
+
7
+ module Log4r
8
+
9
+ class EmailOutputter < Outputter
10
+ attr_reader :server, :port, :domain, :acct, :authtype, :subject, :tls
11
+
12
+ def initialize(_name, hash={})
13
+ super(_name, hash)
14
+ validate(hash)
15
+ @buff = []
16
+ begin
17
+ Logger.log_internal {
18
+ "EmailOutputter '#{@name}' running SMTP client on #{@server}:#{@port}"
19
+ }
20
+ rescue Exception => e
21
+ Logger.log_internal(-2) {
22
+ "EmailOutputter '#{@name}' failed to start SMTP client!"
23
+ }
24
+ Logger.log_internal {e}
25
+ self.level = OFF
26
+ raise e
27
+ end
28
+ end
29
+
30
+ # send out an email with the current buffer
31
+ def flush
32
+ synch { send_mail }
33
+ Logger.log_internal {"Flushed EmailOutputter '#{@name}'"}
34
+ end
35
+
36
+ private
37
+
38
+ def validate(hash)
39
+ @buffsize = (hash[:buffsize] or hash['buffsize'] or 100).to_i
40
+ @formatfirst = Log4rTools.decode_bool(hash, :formatfirst, false)
41
+ decode_immediate_at(hash)
42
+ validate_smtp_params(hash)
43
+ end
44
+
45
+ def decode_immediate_at(hash)
46
+ @immediate = Hash.new
47
+ _at = (hash[:immediate_at] or hash['immediate_at'])
48
+ return if _at.nil?
49
+ Log4rTools.comma_split(_at).each {|lname|
50
+ level = LNAMES.index(lname)
51
+ if level.nil?
52
+ Logger.log_internal(-2) do
53
+ "EmailOutputter: skipping bad immediate_at level name '#{lname}'"
54
+ end
55
+ next
56
+ end
57
+ @immediate[level] = true
58
+ }
59
+ end
60
+
61
+ def validate_smtp_params(hash)
62
+ @from = (hash[:from] or hash['from'])
63
+ raise ArgumentError, "Must specify from address" if @from.nil?
64
+ _to = (hash[:to] or hash['to'] or "")
65
+ @to = Log4rTools.comma_split(_to)
66
+ raise ArgumentError, "Must specify recepients" if @to.empty?
67
+ @server = (hash[:server] or hash['server'] or 'localhost')
68
+ @port = (hash[:port] or hash['port'] or 25).to_i
69
+ @domain = (hash[:domain] or hash['domain'] or ENV['HOSTNAME'])
70
+ @acct = (hash[:acct] or hash['acct'])
71
+ @passwd = (hash[:passwd] or hash['passwd'])
72
+ @authtype = (hash[:authtype] or hash['authtype'] or :cram_md5).to_s.to_sym
73
+ @subject = (hash[:subject] or hash['subject'] or "Message of #{$0}")
74
+ @tls = (hash[:tls] or hash['tls'] or nil)
75
+ @params = [@server, @port, @domain, @acct, @passwd, @authtype]
76
+ end
77
+
78
+ def canonical_log(event)
79
+ synch {
80
+ @buff.push case @formatfirst
81
+ when true then @formatter.format event
82
+ else event
83
+ end
84
+ send_mail if @buff.size >= @buffsize or @immediate[event.level]
85
+ }
86
+ end
87
+
88
+ def send_mail
89
+ msg =
90
+ case @formatfirst
91
+ when true then @buff.join
92
+ else @buff.collect{|e| @formatter.format e}.join
93
+ end
94
+
95
+ ### build a mail header for RFC 822
96
+ rfc822msg =
97
+ "From: #{@from}\n" +
98
+ "To: #{@to}\n" +
99
+ "Subject: #{@subject}\n" +
100
+ "Date: #{Time.now.strftime( "%a, %d %b %Y %H:%M:%S %z %Z")}\n" +
101
+ "Message-Id: <#{"%.8f" % Time.now.to_f}@#{@domain}>\n\n" +
102
+ "#{msg}"
103
+
104
+ ### send email
105
+ begin
106
+
107
+ smtp = Net::SMTP.new( @server, @port )
108
+
109
+ if ( @tls )
110
+
111
+ # >1.8.7 has smtp_tls built in, 1.8.6 requires smtp_tls
112
+ if RUBY_VERSION < "1.8.7" then
113
+ begin
114
+ require 'rubygems'
115
+ require 'smtp_tls'
116
+ smtp.enable_starttls if smtp.respond_to?(:enable_starttls)
117
+ rescue LoadError => e
118
+ Logger.log_internal(-2) {
119
+ "EmailOutputter '#{@name}' unable to load smtp_tls, needed to support TLS on Ruby versions < 1.8.7"
120
+ }
121
+ raise e
122
+ end
123
+ else # RUBY_VERSION >= 1.8.7
124
+ smtp.enable_starttls_auto if smtp.respond_to?(:enable_starttls_auto)
125
+ end
126
+
127
+ end # if @tls
128
+
129
+ smtp.start(@domain, @acct, @passwd, @authtype) do |s|
130
+ s.send_message(rfc822msg, @from, @to)
131
+ end
132
+ rescue Exception => e
133
+ Logger.log_internal(-2) {
134
+ "EmailOutputter '#{@name}' couldn't send email!"
135
+ }
136
+ Logger.log_internal {e}
137
+ self.level = OFF
138
+ raise e
139
+ ensure @buff.clear
140
+ end # begin
141
+ end # def send_mail
142
+ end # class EmailOutputter
143
+ end # module Log4r
@@ -0,0 +1,57 @@
1
+ # :nodoc:
2
+ # Version:: $Id$
3
+
4
+ require "log4r/outputter/iooutputter"
5
+ require "log4r/staticlogger"
6
+
7
+ module Log4r
8
+
9
+ # Convenience wrapper for File. Additional hash arguments are:
10
+ #
11
+ # [<tt>:filename</tt>] Name of the file to log to.
12
+ # [<tt>:trunc</tt>] Truncate the file?
13
+ class FileOutputter < IOOutputter
14
+ attr_reader :trunc, :filename
15
+
16
+ def initialize(_name, hash={})
17
+ super(_name, nil, hash)
18
+
19
+ @trunc = Log4rTools.decode_bool(hash, :trunc, false)
20
+ _filename = (hash[:filename] or hash['filename'])
21
+ @create = Log4rTools.decode_bool(hash, :create, true)
22
+
23
+ if _filename.class != String
24
+ raise TypeError, "Argument 'filename' must be a String", caller
25
+ end
26
+
27
+ # file validation
28
+ if FileTest.exist?( _filename )
29
+ if not FileTest.file?( _filename )
30
+ raise StandardError, "'#{_filename}' is not a regular file", caller
31
+ elsif not FileTest.writable?( _filename )
32
+ raise StandardError, "'#{_filename}' is not writable!", caller
33
+ end
34
+ else # ensure directory is writable
35
+ dir = File.dirname( _filename )
36
+ if not FileTest.writable?( dir )
37
+ raise StandardError, "'#{dir}' is not writable!"
38
+ end
39
+ end
40
+
41
+ @filename = _filename
42
+ if ( @create == true ) then
43
+ @out = File.new(@filename, (@trunc ? "wb" : "ab"))
44
+ @out.sync = Log4rTools.decode_bool(hash, :sync, false)
45
+ Logger.log_internal {
46
+ "FileOutputter '#{@name}' writing to #{@filename}"
47
+ }
48
+ else
49
+ Logger.log_internal {
50
+ "FileOutputter '#{@name}' called with :create == false, #{@filename}"
51
+ }
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,55 @@
1
+ # :nodoc:
2
+ require "log4r/outputter/outputter"
3
+ require "log4r/staticlogger"
4
+
5
+ module Log4r
6
+
7
+ ##
8
+ # IO Outputter invokes print then flush on the wrapped IO
9
+ # object. If the IO stream dies, IOOutputter sets itself to OFF
10
+ # and the system continues on its merry way.
11
+ #
12
+ # To find out why an IO stream died, create a logger named 'log4r'
13
+ # and look at the output.
14
+
15
+ class IOOutputter < Outputter
16
+
17
+ # IOOutputter needs an IO object to write to.
18
+ def initialize(_name, _out, hash={})
19
+ super(_name, hash)
20
+ @out = _out
21
+ end
22
+
23
+ def closed?
24
+ @out.closed?
25
+ end
26
+
27
+ # Close the IO and sets level to OFF
28
+ def close
29
+ @out.close unless @out.nil? || closed?
30
+ @level = OFF
31
+ OutputterFactory.create_methods(self)
32
+ Logger.log_internal {"Outputter '#{@name}' closed IO and set to OFF"}
33
+ end
34
+
35
+ #######
36
+ private
37
+ #######
38
+
39
+ # perform the write
40
+ def write(data)
41
+ begin
42
+ @out.print data
43
+ @out.flush
44
+ rescue IOError => ioe # recover from this instead of crash
45
+ Logger.log_internal {"IOError in Outputter '#{@name}'!"}
46
+ Logger.log_internal {ioe}
47
+ close
48
+ rescue NameError => ne
49
+ Logger.log_internal {"Outputter '#{@name}' IO is #{@out.class}!"}
50
+ Logger.log_internal {ne}
51
+ close
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,134 @@
1
+ # :include: ../rdoc/outputter
2
+ #
3
+ # == Other Info
4
+ #
5
+ # Version:: $Id$
6
+ # Author:: Leon Torres <leon@ugcs.caltech.edu>
7
+
8
+ require "thread"
9
+
10
+ require "log4r/outputter/outputterfactory"
11
+ require "log4r/formatter/formatter"
12
+ require "log4r/staticlogger"
13
+
14
+ require 'monitor'
15
+
16
+ module Log4r
17
+
18
+ class Outputter < Monitor
19
+ attr_reader :name, :level, :formatter
20
+ @@outputters = Hash.new
21
+
22
+ # An Outputter needs a name. RootLogger will be loaded if not already
23
+ # done. The hash arguments are as follows:
24
+ #
25
+ # [<tt>:level</tt>] Logger level. Optional, defaults to root level
26
+ # [<tt>:formatter</tt>] A Formatter. Defaults to DefaultFormatter
27
+
28
+ def initialize(_name, hash={})
29
+ super()
30
+ if _name.nil?
31
+ raise ArgumentError, "Bad arguments. Name and IO expected.", caller
32
+ end
33
+ @name = _name
34
+ validate_hash(hash)
35
+ @@outputters[@name] = self
36
+ end
37
+
38
+ # dynamically change the level
39
+ def level=(_level)
40
+ Log4rTools.validate_level(_level)
41
+ @level = _level
42
+ OutputterFactory.create_methods(self)
43
+ Logger.log_internal {"Outputter '#{@name}' level is #{LNAMES[_level]}"}
44
+ end
45
+
46
+ # Set the levels to log. All others will be ignored
47
+ def only_at(*levels)
48
+ raise ArgumentError, "Gimme some levels!", caller if levels.empty?
49
+ raise ArgumentError, "Can't log only_at ALL", caller if levels.include? ALL
50
+ levels.each {|level| Log4rTools.validate_level(level)}
51
+ @level = levels.sort.first
52
+ OutputterFactory.create_methods self, levels
53
+ Logger.log_internal {
54
+ "Outputter '#{@name}' writes only on " +
55
+ levels.collect{|l| LNAMES[l]}.join(", ")
56
+ }
57
+ end
58
+
59
+ # Dynamically change the formatter. You can just specify a Class
60
+ # object and the formatter will invoke +new+ or +instance+
61
+ # on it as appropriate.
62
+
63
+ def formatter=(_formatter)
64
+ if _formatter.kind_of?(Formatter)
65
+ @formatter = _formatter
66
+ elsif _formatter.kind_of?(Class) and _formatter <= Formatter
67
+ if _formatter.respond_to? :instance
68
+ @formatter = _formatter.instance
69
+ else
70
+ @formatter = _formatter.new
71
+ end
72
+ else
73
+ raise TypeError, "Argument was not a Formatter!", caller
74
+ end
75
+ Logger.log_internal {"Outputter '#{@name}' using #{@formatter.class}"}
76
+ end
77
+
78
+ # Call flush to force an outputter to write out any buffered
79
+ # log events. Similar to IO#flush, so use in a similar fashion.
80
+
81
+ def flush
82
+ end
83
+
84
+ #########
85
+ protected
86
+ #########
87
+
88
+ # Validates the common hash arguments. For now, that would be
89
+ # +:level+, +:formatter+ and the string equivalents
90
+ def validate_hash(hash)
91
+ # default to root level and DefaultFormatter
92
+ if hash.empty?
93
+ self.level = Logger.root.level
94
+ @formatter = DefaultFormatter.new
95
+ return
96
+ end
97
+ self.level = (hash[:level] or hash['level'] or Logger.root.level)
98
+ self.formatter = (hash[:formatter] or hash['formatter'] or DefaultFormatter.new)
99
+ end
100
+
101
+ #######
102
+ private
103
+ #######
104
+
105
+ # This method handles all log events passed to a typical Outputter.
106
+ # Overload this to change the overall behavior of an outputter. Make
107
+ # sure that the new behavior is thread safe.
108
+
109
+ def canonical_log(logevent)
110
+ synch { write(format(logevent)) }
111
+ end
112
+
113
+ # Common method to format data. All it does is call the resident
114
+ # formatter's format method. If a different formatting behavior is
115
+ # needed, then overload this method.
116
+
117
+ def format(logevent)
118
+ # @formatter is guaranteed to be DefaultFormatter if no Formatter
119
+ # was specified
120
+ @formatter.format(logevent)
121
+ end
122
+
123
+ # Abstract method to actually write the data to a destination.
124
+ # Custom outputters should overload this to specify how the
125
+ # formatted data should be written and to where.
126
+
127
+ def write(data)
128
+ end
129
+
130
+ def synch; synchronize { yield } end
131
+
132
+ end
133
+
134
+ end
@@ -0,0 +1,60 @@
1
+ # :nodoc:
2
+ # Version: $Id$
3
+
4
+ require "log4r/base"
5
+ require "log4r/repository"
6
+
7
+ require 'monitor'
8
+
9
+ module Log4r
10
+ class Outputter < Monitor
11
+
12
+ class OutputterFactory #:nodoc:
13
+ include Singleton
14
+
15
+ # handles two cases: logging above a level (no second arg specified)
16
+ # or logging a set of levels (passed into the second argument)
17
+ def self.create_methods(out, levels=nil)
18
+ Logger.root # force levels to be loaded
19
+
20
+ # first, undefine all the log levels
21
+ for mname in LNAMES
22
+ undefine_log(mname.downcase, out)
23
+ end
24
+ if not levels.nil? and levels.include? OFF
25
+ raise TypeError, "Can't log only_at OFF", caller[1..-1]
26
+ end
27
+ return out if out.level == OFF
28
+
29
+ if levels.nil? # then define the log methods for lev >= outlev
30
+ for lev in out.level...LEVELS
31
+ define_log(LNAMES[lev].downcase, lev, out)
32
+ end
33
+ else # define the logs only for assigned levels
34
+ for lev in levels
35
+ define_log(LNAMES[lev].downcase, lev, out)
36
+ end
37
+ end
38
+ return out
39
+ end
40
+
41
+ # we need to synch the actual write/format for thread safteyness
42
+ def self.define_log(mname, level, out)
43
+ return if mname == 'off' || mname == 'all'
44
+ mstr = %-
45
+ def out.#{mname}(logevent)
46
+ canonical_log(logevent)
47
+ end
48
+ -
49
+ module_eval mstr
50
+ end
51
+
52
+ def self.undefine_log(mname, out)
53
+ return if mname == 'off' || mname == 'all'
54
+ mstr = "def out.#{mname}(logevent); end"
55
+ module_eval mstr
56
+ end
57
+ end
58
+
59
+ end
60
+ end