diff --git a/bentoml/_internal/configuration/containers.py b/bentoml/_internal/configuration/containers.py index 4d7b35bf90a..47bf2631d53 100644 --- a/bentoml/_internal/configuration/containers.py +++ b/bentoml/_internal/configuration/containers.py @@ -178,6 +178,12 @@ def _is_ip_address(addr: str) -> bool: }, }, }, + "logging": { + "formatting": { + "trace_id_format": str, + "span_id_format": str, + } + }, } ) @@ -535,5 +541,12 @@ def duration_buckets( ) return DEFAULT_BUCKET + @providers.SingletonFactory + @staticmethod + def logging_formatting( + cfg: dict[str, t.Any] = Provide[config.logging.formatting], + ) -> dict[str, str]: + return cfg + BentoMLContainer = _BentoMLContainerClass() diff --git a/bentoml/_internal/configuration/default_configuration.yaml b/bentoml/_internal/configuration/default_configuration.yaml index 95224193d7f..8daa523629c 100644 --- a/bentoml/_internal/configuration/default_configuration.yaml +++ b/bentoml/_internal/configuration/default_configuration.yaml @@ -51,3 +51,8 @@ tracing: otlp: protocol: Null url: Null + +logging: + formatting: + trace_id_format: 032x + span_id_format: 016x diff --git a/bentoml/_internal/log.py b/bentoml/_internal/log.py index 6829dd7e473..9feddc31760 100644 --- a/bentoml/_internal/log.py +++ b/bentoml/_internal/log.py @@ -50,6 +50,7 @@ def filter(self, record: logging.LogRecord) -> bool: ) DATE_FORMAT = "%Y-%m-%dT%H:%M:%S%z" + SERVER_LOGGING_CONFIG: dict[str, t.Any] = { "version": 1, "disable_existing_loggers": True, @@ -111,10 +112,19 @@ def trace_record_factory(*args: t.Any, **kwargs: t.Any): record = default_factory(*args, **kwargs) record.levelname_bracketed = f"[{record.levelname}]" # type: ignore (adding fields to record) record.component = f"[{_component_name()}]" # type: ignore (adding fields to record) - if trace_context.trace_id == 0: + trace_id = trace_context.trace_id + if trace_id in (0, None): record.trace_msg = "" # type: ignore (adding fields to record) else: - record.trace_msg = f" (trace={trace_context.trace_id},span={trace_context.span_id},sampled={trace_context.sampled})" # type: ignore (adding fields to record) + from .configuration.containers import BentoMLContainer + + logging_formatting = BentoMLContainer.logging_formatting.get() + trace_id_format = logging_formatting["trace_id_format"] + span_id_format = logging_formatting["span_id_format"] + + trace_id = format(trace_id, trace_id_format) + span_id = format(trace_context.span_id, span_id_format) + record.trace_msg = f" (trace={trace_id},span={span_id},sampled={trace_context.sampled})" # type: ignore (adding fields to record) record.request_id = trace_context.request_id # type: ignore (adding fields to record) return record diff --git a/docs/source/guides/logging.rst b/docs/source/guides/logging.rst index 443d45f7de6..e326abdc18d 100644 --- a/docs/source/guides/logging.rst +++ b/docs/source/guides/logging.rst @@ -89,15 +89,30 @@ your ``bentoml_configuration.yml``: .. code-block:: yaml runners: - logging: - access: - enabled: True - ... + logging: + access: + enabled: True + ... The available configuration options are identical to the webserver request logging options above. These logs are disabled by default in order to prevent double logging of requests. +Logging Formatting +"""""""""""""""""" + +You may configure the logging formatting options at the top level of your ``bentoml_configuration.yml``. +The default configuration is shown below, where the opentelemetry trace_id and span_id are logged in +hexadecimal format, consistent with opentelemetry logging instrumentation. + +.. code-block:: yaml + + logging: + formatting: + trace_id_format: 032x + span_id_format: 016x + + Library Logging ---------------