Skip to content

Frontend Logging

Plan Metadata

  • Plan type: sub-plan
  • Parent plan: logging.md
  • Depends on: N/A
  • Status: documentation

Status semantics: - draft: Plan is being created or updated and is not final. - approved: Plan is approved but not yet applied in code. - documentation: Code currently exists and matches the plan contract.

Update rule: - When an existing plan is edited, set status to draft until re-approved.

System Intent

  • What is being built: A frontend logging contract for React Native/Expo that standardizes log payload shape and centralizes logging through shared utilities.
  • Primary consumer(s): Mobile app components, shared frontend utility code, and debugging workflows.
  • Boundary (black-box scope only): Frontend logging API (useLogging, function logger, and LoggingContextProvider) and emitted log event contract from logging.md.
  • Context placement: LoggingContextProvider can be mounted at any feature boundary and nested by flow (for example conversation and upload-memory).
  • Signal rule: prefer step-start/transition/error logs and avoid explicit success logs.

Stage Gate Tracker

  • [x] Stage 1 Mermaid approved
  • [x] Stage 2 I/O contracts approved
  • [x] Stage 3 pseudocode/technical details approved or skipped

1. Mermaid Diagram

Reference: .agent/skills/create-mermaid-diagram/SKILL.md

flowchart TD
  FeatureBoundary[Feature Boundary - any React subtree] -->|provides flow scope| LoggingProvider[Logging Context Provider - main/app/lib/logging/frontend-logger.tsx]
  LoggingProvider -->|provides default flow| UseLoggingHook[useLogging Hook - main/app/lib/logging/frontend-logger.tsx]
  FrontendFactory[Function Logger Factory - createLogger in main/app/lib/logging/frontend-logger.tsx]
  LoggingProvider -->|catches render errors and emits error logs| ErrorBoundary[Logging Error Boundary - main/app/lib/logging/frontend-logger.tsx]
  UseLoggingHook -->|returns logger function| FeatureCode[Feature Components and Hooks - main/app/components]
  FrontendFactory -->|returns callable logger for non-react frontend code| UtilityCode[Frontend Utility Code - main/app/lib]
  FeatureCode -->|log event payload| ConsoleOut[Console Output - runtime console.log]
  UtilityCode -->|log event payload| ConsoleOut
  ErrorBoundary -->|error payload with stack| ConsoleErr[Console Error Output - runtime console.error]

  classDef unchanged fill:#d3d3d3,stroke:#666,stroke-width:1px;
  classDef updated fill:#ffe58a,stroke:#666,stroke-width:1px;
  classDef deleted fill:#f4a6a6,stroke:#666,stroke-width:1px;
  classDef created fill:#a8e6a3,stroke:#666,stroke-width:1px;

  class FeatureBoundary unchanged;
  class LoggingProvider,UseLoggingHook,FrontendFactory,ErrorBoundary unchanged;
  class FeatureCode,UtilityCode,ConsoleOut,ConsoleErr unchanged;

2. Black-Box Inputs and Outputs

Keep this short. Define types in JSON-style blocks and capture each flow with path-level rows. - Flow naming rule: each flow uses this format: - ### Flow: `<flowname>` - - Test files: <path/to/test_file.ext>, ... (or N/A when no automated test is required) - - Core files: <path/to/core_file.ext>, ... - N/A means explicit no-test-required waiver for that flow (not a missing mapping).

Global Types

Define shared types used across multiple flows.

FrontendLoggerInput {
  step: string (required step label)
  additional?: unknown (optional structured context)
}

FrontendLogEvent {
  flow: string (resolved from provider context or "unknown-flow")
  step: string
  additional?: unknown
  timestamp: string (ISO8601)
}

LoggingProviderInput {
  flow: string (default flow for descendant hooks)
}

Flow: frontendUseLogging

  • Test files: main/app/__tests__/frontend-logger.test.tsx
  • Core files: main/app/lib/logging/frontend-logger.tsx

Type Definitions

FrontendUseLoggingInput {
  provider_flow?: string
  logger_input: FrontendLoggerInput
}

FrontendUseLoggingOutput {
  emitted_event: FrontendLogEvent
}

Paths

path-name input output/expected state change path-type notes updated
frontend-use-logging.provider-flow FrontendUseLoggingInput provider_flow set FrontendUseLoggingOutput emitted_event.flow=provider_flow happy path useLogging resolves flow from nearest provider
frontend-use-logging.unknown-flow-fallback FrontendUseLoggingInput provider_flow omitted FrontendUseLoggingOutput emitted_event.flow="unknown-flow" subpath fallback flow is used when no provider wraps the hook
frontend-use-logging.step-propagation FrontendUseLoggingInput logger_input.step FrontendUseLoggingOutput emitted_event.step=logger_input.step happy path step is forwarded unchanged

Flow: frontendProviderErrorCapture

  • Test files: main/app/__tests__/frontend-logger.test.tsx
  • Core files: main/app/lib/logging/frontend-logger.tsx

Type Definitions

FrontendProviderErrorInput {
  provider: LoggingProviderInput
  thrown_error: Error
  component_stack: string
}

FrontendProviderErrorOutput {
  emitted_error_event: FrontendLogEvent
  emitted_error_event.step: "error-boundary"
  emitted_error_event.additional.stack: string
  emitted_error_event.additional.componentStack: string
}

Paths

path-name input output/expected state change path-type notes updated
frontend-provider-error-capture.render-error FrontendProviderErrorInput FrontendProviderErrorOutput emitted via console.error happy path provider catches render errors and logs stack context

Flow: frontendFunctionLogger

  • Test files: main/app/__tests__/frontend-logger.test.tsx
  • Core files: main/app/lib/logging/frontend-logger.tsx

Type Definitions

FrontendFunctionLoggerInput {
  create_flow: string
  logger_input: FrontendLoggerInput
}

FrontendFunctionLoggerOutput {
  emitted_event: FrontendLogEvent
}

Paths

path-name input output/expected state change path-type notes updated
frontend-function-logger.emit FrontendFunctionLoggerInput FrontendFunctionLoggerOutput emitted_event.flow=create_flow happy path non-react code gets same logging contract without hooks

3. Pseudocode / Technical Details for Critical Flows (Optional)

Not needed...

After all stages are approved, apply .agent/skills/reconcile-plans/SKILL.md to propagate contract updates across linked plans.