aboutsummaryrefslogtreecommitdiffstats
path: root/lib/webrick/log.rb
blob: 7542d8f79a992b800f35cba01363e74273f7071c (plain)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# frozen_string_literal: false
#--
# log.rb -- Log Class
#
# Author: IPR -- Internet Programming with Ruby -- writers
# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
# reserved.
#
# $IPR: log.rb,v 1.26 2002/10/06 17:06:10 gotoyuzo Exp $

module WEBrick

  ##
  # A generic logging class

  class BasicLog

    # Fatal log level which indicates a server crash

    FATAL = 1

    # Error log level which indicates a recoverable error

    ERROR = 2

    # Warning log level which indicates a possible problem

    WARN  = 3

    # Information log level which indicates possibly useful information

    INFO  = 4

    # Debugging error level for messages used in server development or
    # debugging

    DEBUG = 5

    # log-level, messages above this level will be logged
    attr_accessor :level

    ##
    # Initializes a new logger for +log_file+ that outputs messages at +level+
    # or higher.  +log_file+ can be a filename, an IO-like object that
    # responds to #<< or nil which outputs to $stderr.
    #
    # If no level is given INFO is chosen by default

    def initialize(log_file=nil, level=nil)
      @level = level || INFO
      case log_file
      when String
        @log = open(log_file, "a+")
        @log.sync = true
        @opened = true
      when NilClass
        @log = $stderr
      else
        @log = log_file  # requires "<<". (see BasicLog#log)
      end
    end

    ##
    # Closes the logger (also closes the log device associated to the logger)
    def close
      @log.close if @opened
      @log = nil
    end

    ##
    # Logs +data+ at +level+ if the given level is above the current log
    # level.

    def log(level, data)
      if @log && level <= @level
        data += "\n" if /\n\Z/ !~ data
        @log << data
      end
    end

    ##
    # Synonym for log(INFO, obj.to_s)
    def <<(obj)
      log(INFO, obj.to_s)
    end

    # Shortcut for logging a FATAL message
    def fatal(msg) log(FATAL, "FATAL " << format(msg)); end
    # Shortcut for logging an ERROR message
    def error(msg) log(ERROR, "ERROR " << format(msg)); end
    # Shortcut for logging a WARN message
    def warn(msg)  log(WARN,  "WARN  " << format(msg)); end
    # Shortcut for logging an INFO message
    def info(msg)  log(INFO,  "INFO  " << format(msg)); end
    # Shortcut for logging a DEBUG message
    def debug(msg) log(DEBUG, "DEBUG " << format(msg)); end

    # Will the logger output FATAL messages?
    def fatal?; @level >= FATAL; end
    # Will the logger output ERROR messages?
    def error?; @level >= ERROR; end
    # Will the logger output WARN messages?
    def warn?;  @level >= WARN; end
    # Will the logger output INFO messages?
    def info?;  @level >= INFO; end
    # Will the logger output DEBUG messages?
    def debug?; @level >= DEBUG; end

    private

    ##
    # Formats +arg+ for the logger
    #
    # * If +arg+ is an Exception, it will format the error message and
    #   the back trace.
    # * If +arg+ responds to #to_str, it will return it.
    # * Otherwise it will return +arg+.inspect.
    def format(arg)
      if arg.is_a?(Exception)
        "#{arg.class}: #{arg.message}\n\t" <<
        arg.backtrace.join("\n\t") << "\n"
      elsif arg.respond_to?(:to_str)
        arg.to_str
      else
        arg.inspect
      end
    end
  end

  ##
  # A logging class that prepends a timestamp to each message.

  class Log < BasicLog
    # Format of the timestamp which is applied to each logged line.  The
    # default is <tt>"[%Y-%m-%d %H:%M:%S]"</tt>
    attr_accessor :time_format

    ##
    # Same as BasicLog#initialize
    #
    # You can set the timestamp format through #time_format
    def initialize(log_file=nil, level=nil)
      super(log_file, level)
      @time_format = "[%Y-%m-%d %H:%M:%S]"
    end

    ##
    # Same as BasicLog#log
    def log(level, data)
      tmp = Time.now.strftime(@time_format)
      tmp << " " << data
      super(level, tmp)
    end
  end
end