Email Logging¶
Red Mail also provides logging handlers which extends the logging library’s handlers from the standard library. The logging library also has SMTPHandler but its features are somewhat restricted. It does only send a logging message formatted as plain text and it sends only one log record per email.
Red Mail’s email handlers, on the other hand, are capable of formatting the emails in arbitrary ways and it also enables to send multiple log records with one email. Red Mail is more feature complete and provides more customizable logging experience.
There are two log handlers provided by Red Mail:
EmailHandler: Sends one log record per email
MultiEmailHandler: Sends multiple log records with one email
The mechanics are simple and very similar between these two handlers.
EmailHandler¶
To send one log record per email, use EmailHandler
:
import logging
from redmail import EmailHandler
hdlr = EmailHandler(
host="localhost",
port=0,
subject="A log record",
sender="no-reply@example.com",
receivers=["me@example.com"],
)
logger = logging.getLogger(__name__)
logger.addHandler(hdlr)
# To use:
logger.warning("A warning happened")
Note
You may pass the EmailSender
directly as an argument email
, for
example:
from redmail import EmailSender
hdlr = EmailHandler(
email=EmailSender(host="localhost", port=0)
subject="A log record",
receivers=["me@example.com"],
)
Note that a copy of the EmailSender
is created
in order to avoid affecting the usage of the instance
elsewhere. Additional arguments (such as subject, sender,
receivers, text, html, etc.) are set as attributes to
this copied instance.
You may also template the subject and the bodies:
import logging
from redmail import EmailHandler
hdlr = EmailHandler(
host="localhost",
port=0,
subject="Log Record: {record.levelname}",
receivers=["me@example.com"],
text="Logging level: {{ record.levelname }}\nMessage: {{ msg }}",
html="<ul><li>Logging level: {{ record.levelname }}</li><li>Message: {{ msg }}</li></ul>",
)
logger = logging.getLogger(__name__)
logger.addHandler(hdlr)
As you may have noted, the subject can contain string formatting. The following arguments are passed to the string format:
Argument |
Type |
Description |
---|---|---|
record |
logging.LogRecord |
Log records to send |
handler |
EmailHandler |
EmailHandler itself |
In addition, the text and HTML bodies are processed using Jinja and the following parameters are passed:
Argument |
Type |
Description |
---|---|---|
record |
logging.LogRecord |
Log record |
msg |
str |
Formatted message |
handler |
EmailHandler |
EmailHandler itself |
MultiEmailHandler¶
To send multiple log records with one email, use MultiEmailHandler
:
import logging
from redmail import MultiEmailHandler
hdlr = MultiEmailHandler(
capacity=2, # Sends email after every second record
host="localhost",
port=0,
subject="log records",
sender="no-reply@example.com",
receivers=["me@example.com"],
)
logger = logging.getLogger(__name__)
logger.addHandler(hdlr)
# To use:
logger.warning("A warning happened")
logger.warning("Another warning happened")
# (Now an email should have been sent)
# You may also manually flush
logger.warning("A warning happened")
hdlr.flush()
Note
You may pass the EmailSender
directly as an argument email
, for
example:
from redmail import EmailSender
hdlr = MultiEmailHandler(
email=EmailSender(host="localhost", port=0)
subject="Log records",
receivers=["me@example.com"],
)
Note that a copy of the EmailSender
is created
in order to avoid affecting the usage of the instance
elsewhere. Additional arguments (such as subject, sender,
receivers, text, html, etc.) are set as attributes to
this copied instance.
You may also template the subject and the bodies:
import logging
from redmail import EmailHandler
hdlr = MultiEmailHandler(
host="localhost",
port=0,
subject="Log Records: {min_level_name} - {max_level_name}",
receivers=["me@example.com"],
text="""Logging level:
{% for record in records %}
Level name: {{ record.levelname }}
Message: {{ record.msg }}
{% endfor %}
""",
html="""
<ul>
{% for record in records %}
<li>Logging level: {{ record.levelname }}</li>
<li>Message: {{ record.msg }}</li>
{% endfor %}
</ul>
""",
)
logger = logging.getLogger(__name__)
logger.addHandler(hdlr)
As you may have noted, the subject can contain string formatting. The following arguments are passed to the string format:
Argument |
Type |
Description |
---|---|---|
records |
list of logging.LogRecord |
Log records to send |
min_level_name |
str |
Name of the lowest log level name |
max_level_name |
str |
Name of the highest log level name |
handler |
MultiEmailHandler |
MultiEmailHandler itself |
In addition, the text and HTML bodies are processed using Jinja and the following parameters are passed:
Argument |
Type |
Description |
---|---|---|
records |
list of logging.LogRecord |
List of log records |
msgs |
list of str |
List of formatted messages |
handler |
MultiEmailHandler |
MultiEmailHandler itself |