aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/buffered_logger.rb
blob: 85fb41f31877d6a841d7fd905ed9f14822bb77c1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
require 'thread'
require 'logger'
require 'active_support/core_ext/logger'
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/deprecation'
require 'fileutils'

module ActiveSupport
  # Inspired by the buffered logger idea by Ezra
  class BufferedLogger
    module Severity
      DEBUG   = 0
      INFO    = 1
      WARN    = 2
      ERROR   = 3
      FATAL   = 4
      UNKNOWN = 5
    end
    include Severity

    MAX_BUFFER_SIZE = 1000

    ##
    # :singleton-method:
    # Set to false to disable the silencer
    cattr_accessor :silencer
    self.silencer = true

    # Silences the logger for the duration of the block.
    def silence(temporary_level = ERROR)
      if silencer
        begin
          logger = self.class.new @log_dest.dup, temporary_level
          yield logger
        ensure
          logger.close
        end
      else
        yield self
      end
    end
    deprecate :silence

    attr_reader :auto_flushing
    deprecate :auto_flushing

    def initialize(log, level = DEBUG)
      @log_dest      = log

      unless log.respond_to?(:write)
        unless File.exist?(File.dirname(log))
          ActiveSupport::Deprecation.warn(<<-eowarn)
Automatic directory creation for '#{log}' is deprecated.  Please make sure the directory for your log file exists before creating the logger.
          eowarn
          FileUtils.mkdir_p(File.dirname(log))
        end
      end

      @log = open_logfile log
      self.level = level
    end

    def open_log(log, mode)
      open(log, mode).tap do |open_log|
        open_log.set_encoding(Encoding::BINARY) if open_log.respond_to?(:set_encoding)
        open_log.sync = true
      end
    end
    deprecate :open_log

    def level
      @log.level
    end

    def level=(l)
      @log.level = l
    end

    def add(severity, message = nil, progname = nil, &block)
      @log.add(severity, message, progname, &block)
    end

    # Dynamically add methods such as:
    # def info
    # def warn
    # def debug
    Severity.constants.each do |severity|
      class_eval <<-EOT, __FILE__, __LINE__ + 1
        def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block)
          add(#{severity}, message, progname, &block)                   #   add(DEBUG, message, progname, &block)
        end                                                             # end

        def #{severity.downcase}?                                       # def debug?
          #{severity} >= level                                         #   DEBUG >= level
        end                                                             # end
      EOT
    end

    # Set the auto-flush period. Set to true to flush after every log message,
    # to an integer to flush every N messages, or to false, nil, or zero to
    # never auto-flush. If you turn auto-flushing off, be sure to regularly
    # flush the log yourself -- it will eat up memory until you do.
    def auto_flushing=(period)
    end
    deprecate :auto_flushing=

    def flush
    end
    deprecate :flush

    def respond_to?(method, include_private = false)
      return false if method.to_s == "flush"
      super
    end

    def close
      @log.close
    end

    private
    def open_logfile(log)
      Logger.new log
    end
  end
end