What You Need Before Starting
You need a Python service that already uses the standard logging module, and an OTLP
endpoint to send telemetry to — either a running OpenTelemetry Collector, or a backend that accepts OTLP
directly. If you don't have a Collector running yet, see our
Collector configuration guide first.
Step 1: Install the SDK
pip install opentelemetry-sdk opentelemetry-exporter-otlp
This gives you the core SDK plus the OTLP exporter package, which handles serializing telemetry into the OTLP protocol and sending it over gRPC or HTTP.
Step 2: Configure the Logger Provider
import logging
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
provider = LoggerProvider()
provider.add_log_record_processor(
BatchLogRecordProcessor(
OTLPLogExporter(endpoint="http://<YOUR_HOST>:4318/v1/logs")
)
)
set_logger_provider(provider)
logger = logging.getLogger("my-service")
logger.addHandler(LoggingHandler(logger_provider=provider))
logger.setLevel(logging.INFO)
The BatchLogRecordProcessor batches log records before sending, matching the same batching
principle covered in the Collector configuration guide — sending one log at a time creates unnecessary
network overhead.
Step 3: Log Normally
logger.info("Order processed", extra={"order_id": "ord_1234", "amount": 42.50})
logger.error("Payment failed", extra={"order_id": "ord_1234", "reason": "card_declined"})
Once the handler is attached, ordinary logger.info() and logger.error() calls
are automatically exported as OTLP log records — no changes needed to how the rest of your application
logs. The extra dictionary becomes structured attributes rather than being flattened into a
plain-text message, which matters for searchability later.
Verifying It's Working
Send a test request that triggers a log line, then check your observability platform's log explorer,
filtered to service_name="my-service". If nothing arrives, the most common culprits are an
incorrect endpoint port (4318 for HTTP, 4317 for gRPC), a missing trailing /v1/logs path on
the HTTP exporter, or a firewall blocking the connection between your app and the Collector.
Where to Go From Here
Once logs are flowing, the natural next step is adding trace context so your logs and traces correlate — covered conceptually in Logs vs Metrics vs Traces. If your app runs in Kubernetes rather than as a standalone process, the deployment pattern changes slightly; see Kubernetes Observability with OTel.
Conclusion
Instrumenting a Python app with OpenTelemetry logging is a small, additive change — you keep your
existing logging calls and add an exporter underneath them. The bigger payoff comes once
every service in your stack does the same thing consistently, giving you a uniform telemetry format
across your whole system rather than a patchwork of custom log formats.
Send Python Logs to XplurData
Point the OTLP exporter at your XplurData Collector endpoint — no additional configuration needed.
Deploy XplurData