diff --git a/ska_logging/__init__.py b/ska_logging/__init__.py index 47c2feb8a0bf55ef42273b3ae1eb258620af86f1..1dcf20a50f0e7f7a37b878a0ba0ca69424513b50 100644 --- a/ska_logging/__init__.py +++ b/ska_logging/__init__.py @@ -2,12 +2,22 @@ """Module init code.""" -__all__ = ("configure_logging", "get_default_formatter") +__all__ = ( + "configure_logging", + "get_default_formatter", + "SkaLoggingError", + "SkaLoggingTagsFormatError", +) __author__ = "Anton Joubert" __email__ = "ajoubert+ska@ska.ac.za" -from .configuration import configure_logging, get_default_formatter +from .configuration import ( + configure_logging, + get_default_formatter, + SkaLoggingError, + SkaLoggingTagsFormatError, +) # BEGIN VERSION CHECK diff --git a/ska_logging/configuration.py b/ska_logging/configuration.py index efa85e52fb7935e95ee39f78e0ef7ed4480a3ebc..11135f31b1cb2b14562ec76bdc33dc49cd6abb48 100644 --- a/ska_logging/configuration.py +++ b/ska_logging/configuration.py @@ -7,6 +7,14 @@ import logging.config import time +class SkaLoggingError(Exception): + """Base class for all SKA Logger exceptions.""" + + +class SkaLoggingTagsFormatError(SkaLoggingError): + """Invalid format for the 'tags' field string.""" + + class _UTCFormatter(logging.Formatter): converter = time.gmtime @@ -38,6 +46,8 @@ _FORMAT_STR_WITH_TAGS = ( "%(message)s" ) +_INVALID_TAG_CHARS = ("|", "%") + _LOGGING_CONFIG = { "version": 1, "disable_existing_loggers": False, @@ -113,17 +123,33 @@ def get_default_formatter(tags=False): Parameters ---------- - tags : bool, optional - If true, then include the "tags" field in the format string. This requires - a tags filter to be linked to the corresponding handler. + tags : bool or str, optional + If boolean, then treated as a toggle: + - True: include the "tags" field in the format string. This requires + a tags filter to be linked to the corresponding handler. + - False: exclude the "tags" field from the format string. + If string, then it is a static tag. Instead of using a logging filter, the + formatter will just use this static string for the "tags" field directly. Returns ------- logging.Formatter A new default formatter. + Raises + ------ + SkaLoggingTagsFormatError: + If the static tags string has an invalid format. + """ - if tags: + if isinstance(tags, str): + invalid_chars = [c for c in _INVALID_TAG_CHARS if c in tags] + if invalid_chars: + raise SkaLoggingTagsFormatError( + "Invalid char(s) {} in tags: {!r}".format(invalid_chars, tags) + ) + format_str = _FORMAT_STR_WITH_TAGS.replace("%(tags)s", tags) + elif tags: format_str = _FORMAT_STR_WITH_TAGS else: format_str = _FORMAT_STR_NO_TAGS diff --git a/tests/test_configuration.py b/tests/test_configuration.py index a386d4166bec57c1d7d92338a56bd0173a811750..3e72a36a1bb83fbdae61416e8b3fea67f0c7f3da 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -9,7 +9,7 @@ import pytest import ska_logging.configuration -from ska_logging import configure_logging, get_default_formatter +from ska_logging import configure_logging, get_default_formatter, SkaLoggingTagsFormatError @pytest.fixture @@ -165,7 +165,7 @@ class TestConfigureLogging: assert get_named_handler(logger, "test") -class TestGetFormatter: +class TestGetDefaultFormatter: """Tests for :func:`~ska_logging.configuration.get_default_formatter`.""" def test_default_no_tags(self): @@ -173,16 +173,29 @@ class TestGetFormatter: assert isinstance(formatter, ska_logging.configuration._UTCFormatter) assert formatter._fmt == ska_logging.configuration._FORMAT_STR_NO_TAGS - def test_get_without_tags(self): + def test_get_tags_disabled(self): formatter = get_default_formatter(tags=False) assert isinstance(formatter, ska_logging.configuration._UTCFormatter) assert formatter._fmt == ska_logging.configuration._FORMAT_STR_NO_TAGS - def test_get_with_tags(self): + def test_get_tags_enabled(self): formatter = get_default_formatter(tags=True) assert isinstance(formatter, ska_logging.configuration._UTCFormatter) assert formatter._fmt == ska_logging.configuration._FORMAT_STR_WITH_TAGS + def test_get_tags_static_string(self): + formatter = get_default_formatter(tags="test-key:test-value") + assert isinstance(formatter, ska_logging.configuration._UTCFormatter) + tags_format = ska_logging.configuration._FORMAT_STR_WITH_TAGS + expected_format = tags_format.replace("%(tags)s", "test-key:test-value") + assert formatter._fmt == expected_format + + def test_get_tags_invalid_static_string(self): + with pytest.raises(SkaLoggingTagsFormatError): + get_default_formatter(tags="no|pipes|allowed") + with pytest.raises(SkaLoggingTagsFormatError): + get_default_formatter(tags="no%percentage%symbols%allowed") + class TestOverride: """Tests for :func:`~ska_logging.configuration._override`.