Skip to content

feat(apm): editor APM enrichment service + tRPC route#2838

Open
jonmcwest wants to merge 1 commit into
06-22-feat_apm_agent_file-read_enrichmentfrom
06-22-feat_apm_editor_apm_enrichment_service_trpc_route
Open

feat(apm): editor APM enrichment service + tRPC route#2838
jonmcwest wants to merge 1 commit into
06-22-feat_apm_agent_file-read_enrichmentfrom
06-22-feat_apm_editor_apm_enrichment_service_trpc_route

Conversation

@jonmcwest

@jonmcwest jonmcwest commented Jun 22, 2026

Copy link
Copy Markdown

Problem

The editor has no way to surface APM (Application Performance Monitoring) data alongside source files. Users viewing a file in the editor cannot see per-line tracing stats such as call counts, error rates, or latency percentiles without leaving the editor and navigating to the PostHog tracing explorer.

Changes

Introduced a new ApmEnrichmentService that queries the PostHog tracing/spans/symbol-stats/ endpoint in line-granularity mode for a given file path. The service reuses the existing ENRICHMENT_AUTH port for PostHog API credentials and active project resolution, so no new authentication wiring is needed.

  • Added ApmEnrichmentService with an enrichFile method that returns per-line stats (count, errorCount, p50Ms, p95Ms, percentage changes) and a tracingUrl pointing to the PostHog tracing explorer, or null when unauthenticated or when the query fails.
  • Registered the service as a singleton via a new apmEnrichmentModule Inversify ContainerModule and loaded it into the main DI container.
  • Exposed the service over tRPC via a new apmEnrichment.enrichFile query procedure, registered on both the host router and the main app router.
  • Added APM_ENRICHMENT_SERVICE as a typed DI identifier and declared the binding in MainBindings.

How did you test this?

Added unit tests in apmEnrichment.test.ts covering:

  • Returns null and makes no network request when the user is unauthenticated.
  • POSTs a correctly shaped line-mode TraceSpansSymbolStatsQuery to the right endpoint with the right Authorization header and date range.
  • Maps response rows to the expected SerializedApmEnrichment shape, including nanosecond-to-millisecond conversion and percentage change fields.
  • Returns null when the symbol-stats endpoint responds with a non-OK status.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

jonmcwest commented Jun 22, 2026

Copy link
Copy Markdown
Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@jonmcwest jonmcwest marked this pull request as ready for review June 22, 2026 12:55
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit df9dcd6.

@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
packages/workspace-server/src/services/apm-enrichment/apmEnrichment.ts:91-96
The access-token fetch failure logs at `debug` while the expected "not yet authenticated" path logs at `info`. If `getValidAccessToken` ever throws unexpectedly (network error, token store corrupted, etc.) the signal will be buried below the noise of normal debug output and be very hard to diagnose. `warn` is a more appropriate level for an unplanned exception.

```suggestion
    } catch (err) {
      this.log.warn("Failed to resolve access token", {
        message: err instanceof Error ? err.message : String(err),
      });
      return null;
    }
```

### Issue 2 of 2
packages/workspace-server/src/services/apm-enrichment/apmEnrichment.test.ts:71-85
**Tests prefer parameterized form for similar scenarios**

The "returns null" cases (unauthenticated at line 71 and HTTP 500 at line 156) test the same observable outcome with different failure triggers. Per the team's preference for parameterised tests, these are good candidates for an `it.each` table, e.g. pairing `(description, authFactory, fetchResponse)` rows. In addition, the `catch` branch in `resolveApiConfig` — when `getValidAccessToken()` itself throws — has no coverage at all, which would be a natural third row in such a table.

Reviews (1): Last reviewed commit: "feat(apm): editor APM enrichment service..." | Re-trigger Greptile

Comment thread packages/workspace-server/src/services/apm-enrichment/apmEnrichment.test.ts Outdated
@jonmcwest jonmcwest force-pushed the 06-22-feat_apm_agent_file-read_enrichment branch from 696d183 to d02ea61 Compare June 22, 2026 14:39
@jonmcwest jonmcwest force-pushed the 06-22-feat_apm_editor_apm_enrichment_service_trpc_route branch from 502d78c to 214b340 Compare June 22, 2026 14:39
@jonmcwest jonmcwest force-pushed the 06-22-feat_apm_editor_apm_enrichment_service_trpc_route branch from 214b340 to df9dcd6 Compare June 22, 2026 15:29
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.

1 participant