Hone logo
Hone
Problems

Custom Logging Handler in Python

Logging is a crucial aspect of software development, enabling developers to track events, debug issues, and monitor application behavior. This challenge asks you to implement a custom logging handler in Python that writes log messages to a file, allowing for flexible and configurable logging within applications. This is useful for creating robust and maintainable applications.

Problem Description

You are tasked with creating a custom logging handler class named FileLoggingHandler. This handler should inherit from Python's built-in logging.Handler class and write log messages to a specified file. The handler should accept a filename as an argument during initialization and include a method to set the logging level. The handler should format the log messages as follows: [Timestamp] [Level] [Message]. The timestamp should be in ISO 8601 format (YYYY-MM-DD HH:MM:SS.mmmmmm).

Key Requirements:

  • Inheritance: The class must inherit from logging.Handler.
  • Initialization: The constructor (__init__) must accept a filename argument (string) specifying the file to write logs to.
  • Logging Level: The class must have a method set_level(level) that accepts a logging level (e.g., logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL) and sets an internal attribute to store it.
  • Emit: The emit(record) method must be implemented to format and write log messages to the specified file. It should receive a LogRecord object as input.
  • File Handling: The file should be opened in append mode ('a') to ensure that new log messages are added to the end of the file without overwriting existing content. The file should be properly closed after each write operation.
  • Timestamp Formatting: The timestamp in the log message must be formatted according to ISO 8601.
  • Error Handling: The handler should gracefully handle potential file I/O errors (e.g., file not found, permission denied) by printing an error message to the console and continuing to operate.

Expected Behavior:

When a log message is emitted to the handler, it should be written to the specified file in the format [Timestamp] [Level] [Message]. The timestamp should be accurate to microseconds. The handler should function correctly regardless of the logging level of the root logger or other handlers.

Edge Cases to Consider:

  • File does not exist or is not writable.
  • Invalid logging level provided to set_level().
  • Handling of exceptions during file writing.
  • Multiple threads accessing the same file (consider thread safety if required - not explicitly required for this challenge, but good to think about).

Examples

Example 1:

Input: filename = "app.log", level = logging.DEBUG, message = "Application started"
Output: app.log contains: "[2023-10-27 10:30:00.123456] DEBUG Application started"
Explanation: The log message is written to the file "app.log" with the current timestamp, DEBUG level, and the provided message.

Example 2:

Input: filename = "error.log", level = logging.ERROR, message = "An error occurred"
Output: error.log contains: "[2023-10-27 10:31:00.789012] ERROR An error occurred"
Explanation: The log message is written to the file "error.log" with the current timestamp, ERROR level, and the provided message.

Example 3: (Edge Case - File Not Writable)

Input: filename = "/root/protected.log", level = logging.WARNING, message = "Warning message"
Output: Console output: "Error: Could not write to file /root/protected.log"
error.log (if it exists) contains nothing.
Explanation: The handler attempts to write to a file it doesn't have permission to access. It prints an error message to the console and does not write to the file.

Constraints

  • The filename must be a string.
  • The logging level must be one of the predefined constants in the logging module (e.g., logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL).
  • The timestamp must be formatted in ISO 8601 format with microseconds.
  • The code should be reasonably efficient; avoid unnecessary operations.

Notes

  • You'll need to import the logging module.
  • Consider using the time module to get the current timestamp.
  • The LogRecord object passed to emit() contains information about the log message, including the level, message, and other attributes.
  • Think about how to handle potential exceptions during file I/O operations. A try...except block is recommended.
  • This challenge focuses on the core functionality of a logging handler. More advanced features like log rotation or custom formatting are beyond the scope of this exercise.
Loading editor...
python