-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add some 🟥🟧🟨🟩🟦🟪 to the logs #478
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,8 @@ | |
import time | ||
from typing import Iterator, Optional, Union | ||
|
||
import colors | ||
|
||
import goth | ||
import goth.api_monitor | ||
from goth.assertions.monitor import EventMonitor | ||
|
@@ -20,32 +22,37 @@ | |
logger = logging.getLogger(__name__) | ||
|
||
|
||
class UTCFormatter(logging.Formatter): | ||
"""Custom `logging` formatter that uses `time.gmtime`.""" | ||
class CustomFileLogFormatter(logging.Formatter): | ||
"""`Formatter` that uses `time.gmtime` for time and strips ANSI color codes.""" | ||
|
||
converter = time.gmtime | ||
|
||
def format(self, record: logging.LogRecord) -> str: | ||
"""Format the message and remove ANSI color codes from it.""" | ||
text = super().format(record) | ||
return colors.strip_color(text) | ||
|
||
|
||
LOGGING_CONFIG = { | ||
"version": 1, | ||
"formatters": { | ||
"none": {"format": "%(message)s"}, | ||
"simple": {"format": "%(levelname)-8s [%(name)-30s] %(message)s"}, | ||
"date": { | ||
"()": UTCFormatter, | ||
"console": {"format": "%(levelname)-8s [%(name)-30s] %(message)s"}, | ||
"file": { | ||
"()": CustomFileLogFormatter, | ||
"format": "%(asctime)s %(levelname)-8s %(name)-30s %(message)s", | ||
"datefmt": "%Y-%m-%d %H:%M:%S%z", | ||
}, | ||
}, | ||
"handlers": { | ||
"console": { | ||
"class": "logging.StreamHandler", | ||
"formatter": "simple", | ||
"formatter": "console", | ||
"level": "INFO", | ||
}, | ||
"runner_file": { | ||
"class": "logging.FileHandler", | ||
"formatter": "date", | ||
"formatter": "file", | ||
"filename": "%(base_log_dir)s/runner.log", | ||
"encoding": "utf-8", | ||
"level": "DEBUG", | ||
|
@@ -123,9 +130,9 @@ def configure_logging_for_test(test_log_dir: Path) -> None: | |
proxy_handler = None | ||
|
||
try: | ||
formatter = logging.Formatter( | ||
fmt=LOGGING_CONFIG["formatters"]["date"]["format"], | ||
datefmt=LOGGING_CONFIG["formatters"]["date"]["datefmt"], | ||
formatter = CustomFileLogFormatter( | ||
fmt=LOGGING_CONFIG["formatters"]["file"]["format"], | ||
datefmt=LOGGING_CONFIG["formatters"]["file"]["datefmt"], | ||
) | ||
|
||
# TODO: ensure the new files created here do not conflict with probe logs | ||
|
@@ -148,16 +155,25 @@ def configure_logging_for_test(test_log_dir: Path) -> None: | |
api_monitor_logger.handlers.remove(proxy_handler) | ||
|
||
|
||
class MonitorHandler(logging.Handler): | ||
"""A logging handler that passes messages from log records to an event monitor.""" | ||
class MonitoringFilter(logging.Filter): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I switched from using custom |
||
"""A logging `Filter` that feeds messages to the underlying event monitor. | ||
|
||
After doing this it also adds some color to the messages for greater fun. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👯 |
||
""" | ||
|
||
def __init__(self, monitor: EventMonitor[str]): | ||
self._monitor = monitor | ||
def __init__(self, monitor: EventMonitor[str], color: Optional[str] = None): | ||
super().__init__() | ||
self._monitor: EventMonitor[str] = monitor | ||
self._color: Optional[str] = color | ||
|
||
def handle(self, record: logging.LogRecord) -> None: | ||
"""Add the `record`'s message to the associated event monitor.""" | ||
self._monitor.add_event_sync(record.getMessage()) | ||
def filter(self, record: logging.LogRecord) -> bool: | ||
"""Pass the record's message to the monitor, add colors to the message.""" | ||
message = record.getMessage() | ||
self._monitor.add_event_sync(message) | ||
if self._color: | ||
record.msg = colors.color(message, fg=self._color) | ||
record.args = () | ||
return True | ||
|
||
|
||
@contextlib.contextmanager | ||
|
@@ -170,10 +186,9 @@ def monitored_logger(name: str, monitor: EventMonitor[str]) -> Iterator[logging. | |
""" | ||
|
||
logger_ = logging.getLogger(name) | ||
handler = MonitorHandler(monitor) | ||
filter = MonitoringFilter(monitor, "cyan") | ||
logger_.filters.insert(0, filter) | ||
try: | ||
logger_.addHandler(handler) | ||
yield logger_ | ||
finally: | ||
if handler in logger_.handlers: | ||
logger_.removeHandler(handler) | ||
logger.removeFilter(filter) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previous assertion success/failure messages that included details of events that made the assertion succeed or fail were a bit unreadable, so I've decided to split them in two messages: one containing the event details and logged with
DEBUG
level, and another one, in color, only stating that the assertion succeeds or fails with a given result, logged as before (usually asINFO
).