Skip to content

feat(analytics): break usage and cost down by calling extension - #829

Merged
CybotTM merged 1 commit into
mainfrom
feat/analytics-caller-source-cost
Aug 19, 2026
Merged

feat(analytics): break usage and cost down by calling extension#829
CybotTM merged 1 commit into
mainfrom
feat/analytics-caller-source-cost

Conversation

@CybotTM

@CybotTM CybotTM commented Aug 19, 2026

Copy link
Copy Markdown
Member

Makes the caller attribution from ADR-177 answer the question it exists for: which extension spends what. Stacked on #827 (the ADR); the diff against that branch is the implementation.

Why the telemetry column was not enough. Cost is aggregated daily in tx_nrllm_service_usage, and every analytics figure reads that table; telemetry carries no cost, is purged on its own retention schedule, and shares no key a per-day aggregate could join on. So the identity travels the cost path too: source_extension becomes a column on the usage table and part of its daily aggregation key — two extensions on one model on one day stay two rows. UsageMiddleware reads it from the same request metadata TelemetryMiddleware reads, so the cost row and the telemetry row cannot disagree about who called.

In the backend: the Analytics module gains a By extension chart next to provider/model/service and a per-extension table with cost, requests and tokens. Unannotated usage — wizard tasks, scheduler runs, anything that names no caller — is labelled Unattributed instead of being hidden or folded into another bucket. EN and DE labels included; the admin docs page gained a section stating what the numbers mean and that attribution is an unverified claim, not an access control.

Surface: UsageTrackerServiceInterface::trackUsage() grows one optional trailing $sourceExtension; api-surface.txt is regenerated and the diff is that one additive line. Rows written before this change carry '' and stay unattributed — no migration invents an origin.

Tests (both guards were watched failing before they were kept):

  • Aggregation key: removing source_extension from the tracker's lookup makes the two new functional tests fail with 1 is identical to 2 — the rows collapse into one.
  • Middleware wiring: hard-coding the read to '' fails the new unit test.
  • Also new: unattributed-vs-attributed separation, varchar(64) truncation, and the analytics breakdown ordering with its unattributed label.

Gates run locally: cgl, PHPStan level 10, full unit suite (7217 tests), functional -d sqlite for the touched classes (103 tests). Rector was not run locally (its -p 8.2 pin needs a second .Build); CI is the verdict there.

Copilot AI lite review requested due to automatic review settings August 19, 2026 14:15
@CybotTM
CybotTM requested a review from a team as a code owner August 19, 2026 14:15
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests Test-related changes labels Aug 19, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

github-actions[bot]
github-actions Bot previously approved these changes Aug 19, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for maintainer PR

All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.

github-actions[bot]
github-actions Bot previously approved these changes Aug 19, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for maintainer PR

All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 53.33333% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.01%. Comparing base (98cea0d) to head (b82dc0c).

Files with missing lines Patch % Lines
Classes/Service/UsageAnalyticsService.php 0.00% 4 Missing ⚠️
Classes/Controller/Backend/AnalyticsController.php 0.00% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##               main     #829      +/-   ##
============================================
- Coverage     87.02%   87.01%   -0.02%     
- Complexity     9806     9809       +3     
============================================
  Files           572      572              
  Lines         31720    31733      +13     
============================================
+ Hits          27604    27611       +7     
- Misses         4116     4122       +6     
Flag Coverage Δ
unit 65.17% <53.33%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
Classes/Provider/Middleware/UsageMiddleware.php 100.00% <100.00%> (ø)
Classes/Service/UsageTrackerService.php 100.00% <100.00%> (ø)
Classes/Controller/Backend/AnalyticsController.php 93.87% <0.00%> (-6.13%) ⬇️
Classes/Service/UsageAnalyticsService.php 89.87% <0.00%> (-1.20%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

github-actions[bot]
github-actions Bot previously approved these changes Aug 19, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for maintainer PR

All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.

@CybotTM
CybotTM dismissed github-actions[bot]’s stale review August 19, 2026 22:01

The merge-base changed after approval.

The caller identity from ADR-177 reached telemetry only, where no cost
is recorded — so it could not answer the question it exists for. It now
travels the cost path as well (ADR-178): source_extension is a column on
tx_nrllm_service_usage and part of its daily aggregation key, fed from
the same request metadata TelemetryMiddleware reads, so the cost row and
the telemetry row cannot disagree about who called.

The Analytics module gains a By-extension chart and a per-extension
table (cost, requests, tokens). Calls that name no caller are listed as
Unattributed rather than hidden.

trackUsage() grows one optional trailing parameter; api-surface.txt is
regenerated additively.

Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
@CybotTM
CybotTM force-pushed the feat/analytics-caller-source-cost branch from 92e810f to b82dc0c Compare August 19, 2026 22:01

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for maintainer PR

All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.

@sonarqubecloud

Copy link
Copy Markdown

@CybotTM

CybotTM commented Aug 19, 2026

Copy link
Copy Markdown
Member Author

Self-review: b82dc0c

The review this pull request demands is unsatisfiable (Copilot quota wall or repeated bot failures on this head). Per the documented fallback, the diff on this head was reviewed by the PR author; this comment is the on-the-record attestation the merge gate reads back. It stops matching on the next push.

@CybotTM
CybotTM added this pull request to the merge queue Aug 19, 2026
Merged via the queue into main with commit c650302 Aug 19, 2026
92 checks passed
@CybotTM
CybotTM deleted the feat/analytics-caller-source-cost branch August 19, 2026 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation tests Test-related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants