How to setup logging#
Using functions from apstools.utils.log_utils
, it is easy to setup
logging [5] reports to either the console or a file. Refer to the logging
levels, as described in the section What are the logging levels? below.
To setup for logging in your code:
1import logging
2logger = logging.getLogger(__name__)
You can use this code in any module to create a logger
object. Use one of
the levels such as logger.warning("a warning message")
or
logger.debug("some detail")
to add messages for logging. INFO
and
DEBUG
level messages will not be reported unless you adjust the level to
allow this level of detail. To set the level:
1logger.setLevel(logging.DEBUG) # allow any log content at this level
Yet still, you may not see any output on your console unless you provide a handler which tells the logger what to do with each message. A logger has its own reporting level which determines which messages to report.
Tip
Set the logger level to the lowest level of any of the handlers you will use.
In the next sections, we show you how to add handlers. You can add multiple
handlers to a logger
for different types of reporting.
Handlers#
Logging handlers describe when, where, and how to report a logging message. The sections below show how to report to the console and to files. The logging documentation ([5]) shows how to report to more places. The bluesky documentation [1] provides debugging and logging guidance.
Reporting to the console (StreamHandler
)#
Starting with the logger
from How to setup logging, add a handler for
reporting INFO
(and higher) messages to the console. You can change the
level with a keyword argument, see
stream_log_handler()
.
1logger.addHandler(stream_log_handler()) # logger to the console
Reporting to a file (FileHandler
or RotatingFileHandler
)#
Starting with the logger
from How to setup logging, add a handler for
reporting DEBUG
(and higher) messages to the file. The log file
will be named .logs/my_log_file.log
with up to 9 older
files, each no larger than 1 MB.
1BYTE = 1
2kB = 1024 * BYTE
3MB = 1024 * kB
4
5logger.addHandler(
6 file_log_handler( # logger to a file
7 "my_log_file,
8 maxBytes=1 * MB,
9 backupCount=9,
10 level="DEBUG",
11 )
12)
Reporting from included packages#
Some of the packages included might report via Python’s logging
package. For
example, bluesky
[2] and ophyd
[4] have several logger names that report messages. Here,
we enable reporting from the top-level logger names in both these packages:
1BYTE = 1
2kB = 1024 * BYTE
3MB = 1024 * kB
4
5log_these_names = {
6 "bluesky": "INFO",
7 "ophyd": "INFO",
8}
9for logger_name, level in log_these_names.items():
10 _l = logging.getLogger(logger_name)
11 _l.setLevel(logging.DEBUG) # allow any log content at this level
12 _l.addHandler(
13 file_log_handler( # logger to a file
14 logger_name,
15 logger_name,
16 maxBytes=1 * MB,
17 backupCount=9,
18 level=level, # filter reporting to this level
19 )
20 )
Recording IPython console Input and Output#
IPython offers its own logging process for recording the input (IN
) and
output (OUT
) messages. When diagnosing problems, or for education reasons,
it is useful to record this content to a file for later review.
This will create a file .logs/ipython_console.log
(relative to
the current working directory) for this log.
1setup_IPython_console_logging()
What are the logging levels?#
text |
symbol |
remarks |
---|---|---|
|
|
rare for any messages |
|
|
|
|
|
default reporting level |
|
|
|
|
|
the most verbose level |
A logging handler will report any messages it receives at its current level or
higher as shown in this table. With the default level (WARNING
), you will
only receive messages from logger.critical()
, logger.error()
,
and logger.warning()
calls.
Simply put, WARNING level only reports when something has gone wrong.
The usual practice is to set the logger
(instance of logging.Logger
)
to the lowest level used by any handler.
The bluesky documentation ([3]) provides a flowchart illustrating how a log message will be reported by a handler.
References