OpenTelemetry Logging Instrumentation

The OpenTelemetry logging integration automatically injects tracing context into log statements.

The integration registers a custom log record factory with the the standard library logging module that automatically inject tracing context into log record objects. Optionally, the integration can also call logging.basicConfig() to set a logging format with placeholders for span ID, trace ID and service name.

The following keys are injected into log record objects by the factory:

  • otelSpanID

  • otelTraceID

  • otelServiceName

  • otelTraceSampled

The integration uses the following logging format by default:

%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s trace_sampled=%(otelTraceSampled)s] - %(message)s

Enable trace context injection

The integration is opt-in and must be enabled explicitly by setting the environment variable OTEL_PYTHON_LOG_CORRELATION to true.

The integration always registers the custom factory that injects the tracing context into the log record objects. Setting OTEL_PYTHON_LOG_CORRELATION to true calls logging.basicConfig() to set a logging format that actually makes use of the injected variables.

Environment variables

OTEL_PYTHON_LOG_CORRELATION

This env var must be set to true in order to enable trace context injection into logs by calling logging.basicConfig() and setting a logging format that makes use of the injected tracing variables.

Alternatively, set_logging_format argument can be set to True when initializing the LoggingInstrumentor class to achieve the same effect.

LoggingInstrumentor(set_logging_format=True)

The default value is false.

OTEL_PYTHON_LOG_FORMAT

This env var can be used to instruct the instrumentation to use a custom logging format.

Alternatively, a custom logging format can be passed to the LoggingInstrumentor as the logging_format argument. For example:

LoggingInstrumentor(logging_format='%(msg)s [span_id=%(span_id)s]')

The default value is:

%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s trace_sampled=%(otelTraceSampled)s] - %(message)s
OTEL_PYTHON_LOG_LEVEL

This env var can be used to set a custom logging level.

Alternatively, log level can be passed to the LoggingInstrumentor during initialization. For example:

LoggingInstrumentor(log_level=logging.DEBUG)

The default value is info.

Options are:

  • info

  • error

  • debug

  • warning

Manually calling logging.basicConfig

logging.basicConfig() can be called to set a global logging level and format. Only the first ever call has any effect on the global logger. Any subsequent calls have no effect and do not override a previously configured global logger. This integration calls logging.basicConfig() for you when OTEL_PYTHON_LOG_CORRELATION is set to true. It uses the format and level specified by OTEL_PYTHON_LOG_FORMAT and OTEL_PYTHON_LOG_LEVEL environment variables respectively.

If you code or some other library/framework you are using calls logging.basicConfig before this integration is enabled, then this integration’s logging format will not be used and log statements will not contain tracing context. For this reason, you’ll need to make sure this integration is enabled as early as possible in the service lifecycle or your framework is configured to use a logging format with placeholders for tracing context. This can be achieved by adding the following placeholders to your logging format:

%(otelSpanID)s %(otelTraceID)s %(otelServiceName)s %(otelTraceSampled)s

API

from opentelemetry.instrumentation.logging import LoggingInstrumentor

LoggingInstrumentor().instrument(set_logging_format=True)

Note

If you do not set OTEL_PYTHON_LOG_CORRELATION to true but instead set the logging format manually or through your framework, you must ensure that this integration is enabled before you set the logging format. This is important because unless the integration is enabled, the tracing context variables are not injected into the log record objects. This means any attempted log statements made after setting the logging format and before enabling this integration will result in KeyError exceptions. Such exceptions are automatically swallowed by the logging module and do not result in crashes but you may still lose out on important log messages.

class opentelemetry.instrumentation.logging.LoggingInstrumentor(*args, **kwargs)[source]

Bases: BaseInstrumentor

An instrumentor for stdlib logging module.

This instrumentor injects tracing context into logging records and optionally sets the global logging format to the following:

%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s trace_sampled=%(otelTraceSampled)s] - %(message)s

def log_hook(span: Span, record: LogRecord):
        if span and span.is_recording():
            record.custom_user_attribute_from_log_hook = "some-value"
Parameters:
  • tracer_provider – Tracer provider instance that can be used to fetch a tracer.

  • set_logging_format – When set to True, it calls logging.basicConfig() and sets a logging format.

  • logging_format – Accepts a string and sets it as the logging format when set_logging_format is set to True.

  • log_level – Accepts one of the following values and sets the logging level to it. logging.INFO logging.DEBUG logging.WARN logging.ERROR logging.FATAL

  • log_hook – execute custom logic when record is created

See BaseInstrumentor

instrumentation_dependencies()[source]

Return a list of python packages with versions that the will be instrumented.

The format should be the same as used in requirements.txt or pyproject.toml.

For example, if an instrumentation instruments requests 1.x, this method should look like: :rtype: Collection[str]

def instrumentation_dependencies(self) -> Collection[str]:

return [‘requests ~= 1.0’]

This will ensure that the instrumentation will only be used when the specified library is present in the environment.