python logging: email entire log file as attachment when level >= ERROR

3 min read 07-10-2024
python logging: email entire log file as attachment when level >= ERROR


Sending Your Python Log File by Email: A Comprehensive Guide

Debugging a Python application can be tricky, especially when errors pop up unexpectedly. Sometimes, you need more than just the console output. Sending your entire log file by email when serious errors occur can provide a complete snapshot of what went wrong.

This article will guide you through configuring your Python logging system to automatically email the entire log file as an attachment whenever the logging level reaches ERROR or higher.

Scenario:

Imagine your Python application is running in a production environment. You want to be notified immediately whenever a critical error occurs, including all relevant information from the logs.

Original Code (Basic Logging Configuration):

import logging

logging.basicConfig(filename='my_app.log', level=logging.DEBUG, 
                    format='%(asctime)s - %(levelname)s - %(message)s')

# Example logging
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message') 

This code sets up a basic logging configuration, writing logs to a file named 'my_app.log' at the DEBUG level.

Adding Email Functionality:

To send the entire log file as an attachment when the logging level reaches ERROR, we'll leverage the smtplib and email modules in Python.

Enhanced Code (with Email Functionality):

import logging
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

# Logging Configuration
logging.basicConfig(filename='my_app.log', level=logging.DEBUG,
                    format='%(asctime)s - %(levelname)s - %(message)s')

# Email Credentials
sender_email = '[email protected]'
sender_password = 'your_password'
receiver_email = '[email protected]'

# Email Sending Function
def send_log_email(log_file_path):
    msg = MIMEMultipart()
    msg['From'] = sender_email
    msg['To'] = receiver_email
    msg['Subject'] = 'Error Log File Attached'

    body = 'An error occurred in your application. Please find the attached log file for details.'
    msg.attach(MIMEText(body, 'plain'))

    # Attach Log File
    with open(log_file_path, 'rb') as attachment:
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(attachment.read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition', f'attachment; filename="{log_file_path}"')
        msg.attach(part)

    # Send Email
    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
        server.login(sender_email, sender_password)
        server.sendmail(sender_email, receiver_email, msg.as_string())

# Custom Filter to Trigger Email
class ErrorFilter(logging.Filter):
    def filter(self, record):
        return record.levelno >= logging.ERROR

# Attach Filter to Logger
logger = logging.getLogger()
logger.addFilter(ErrorFilter())

# Handle Error Logging
logging.error('This is an error message, triggering email!')

# Example usage of the logger
logging.info('This is an info message') 
logging.debug('This is a debug message') 

Explanation:

  1. Email Configuration: We define your email credentials (sender email, password, and receiver email) at the top of the code.
  2. send_log_email() Function: This function creates a multipart email message, adds the email body, attaches the log file, and sends the email using the smtplib module.
  3. ErrorFilter Class: This custom filter checks if the logging level is ERROR or higher. If it is, the filter allows the log record to pass through, triggering the email functionality.
  4. Attaching Filter: The filter is attached to the root logger (logging.getLogger()) so that any logger within the application will be subject to this filter.

Key Improvements:

  • Conditional Emailing: Only sends emails when the logging level is ERROR or above, preventing unnecessary emails for less critical events.
  • Complete Log File: Attaches the entire log file as an attachment, providing a comprehensive view of the error context.
  • Custom Filter: Improves code readability by using a filter to control which logs trigger email notifications.

Important Considerations:

  • Security: Store your email credentials securely. Consider environment variables or a dedicated credentials file.
  • Email Server Settings: Make sure to use the correct SMTP server address and port for your email provider.
  • Log Rotation: Implement log rotation to prevent your log file from growing indefinitely. You can use the logging.handlers.RotatingFileHandler for this.
  • Error Handling: Add error handling in the send_log_email() function to catch any potential issues with sending the email.

By implementing these steps, you'll create a reliable system for receiving timely email notifications when critical errors occur in your Python application. This allows for prompt troubleshooting and keeps you informed about the health of your application.