Skip to content

feat(micrometer): observe transactions as storm.transaction Observations#236

Merged
zantvoort merged 1 commit into
mainfrom
feat/transaction-observations
Jul 11, 2026
Merged

feat(micrometer): observe transactions as storm.transaction Observations#236
zantvoort merged 1 commit into
mainfrom
feat/transaction-observations

Conversation

@zantvoort

Copy link
Copy Markdown
Collaborator

Queries are observed since the Micrometer binding landed (#203/#231), but the transaction boundaries around them were not: long-running transactions, rollback rates, and per-domain transaction behavior were invisible. This completes the observability story — spans for queries, spans for transactions, trace-context comments for the database's own logs.

Fixes #235

What's included

  • QueryObserver.onTransaction — a default no-op hook on the existing SPI, invoked when the pending transaction scope materializes a physical transaction (an outermost block or REQUIRES_NEW) and completed with the outcome. Joined blocks and savepoint scopes run inside an existing transaction and are deliberately not double-counted. The hook sits in the shared scope engine, so blocking, suspend, and Spring-bridged transactions are covered by one code path; observer failures are contained and never affect the transaction.
  • storm.transaction observations in MicrometerQueryObserver: duration, storm.tx.outcome (committed/rolled_back, with completion failures recorded as errors), storm.tx.propagation, storm.tx.read_only, plus the observer's extra key values (storm.database in multi-database setups).
  • Zero new wiring: the starters, the Ktor plugin, and builder-composed templates pick up the signal through the query observer they already carry — existing observers are unaffected by the default method.

Verification

  • Full reactor green (13,754 tests).
  • New tests: committed and rolled-back outcomes on live transactions, and the nesting semantics — outer transaction and REQUIRES_NEW each observed, joined REQUIRED block skipped.
  • The unchanged transaction suites across all stacks pass with the hook active in the scope engine.

Docs: observability sections of spring-integration.md and ktor-integration.md gain the transaction signal; CHANGELOG entry.

Queries are observed since the Micrometer binding landed, but the
transaction boundaries around them were not: long-running transactions,
rollback rates, and per-domain transaction behavior were invisible.

- The QueryObserver SPI gains a default no-op onTransaction hook,
  invoked when the pending transaction scope materializes a physical
  transaction (an outermost block or REQUIRES_NEW; joined blocks and
  savepoint scopes run inside an existing transaction and are not
  double-counted) and completed with the outcome. The hook sits in the
  shared scope engine, so blocking, suspend, and Spring-bridged
  transactions are covered identically. Observer failures are contained
  and never affect the transaction.
- MicrometerQueryObserver reports storm.transaction observations with
  storm.tx.outcome (committed/rolled_back), storm.tx.propagation,
  storm.tx.read_only, and the observer's extra key values
  (storm.database in multi-database setups).
- No new wiring: the starters, the Ktor plugin, and builder-composed
  templates pick the signal up through their existing query observer.

Fixes #235
@zantvoort zantvoort merged commit dae70e7 into main Jul 11, 2026
7 checks passed
@zantvoort zantvoort deleted the feat/transaction-observations branch July 11, 2026 23:28
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.

Instrument transactions with Micrometer Observations

1 participant