1
0

logging.rst 6.9 KB

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