feat: implement structured logging for server and client
Server: - Add pino and pino-http for structured logging - Create @Logged class decorator using Proxy pattern for automatic method logging - Add pino redact config for sensitive data (password, token, etc.) - Move AuthMiddleware to controllers folder (per architecture diagram) - Add LoggingMiddleware for HTTP request logging - Replace console.log/error with structured logger in controllers and app.ts - Decorate all repositories and GPTAdapter with @Logged Client: - Add react-native-logs with namespaced loggers (apiLogger, storeLogger) - Add request/response logging to ApiClient with duration tracking
This commit is contained in:
51
CLAUDE.md
51
CLAUDE.md
@@ -47,6 +47,8 @@ npm run start -w @caldav/server # Run compiled server (port 3000)
|
||||
| | Mongoose | ODM |
|
||||
| | GPT (OpenAI) | AI/LLM for chat |
|
||||
| | JWT | Authentication |
|
||||
| | pino / pino-http | Structured logging |
|
||||
| | react-native-logs | Client-side logging |
|
||||
| Planned | iCalendar | Event export/import |
|
||||
|
||||
## Architecture
|
||||
@@ -83,9 +85,12 @@ src/
|
||||
│ ├── EventConfirmDialog.tsx # AI-proposed event confirmation modal
|
||||
│ └── ProposedEventCard.tsx # Chat event proposal (uses EventCardBase + confirm/reject buttons)
|
||||
├── Themes.tsx # Centralized color/theme definitions
|
||||
├── logging/
|
||||
│ ├── index.ts # Re-exports
|
||||
│ └── logger.ts # react-native-logs config (apiLogger, storeLogger)
|
||||
├── services/
|
||||
│ ├── index.ts # Re-exports all services
|
||||
│ ├── ApiClient.ts # HTTP client (get, post, put, delete)
|
||||
│ ├── ApiClient.ts # HTTP client with request logging (get, post, put, delete)
|
||||
│ ├── AuthService.ts # login(), register(), logout(), refresh()
|
||||
│ ├── EventService.ts # getAll(), getById(), getByDateRange(), create(), update(), delete()
|
||||
│ └── ChatService.ts # sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation()
|
||||
@@ -103,12 +108,16 @@ src/
|
||||
```
|
||||
src/
|
||||
├── app.ts # Entry point, DI setup, Express config
|
||||
├── controllers/ # Request handlers
|
||||
├── controllers/ # Request handlers + middleware (per architecture diagram)
|
||||
│ ├── AuthController.ts # login(), register(), refresh(), logout()
|
||||
│ ├── ChatController.ts # sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation()
|
||||
│ └── EventController.ts # create(), getById(), getAll(), getByDateRange(), update(), delete()
|
||||
├── middleware/
|
||||
│ └── AuthMiddleware.ts # authenticate() - JWT validation
|
||||
│ ├── EventController.ts # create(), getById(), getAll(), getByDateRange(), update(), delete()
|
||||
│ ├── AuthMiddleware.ts # authenticate() - JWT validation
|
||||
│ └── LoggingMiddleware.ts # httpLogger - pino-http request logging
|
||||
├── logging/
|
||||
│ ├── index.ts # Re-exports
|
||||
│ ├── logger.ts # pino config with redact for sensitive data
|
||||
│ └── Logged.ts # @Logged() class decorator for automatic method logging
|
||||
├── routes/ # API endpoint definitions
|
||||
│ ├── index.ts # Combines all routes under /api
|
||||
│ ├── auth.routes.ts # /api/auth/*
|
||||
@@ -239,6 +248,32 @@ const Schema = new Schema<Doc, Model<Doc, {}, {}, IdVirtual>, {}, {}, IdVirtual>
|
||||
|
||||
Repositories use `doc.toJSON() as unknown as Type` casting (required because Mongoose's TypeScript types don't reflect virtual fields in toJSON output).
|
||||
|
||||
### Logging
|
||||
|
||||
Structured logging with pino (server) and react-native-logs (client).
|
||||
|
||||
**Server Logging:**
|
||||
- `pino` with `pino-pretty` for development, JSON in production
|
||||
- `pino-http` middleware logs all HTTP requests (method, path, status, duration)
|
||||
- `@Logged()` class decorator for automatic method logging on repositories and services
|
||||
- Sensitive data (password, token, etc.) automatically redacted via pino's `redact` config
|
||||
|
||||
**@Logged Decorator Pattern:**
|
||||
```typescript
|
||||
@Logged("MongoEventRepository")
|
||||
export class MongoEventRepository implements EventRepository { ... }
|
||||
|
||||
@Logged("GPTAdapter")
|
||||
export class GPTAdapter implements AIProvider { ... }
|
||||
```
|
||||
|
||||
The decorator uses a Proxy to intercept method calls lazily, preserves sync/async nature, and logs start/completion/failure with duration.
|
||||
|
||||
**Client Logging:**
|
||||
- `react-native-logs` with namespaced loggers (apiLogger, storeLogger)
|
||||
- ApiClient logs all requests with method, endpoint, status, duration
|
||||
- Log level: debug in __DEV__, warn in production
|
||||
|
||||
## MVP Feature Scope
|
||||
|
||||
### Must-Have
|
||||
@@ -274,6 +309,8 @@ JWT_EXPIRES_IN=1h
|
||||
MONGODB_URI=mongodb://root:mongoose@localhost:27017/calchat?authSource=admin
|
||||
OPENAI_API_KEY=sk-proj-...
|
||||
USE_TEST_RESPONSES=false # true = static test responses, false = real GPT AI
|
||||
LOG_LEVEL=debug # debug | info | warn | error | fatal
|
||||
NODE_ENV=development # development = pretty logs, production = JSON
|
||||
```
|
||||
|
||||
## Current Implementation Status
|
||||
@@ -299,6 +336,8 @@ USE_TEST_RESPONSES=false # true = static test responses, false = real GPT AI
|
||||
- `ChatRepository` interface: updateMessage() added for respondedAction tracking
|
||||
- `GPTAdapter`: Full implementation with OpenAI GPT (gpt-5-mini model), function calling for calendar operations
|
||||
- `ai/utils/`: Provider-agnostic shared utilities (systemPrompt, toolDefinitions, toolExecutor, eventFormatter)
|
||||
- `logging/`: Structured logging with pino, pino-http middleware, @Logged decorator
|
||||
- All repositories and GPTAdapter decorated with @Logged for automatic method logging
|
||||
- **Stubbed (TODO):**
|
||||
- `AuthMiddleware.authenticate()`: Currently uses fake user for testing
|
||||
- `AuthController`: refresh(), logout()
|
||||
@@ -323,7 +362,7 @@ USE_TEST_RESPONSES=false # true = static test responses, false = real GPT AI
|
||||
- KeyboardAvoidingView for proper keyboard handling (iOS padding, Android height)
|
||||
- Auto-scroll to end on new messages and keyboard show
|
||||
- keyboardDismissMode="interactive" and keyboardShouldPersistTaps="handled"
|
||||
- `ApiClient`: get(), post(), put(), delete() implemented
|
||||
- `ApiClient`: get(), post(), put(), delete() implemented with request/response logging
|
||||
- `EventService`: getAll(), getById(), getByDateRange(), create(), update(), delete() - fully implemented
|
||||
- `ChatService`: sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation() - fully implemented with cursor pagination
|
||||
- `EventCardBase`: Shared base component with event layout (header, date/time/recurring icons, description) - used by both EventCard and ProposedEventCard
|
||||
|
||||
Reference in New Issue
Block a user