Skip to content

fix: name a DB span for its operation, not "db query" - #14

Merged
ash-krnl merged 1 commit into
mainfrom
fix/db-span-operation-name
Aug 27, 2026
Merged

fix: name a DB span for its operation, not "db query"#14
ash-krnl merged 1 commit into
mainfrom
fix/db-span-operation-name

Conversation

@ash-krnl

Copy link
Copy Markdown
Contributor

Why

Core derives a DB span's semantic type by matching the verb inside the span name (classifyDBType, internal/content/session.go) and never reads db_operation — which this SDK already computes and sends. Two of the three DB span sites hardcoded the name:

dbapi       start_span("db query")
asyncpg     start_span("db query")
sqlalchemy  start_span(f"db {verb.lower()}")   # already correct

So every statement through sqlite3, psycopg2, mysql, pymysql or asyncpg stored as a generic database_query — a SELECT indistinguishable from a DELETE — while db_statement sat right there carrying the verb. Only the SQLAlchemy path classified correctly, which made it look like a driver quirk rather than a naming bug.

What changed

One _db_span_name(statement) helper, used at all three sites, so the convention is the rule rather than the exception. Core upper-cases the name before matching, so case here is irrelevant. A statement with no readable verb keeps "db query", the previous name — no behavior change for those.

Verification

Five statements through sqlite3 against a local stack:

Statement Before After
CREATE TABLE … database_query database_query
INSERT INTO … database_query database_insert
SELECT … FROM … database_query database_select
UPDATE … SET … database_query database_update
DELETE FROM … database_query database_delete

390 tests pass. The 5 failures under tests/instrumentation are unrelated and reproduce on an unmodified tree (git stash confirmed) — they need asyncpg and pymongo, which aren't installed in this environment.

Note for reviewers

Found while restoring span instrumentation in openbox-citadel-sdk-python (OpenBox-AI/openbox-citadel-sdk-python#1). Two related observations, not addressed here:

  • install_dbapi patches the DB-API governance seam but instruments no driver, so nothing constructs a CursorTracer and no SQL raises a span at all. install_redis and install_asyncpg patch their drivers; the DB-API family has no equivalent step. Worked around SDK-side for now.
  • HTTP spans set only current-convention attributes (url.full, http.request.method) and the status code never lands in attributes, so the dashboard renders no request link and no status badge — it reads attrs["http.url"] and attrs["http.response.status_code"]. Also worked around SDK-side. Both may belong here instead.

🤖 Generated with Claude Code

Core derives a DB span's semantic type by matching the verb inside the span
NAME (`classifyDBType` in internal/content/session.go) and never reads
`db_operation`, which this SDK already sends. Two of the three DB span sites
named every span "db query":

    dbapi       start_span("db query")
    asyncpg     start_span("db query")
    sqlalchemy  start_span(f"db {verb.lower()}")   <- already correct

So every statement through sqlite3, psycopg2, mysql, pymysql or asyncpg was
stored as a generic `database_query`, and a SELECT was indistinguishable from a
DELETE in the record — while `db_statement` sat right there carrying the verb.
Only the SQLAlchemy path classified correctly, which is what made this look
like a driver quirk rather than a naming bug.

All three sites now share one `_db_span_name` helper, so the odd one out is the
convention rather than the exception. Core upper-cases the name before matching,
so the verb's case here does not matter; a statement with no readable verb keeps
"db query", the previous name.

Verified end to end against a local stack: five statements through sqlite3 now
store as database_query (CREATE), database_insert, database_select,
database_update and database_delete, where all five were database_query before.

390 tests pass. The 5 failures in tests/instrumentation are unrelated to this
change and reproduce on an unmodified tree — they need asyncpg and pymongo,
which are not installed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ash-krnl
ash-krnl merged commit 24d33b8 into main Aug 27, 2026
2 checks passed
@ash-krnl
ash-krnl deleted the fix/db-span-operation-name branch August 27, 2026 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant