log4r-color 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. data/INSTALL +11 -0
  2. data/LICENSE +90 -0
  3. data/LICENSE.LGPLv3 +165 -0
  4. data/README +95 -0
  5. data/Rakefile +80 -0
  6. data/TODO +2 -0
  7. data/doc/content/contact.html +22 -0
  8. data/doc/content/contribute.html +21 -0
  9. data/doc/content/index.html +90 -0
  10. data/doc/content/license.html +56 -0
  11. data/doc/content/manual.html +449 -0
  12. data/doc/dev/README.developers +55 -0
  13. data/doc/dev/checklist +23 -0
  14. data/doc/dev/things-to-do +5 -0
  15. data/doc/images/log4r-logo.png +0 -0
  16. data/doc/images/logo2.png +0 -0
  17. data/doc/log4r.css +111 -0
  18. data/doc/rdoc-log4r.css +696 -0
  19. data/doc/templates/main.html +147 -0
  20. data/examples/README +19 -0
  21. data/examples/ancestors.rb +53 -0
  22. data/examples/chainsaw_settings.xml +7 -0
  23. data/examples/color_output.rb +26 -0
  24. data/examples/customlevels.rb +34 -0
  25. data/examples/filelog.rb +25 -0
  26. data/examples/fileroll.rb +40 -0
  27. data/examples/gmail.rb +30 -0
  28. data/examples/gmail.yaml +95 -0
  29. data/examples/log4r_yaml.yaml +0 -0
  30. data/examples/logclient.rb +25 -0
  31. data/examples/logserver.rb +18 -0
  32. data/examples/moderate.xml +29 -0
  33. data/examples/moderateconfig.rb +66 -0
  34. data/examples/myformatter.rb +23 -0
  35. data/examples/outofthebox.rb +21 -0
  36. data/examples/rdoc-gen +2 -0
  37. data/examples/rrconfig.xml +63 -0
  38. data/examples/rrsetup.rb +42 -0
  39. data/examples/simpleconfig.rb +39 -0
  40. data/examples/syslogcustom.rb +52 -0
  41. data/examples/xmlconfig.rb +25 -0
  42. data/examples/yaml.rb +30 -0
  43. data/lib/log4r.rb +20 -0
  44. data/lib/log4r/GDC.rb +41 -0
  45. data/lib/log4r/MDC.rb +59 -0
  46. data/lib/log4r/NDC.rb +86 -0
  47. data/lib/log4r/base.rb +90 -0
  48. data/lib/log4r/config.rb +9 -0
  49. data/lib/log4r/configurator.rb +224 -0
  50. data/lib/log4r/formatter/formatter.rb +105 -0
  51. data/lib/log4r/formatter/log4jxmlformatter.rb +61 -0
  52. data/lib/log4r/formatter/patternformatter.rb +145 -0
  53. data/lib/log4r/lib/drbloader.rb +52 -0
  54. data/lib/log4r/lib/xmlloader.rb +24 -0
  55. data/lib/log4r/logevent.rb +28 -0
  56. data/lib/log4r/logger.rb +199 -0
  57. data/lib/log4r/loggerfactory.rb +89 -0
  58. data/lib/log4r/logserver.rb +28 -0
  59. data/lib/log4r/outputter/consoleoutputters.rb +49 -0
  60. data/lib/log4r/outputter/datefileoutputter.rb +117 -0
  61. data/lib/log4r/outputter/emailoutputter.rb +143 -0
  62. data/lib/log4r/outputter/fileoutputter.rb +56 -0
  63. data/lib/log4r/outputter/iooutputter.rb +55 -0
  64. data/lib/log4r/outputter/outputter.rb +146 -0
  65. data/lib/log4r/outputter/outputterfactory.rb +61 -0
  66. data/lib/log4r/outputter/remoteoutputter.rb +40 -0
  67. data/lib/log4r/outputter/rollingfileoutputter.rb +234 -0
  68. data/lib/log4r/outputter/scribeoutputter.rb +37 -0
  69. data/lib/log4r/outputter/staticoutputter.rb +32 -0
  70. data/lib/log4r/outputter/syslogoutputter.rb +130 -0
  71. data/lib/log4r/outputter/udpoutputter.rb +53 -0
  72. data/lib/log4r/rdoc/GDC +14 -0
  73. data/lib/log4r/rdoc/MDC +16 -0
  74. data/lib/log4r/rdoc/NDC +41 -0
  75. data/lib/log4r/rdoc/configurator +243 -0
  76. data/lib/log4r/rdoc/emailoutputter +103 -0
  77. data/lib/log4r/rdoc/formatter +39 -0
  78. data/lib/log4r/rdoc/log4r +89 -0
  79. data/lib/log4r/rdoc/logger +175 -0
  80. data/lib/log4r/rdoc/logserver +85 -0
  81. data/lib/log4r/rdoc/outputter +108 -0
  82. data/lib/log4r/rdoc/patternformatter +128 -0
  83. data/lib/log4r/rdoc/scribeoutputter +16 -0
  84. data/lib/log4r/rdoc/syslogoutputter +29 -0
  85. data/lib/log4r/rdoc/win32eventoutputter +7 -0
  86. data/lib/log4r/rdoc/yamlconfigurator +20 -0
  87. data/lib/log4r/repository.rb +88 -0
  88. data/lib/log4r/staticlogger.rb +49 -0
  89. data/lib/log4r/yamlconfigurator.rb +196 -0
  90. data/tests/README +10 -0
  91. data/tests/testGDC.rb +26 -0
  92. data/tests/testMDC.rb +42 -0
  93. data/tests/testNDC.rb +27 -0
  94. data/tests/testall.rb +6 -0
  95. data/tests/testbase.rb +49 -0
  96. data/tests/testchainsaw.rb +48 -0
  97. data/tests/testcoloroutput.rb +14 -0
  98. data/tests/testconf.xml +37 -0
  99. data/tests/testcustom.rb +27 -0
  100. data/tests/testformatter.rb +27 -0
  101. data/tests/testlogger.rb +196 -0
  102. data/tests/testoutputter.rb +132 -0
  103. data/tests/testpatternformatter.rb +78 -0
  104. data/tests/testthreads.rb +35 -0
  105. data/tests/testxmlconf.rb +45 -0
  106. metadata +195 -0
@@ -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,49 @@
1
+ # :nodoc:
2
+ require "log4r/outputter/iooutputter"
3
+ require "colorize"
4
+
5
+ module Log4r
6
+ # Same as IOOutputter(name, $stdout)
7
+ class StdoutOutputter < IOOutputter
8
+ def initialize(_name, hash={})
9
+ super(_name, $stdout, hash)
10
+ end
11
+ end
12
+
13
+ # Same as IOOutputter(name, $stderr)
14
+ class StderrOutputter < IOOutputter
15
+ def initialize(_name, hash={})
16
+ super(_name, $stderr, hash)
17
+ end
18
+ end
19
+
20
+ class ColorOutputter < IOOutputter
21
+ def initialize(_name, hash={})
22
+ super(_name, $stdout, hash)
23
+ end
24
+
25
+ private
26
+
27
+ def canonical_log(logevent)
28
+ synch { write(format(logevent), logevent.level) }
29
+ end
30
+
31
+ # perform the write
32
+ def write(data, lv)
33
+ begin
34
+ key = level_key(lv)
35
+ @out.print data.colorize(colors[key])
36
+ @out.flush
37
+ @out.print "".uncolorize
38
+ rescue IOError => ioe # recover from this instead of crash
39
+ Logger.log_internal {"IOError in Outputter '#{@name}'!"}
40
+ Logger.log_internal {ioe}
41
+ close
42
+ rescue NameError => ne
43
+ Logger.log_internal {"Outputter '#{@name}' IO is #{@out.class}!"}
44
+ Logger.log_internal {ne}
45
+ close
46
+ end
47
+ end
48
+ end
49
+ 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 ? "w" : "a"))
111
+ Logger.log_internal {
112
+ "DateFileOutputter '#{@name}' now writing to #{@filename}"
113
+ }
114
+ end
115
+ end
116
+
117
+ end
@@ -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,56 @@
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 ? "w" : "a"))
44
+ Logger.log_internal {
45
+ "FileOutputter '#{@name}' writing to #{@filename}"
46
+ }
47
+ else
48
+ Logger.log_internal {
49
+ "FileOutputter '#{@name}' called with :create == false, #{@filename}"
50
+ }
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end