codeflash-internal/js/cf-webapp/proof/08-server-action-timing.md
Kevin Turcios 566424e97f
feat: add server action timing and expand PostHog analytics (#2552)
## Summary

- Add `withTiming()` wrapper for server actions with Sentry span
reporting and slow action warnings (>1s)
- Add centralized `captureEvent()` helper for PostHog tracking
- Add 5 new PostHog tracking events: optimization_reviewed,
repository_connected, api_key_created, member_invited,
billing_page_viewed
- Instrument 4 server actions with `withTiming()`:
getOrganizationMembers, getRepositoryById,
getRepositoriesWithStagingEvents, getAllOptimizationEvents

## Proof of Correctness

See
[`js/cf-webapp/proof/08-server-action-timing.md`](js/cf-webapp/proof/08-server-action-timing.md)

## How to Verify

```bash
cd js/cf-webapp
bash proof/reproducers/08-server-action-timing.sh
```

21 checks verify: withTiming utility, 4 instrumented actions,
captureEvent helper, 5 tracking functions, and all tracking calls wired
into action files.

## Test Plan

- [ ] Run reproducer: `bash
proof/reproducers/08-server-action-timing.sh` (21/21 pass)
- [ ] Verify server actions still work correctly
- [ ] Check Sentry for `server.action` spans after deployment
2026-04-04 11:34:53 -05:00

2.8 KiB

Proof: Server Action Timing + PostHog Analytics (9155cd5b)

What

  1. withTiming() — generic wrapper for server actions that measures execution time, creates Sentry spans, and warns on slow actions (>1s)
  2. Centralized captureEvent() helper for PostHog tracking
  3. 5 new PostHog tracking events for key user journeys
  4. 4 server actions instrumented with withTiming()

withTiming() Implementation

export function withTiming<TArgs extends unknown[], TReturn>(
  actionName: string,
  fn: (...args: TArgs) => Promise<TReturn>,
): (...args: TArgs) => Promise<TReturn> {
  return async (...args: TArgs): Promise<TReturn> => {
    const start = performance.now()
    const result = await Sentry.startSpan(
      { name: actionName, op: "server.action" },
      async (span) => {
        const res = await fn(...args)
        const durationMs = performance.now() - start
        span.setAttribute("server_action.duration_ms", durationMs)
        if (durationMs > SLOW_ACTION_THRESHOLD_MS) {
          console.warn(`[ServerAction] Slow action: ${actionName} took ${durationMs.toFixed(0)}ms`)
          span.setAttribute("server_action.slow", true)
        }
        return res
      },
    )
    return result
  }
}

New PostHog Events

Event Trigger Properties
optimization_reviewed Viewing optimization detail traceId, functionName, repositoryName, status
repository_connected Viewing repository detail repositoryId, repositoryName
api_key_created Generating API key keyName, organizationId
member_invited Adding org/repo member invitedUsername, role, scope, targetId
billing_page_viewed Opening billing page username

Instrumented Server Actions

  • getOrganizationMembers (members/action.ts)
  • getRepositoryById (repositories/[repositoryId]/action.ts)
  • getRepositoriesWithStagingEvents (review-optimizations/action.ts)
  • getAllOptimizationEvents (review-optimizations/action.ts)

Files Changed

File Change
src/lib/server-action-timing.ts New: withTiming() wrapper
src/lib/analytics/tracking.ts New: captureEvent() + 5 tracking functions
src/app/(dashboard)/members/action.ts Wrap with withTiming, add trackMemberInvited
src/app/(dashboard)/repositories/[repositoryId]/action.ts Wrap with withTiming, add trackRepositoryConnected
src/app/(dashboard)/review-optimizations/action.ts Wrap with withTiming
src/app/(dashboard)/review-optimizations/[traceId]/action.ts Add trackOptimizationReviewed
src/app/(dashboard)/billing/page.tsx Add trackBillingPageViewed
src/app/(dashboard)/apikeys/tokenfuncs.ts Add trackApiKeyCreated

How to Verify

cd js/cf-webapp
bash proof/reproducers/08-server-action-timing.sh