Open a tracing span per transaction and parent in-tx queries under it#1
Open
Diggsey wants to merge 1 commit into
Open
Open a tracing span per transaction and parent in-tx queries under it#1Diggsey wants to merge 1 commit into
Diggsey wants to merge 1 commit into
Conversation
Builds on the per-query span work: `Transaction` opens its own hardcoded INFO-level `db.transaction` span at begin, recorded on the connection. The backend executor's `QueryLogger::new_under_span` parents the query span under the connection's currently open tx span, so queries run via `&mut *tx` show up as children of the transaction in the trace tree without the caller having to wrap anything. Span shape (OTel semconv): `db.system.name`, `db.operation.name = "BEGIN"`, `db.transaction.outcome` (Empty, recorded as "committed" / "rolled_back" / "dropped" before close), `otel.kind = "client"`. Only the outermost transaction owns the span; nested savepoints share it (the SAVEPOINT / RELEASE / ROLLBACK TO SQL query spans inside are the savepoint markers). Same `!Send` discipline as the query span — the connection stores only `Span` plus the caller's `Span::current()` id at begin time, no `EnteredSpan` across awaits. The caller's `Span::current()` id at begin time is also the heuristic for auto-parenting: at query time the executor's `query_parent_span` returns the tx span only if the current span hasn't changed since begin. If the caller has wrapped a region in their own `.instrument(my_span)` between begin and the query, we return `None` and the query parents under the caller's current — respecting their explicit hierarchy instead of clobbering it. `Transaction::span()` is publicly exposed for callers passing the transaction around procedurally who want to `.instrument(tx.span())` their own futures to nest user spans under the transaction. Trait additions (all default no-op / `None` so out-of-tree drivers keep compiling): `TransactionManager::set_transaction_span`, `clear_transaction_span`, `current_transaction_span`, `query_parent_span`. SQLite threads `parent_span` through `ConnectionWorker::execute` so the worker thread enters the right parent before opening the query span.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on the per-query span work:
Transactionopens its own hardcoded INFO-leveldb.transactionspan at begin, recorded on the connection. The backend executor'sQueryLogger::new_under_spanparents the query span under the connection's currently open tx span, so queries run via&mut *txshow up as children of the transaction in the trace tree without the caller having to wrap anything.Span shape (OTel semconv):
db.system.name,db.operation.name = "BEGIN",db.transaction.outcome(Empty, recorded as "committed" / "rolled_back" / "dropped" before close),otel.kind = "client".Only the outermost transaction owns the span; nested savepoints share it (the SAVEPOINT / RELEASE / ROLLBACK TO SQL query spans inside are the savepoint markers). Same
!Senddiscipline as the query span — the connection stores onlySpanplus the caller'sSpan::current()id at begin time, noEnteredSpanacross awaits.The caller's
Span::current()id at begin time is also the heuristic for auto-parenting: at query time the executor'squery_parent_spanreturns the tx span only if the current span hasn't changed since begin. If the caller has wrapped a region in their own.instrument(my_span)between begin and the query, we returnNoneand the query parents under the caller's current — respecting their explicit hierarchy instead of clobbering it.Transaction::span()is publicly exposed for callers passing the transaction around procedurally who want to.instrument(tx.span())their own futures to nest user spans under the transaction.Trait additions (all default no-op /
Noneso out-of-tree drivers keep compiling):TransactionManager::set_transaction_span,clear_transaction_span,current_transaction_span,query_parent_span. SQLite threadsparent_spanthroughConnectionWorker::executeso the worker thread enters the right parent before opening the query span.Does your PR solve an issue?
fixes transact-rs#1896
Is this a breaking change?
No
This PR was written with assistance from Claude Code