Phase B2 of docs/SPEC.md section 5, on QQQ 4.1.0-RC.13 (qqq#1226, statement execution listener SPI).
AttributionListener (core StatementExecutionListener): aggregates statements per unit of work (HTTP route template, scheduled job, process), process, table, operation and statement fingerprint in bounded memory (attribution_max_keys, overflow into (other)), with per-unit sampling. Ignores the qbit's own db_perf_ tables and the flusher thread, so it never measures itself.
N+1: per unit of work, statement shapes repeated at least n_plus_one_threshold times become db_perf_repeat_pattern rows (units affected, max and total repeats).
AttributionFlusher: per-pod daemon; every attribution_flush_seconds swaps the aggregates and writes one batched insert per table as the system user; never retries forever or blocks statement threads; flushes once on shutdown. Registered as a QQQ runtime service; hosts without the launcher call DbPerfRuntime.of(instance).startAttribution().
Pom: QQQ 4.1.0-RC.13.
Tests: 102 (H2 + PostgreSQL 17) against released RC.13, checkstyle clean, JaCoCo gate met. Implementation by Codex, reviewed by Claude.
Phase B2 of docs/SPEC.md section 5, on QQQ 4.1.0-RC.13 (qqq#1226, statement execution listener SPI).
- `AttributionListener` (core `StatementExecutionListener`): aggregates statements per unit of work (HTTP route template, scheduled job, process), process, table, operation and statement fingerprint in bounded memory (`attribution_max_keys`, overflow into `(other)`), with per-unit sampling. Ignores the qbit's own `db_perf_` tables and the flusher thread, so it never measures itself.
- N+1: per unit of work, statement shapes repeated at least `n_plus_one_threshold` times become `db_perf_repeat_pattern` rows (units affected, max and total repeats).
- `AttributionFlusher`: per-pod daemon; every `attribution_flush_seconds` swaps the aggregates and writes one batched insert per table as the system user; never retries forever or blocks statement threads; flushes once on shutdown. Registered as a QQQ runtime service; hosts without the launcher call `DbPerfRuntime.of(instance).startAttribution()`.
- Pom: QQQ 4.1.0-RC.13.
Tests: 102 (H2 + PostgreSQL 17) against released RC.13, checkstyle clean, JaCoCo gate met. Implementation by Codex, reviewed by Claude.
Labelled `release:rc`: merging cuts qbit-db-performance 0.1.0-RC.1.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Phase B2 of docs/SPEC.md section 5, on QQQ 4.1.0-RC.13 (qqq#1226, statement execution listener SPI).
AttributionListener(coreStatementExecutionListener): aggregates statements per unit of work (HTTP route template, scheduled job, process), process, table, operation and statement fingerprint in bounded memory (attribution_max_keys, overflow into(other)), with per-unit sampling. Ignores the qbit's owndb_perf_tables and the flusher thread, so it never measures itself.n_plus_one_thresholdtimes becomedb_perf_repeat_patternrows (units affected, max and total repeats).AttributionFlusher: per-pod daemon; everyattribution_flush_secondsswaps the aggregates and writes one batched insert per table as the system user; never retries forever or blocks statement threads; flushes once on shutdown. Registered as a QQQ runtime service; hosts without the launcher callDbPerfRuntime.of(instance).startAttribution().Tests: 102 (H2 + PostgreSQL 17) against released RC.13, checkstyle clean, JaCoCo gate met. Implementation by Codex, reviewed by Claude.
Labelled
release:rc: merging cuts qbit-db-performance 0.1.0-RC.1.🤖 Generated with Claude Code