33bcf327f8abba60eade081bb0ce804f2c231905
[feedcatcher.git] / vendor / rails / activesupport / lib / active_support / buffered_logger.rb
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 ##
17 # :singleton-method:
18 # Set to false to disable the silencer
19 cattr_accessor :silencer
20 self.silencer = true
21
22 # Silences the logger for the duration of the block.
23 def silence(temporary_level = ERROR)
24 if silencer
25 begin
26 old_logger_level, self.level = level, temporary_level
27 yield self
28 ensure
29 self.level = old_logger_level
30 end
31 else
32 yield self
33 end
34 end
35
36 attr_accessor :level
37 attr_reader :auto_flushing
38
39 def initialize(log, level = DEBUG)
40 @level = level
41 @buffer = {}
42 @auto_flushing = 1
43 @guard = Mutex.new
44
45 if log.respond_to?(:write)
46 @log = log
47 elsif File.exist?(log)
48 @log = open(log, (File::WRONLY | File::APPEND))
49 @log.sync = true
50 else
51 FileUtils.mkdir_p(File.dirname(log))
52 @log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
53 @log.sync = true
54 @log.write("# Logfile created on %s" % [Time.now.to_s])
55 end
56 end
57
58 def add(severity, message = nil, progname = nil, &block)
59 return if @level > severity
60 message = (message || (block && block.call) || progname).to_s
61 # If a newline is necessary then create a new message ending with a newline.
62 # Ensures that the original message is not mutated.
63 message = "#{message}\n" unless message[-1] == ?\n
64 buffer << message
65 auto_flush
66 message
67 end
68
69 for severity in Severity.constants
70 class_eval <<-EOT, __FILE__, __LINE__
71 def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block)
72 add(#{severity}, message, progname, &block) # add(DEBUG, message, progname, &block)
73 end # end
74 #
75 def #{severity.downcase}? # def debug?
76 #{severity} >= @level # DEBUG >= @level
77 end # end
78 EOT
79 end
80
81 # Set the auto-flush period. Set to true to flush after every log message,
82 # to an integer to flush every N messages, or to false, nil, or zero to
83 # never auto-flush. If you turn auto-flushing off, be sure to regularly
84 # flush the log yourself -- it will eat up memory until you do.
85 def auto_flushing=(period)
86 @auto_flushing =
87 case period
88 when true; 1
89 when false, nil, 0; MAX_BUFFER_SIZE
90 when Integer; period
91 else raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}"
92 end
93 end
94
95 def flush
96 @guard.synchronize do
97 unless buffer.empty?
98 old_buffer = buffer
99 @log.write(old_buffer.join)
100 end
101
102 # Important to do this even if buffer was empty or else @buffer will
103 # accumulate empty arrays for each request where nothing was logged.
104 clear_buffer
105 end
106 end
107
108 def close
109 flush
110 @log.close if @log.respond_to?(:close)
111 @log = nil
112 end
113
114 protected
115 def auto_flush
116 flush if buffer.size >= @auto_flushing
117 end
118
119 def buffer
120 @buffer[Thread.current] ||= []
121 end
122
123 def clear_buffer
124 @buffer.delete(Thread.current)
125 end
126 end
127 end