Story 15.3 — JOIN query counter (elasticsql / licensing)
Part of Epic 15 (telemetry). Adds a per-interval, disaggregated cross-index JOIN counter to the runtime telemetry layer so the Story-15.2 daily product-instance ping can carry a join_query_count delta, and the R1 dashboard (Story 15.5) can show how much JOIN workload R1 runs — with NO PII (integer counters only).
Scope (this repo — licensing module)
TelemetryCollector.scala:
JoinRow enum (Passthrough row 1 / CrossCluster row 2 / Coordinator row 3)
- 3
AtomicLong buckets + incrementJoin(JoinRow) (lock-free, mirrors incrementQueries)
collectAndResetJoinCounts(): (Long, Map[String,Long]) helper (returns total + all-3-keys map)
- extended
collect (read .get(), NO reset) and collectAndReset (read .getAndSet(0L), per-interval delta flush)
TelemetryData gains joinQueryCount: Long (total) + joinQueryByRow: Map[String,Long] (always all 3 keys, even when 0)
TelemetryCollector.Noop overrides incrementJoin (no-op) and collectAndResetJoinCounts (zeros, all 3 keys)
- Scaladoc updated: JOIN fields are per-interval DELTAS (reset each
collectAndReset), distinct from the cumulative queriesTotal (left unchanged).
Behaviour
joinQueryCount == passthrough + cross_cluster + coordinator on every collected snapshot.
collect never resets; collectAndReset/collectAndResetJoinCounts reset (per-interval delta + clean-shutdown flush).
- No SQL text, no org/query identifiers — only integers (AC 7).
Tests
8 new TelemetryCollectorSpec cases: per-row increment + total, all-3-keys-always (incl. 0), collect-no-reset, collectAndReset-reset, collectAndResetJoinCounts reset (and queriesTotal unaffected), concurrent increment, no-PII, Noop no-op. 16/16 pass.
Build
scalafmtAll; + licensing/compile + + core/compile clean (Scala 2.12.20 + 2.13.16).
The increment hooks live downstream in softclient4es-arrow (sidecar/federation/REPL) and the AC-5a disabled-tick reset in softclient4es-extensions; this repo owns the counter carrier + delta exposed on TelemetryData.
Spec: _bmad-output/implementation-artifacts/15-3-join-query-counter.md
🤖 Generated with Claude Code
Story 15.3 — JOIN query counter (elasticsql / licensing)
Part of Epic 15 (telemetry). Adds a per-interval, disaggregated cross-index JOIN counter to the runtime telemetry layer so the Story-15.2 daily product-instance ping can carry a
join_query_countdelta, and the R1 dashboard (Story 15.5) can show how much JOIN workload R1 runs — with NO PII (integer counters only).Scope (this repo —
licensingmodule)TelemetryCollector.scala:JoinRowenum (Passthroughrow 1 /CrossClusterrow 2 /Coordinatorrow 3)AtomicLongbuckets +incrementJoin(JoinRow)(lock-free, mirrorsincrementQueries)collectAndResetJoinCounts(): (Long, Map[String,Long])helper (returns total + all-3-keys map)collect(read.get(), NO reset) andcollectAndReset(read.getAndSet(0L), per-interval delta flush)TelemetryDatagainsjoinQueryCount: Long(total) +joinQueryByRow: Map[String,Long](always all 3 keys, even when 0)TelemetryCollector.NoopoverridesincrementJoin(no-op) andcollectAndResetJoinCounts(zeros, all 3 keys)collectAndReset), distinct from the cumulativequeriesTotal(left unchanged).Behaviour
joinQueryCount == passthrough + cross_cluster + coordinatoron every collected snapshot.collectnever resets;collectAndReset/collectAndResetJoinCountsreset (per-interval delta + clean-shutdown flush).Tests
8 new
TelemetryCollectorSpeccases: per-row increment + total, all-3-keys-always (incl. 0), collect-no-reset, collectAndReset-reset,collectAndResetJoinCountsreset (and queriesTotal unaffected), concurrent increment, no-PII, Noop no-op. 16/16 pass.Build
scalafmtAll;+ licensing/compile++ core/compileclean (Scala 2.12.20 + 2.13.16).The increment hooks live downstream in softclient4es-arrow (sidecar/federation/REPL) and the AC-5a disabled-tick reset in softclient4es-extensions; this repo owns the counter carrier + delta exposed on
TelemetryData.Spec:
_bmad-output/implementation-artifacts/15-3-join-query-counter.md🤖 Generated with Claude Code