logging.rst 7.0 KB

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