Skip to content

feat(emit): a broken database call fails the way the database would - #69

Merged
ETWOYA merged 2 commits into
mainfrom
feat/rich-db-errors
Oct 6, 2026
Merged

ETWOYA merged 2 commits into
mainfrom
feat/rich-db-errors

Conversation

@dankoverride

Copy link
Copy Markdown
Collaborator

A broken database call fails the way the database would

When a diagram breaks a call into a database (for example api[Orders API] -->|broken: wrong column| db[(SQL Server)]), the telemetry now reads like a real database failure, following the OpenTelemetry database and exception conventions. Someone who has not seen the diagram can name the failing query and the cause from the trace alone.

The database client span (SELECT dbo.Orders): status ERROR, db.system.name, db.namespace, db.collection.name, db.operation.name, db.query.text (the statement that failed), db.response.status_code, error.type, server.address and server.port.

An exception event on it: the driver's exception type (Microsoft.Data.SqlClient.SqlException or Npgsql.PostgresException), a message naming the cause (Invalid column name 'Discount'.), the error number and a realistic stack trace. wrong column, wrong table, syntax error and division by zero each map to the database's own error; a quoted name (broken: wrong column 'ShipDate') sets the column or table.

Up the chain: the error climbs the synchronous call chain to the entry point. It stops at queues: a publish succeeded once the broker took the message.

Scoped: only the broken edge (or run N with broken on #N) fails; healthy calls to the same database stay OK and now carry a real statement instead of a placeholder.

Behaviour changes to know:

  • Database spans now carry db.namespace, server.address and server.port, and SQL Server labels report microsoft.sql_server instead of postgresql. Tools that identify a database by system plus namespace or address will see these as new, more accurate nodes.
  • Every broken edge (not only database ones) now marks its synchronous callers as ERROR.
  • failedSpanCount counts failed edges, not red spans (documented).

Tests: .NET 1223 passed (16 new, including a three-tier chain and a queue hop); SPA vitest 44 passed. Output is derived only from the diagram, so a shared link replays the same SQL and error.

🤖 Generated with Claude Code

dankoverride and others added 2 commits October 6, 2026 12:37
A broken edge into a datastore used to emit a span named "api -> db" with
the diagram's reason as its status and a placeholder query, so nobody
without the diagram could say which query failed or why.

The DB client span now carries the statement that ran (db.query.text,
db.namespace, db.collection.name, db.operation.name, db.system.name read
off the label) and, when the edge is broken, the error the driver would
return: db.response.status_code, error.type, and an exception event with
exception.type, exception.message and exception.stacktrace. "wrong column"
on SQL Server is SqlException 207, "Invalid column name 'Discount'.", with
the column in the query; a quoted name in the reason picks the column.
Wrong table, syntax error and division by zero get their own errors, and
PostgreSQL gets its own SQLSTATE and wording.

The calling span is now ERROR with the same description, so the failure
shows up the chain. Healthy calls, including other calls into the same
database, carry a real statement and stay green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…server

A broken call now fails every synchronous span above it, up to the entry
point, not only its direct caller. It stops at an async hop: a publish
succeeded once the broker took the message, so a consumer failing later is
not the producer's error.

failedSpanCount is documented as counting failed edges, not red spans.

DB client spans carry server.address (the node label) and server.port
(1433 for SQL Server, 5432 for PostgreSQL).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dankoverride
dankoverride requested a review from ETWOYA as a code owner October 6, 2026 16:41
@ETWOYA
ETWOYA merged commit 37ae7a5 into main Oct 6, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants