Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/trunk/activesupport/lib/active_support/buffered_logger.rb

Revision 9013, 3.2 kB (checked in by david, 1 year ago)

Fixed that BufferedLogger should create its own directory if one doesnt already exist (closes #11285) [lotswholetime]

Line 
1 module ActiveSupport
2   # Inspired by the buffered logger idea by Ezra
3   class BufferedLogger
4     module Severity
5       DEBUG   = 0
6       INFO    = 1
7       WARN    = 2
8       ERROR   = 3
9       FATAL   = 4
10       UNKNOWN = 5
11     end
12     include Severity
13
14     MAX_BUFFER_SIZE = 1000
15
16     # Set to false to disable the silencer
17     cattr_accessor :silencer
18     self.silencer = true
19
20     # Silences the logger for the duration of the block.
21     def silence(temporary_level = ERROR)
22       if silencer
23         begin
24           old_logger_level, self.level = level, temporary_level
25           yield self
26         ensure
27           self.level = old_logger_level
28         end
29       else
30         yield self
31       end
32     end
33
34     attr_accessor :level
35     attr_reader :auto_flushing
36     attr_reader :buffer
37
38     def initialize(log, level = DEBUG)
39       @level         = level
40       @buffer        = []
41       @auto_flushing = 1
42       @no_block = false
43
44       if log.respond_to?(:write)
45         @log = log
46       elsif File.exist?(log)
47         @log = open(log, (File::WRONLY | File::APPEND))
48         @log.sync = true
49       else
50         FileUtils.mkdir_p(File.dirname(log))
51         @log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
52         @log.sync = true
53         @log.write("# Logfile created on %s" % [Time.now.to_s])
54       end
55     end
56
57     def set_non_blocking_io
58       if !RUBY_PLATFORM.match(/java|mswin/) && !(@log == STDOUT) && @log.respond_to?(:write_nonblock)
59         @no_block = true
60       end
61     end
62
63     def add(severity, message = nil, progname = nil, &block)
64       return if @level > severity
65       message = (message || (block && block.call) || progname).to_s
66       # If a newline is necessary then create a new message ending with a newline.
67       # Ensures that the original message is not mutated.
68       message = "#{message}\n" unless message[-1] == ?\n
69       buffer << message
70       auto_flush
71       message
72     end
73
74     for severity in Severity.constants
75       class_eval <<-EOT, __FILE__, __LINE__
76         def #{severity.downcase}(message = nil, progname = nil, &block)
77           add(#{severity}, message, progname, &block)
78         end
79
80         def #{severity.downcase}?
81           #{severity} >= @level
82         end
83       EOT
84     end
85
86     # Set the auto-flush period. Set to true to flush after every log message,
87     # to an integer to flush every N messages, or to false, nil, or zero to
88     # never auto-flush. If you turn auto-flushing off, be sure to regularly
89     # flush the log yourself -- it will eat up memory until you do.
90     def auto_flushing=(period)
91       @auto_flushing =
92         case period
93         when true;                1
94         when false, nil, 0;       MAX_BUFFER_SIZE
95         when Integer;             period
96         else raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}"
97         end
98     end
99
100     def flush
101       unless buffer.empty?
102         if @no_block
103           @log.write_nonblock(buffer.slice!(0..-1).join)
104         else
105           @log.write(buffer.slice!(0..-1).join)
106         end
107       end
108     end
109
110     def close
111       flush
112       @log.close if @log.respond_to?(:close)
113       @log = nil
114     end
115
116     protected
117       def auto_flush
118         flush if buffer.size >= @auto_flushing
119       end
120   end
121 end
Note: See TracBrowser for help on using the browser.