logging.rst 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. Email Logging
  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. sender="no-reply@example.com",
  31. receivers=["me@example.com"],
  32. )
  33. logger = logging.getLogger(__name__)
  34. logger.addHandler(hdlr)
  35. # To use:
  36. logger.warning("A warning happened")
  37. .. note::
  38. You may pass the :class:`.EmailSender`
  39. directly as an argument ``email``, for
  40. example:
  41. .. code-block:: python
  42. from redmail import EmailSender
  43. hdlr = EmailHandler(
  44. email=EmailSender(host="localhost", port=0)
  45. subject="A log record",
  46. receivers=["me@example.com"],
  47. )
  48. Note that a copy of the :class:`.EmailSender` is created
  49. in order to avoid affecting the usage of the instance
  50. elsewhere. Additional arguments (such as subject, sender,
  51. receivers, text, html, etc.) are set as attributes to
  52. this copied instance.
  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. sender="no-reply@example.com",
  97. receivers=["me@example.com"],
  98. )
  99. logger = logging.getLogger(__name__)
  100. logger.addHandler(hdlr)
  101. # To use:
  102. logger.warning("A warning happened")
  103. logger.warning("Another warning happened")
  104. # (Now an email should have been sent)
  105. # You may also manually flush
  106. logger.warning("A warning happened")
  107. hdlr.flush()
  108. .. note::
  109. You may pass the :class:`.EmailSender`
  110. directly as an argument ``email``, for
  111. example:
  112. .. code-block:: python
  113. from redmail import EmailSender
  114. hdlr = MultiEmailHandler(
  115. email=EmailSender(host="localhost", port=0)
  116. subject="Log records",
  117. receivers=["me@example.com"],
  118. )
  119. Note that a copy of the :class:`.EmailSender` is created
  120. in order to avoid affecting the usage of the instance
  121. elsewhere. Additional arguments (such as subject, sender,
  122. receivers, text, html, etc.) are set as attributes to
  123. this copied instance.
  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. ======== ========================= ==========================