forked from ray-project/ray
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "Revert "Global logging format changes" (ray-project#34126)" (r…
…ay-project#34182) Attempts to consolidate logging configuration by introducing reasonable defaults in ray/log.py. This new logging configuration is done once in ray/__init__.py at the top of the module. Subsequent calls to the configuration are ignored. A logger for ray.rllib is configured at the WARN level, to address Revert "Simplify logging configuration. (ray-project#30863)" ray-project#31858. With this change, Revert "Simplify logging configuration. (ray-project#30863)" ray-project#31858 can be reverted, again simplifying and consolidating logging configuration. Modified test_output.py::test_logger_config to test only the logger config, not launch a ray cluster. The test was failing intermittently, I think due to a race condition between the launch of the cluster and the reading of the subprocess's stdout, and anyway it wasn't necessary to call ray.init here to check that logging was configured correctly. Modified python/ray/tune/tests/test_commands.py::test_ls_with_cfg to test the underlying data, not what gets printed to stdout (which has changed with the new logging system). Modified a logging message in ray.tune.automl.search_policy.AutoMLSearcher.on_trial_complete, which in certain cases emits a logging message which tries to format a NoneType into a %f during log message formatting. This was a previously-undetected bug which showed up because the default log level is now INFO. This fixes a test that was failing in test_automl_searcher.py::AutoMLSearcherTest. Signed-off-by: e428265 <[email protected]>
- Loading branch information
1 parent
b745551
commit 360f405
Showing
34 changed files
with
537 additions
and
192 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import logging | ||
import re | ||
from logging.config import dictConfig | ||
import threading | ||
|
||
|
||
class ContextFilter(logging.Filter): | ||
"""A filter that adds ray context info to log records. | ||
This filter adds a package name to append to the message as well as information | ||
about what worker emitted the message, if applicable. | ||
""" | ||
|
||
logger_regex = re.compile(r"ray(\.(?P<subpackage>\w+))?(\..*)?") | ||
package_message_names = { | ||
"air": "AIR", | ||
"data": "Data", | ||
"rllib": "RLlib", | ||
"serve": "Serve", | ||
"train": "Train", | ||
"tune": "Tune", | ||
"workflow": "Workflow", | ||
} | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
|
||
def filter(self, record: logging.LogRecord) -> bool: | ||
"""Add context information to the log record. | ||
This filter adds a package name from where the message was generated as | ||
well as the worker IP address, if applicable. | ||
Args: | ||
record: Record to be filtered | ||
Returns: | ||
True if the record is to be logged, False otherwise. (This filter only | ||
adds context, so records are always logged.) | ||
""" | ||
match = self.logger_regex.search(record.name) | ||
if match and match["subpackage"] in self.package_message_names: | ||
record.package = f"[Ray {self.package_message_names[match['subpackage']]}]" | ||
else: | ||
record.package = "" | ||
|
||
return True | ||
|
||
|
||
class PlainRayHandler(logging.StreamHandler): | ||
"""A plain log handler. | ||
This handler writes to whatever sys.stderr points to at emit-time, | ||
not at instantiation time. See docs for logging._StderrHandler. | ||
""" | ||
|
||
def __init__(self): | ||
super().__init__() | ||
self.plain_handler = logging._StderrHandler() | ||
self.plain_handler.level = self.level | ||
self.plain_handler.formatter = logging.Formatter(fmt="%(message)s") | ||
|
||
def emit(self, record: logging.LogRecord): | ||
"""Emit the log message. | ||
If this is a worker, bypass fancy logging and just emit the log record. | ||
If this is the driver, emit the message using the appropriate console handler. | ||
Args: | ||
record: Log record to be emitted | ||
""" | ||
import ray | ||
|
||
if ( | ||
hasattr(ray, "_private") | ||
and ray._private.worker.global_worker.mode | ||
== ray._private.worker.WORKER_MODE | ||
): | ||
self.plain_handler.emit(record) | ||
else: | ||
logging._StderrHandler.emit(self, record) | ||
|
||
|
||
logger_initialized = False | ||
logging_config_lock = threading.Lock() | ||
|
||
|
||
def generate_logging_config(): | ||
"""Generate the default Ray logging configuration.""" | ||
with logging_config_lock: | ||
global logger_initialized | ||
if logger_initialized: | ||
return | ||
logger_initialized = True | ||
|
||
formatters = { | ||
"plain": { | ||
"datefmt": "[%Y-%m-%d %H:%M:%S]", | ||
"format": "%(asctime)s %(package)s %(levelname)s %(name)s::%(message)s", | ||
}, | ||
} | ||
filters = {"context_filter": {"()": ContextFilter}} | ||
handlers = { | ||
"default": { | ||
"()": PlainRayHandler, | ||
"formatter": "plain", | ||
"filters": ["context_filter"], | ||
} | ||
} | ||
|
||
loggers = { | ||
# Default ray logger; any log message that gets propagated here will be | ||
# logged to the console. Disable propagation, as many users will use | ||
# basicConfig to set up a default handler. If so, logs will be | ||
# printed twice unless we prevent propagation here. | ||
"ray": { | ||
"level": "INFO", | ||
"handlers": ["default"], | ||
"propagate": False, | ||
}, | ||
# Special handling for ray.rllib: only warning-level messages passed through | ||
# See https://github.com/ray-project/ray/pull/31858 for related PR | ||
"ray.rllib": { | ||
"level": "WARN", | ||
}, | ||
} | ||
|
||
dictConfig( | ||
{ | ||
"version": 1, | ||
"formatters": formatters, | ||
"filters": filters, | ||
"handlers": handlers, | ||
"loggers": loggers, | ||
} | ||
) |
Oops, something went wrong.