1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # A simple logger for Nit
19 # Create a new `Logger` with a severity level threshold set to `warn_level`:
22 # var logger = new Logger(warn_level)
25 # Messages with a severity equal or higher than `warn_level` will be displayed:
28 # logger.error "Displays an error."
29 # logger.warn "Displays a warning."
32 # Messages with a lower severity are silenced:
35 # logger.info "Displays nothing."
38 # `FileLogger` can be used to output the messages into a file:
41 # var log_file = "my.log"
43 # logger = new FileLogger(warn_level, log_file, append = false)
44 # logger.error("An error")
45 # logger.info("Some info")
48 # assert log_file.to_path.read_all == "An error\n"
49 # log_file.to_path.delete
54 # Each message is associated with a level that indicate its severity.
55 # Only messages with a severity equal to or higher than the logger `level`
56 # threshold will be displayed.
58 # Severity levels from the most severe to the least severe:
60 # * `unknown_level`: An unknown message that should always be outputted.
61 # * `fatal_level`: An unhandleable error that results in a program crash.
62 # * `error_level`: A handleable error condition.
63 # * `warn_level`: A warning.
64 # * `info_level`: Generic (useful) information about system operation.
65 # * `debug_level`: Low-level information for developpers.
67 # ## Formatting messages
69 # You can create custom formatters by implementing the `Formatter` interface.
75 # redef fun format(level, message) do
76 # if level < warn_level then return super
77 # return "!!!{message}!!!"
82 # See `DefaultFormatter` for a more advanced implementation example.
84 # Each Logger can be given a default formatter used to format the every messages
85 # before outputting them:
88 # var formatter = new MyFormatter
89 # var stderr = new StringWriter
90 # var logger = new Logger(warn_level, stderr, formatter)
92 # logger.warn("This is a warning.")
93 # assert stderr.to_s.trim.split("\n").last == "!!!This is a warning.!!!"
96 # Optionally, a `Formatter` can be given to replace the `default_formatter`
100 # # Create a formatter with no default decorator
101 # logger = new Logger(warn_level, stderr, null)
103 # # Display a message without any formatter
104 # logger.warn("This is a warning.")
105 # assert stderr.to_s.trim.split("\n").last == "This is a warning."
107 # # Display a message with a custom formatter
108 # logger.warn("This is a warning.", formatter)
109 # assert stderr.to_s.trim.split("\n").last == "!!!This is a warning.!!!"
115 # A simple logging utility
117 # `Logger` provides a simple way to output messages from applications.
119 # Each message is associated with a level that indicate its severity.
120 # Only messages with a severity equal to or higher than the logger `level`
121 # threshold will be displayed.
124 # var logger = new Logger(warn_level)
125 # assert logger.unknown("unkown")
126 # assert logger.fatal("fatal")
127 # assert logger.error("error")
128 # assert logger.warn("warn")
129 # assert not logger.info("info")
130 # assert not logger.debug("debug")
136 # Messages with a severity level greater than or equal to `level` will be displayed.
137 # Default is `warn_level`.
139 # See `unknown_level`, `fatal_level`, error_level``, `warn_level`,
140 # `info_level` and `debug_level`.
141 var level
: Int = warn_level
is optional
, writable
143 # Kind of `Writer` used to output messages
146 # Writer used to output messages
148 # Default is `stderr`.
149 var out
: OUT = stderr
is optional
151 # Formatter used to format messages before outputting them
153 # By default no formatter is used.
155 # See `DefaultFormatter`.
156 var default_formatter
: nullable Formatter = null is optional
, writable
158 # Output a message with `level` severity
160 # Only output messages with `level` severity greater than of equal to `self.level`.
163 # var stderr = new StringWriter
164 # var logger = new Logger(warn_level, stderr, null)
166 # # This message will be displayed:
167 # assert logger.warn("This is a warning.")
168 # assert stderr.to_s.trim.split("\n").last == "This is a warning."
170 # # This message will not:
171 # assert not logger.info("This is some info.")
172 # assert stderr.to_s.trim.split("\n").last == "This is a warning."
175 # Each logger can be given a default formatter used to format the messages
176 # before outputting them:
179 # var formatter = new DefaultFormatter(no_color = true)
180 # logger = new Logger(warn_level, stderr, formatter)
181 # logger.warn("This is a warning.")
182 # assert stderr.to_s.trim.split("\n").last == "Warning: This is a warning."
185 # Optionally, a `Formatter` can be given to replace the `default_formatter`
189 # # Create a formatter with no default decorator
190 # logger = new Logger(warn_level, stderr, null)
192 # # Display a message without any formatter
193 # logger.warn("This is a warning.")
194 # assert stderr.to_s.trim.split("\n").last == "This is a warning."
196 # # Display a message with a custom formatter
197 # logger.warn("This is a warning.", formatter)
198 # assert stderr.to_s.trim.split("\n").last == "Warning: This is a warning."
200 fun add
(level
: Int, message
: Writable, formatter
: nullable Formatter): Bool do
201 var format
= formatter
or else default_formatter
202 if format
== null then
203 return add_raw
(level
, message
)
205 return add_raw
(level
, format
.format
(level
, message
))
208 # Output a message with `level` severity without formatting it
210 # Only output messages with `level` severity greater than of equal to `self.level`.
213 # var stderr = new StringWriter
214 # var logger = new Logger(warn_level, stderr, null)
216 # # This message will be displayed:
217 # assert logger.add_raw(warn_level, "This is a warning.")
218 # assert stderr.to_s.trim.split("\n").last == "This is a warning."
220 # # This message will not:
221 # assert not logger.add_raw(info_level, "This is some info.")
222 # assert stderr.to_s.trim.split("\n").last == "This is a warning."
224 fun add_raw
(level
: Int, message
: Writable): Bool do
225 if level
< self.level
then return false
226 out
.write
(message
.write_to_string
)
231 # Output a message with `unknown_level` severity
233 # Unkown severity messages are always outputted.
234 fun unknown
(message
: String, formatter
: nullable Formatter): Bool do
235 return add
(unknown_level
, message
, formatter
)
238 # Output a message with `fatal_level` severity
239 fun fatal
(message
: String, formatter
: nullable Formatter): Bool do
240 return add
(fatal_level
, message
, formatter
)
243 # Output a message with `error_level` severity
244 fun error
(message
: String, formatter
: nullable Formatter): Bool do
245 return add
(error_level
, message
, formatter
)
248 # Output a message with `warn_level` severity
249 fun warn
(message
: String, formatter
: nullable Formatter): Bool do
250 return add
(warn_level
, message
, formatter
)
253 # Output a message with `info_level` severity
254 fun info
(message
: String, formatter
: nullable Formatter): Bool do
255 return add
(info_level
, message
, formatter
)
258 # Output a message with `debug` severity
259 fun debug
(message
: String, formatter
: nullable Formatter): Bool do
260 return add
(debug_level
, message
, formatter
)
264 # Log messages to a file
267 # var log_file = "my_file.log"
268 # var logger = new FileLogger(warn_level, log_file, append = false)
269 # logger.error("An error")
270 # logger.info("Some info")
272 # assert log_file.to_path.read_all == "An error\n"
274 # logger = new FileLogger(warn_level, log_file, append = true)
275 # logger.error("Another error")
277 # assert log_file.to_path.read_all == "An error\nAnother error\n"
279 # log_file.to_path.delete
283 autoinit level
, file
, append
, default_formatter
285 redef type OUT: FileWriter
287 # File where messages will be written
290 # Append messages to `file`
292 # If `append` is `false`, the `file` will be overwritten.
293 var append
: Bool = true is optional
298 old
= file
.to_path
.read_all
300 out
= new FileWriter.open
(file
)
301 out
.set_buffering_mode
(0, buffer_mode_line
)
307 # Close the logger and its `file`
308 fun close
do out
.close
311 # Format messages before outputing them
313 # A `Logger` can use a `Formatter` to format the messages before outputting them.
315 # See `DefaultFormatter`.
318 # Format `message` depending of its severity `level`
319 fun format
(level
: Int, message
: Writable): Writable do return message
322 # Default `Logger` formatter
324 # The default formatter decorates the messages with severity labels and colors.
325 class DefaultFormatter
328 # Do not decorate messages with colors
331 # var formatter = new DefaultFormatter(no_color = true)
332 # assert formatter.format(error_level, "My message.") == "Error: My message."
334 var no_color
= false is optional
, writable
336 redef fun format
(level
, message
) do
337 var string
= message
.write_to_string
339 if level
== fatal_level
then
340 string
= "Fatal: {string}"
341 else if level
== error_level
then
342 string
= "Error: {string}"
343 else if level
== warn_level
then
344 string
= "Warning: {string}"
345 else if level
== info_level
then
346 string
= "Info: {string}"
347 else if level
== debug_level
then
348 string
= "Debug: {string}"
351 if no_color
then return string
353 if level
== fatal_level
then
355 else if level
== error_level
then
357 else if level
== warn_level
then
359 else if level
== info_level
then
361 else if level
== debug_level
then
371 # Unknown severity level
373 # These messages are always displayed.
376 var unknown_level
= 5
378 # Fatal severity level
383 # Error severity level
388 # Warning severity level
393 # Info severity level
398 # Debug severity level