Hone logo
Hone
Problems

Structured Logging in Python

Structured logging is a powerful technique for improving the observability of your applications. Instead of just writing plain text messages, structured logging formats log data as key-value pairs, making it easier to search, filter, and analyze logs using tools like Elasticsearch, Splunk, or even simple grep commands. This challenge asks you to implement a basic structured logger that can log messages with different severity levels and associated metadata.

Problem Description

You are tasked with creating a Python class called StructuredLogger that provides a simple interface for structured logging. The logger should support the following severity levels: DEBUG, INFO, WARNING, ERROR, and CRITICAL. For each log message, you should be able to associate arbitrary metadata (a dictionary of key-value pairs) to provide context. The logger should then format the log message as a JSON-like string, including the severity level, timestamp, and metadata.

Key Requirements:

  • Severity Levels: The logger must support the five standard Python logging severity levels.
  • Metadata: The logger must accept a dictionary of metadata to be included in each log message.
  • Timestamp: Each log message must include a timestamp (in ISO 8601 format).
  • JSON-like Output: The log message should be formatted as a string that resembles JSON, but without strict JSON validation (e.g., no need to escape special characters). The format should be: {"severity": "LEVEL", "timestamp": "YYYY-MM-DDTHH:MM:SS", "message": "MESSAGE", "metadata": {METADATA}}.
  • Error Handling: The logger should gracefully handle cases where the metadata is not a dictionary.

Expected Behavior:

When you call the log() method of the StructuredLogger class, it should:

  1. Accept a message string and an optional metadata dictionary.
  2. Format the message according to the specified format, including the severity level, timestamp, message, and metadata.
  3. Return the formatted log message string.

Edge Cases to Consider:

  • Invalid severity levels (levels not in the defined set). The logger should default to INFO in this case.
  • Metadata that is not a dictionary. The logger should log a warning and omit the metadata.
  • Empty metadata dictionary. The metadata section should still be present in the output, but empty.

Examples

Example 1:

Input: logger = StructuredLogger(); logger.log("Application started", metadata={"version": "1.0.0"})
Output: '{"severity": "INFO", "timestamp": "2023-10-27T10:00:00", "message": "Application started", "metadata": {"version": "1.0.0"}}'
Explanation: The message is logged with INFO severity, a timestamp, and the provided metadata.  The timestamp is a placeholder.

Example 2:

Input: logger = StructuredLogger(); logger.log("Error processing data", severity="ERROR", metadata="not a dictionary")
Output: '{"severity": "ERROR", "timestamp": "2023-10-27T10:01:00", "message": "Error processing data", "metadata": {}}'
Explanation: The message is logged with ERROR severity. The metadata is invalid (not a dictionary), so a warning is logged internally, and the metadata section is empty in the output. The timestamp is a placeholder.

Example 3:

Input: logger = StructuredLogger(); logger.log("Debug message", severity="DEBUG", metadata={})
Output: '{"severity": "DEBUG", "timestamp": "2023-10-27T10:02:00", "message": "Debug message", "metadata": {}}'
Explanation: The message is logged with DEBUG severity, and an empty metadata dictionary is included. The timestamp is a placeholder.

Constraints

  • The timestamp must be in ISO 8601 format (YYYY-MM-DDTHH:MM:SS).
  • The metadata must be a dictionary or omitted.
  • The logger class should be named StructuredLogger.
  • The log method should accept a message string, an optional severity level (string), and an optional metadata dictionary.
  • The severity level defaults to "INFO" if not provided or invalid.
  • The code should be reasonably efficient (avoid unnecessary loops or complex operations).

Notes

  • You don't need to implement actual logging to a file or external service. The focus is on formatting the log message correctly.
  • Consider using the datetime module to generate the timestamp.
  • Think about how to handle invalid severity levels gracefully.
  • The JSON-like format doesn't need to be perfectly valid JSON. Simple string formatting is sufficient.
  • The timestamp should be generated at the time of logging.
Loading editor...
python