Skip to content

feat: add AI request tracing and structured client logging - #1

Open
TrainTravel wants to merge 12 commits into
mainfrom
feat/ai-request-tracing
Open

feat: add AI request tracing and structured client logging#1
TrainTravel wants to merge 12 commits into
mainfrom
feat/ai-request-tracing

Conversation

@TrainTravel

Copy link
Copy Markdown
Owner

Summary

  • Adds src/lib/logger.ts — lightweight structured logger with [OutputFirst][level] prefix; debug/info suppressed in production
  • Every AI call (reflection, feedback, chat) generates a UUID requestId passed as X-Request-Id header; error UI shows Ref: <8-char-id> for easy bug reporting
  • All three edge functions (reflection, french-feedback, french-chat) prefix every log line with [${requestId}] and include requestId in error response bodies

Test plan

  • npm run dev → open DevTools Console → complete a journal → observe ai.request.start / ai.request.success logs with matching requestId
  • Check Supabase dashboard → Functions → Logs → find the same short ID in edge function logs
  • To test error path: use an invalid VITE_SUPABASE_URL → confirm ai.request.error log appears in console and Ref: xxxxxxxx appears in error UI

🤖 Generated with Claude Code

TrainTravel and others added 5 commits February 27, 2026 11:36
Adds 25 tests across 5 spec files covering all main user flows:
home screen, full journal flow (mocked AI), brain dump, section
navigation, and language toggle/persistence. All Supabase and edge
function calls are intercepted so tests run offline and deterministically.

- playwright.config.ts: Chromium, baseURL localhost:8080, auto-starts dev server
- e2e/helpers/mocks.ts: shared route mocks and localStorage helpers
- e2e/home.spec.ts: 6 rendering tests
- e2e/journal-flow.spec.ts: happy path, skip-gratitude, BreatheScreen clock test
- e2e/braindump.spec.ts: input, submission, and navigation
- e2e/navigation.spec.ts: each section open/back
- e2e/language.spec.ts: toggle, persistence after reload, bilingual order
- .github/workflows/e2e.yml: runs on push/PR to main, uploads HTML report
- docs/e2e-tests.md: permanent summary of all tests and helpers
- CLAUDE.md: add Agentic AI Development & Iteration guidelines,
  update Important Notes to reference new test suite

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Language type extended to 'fr' | 'en' | 'es'
- Toggle cycles FR→EN→ES→FR; LanguageToggle shows FR/EN/ES label
- t(fr, en, es) and bilingual(fr, en, es) now take 3 required args
- isEs added to LanguageContext alongside existing isFr
- bilingual() in ES mode renders "ES / EN" (English anchor)
- EmotionWord.es and EmotionSuggestion.categoryEs added with full translations
- All 17 screens/components updated with Spanish strings
- BrainDumpScreen adds PLACEHOLDERS_ES array
- ThoughtCard/ClusterCard receive dateLocale string (es-ES support)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- setSpanishLanguage() helper added to e2e/helpers/mocks.ts
- 4 new tests in language.spec.ts:
  - toggle cycles all three languages FR→EN→ES→FR
  - ES mode shows "Escribir hoy" CTA and "ES" toggle label
  - bilingual ES-first order shows "Volcado mental / Brain Dump"
  - ES preference persists after page reload
- Updated "toggle back to French from English" test: now clicks 3x
  since toggle cycle changed from 2-way to 3-way
- Total: 29 tests (was 25)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude must always create a feature branch before making code changes
and open a PR rather than committing directly to main.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Every AI call (reflection, feedback, chat) now generates a UUID requestId
that flows as X-Request-Id header to edge functions, which prefix all log
lines with [requestId] and include it in error response bodies. The frontend
structured logger (src/lib/logger.ts) emits start/success/error events with
latencyMs; error UI surfaces a short Ref: <8-char-id> for easy bug reporting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

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.

Pull request overview

This PR adds end-to-end request correlation for AI calls (client + Supabase Edge Functions) via a requestId, introduces a lightweight structured client logger, and expands the UI to support Spanish alongside new Playwright E2E coverage.

Changes:

  • Add structured client logging (src/lib/logger.ts) and attach X-Request-Id to reflection/feedback/chat requests.
  • Propagate requestId through Supabase Edge Function logs/error responses for reflection, french-feedback, and french-chat.
  • Add Spanish UI language support and introduce Playwright E2E tests + CI workflow.

Reviewed changes

Copilot reviewed 33 out of 34 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
supabase/functions/reflection/index.ts Allow x-request-id header; include requestId in logs and many error responses
supabase/functions/french-feedback/index.ts Allow x-request-id header; include requestId in logs and many error responses
supabase/functions/french-chat/index.ts Allow x-request-id header; include requestId in logs and many error responses
src/types/journal.ts Add Spanish fields to emotion vocabulary/categories
src/lib/logger.ts New lightweight structured logger with prod suppression for debug/info
src/contexts/LanguageContext.tsx Add es language, update t/bilingual, and language cycling FR→EN→ES
src/components/journal/WriteScreen.tsx Update UI strings for ES; adapt to new t signature
src/components/journal/ThoughtGardenScreen.tsx Add ES strings + date locale handling; update ThoughtCard props
src/components/journal/SignUpPrompt.tsx Add ES strings; update t calls
src/components/journal/ReflectionScreen.tsx Add requestId tracing + structured logs; show short ref in error UI; ES strings
src/components/journal/ProgressScreen.tsx Add ES strings
src/components/journal/HomeScreen.tsx Add ES strings; adjust date locale formatting
src/components/journal/GratitudeScreen.tsx Add ES strings; adapt to new t signature
src/components/journal/FeedbackScreen.tsx Add requestId tracing + structured logs; show short ref in error UI; ES strings
src/components/journal/EmotionsScreen.tsx Render ES emotion/category labels
src/components/journal/ClustersScreen.tsx Add ES strings + date locale; pass localized thought count label
src/components/journal/ClusterDetailScreen.tsx Add ES strings + date locale formatting
src/components/journal/ChatScreen.tsx Attach X-Request-Id to chat calls and add partial structured logging
src/components/journal/BreatheScreen.tsx Add ES strings
src/components/journal/BrainDumpScreen.tsx Add ES placeholders + strings
src/components/LanguageToggle.tsx Display FR/EN/ES label
playwright.config.ts Add Playwright configuration (dev server integration)
package.json Add Playwright scripts and dev dependency
package-lock.json Lockfile updates including Playwright
e2e/navigation.spec.ts New navigation E2E coverage
e2e/language.spec.ts New language toggle + persistence E2E coverage
e2e/journal-flow.spec.ts New “happy path” journal flow E2E coverage + clock control test
e2e/home.spec.ts New home screen E2E coverage
e2e/helpers/mocks.ts Shared Supabase/AI mocks and localStorage helpers for E2E
e2e/braindump.spec.ts New Brain Dump E2E coverage
docs/e2e-tests.md Document how to run E2E tests and what they cover
docs/CHANGELOG.md Add changelog entry for Spanish support
CLAUDE.md Document that Playwright E2E suite + CI workflow exist
.github/workflows/e2e.yml Add CI workflow running Playwright tests on Node 22
Comments suppressed due to low confidence (1)

src/components/journal/ChatScreen.tsx:57

  • startTime is currently unused and there is no ai.request.success (or ai.request.error) emitted for startConversation, so chat request tracing is incomplete. Use startTime to log a success event after streamResponse completes, and log an error event (with latency) in the catch block for symmetry with other AI calls.
    const startTime = Date.now();
    logger.info('ai.request.start', { component: 'ChatScreen', requestId: sessionRequestId, action: 'startConversation' });

    try {
      const { data: { session } } = await supabase.auth.getSession();
      if (!session?.access_token) throw new Error('Not authenticated');


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +48 to +49
const requestId = req.headers.get("x-request-id") ?? "no-id";

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

Using the literal fallback "no-id" makes tracing ambiguous when the client forgets to send a header (multiple requests will share the same id). Prefer generating a UUID server-side when the header is missing, and use that value consistently in logs/responses.

Copilot uses AI. Check for mistakes.
Comment on lines 159 to 166
console.error(`[no-id] Error in french-feedback function:`, error);
return new Response(JSON.stringify({
error: "Feedback service error",
code: "INTERNAL_ERROR",
details: error instanceof Error ? error.message : "Unknown error"
details: error instanceof Error ? error.message : "Unknown error",
}), {
status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" },
});

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

The catch block logs with a hardcoded "[no-id]" and the 500 response body omits requestId, which makes it hard to correlate function crashes with client-side failures. Keep requestId in an outer scope and include it both in the catch log prefix and in the INTERNAL_ERROR JSON response.

Copilot uses AI. Check for mistakes.
Comment thread supabase/functions/french-feedback/index.ts Outdated
Comment on lines +15 to +16
const requestId = req.headers.get("x-request-id") ?? "no-id";

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

Using a fixed fallback like "no-id" will collapse multiple requests into the same id when the header is missing. Prefer generating a UUID in the edge function if x-request-id is not present, so logs remain uniquely attributable.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Comment thread src/components/journal/ChatScreen.tsx
Comment thread docs/CHANGELOG.md
Comment on lines +151 to 156
console.error(`[no-id] Error in reflection function:`, error);
return new Response(JSON.stringify({
error: "Reflection service error",
code: "INTERNAL_ERROR",
details: error instanceof Error ? error.message : "Unknown error"
details: error instanceof Error ? error.message : "Unknown error",
}), {

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

The catch block logs with a hardcoded "[no-id]" and the 500 response body omits requestId, which breaks end-to-end request tracing for unexpected failures. Define requestId outside the try/catch and include it in the catch log prefix and in the INTERNAL_ERROR JSON response body.

Copilot uses AI. Check for mistakes.
Comment on lines +232 to 239
console.error(`[no-id] Error in french-chat function:`, error);
return new Response(JSON.stringify({
error: "Chat service error",
code: "INTERNAL_ERROR",
details: error instanceof Error ? error.message : "Unknown error"
details: error instanceof Error ? error.message : "Unknown error",
}), {
status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" },
});

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

The catch block hardcodes "[no-id]" and the 500 response body does not include requestId. This breaks correlating unexpected runtime errors with the client request and with other function logs. Keep requestId in an outer scope and include it in both the catch log prefix and the INTERNAL_ERROR JSON response.

Copilot uses AI. Check for mistakes.
};

const promptText = t(prompt.fr, prompt.en);
const promptText = t(prompt.fr, prompt.en, prompt.en);

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

promptText passes prompt.en as the Spanish argument, which causes ES mode to display the English prompt as both primary and secondary (losing the bilingual/trilingual intent). Either extend BilingualPrompt/prompt data to include an es field and pass it here, or explicitly choose a consistent fallback (e.g., show FR primary + EN secondary even in ES mode).

Suggested change
const promptText = t(prompt.fr, prompt.en, prompt.en);
const promptText = t(prompt.fr, prompt.en, prompt.fr);

Copilot uses AI. Check for mistakes.
};

const promptText = t(prompt.fr, prompt.en);
const promptText = t(prompt.fr, prompt.en, prompt.en);

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

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

promptText uses prompt.en for the Spanish argument, so ES mode ends up rendering the English prompt as both primary and secondary. Consider adding Spanish prompt strings (extend BilingualPrompt with es) or choose an explicit fallback strategy for ES mode to avoid duplicate English text.

Suggested change
const promptText = t(prompt.fr, prompt.en, prompt.en);
const promptText = t(prompt.fr, prompt.en, prompt.fr);

Copilot uses AI. Check for mistakes.

Copilot AI commented Mar 1, 2026

Copy link
Copy Markdown

@TrainTravel I've opened a new pull request, #2, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 3 commits March 1, 2026 12:34
…-feedback

Co-authored-by: TrainTravel <25241752+TrainTravel@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Copilot AI commented Mar 1, 2026

Copy link
Copy Markdown

@TrainTravel I've opened a new pull request, #3, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 3 commits March 1, 2026 12:39
Co-authored-by: TrainTravel <25241752+TrainTravel@users.noreply.github.com>
docs: add missing CHANGELOG entries for AI tracing and Playwright E2E suite
Fix non-unique request IDs when x-request-id header is absent in french-feedback

Copilot AI commented Mar 2, 2026

Copy link
Copy Markdown

@TrainTravel I've opened a new pull request, #5, to work on those changes. Once the pull request is ready, I'll request review from you.

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.

3 participants