ThrustLab

Logging & debugging

The SDK uses Python's standard logging module — there's no custom logger to wire up. Enable debug-level on the right loggers when you need to see what's actually going on.

Quick: see SDK retry attempts

import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("thrustlab").setLevel(logging.DEBUG)

The thrustlab logger emits exactly one kind of debug line — the retry backoff, right before each time.sleep() between attempts:

DEBUG:thrustlab:thrustlab: retrying after 0.73s (attempt 1)
DEBUG:thrustlab:thrustlab: retrying after 1.86s (attempt 2)

There's no per-request method/path/status log line — the SDK doesn't log successful requests or the first attempt at all, only the sleep before a retry. For request/response detail (method, path, status), see full HTTP traces below.

See full HTTP traces

The SDK uses httpx under the hood. Its built-in logging gives you full request/response bodies and headers:

import logging
logging.getLogger("httpx").setLevel(logging.DEBUG)

For even more verbose httpcore traces:

logging.getLogger("httpcore").setLevel(logging.DEBUG)

Caution: httpx debug logs print request bodies and headers, including the Authorization: Bearer key_... header. Don't ship them to a log aggregator without redaction.

Capture request_id in your own logs

Every error response embeds a request_id in the JSON error envelope (error.request_id); the SDK (0.3.2+) reads it straight off that envelope and surfaces it as exc.request_id on every raised APIError. Responses also carry an X-Request-ID response header once the backend rollout for it is live, but the SDK doesn't need it — exc.request_id is already populated from the body. Logging this id lets ThrustLab support trace your specific call server-side.

import logging
from thrustlab import Client
from thrustlab.exceptions import APIError

log = logging.getLogger(__name__)
client = Client()

try:
    sim = client.simulations.create(project_id="proj_xxx", ...)
except APIError as exc:
    log.warning(
        "thrustlab call failed",
        extra={
            "code": exc.code,
            "type": exc.type,
            "request_id": exc.request_id,
            "http_status": exc.http_status,
        },
    )
    raise

Successful calls return a plain dict, not a response object — there's no request_id to capture on the happy path. You typically only need it when something failed and you're filing a support ticket.

Inspect the User-Agent

Every request carries:

User-Agent: thrustlab-python/0.3.2 (Python/3.11.6; Linux)

Include this string in support tickets — it tells us which SDK version is calling.

Common debug recipes

"My retries aren't happening"

Confirm the failure is on the retry list (429 / 5xx / network error). 4xx other than 429 fails-fast by design — see retries & timeouts.

logging.getLogger("thrustlab").setLevel(logging.DEBUG)
# Reproduce. The log will show "retrying" lines if the SDK is retrying,
# or jump straight to the typed exception if it isn't.

"The webhook signature keeps failing"

Almost always: handler is verifying against re-encoded JSON instead of raw bytes. See webhook signature verification.

logging.getLogger("thrustlab").setLevel(logging.DEBUG)
# Inspect the bytes you're passing into Webhook.verify.
# If it differs by even one byte from what the server signed, verify fails.

"I'm getting ConfigurationError: no API key provided"

The Client constructor falls back to $THRUSTLAB_API_KEY only — not THRUSTLAB_KEY or API_KEY. Confirm:

import os
print(os.environ.get("THRUSTLAB_API_KEY"))  # should print key_...

If you're running under systemd / supervisord / Docker, the env var has to be set in the unit / container, not just your shell.

See also

We use cookies and analytics tools to understand how you use ThrustLab and improve the experience. Privacy Policy

Python SDK — Logging & debugging · ThrustLab API