Skip to content

Commit

Permalink
add format overriding by environment variables (#722)
Browse files Browse the repository at this point in the history
* add format overriding by environment variables

Signed-off-by: Marc Bestmann <[email protected]>

* add test for env var based formatting

Signed-off-by: Marc Bestmann <[email protected]>

---------

Signed-off-by: Marc Bestmann <[email protected]>
  • Loading branch information
SammyRamone authored Jan 29, 2024
1 parent 94e159d commit 749a6e5
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
22 changes: 22 additions & 0 deletions launch/launch/logging/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,21 @@ def set_screen_format(self, screen_format, *, screen_style=None):
:param screen_format: format specification used when logging to the screen,
as expected by the `logging.Formatter` constructor.
Alternatively, aliases for common formats are available, see above.
This format can also be overridden by the environment variable
'OVERRIDE_LAUNCH_SCREEN_FORMAT'.
:param screen_style: the screen style used if no alias is used for
screen_format.
No style can be provided if a format alias is given.
"""
# Check if the environment variable is set
screen_format_env = os.environ.get('OVERRIDE_LAUNCH_SCREEN_FORMAT')
# If the environment variable is set override the given format
if screen_format_env not in [None, '']:
# encoded escape characters correctly
screen_format = screen_format_env.encode(
'latin1').decode('unicode_escape')
# Set the style correspondingly
screen_style = '{'
if screen_format is not None:
if screen_format == 'default':
screen_format = '[{levelname}] [{name}]: {msg}'
Expand Down Expand Up @@ -258,9 +269,20 @@ def set_log_format(self, log_format, *, log_style=None):
as expected by the `logging.Formatter` constructor.
Alternatively, the 'default' alias can be given to log verbosity level,
logger name and logged message.
This format can also be overridden by the environment variable
'OVERRIDE_LAUNCH_LOG_FORMAT'.
:param log_style: the log style used if no alias is given for log_format.
No style can be provided if a format alias is given.
"""
# Check if the environment variable is set
log_format_env = os.environ.get('OVERRIDE_LAUNCH_LOG_FORMAT')
# If the environment variable is set override the given format
if log_format_env not in [None, '']:
# encoded escape characters correctly
log_format = log_format_env.encode(
'latin1').decode('unicode_escape')
# Set the style correspondingly
log_style = '{'
if log_format is not None:
if log_format == 'default':
log_format = '{created:.7f} [{levelname}] [{name}]: {msg}'
Expand Down
33 changes: 29 additions & 4 deletions launch/test/launch/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ def log_dir(tmpdir_factory):
return str(tmpdir_factory.mktemp('logs'))


def test_bad_logging_launch_config():
@pytest.fixture
def mock_clean_env(monkeypatch):
monkeypatch.delenv('OVERRIDE_LAUNCH_SCREEN_FORMAT', raising=False)
monkeypatch.delenv('OVERRIDE_LAUNCH_LOG_FORMAT', raising=False)


def test_bad_logging_launch_config(mock_clean_env):
"""Tests that setup throws at bad configuration."""
launch.logging.reset()

Expand Down Expand Up @@ -83,7 +89,7 @@ def test_output_loggers_bad_configuration(log_dir):
},
)
])
def test_output_loggers_configuration(capsys, log_dir, config, checks):
def test_output_loggers_configuration(capsys, log_dir, config, checks, mock_clean_env):
checks = {'stdout': set(), 'stderr': set(), 'both': set(), **checks}
launch.logging.reset()
launch.logging.launch_config.log_dir = log_dir
Expand Down Expand Up @@ -162,7 +168,7 @@ def test_output_loggers_configuration(capsys, log_dir, config, checks):
assert (not os.path.exists(own_log_path) or 0 == os.stat(own_log_path).st_size)


def test_screen_default_format_with_timestamps(capsys, log_dir):
def test_screen_default_format_with_timestamps(capsys, log_dir, mock_clean_env):
"""Test screen logging when using the default logs format with timestamps."""
launch.logging.reset()
launch.logging.launch_config.level = logging.DEBUG
Expand All @@ -181,7 +187,7 @@ def test_screen_default_format_with_timestamps(capsys, log_dir):
assert 0 == len(capture.err)


def test_screen_default_format(capsys):
def test_screen_default_format(capsys, mock_clean_env):
"""Test screen logging when using the default logs format."""
launch.logging.reset()

Expand Down Expand Up @@ -218,6 +224,25 @@ def test_log_default_format(log_dir):
assert re.match(r'[0-9]+\.[0-9]+ \[ERROR\] \[some-proc\]: baz', lines[0]) is not None


def test_logging_env_var_format(capsys, monkeypatch):
monkeypatch.setenv('OVERRIDE_LAUNCH_SCREEN_FORMAT', 'TESTSCREEN {message} {name} TESTSCREEN')
monkeypatch.setenv('OVERRIDE_LAUNCH_LOG_FORMAT', 'TESTLOG {message} {name} TESTLOG')
launch.logging.reset()

logger = launch.logging.get_logger('some-proc')
logger.addHandler(launch.logging.launch_config.get_screen_handler())

logger.info('bar')
capture = capsys.readouterr()
lines = capture.out.splitlines()
assert 'TESTSCREEN bar some-proc TESTSCREEN' == lines.pop()

launch.logging.launch_config.get_log_file_handler().flush()
with open(launch.logging.launch_config.get_log_file_path(), 'r') as f:
lines = f.readlines()
assert 'TESTLOG bar some-proc TESTLOG\n' == lines[0]


def test_log_handler_factory(log_dir):
"""Test logging using a custom log handlers."""
class TestStreamHandler(launch.logging.handlers.Handler):
Expand Down

0 comments on commit 749a6e5

Please sign in to comment.