Skip to content

Commit 749a6e5

Browse files
authored
add format overriding by environment variables (#722)
* 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]>
1 parent 94e159d commit 749a6e5

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

launch/launch/logging/__init__.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,21 @@ def set_screen_format(self, screen_format, *, screen_style=None):
206206
:param screen_format: format specification used when logging to the screen,
207207
as expected by the `logging.Formatter` constructor.
208208
Alternatively, aliases for common formats are available, see above.
209+
This format can also be overridden by the environment variable
210+
'OVERRIDE_LAUNCH_SCREEN_FORMAT'.
209211
:param screen_style: the screen style used if no alias is used for
210212
screen_format.
211213
No style can be provided if a format alias is given.
212214
"""
215+
# Check if the environment variable is set
216+
screen_format_env = os.environ.get('OVERRIDE_LAUNCH_SCREEN_FORMAT')
217+
# If the environment variable is set override the given format
218+
if screen_format_env not in [None, '']:
219+
# encoded escape characters correctly
220+
screen_format = screen_format_env.encode(
221+
'latin1').decode('unicode_escape')
222+
# Set the style correspondingly
223+
screen_style = '{'
213224
if screen_format is not None:
214225
if screen_format == 'default':
215226
screen_format = '[{levelname}] [{name}]: {msg}'
@@ -258,9 +269,20 @@ def set_log_format(self, log_format, *, log_style=None):
258269
as expected by the `logging.Formatter` constructor.
259270
Alternatively, the 'default' alias can be given to log verbosity level,
260271
logger name and logged message.
272+
This format can also be overridden by the environment variable
273+
'OVERRIDE_LAUNCH_LOG_FORMAT'.
261274
:param log_style: the log style used if no alias is given for log_format.
262275
No style can be provided if a format alias is given.
263276
"""
277+
# Check if the environment variable is set
278+
log_format_env = os.environ.get('OVERRIDE_LAUNCH_LOG_FORMAT')
279+
# If the environment variable is set override the given format
280+
if log_format_env not in [None, '']:
281+
# encoded escape characters correctly
282+
log_format = log_format_env.encode(
283+
'latin1').decode('unicode_escape')
284+
# Set the style correspondingly
285+
log_style = '{'
264286
if log_format is not None:
265287
if log_format == 'default':
266288
log_format = '{created:.7f} [{levelname}] [{name}]: {msg}'

launch/test/launch/test_logging.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,13 @@ def log_dir(tmpdir_factory):
3131
return str(tmpdir_factory.mktemp('logs'))
3232

3333

34-
def test_bad_logging_launch_config():
34+
@pytest.fixture
35+
def mock_clean_env(monkeypatch):
36+
monkeypatch.delenv('OVERRIDE_LAUNCH_SCREEN_FORMAT', raising=False)
37+
monkeypatch.delenv('OVERRIDE_LAUNCH_LOG_FORMAT', raising=False)
38+
39+
40+
def test_bad_logging_launch_config(mock_clean_env):
3541
"""Tests that setup throws at bad configuration."""
3642
launch.logging.reset()
3743

@@ -83,7 +89,7 @@ def test_output_loggers_bad_configuration(log_dir):
8389
},
8490
)
8591
])
86-
def test_output_loggers_configuration(capsys, log_dir, config, checks):
92+
def test_output_loggers_configuration(capsys, log_dir, config, checks, mock_clean_env):
8793
checks = {'stdout': set(), 'stderr': set(), 'both': set(), **checks}
8894
launch.logging.reset()
8995
launch.logging.launch_config.log_dir = log_dir
@@ -162,7 +168,7 @@ def test_output_loggers_configuration(capsys, log_dir, config, checks):
162168
assert (not os.path.exists(own_log_path) or 0 == os.stat(own_log_path).st_size)
163169

164170

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

183189

184-
def test_screen_default_format(capsys):
190+
def test_screen_default_format(capsys, mock_clean_env):
185191
"""Test screen logging when using the default logs format."""
186192
launch.logging.reset()
187193

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

220226

227+
def test_logging_env_var_format(capsys, monkeypatch):
228+
monkeypatch.setenv('OVERRIDE_LAUNCH_SCREEN_FORMAT', 'TESTSCREEN {message} {name} TESTSCREEN')
229+
monkeypatch.setenv('OVERRIDE_LAUNCH_LOG_FORMAT', 'TESTLOG {message} {name} TESTLOG')
230+
launch.logging.reset()
231+
232+
logger = launch.logging.get_logger('some-proc')
233+
logger.addHandler(launch.logging.launch_config.get_screen_handler())
234+
235+
logger.info('bar')
236+
capture = capsys.readouterr()
237+
lines = capture.out.splitlines()
238+
assert 'TESTSCREEN bar some-proc TESTSCREEN' == lines.pop()
239+
240+
launch.logging.launch_config.get_log_file_handler().flush()
241+
with open(launch.logging.launch_config.get_log_file_path(), 'r') as f:
242+
lines = f.readlines()
243+
assert 'TESTLOG bar some-proc TESTLOG\n' == lines[0]
244+
245+
221246
def test_log_handler_factory(log_dir):
222247
"""Test logging using a custom log handlers."""
223248
class TestStreamHandler(launch.logging.handlers.Handler):

0 commit comments

Comments
 (0)