Randolph,
Below is the updated specification written without code formatting blocks:
The Log Server is responsible for creating, managing, and writing log entries to a file within the local ./logs
directory. It provides functions to enable and disable logging, and to write log messages that are processed asynchronously by a dedicated goroutine.
-
Directory Creation:
On enabling logging, the server must ensure the./logs
directory exists. If it does not, the directory should be created. -
File Naming Convention:
The log file name must be formatted as:
anthropic-debug-YYYYMMDD-HHMMSS.log
where:- YYYY is the 4-digit year
- MM is the 2-digit month
- DD is the 2-digit day
- HH is the 2-digit hour (24-hour format)
- MM is the 2-digit minute
- SS is the 2-digit second
For example:
anthropic-debug-20241209-200245.log
-
EnableLogging() error:
- Creates the
./logs
directory if it does not exist. - Opens a new log file with the specified naming format.
- Sets the internal state to "enabled" and spawns a goroutine to process incoming log messages.
- If logging is already enabled, this function should return immediately without error.
- Returns an error if directory or file creation fails.
- Creates the
-
DisableLogging():
- Sets the internal state to "disabled".
- Closes the log message channel (logChan) to signal the goroutine to complete its work.
- Waits until the goroutine finishes processing all buffered messages.
- Closes the open log file.
- If logging is not currently enabled, this function should return immediately without side effects.
-
WriteLogs(text string):
- If logging is enabled, sends the text message to the logChan channel for asynchronous processing by the goroutine.
- If logging is disabled, returns immediately without writing.
-
Channel-Based Logging:
All log messages are written to a buffered channel (logChan). A single goroutine (processLogs()) reads from this channel and performs all file write operations, ensuring serialized access to the file. -
Mutex Protection:
A sync.Mutex guards critical sections that manipulate the logger’s internal state and perform file operations. The mutex ensures that enabling, disabling, and file I/O are all thread-safe.
- The goroutine spawned by EnableLogging() reads from logChan in a loop.
- Each message read from logChan is written to the file while holding the mutex.
- When DisableLogging() is called, logChan is closed. The goroutine terminates once all remaining messages are processed.
- Upon termination, the goroutine signals completion via the done channel, allowing DisableLogging() to safely close the file.
- If enabling logging fails due to directory or file creation errors, EnableLogging() must return an error. The caller is responsible for handling this error.
- Once enabled, log writes are asynchronous and should not fail silently. However, if a write error occurs, the code should handle it gracefully within the processing goroutine.
- The logChan channel is buffered to handle bursts of log messages. If it becomes full, callers of WriteLogs() may block until there is space available.
- The mutex ensures no concurrent writes to the file, preventing corruption and ensuring that log messages remain ordered as produced.
The Log Server must:
- Create and write to timestamped log files in
./logs
. - Support enabling and disabling logging without losing messages.
- Use a dedicated goroutine and a buffered channel to process log messages asynchronously.
- Employ a mutex to ensure thread-safe access to shared resources.
- Gracefully handle start-up, shutdown, and potential I/O errors.