Back to Docs

Python Integration Guide

Send logs from any Python application to logging.cheap using the OpenTelemetry SDK. This guide bridges Python's built-in logging module to OpenTelemetry (OTLP), so every logging.info() call automatically exports logs to logging.cheap.

How it works: Your app → Python logging → LoggingHandler bridge → OTLP over HTTP → logging.cheap. No agents to install, no collectors to manage, no YAML to configure.

Prerequisites

Get an API Key

Create an API key from your Settings page. Copy the key — it starts with cl_live_ and is only shown once. If you just signed up, an API key prompt appears on your first login.

Install Dependencies

You need three packages: the OpenTelemetry API, the SDK, and the OTLP (OpenTelemetry Protocol) HTTP exporter. We recommend using a virtual environment to isolate dependencies:

terminal
python -m venv .venv && source .venv/bin/activate

Then install the packages:

terminal
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http

The opentelemetry-exporter-otlp-proto-http package sends log data over HTTP, which logging.cheap accepts natively.

Set Environment Variables

The OpenTelemetry SDK reads its configuration from standard OTEL_* environment variables — no hardcoded endpoints or secrets in your code. Set these before running your application:

terminal
# Required: where to send logs
export OTEL_EXPORTER_OTLP_ENDPOINT="https://logging.cheap"

# Required: authenticate with your API key
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer cl_live_YOUR_API_KEY"

# Required: name your service (appears in the log viewer)
export OTEL_SERVICE_NAME="my-python-app"

# Recommended: disable traces and metrics (logging.cheap only accepts logs)
export OTEL_TRACES_EXPORTER="none"
export OTEL_METRICS_EXPORTER="none"

Replace cl_live_YOUR_API_KEY with the key you copied earlier, and my-python-app with a name that identifies your application in the log viewer (e.g. api-server, checkout-service). Make sure to include the Bearer prefix — without it, authentication will fail.

Initialize OpenTelemetry Logging

Create a file called app.py. The OTLP exporter reads configuration from the environment variables above:

app.py
import logging

from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.resources import Resource

# 1. Create a resource describing your service
#    (reads OTEL_SERVICE_NAME from the environment automatically)
resource = Resource.create()

# 2. Set up the logger provider with an OTLP exporter
logger_provider = LoggerProvider(resource=resource)
logger_provider.add_log_record_processor(
    BatchLogRecordProcessor(OTLPLogExporter())
)
set_logger_provider(logger_provider)

# 3. Bridge Python's logging module to OpenTelemetry
handler = LoggingHandler(logger_provider=logger_provider)
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)

# 4. Use Python's standard logging — it's automatically exported!
logging.info("Hello from logging.cheap!", extra={
    "environment": "production",
    "version": "1.0.0",
})

# 5. Flush logs before exiting (important for short-lived scripts)
logger_provider.shutdown()

Run It

terminal
python app.py

If everything is configured correctly, the script will run without errors. Behind the scenes, the BatchLogRecordProcessor batches your log and sends it to https://logging.cheap/v1/logs with your API key.

Understanding the Code

Here's what each piece does, if you're new to OpenTelemetry:

Note on _logs imports: The underscore in opentelemetry._logs and opentelemetry.sdk._logs indicates these modules are still marked as experimental in the OpenTelemetry Python SDK. They are stable and widely used in practice — the underscore is a naming convention that will be removed in a future release.

Using with Flask or Long-Running Apps

For web applications that run continuously, set up OpenTelemetry once at startup and register a shutdown hook to flush logs when the process exits. This example uses Flask (pip install flask):

app.py
import atexit
import logging

from flask import Flask

from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.resources import Resource

# Set up OpenTelemetry logging
resource = Resource.create()
logger_provider = LoggerProvider(resource=resource)
logger_provider.add_log_record_processor(
    BatchLogRecordProcessor(OTLPLogExporter())
)
set_logger_provider(logger_provider)

# Bridge Python logging to OpenTelemetry
handler = LoggingHandler(logger_provider=logger_provider)
logging.getLogger().addHandler(handler)
logging.getLogger().setLevel(logging.INFO)

# Flush logs on shutdown
atexit.register(logger_provider.shutdown)

# Your Flask app
app = Flask(__name__)


@app.route("/")
def hello():
    logging.info("Received a request")
    return "Hello, world!"


if __name__ == "__main__":
    app.run(port=8080)

The atexit.register(logger_provider.shutdown) call ensures that all pending logs are flushed when your application stops. Without it, the last batch of logs may be lost.

Verify in the Log Viewer

Navigate to the log viewer, select a time range that covers the last few minutes, and search for your test message. You should see your "Hello from logging.cheap!" log entry with the service name you set in OTEL_SERVICE_NAME and severity INFO.

If logs don't appear immediately, wait a few seconds for the batch processor to flush, then refresh the page.

Troubleshooting

Next Steps

Your Python application is now sending logs to logging.cheap. In a production application, initialize the logger provider once at startup and register a shutdown hook. All logging.info(), logging.warning(), logging.error() calls throughout your codebase will be exported automatically.

Head to the log viewer to search and explore your logs. For more on the OpenTelemetry Python SDK, see the official OpenTelemetry Python documentation.