Databases, caches and APIs¶
Your tool calls a database or a cache; we show it as a child span under the tool call, with its own timing, so a slow tool says where the time went instead of looking like unexplained server time.
We do not patch your clients for you. Adding observability to an MCP server should not silently monkey-patch your database driver, so this is something you turn on. There are two ways, and the first is better when you can use it.
Nothing from us involved:
pip install opentelemetry-instrumentation-redis \
opentelemetry-instrumentation-psycopg
opentelemetry-instrument python -m your_server
It picks up any instrumentation package the day you install it.
For servers you do not launch yourself — which is most MCP servers, because the client spawns them over stdio and you do not own that command line:
from mcpobs import instrument, instrument_downstream
instrument(mcp)
report = instrument_downstream()
# {'httpx': 'instrumented', 'redis': 'instrumented', 'psycopg': 'instrumented', ...}
It discovers whatever you have installed through OpenTelemetry's own
entry-point group — the same mechanism the agent uses — so
pip install opentelemetry-instrumentation-redis is the entire integration.
It returns a report rather than nothing, because a call that patches an unknown set of libraries should tell you what it touched. It never raises: one package with a version conflict is reported and skipped, never allowed to stop your server booting.
What you get per span kind¶
| Called | Shown as | Fields |
|---|---|---|
| Redis, Postgres, MySQL, Mongo, SQLite | db |
system, operation, collection/table, statement (redacted before storage) |
| HTTP (httpx, requests, aiohttp) | http |
method, status, host, URL; bodies and headers with instrument_httpx() |
| OpenAI, Anthropic, Bedrock | llm |
system, model, input/output tokens |
| Kafka, RabbitMQ, SQS | messaging |
stored and rendered generically |
Key-value stores have no table
Redis and Memcached spans carry an operation (GET, SETEX, DEL) and no
collection, because there is nothing to name. The key itself is not
recorded: a Redis key is frequently customer data (customer:acme:tier), so
it is redacted like any other statement argument.
SQL statements are redacted at normalize time, never at render — a secret that reaches storage cannot be recalled.
Use an explicit cursor¶
opentelemetry-instrumentation-dbapi wraps Cursor.execute, not the
Connection.execute shortcut. The idiomatic one-liner produces no span at all:
This is the most common cause of "my database calls do not show up".