logging.rst 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. Email Logging with Red Mail
  2. ===========================
  3. Red Mail also provides logging handlers which
  4. extends the :stdlib:`logging library's <logging.html>`
  5. :stdlib:`handlers <logging.handlers.html>` from the standard library.
  6. The logging library also has :stdlib:`SMTPHandler <logging.handlers.html#smtphandler>`
  7. but its features are somewhat restricted. It does only
  8. send a logging message formatted as plain text and it
  9. sends only one log record per email.
  10. Red Mail's email handlers, on the other hand,
  11. are capable of formatting the emails in arbitrary ways
  12. and it also enables to send multiple log records
  13. with one email. Red Mail is more feature complete and
  14. provides more customizable logging experience.
  15. There are two log handlers provided by Red Mail:
  16. - :ref:`EmailHandler <ext-emailhandler>`: Sends one log record per email
  17. - :ref:`MultiEmailHandler <ext-multiemailhandler>`: Sends multiple log records with one email
  18. The mechanics are simple and very similar between these two handlers.
  19. .. _ext-emailhandler:
  20. EmailHandler
  21. ------------
  22. To send one log record per email, use :class:`.EmailHandler`.
  23. .. code-block:: python
  24. import logging
  25. from redmail import EmailHandler
  26. hdlr = EmailHandler(
  27. host="localhost",
  28. port=0,
  29. subject="A log record",
  30. receivers=["me@example.com"],
  31. )
  32. logger = logging.getLogger(__name__)
  33. logger.addHandler(hdlr)
  34. .. note::
  35. You may pass the :class:`.EmailSender`
  36. directly as an argument ``email``, for
  37. example:
  38. .. code-block:: python
  39. from redmail import EmailSender
  40. hdlr = EmailHandler(
  41. email=EmailSender(host="localhost", port=0)
  42. subject="A log record",
  43. receivers=["me@example.com"],
  44. )
  45. Note that a copy of the :class:`.EmailSender` is created
  46. in order to avoid affecting the usage of the instance
  47. elsewhere. Additional arguments (such as subject, sender,
  48. receivers, text, html, etc.) are set as attributes to
  49. this copied instance.
  50. To use this, simply:
  51. .. code-block:: python
  52. logger.warning("A warning happened")
  53. You may also template the subject and the bodies:
  54. .. code-block:: python
  55. import logging
  56. from redmail import EmailHandler
  57. hdlr = EmailHandler(
  58. host="localhost",
  59. port=0,
  60. subject="Log Record: {record.levelname}",
  61. receivers=["me@example.com"],
  62. text="Logging level: {{ record.levelname }}\nMessage: {{ msg }}",
  63. html="<ul><li>Logging level: {{ record.levelname }}</li><li>Message: {{ msg }}</li></ul>",
  64. )
  65. logger = logging.getLogger(__name__)
  66. logger.addHandler(hdlr)
  67. As you may have noted, the subject can contain string formatting.
  68. The following arguments are passed to the string format:
  69. ============== ========================= ==================================
  70. Argument Type Description
  71. ============== ========================= ==================================
  72. record logging.LogRecord Log records to send
  73. handler EmailHandler EmailHandler itself
  74. ============== ========================= ==================================
  75. In addition, the text and HTML bodies are processed using Jinja and the
  76. following parameters are passed:
  77. ======== ================= ===================
  78. Argument Type Description
  79. ======== ================= ===================
  80. record logging.LogRecord Log record
  81. msg str Formatted message
  82. handler EmailHandler EmailHandler itself
  83. ======== ================= ===================
  84. .. _ext-multiemailhandler:
  85. MultiEmailHandler
  86. -----------------
  87. To send multiple log records with one email, use :class:`.MultiEmailHandler`:
  88. .. code-block:: python
  89. import logging
  90. from redmail import MultiEmailHandler
  91. hdlr = MultiEmailHandler(
  92. capacity=2, # Sends email after every second record
  93. host="localhost",
  94. port=0,
  95. subject="log records",
  96. receivers=["me@example.com"],
  97. )
  98. logger = logging.getLogger(__name__)
  99. logger.addHandler(hdlr)
  100. .. note::
  101. You may pass the :class:`.EmailSender`
  102. directly as an argument ``email``, for
  103. example:
  104. .. code-block:: python
  105. from redmail import EmailSender
  106. hdlr = MultiEmailHandler(
  107. email=EmailSender(host="localhost", port=0)
  108. subject="Log records",
  109. receivers=["me@example.com"],
  110. )
  111. Note that a copy of the :class:`.EmailSender` is created
  112. in order to avoid affecting the usage of the instance
  113. elsewhere. Additional arguments (such as subject, sender,
  114. receivers, text, html, etc.) are set as attributes to
  115. this copied instance.
  116. To use this, simply:
  117. .. code-block:: python
  118. logger.warning("A warning happened")
  119. logger.warning("A warning happened")
  120. # Should have now sent an email
  121. # Or manually flush
  122. logger.warning("A warning happened")
  123. hdlr.flush()
  124. You may also template the subject and the bodies:
  125. .. code-block:: python
  126. import logging
  127. from redmail import EmailHandler
  128. hdlr = MultiEmailHandler(
  129. host="localhost",
  130. port=0,
  131. subject="Log Records: {min_level_name} - {max_level_name}",
  132. receivers=["me@example.com"],
  133. text="""Logging level:
  134. {% for record in records %}
  135. Level name: {{ record.levelname }}
  136. Message: {{ record.msg }}
  137. {% endfor %}
  138. """,
  139. html="""
  140. <ul>
  141. {% for record in records %}
  142. <li>Logging level: {{ record.levelname }}</li>
  143. <li>Message: {{ record.msg }}</li>
  144. {% endfor %}
  145. </ul>
  146. """,
  147. )
  148. logger = logging.getLogger(__name__)
  149. logger.addHandler(hdlr)
  150. As you may have noted, the subject can contain string formatting.
  151. The following arguments are passed to the string format:
  152. ============== ========================= ==================================
  153. Argument Type Description
  154. ============== ========================= ==================================
  155. records list of logging.LogRecord Log records to send
  156. min_level_name str Name of the lowest log level name
  157. max_level_name str Name of the highest log level name
  158. handler MultiEmailHandler MultiEmailHandler itself
  159. ============== ========================= ==================================
  160. In addition, the text and HTML bodies are processed using Jinja and the
  161. following parameters are passed:
  162. ======== ========================= ==========================
  163. Argument Type Description
  164. ======== ========================= ==========================
  165. records list of logging.LogRecord List of log records
  166. msgs list of str List of formatted messages
  167. handler MultiEmailHandler MultiEmailHandler itself
  168. ======== ========================= ==========================