Configuration - Python

3 min read Updated: 11.09.2026

Options worth knowing

OptionDefaultMeaning
token""public project identifier; required together with the key to send anything
private_key""project secret sent as a bearer token
environmentproductionenvironment column in the panel
urlhttps://dockray.ioaddress of the DockRay instance
timeout5.0HTTP request timeout, in seconds
compressTruegzips the request body once it exceeds 1 KB

Environments

Every environment should report under an unambiguous name - production, staging, preview. The name is a column in the panel and a filter on the error list, so without it a production outage looks exactly like an error someone triggered in a test. Leave your local environment without credentials: with no token and no key the integration loads and stays silent, so you do not need a separate switch to turn it off.

When events are sent

The client never sends anything during the part of the request the visitor is waiting on. send_later() schedules a send without waiting for it - the method returns immediately, and the task keeps running on the event loop:

python
client.send_later(client.capture_exception(error))

The task is held in an internal set until it finishes - a coroutine referenced only by the event loop can be garbage-collected mid-flight, which silently drops the event. A failure is logged to the dock_ray logger rather than propagated up the call stack - no send_later() call interrupts the application it is reporting from.

The ASGI middleware works on the same rhythm: it only reports a transaction once the application has finished writing the response. A slow or unreachable panel costs the visitor nothing.

ASGI middleware and FastAPI

The middleware opens one transaction per request and reports unhandled exceptions. It is written against the plain ASGI interface rather than any specific framework, so it works under FastAPI, Starlette and any other application speaking the protocol - and it does not buffer streaming responses.

python
from fastapi import FastAPI
from dock_ray import DockRayClient, DockRayFastAPIMiddleware

client = DockRayClient(token="...", private_key="...")
app = FastAPI()

app.add_middleware(
    DockRayFastAPIMiddleware,
    client=client,
    exclude_paths=["/health", "/metrics"],
)

@app.on_event("shutdown")
async def shutdown() -> None:
    await client.close()

Every request is reported together with its method, path, duration and response status. exclude_paths defaults to skipping /health and /metrics - paths polled every few seconds by infrastructure monitoring should not crowd real traffic out of the transaction list. capture_transactions=False turns that part of the middleware off, leaving only exception reporting.

HTTPException is handled by FastAPI itself and never reaches the middleware as an exception - expected 404 or 422 responses do not turn into errors, they simply land in the panel as transactions carrying that status code.

The visitor's IP address is read from the X-Forwarded-For or X-Real-IP header before the middleware falls back to the socket address - behind a load balancer that socket belongs to the balancer, not the visitor. Authorization, Cookie and X-Api-Key are stripped from the reported headers.

Manual transactions

Useful for work that happens outside an HTTP request, for example a background worker:

python
import time, uuid
from dock_ray import Span

started = time.time()
await run_daily_cleanup()
ended = time.time()

span = Span(
    span_id=uuid.uuid4().hex[:16],
    trace_id=uuid.uuid4().hex,
    start_timestamp=started,
    end_timestamp=ended,
    status="200",
    description="Daily cleanup",
    op="worker.task",
    data={"url": "job:daily_cleanup", "method": "CLI"},
)

await client.capture_transaction(name="job:daily_cleanup", spans=[span])

The root span - the one without a parent_span_id - carries the URL, the method and the status the panel indexes the transaction by. Without those three fields on the root span, the transaction has nothing to appear on the list by.

Protecting the private key

The private key is a project secret, not an identifier. Keep it in environment variables, in a secrets manager or in the server configuration - never in the repository, in logs, in a screenshot or in code sent to the browser. One project can hold many keys, so production and staging should each get their own: either can be revoked on its own without interrupting the others. A suspicion that a key leaked is reason enough to revoke it and generate a new one.

Next Verification and common problems - Python
Chat with us The chat is closed right now Available: Mo–Fr 08:00–18:00