Extend functionality of make_default_logger:
Introduce support for asynchronous loggers.
Make print function configurable.
Introduce serialize_fn which can be used to perform additional transformations on the logs prior to actual logging.
"""Default logger."""
+from typing import Any, Callable, Mapping, Optional
+
from acme.utils.loggers import aggregators
+from acme.utils.loggers import asynchronous as async_logger
from acme.utils.loggers import base
from acme.utils.loggers import csv
from acme.utils.loggers import filters
@@ -26,24 +29,41 @@ def make_default_logger(
label: str,
save_data: bool = True,
time_delta: float = 1.0,
+ asynchronous: bool = False,
+ print_fn: Optional[Callable[[str], None]] = None,
+ serialize_fn: Optional[Callable[[Mapping[str, Any]], str]] = base.to_numpy,
+ steps_key: str = 'steps',
) -> base.Logger:
"""Make a default Acme logger.
Args:
label: Name to give to the logger.
- save_data: Ignored.
+ save_data: Whether to persist data.
time_delta: Time (in seconds) between logging events.
+ asynchronous: Whether the write function should block or not.
+ print_fn: How to print to terminal (defaults to print).
+ serialize_fn: An optional function to apply to the write inputs before
+ passing them to the various loggers.
+ steps_key: Ignored.
Returns:
- A logger (pipe) object that responds to logger.write(some_dict).
+ A logger object that responds to logger.write(some_dict).
"""
- terminal_logger = terminal.TerminalLogger(label=label, time_delta=time_delta)
+ del steps_key
+ if not print_fn:
+ print_fn = print
+ terminal_logger = terminal.TerminalLogger(label=label, print_fn=print_fn)
loggers = [terminal_logger]
+
if save_data:
loggers.append(csv.CSVLogger(label=label))
- logger = aggregators.Dispatcher(loggers)
+ # Dispatch to all writers and filter Nones and by time.
+ logger = aggregators.Dispatcher(loggers, serialize_fn)
logger = filters.NoneFilter(logger)
+ if asynchronous:
+ logger = async_logger.AsyncLogger(logger)
logger = filters.TimeFilter(logger, time_delta)
+
return logger
