Hone logo
Hone
Problems

Implementing Structured Logging in Go

Structured logging is a powerful technique for improving the observability of your Go applications. Instead of just writing plain text messages, structured logging involves logging data in a key-value format, making it easier to search, filter, and analyze logs. This challenge asks you to implement a simple structured logger that can log messages with associated metadata.

Problem Description

You are tasked with creating a StructuredLogger in Go that allows you to log messages with different severity levels (Info, Warning, Error) and associated key-value metadata. The logger should format the log entries in a JSON-like structure, including a timestamp, severity level, message, and any provided metadata. The goal is to create a flexible and extensible logging solution that facilitates efficient log analysis and debugging.

Key Requirements:

  • Severity Levels: The logger must support at least three severity levels: Info, Warning, and Error.
  • Metadata: The logger must accept a map of key-value pairs as metadata to be included in each log entry. Keys should be strings, and values can be strings, integers, or booleans.
  • Timestamp: Each log entry must include a timestamp indicating when the event occurred.
  • JSON-like Output: The log entries should be formatted in a way that resembles JSON, although a strict JSON encoding is not required. A simple string representation is sufficient.
  • Error Handling: The logger should gracefully handle invalid metadata types (e.g., attempting to log a slice or map as metadata). In such cases, the metadata should be omitted from the log entry.

Expected Behavior:

When calling the Log method with a message, severity level, and metadata, the logger should produce a string representing the log entry. This string should include the timestamp, severity level, message, and metadata (if valid).

Edge Cases to Consider:

  • Empty metadata map.
  • Invalid metadata types (e.g., slices, maps, functions).
  • No message provided.
  • Invalid severity level (although this is less critical for this exercise).

Examples

Example 1:

Input: logger.Log("Request processed", "Info", map["user_id": 123, "request_id": "abc-123"])
Output: "[2023-10-27T10:00:00] [INFO] Request processed  [Metadata: map[request_id:abc-123 user_id:123]]"
Explanation: A standard log entry with timestamp, severity, message, and metadata.  The timestamp is a placeholder.

Example 2:

Input: logger.Log("Error processing request", "Error", map["error_code": 500, "message": "Internal Server Error"])
Output: "[2023-10-27T10:01:00] [ERROR] Error processing request [Metadata: map[error_code:500 message:Internal Server Error]]"
Explanation: An error log entry with timestamp, severity, message, and metadata.

Example 3:

Input: logger.Log("Warning: Low disk space", "Warning", map["disk_usage": 95])
Output: "[2023-10-27T10:02:00] [WARNING] Warning: Low disk space [Metadata: map[disk_usage:95]]"
Explanation: A warning log entry with timestamp, severity, message, and metadata.

Example 4:

Input: logger.Log("Invalid data received", "Error", map["data": [1, 2, 3]])
Output: "[2023-10-27T10:03:00] [ERROR] Invalid data received [Metadata: map[]]"
Explanation: The metadata containing a slice is invalid and is therefore omitted.

Constraints

  • The timestamp should be in a readable format (e.g., YYYY-MM-DDTHH:MM:SS).
  • The metadata keys should be strings.
  • The metadata values should be strings, integers, or booleans.
  • The logger should be thread-safe (although rigorous testing for thread safety is not required for this challenge).
  • The output string should be reasonably concise and easy to parse.

Notes

  • Consider using the time package for timestamp generation.
  • You can use fmt.Sprintf or similar functions to format the log entries.
  • Focus on the core functionality of structured logging. You don't need to implement a full-fledged logging system with file output or remote logging.
  • Think about how to handle different data types in the metadata map. A simple string conversion might be sufficient.
  • The exact format of the output string is not critical, as long as it includes the required information in a clear and consistent manner. The examples provide a guideline.
  • Error handling for invalid metadata types is important for robustness.
Loading editor...
go