Create and code a compact logging framework whose behavior is controlled by configurable handlers. This may be presented as an object-oriented design exercise involving processors such as CapitalizeHandler, AddHandler, or similar components.
Each handler must be configurable on its own, and introducing another behavior should require minimal changes to the existing logger.
The exercise commonly has two stages:
Create a Logger that receives an ordered collection of handlers. When log(message) is invoked, the message must pass through those handlers in sequence.
Provide these handlers:
from typing import Optional
class Logger:
def __init__(self, handlers: list["LogHandler"]):
pass
def log(self, message: str) -> Optional[str]:
"""
Process one log message.
Returns the printed message when the logger prints.
Returns None when output is suppressed, such as by StoreHandler.
"""
pass
class LogHandler:
def handle(self, message: str) -> tuple[str, bool]:
"""
Returns:
(new_message, should_print)
"""
pass
logger = Logger([
RemoveStringHandler("trace: "),
TruncateHandler(11),
CapitalizeHandler(),
])
logger.log("trace: daily report generated")
DAILY REPOR
The handlers change the text in this order:
"trace: ": "daily report generated""daily repor""DAILY REPOR"store = StoreHandler()
logger = Logger([
RemoveStringHandler("[private] "),
CapitalizeHandler(),
store,
])
logger.log("[private] invoice batch delayed")
logger.log("[private] account update finished")
print(store.messages)
['INVOICE BATCH DELAYED', 'ACCOUNT UPDATE FINISHED']
The calls to logger.log(...) produce no printed output because StoreHandler retains the processed messages and disables printing.
Assume that the logger now keeps messages internally. Add, or describe, a keyword-search capability.
A simple initial request may be:
def search(self, keyword: str) -> list[str]:
"""
Return stored messages that contain keyword.
"""
pass
A later question may ask for a faster design.
“How could search be made faster?”
store = IndexedStoreHandler()
logger = Logger([
RemoveStringHandler("[private] "),
CapitalizeHandler(),
store,
])
logger.log("[private] invoice review pending")
logger.log("[private] profile update complete")
logger.log("[private] invoice update complete")
print(store.search("invoice"))
print(store.search("complete"))
['INVOICE REVIEW PENDING', 'INVOICE UPDATE COMPLETE']
['PROFILE UPDATE COMPLETE', 'INVOICE UPDATE COMPLETE']
[object Object]