books/docs/architecture/monitoring-and-observability.md
Greg fa8acef423 Epic 1, Story 1.1: Project Initialization & Repository Setup
- Initialize Git repository with main branch
- Create comprehensive .gitignore for Node.js, React, and environment files
- Set up directory structure (frontend/, backend/, docs/)
- Create detailed README.md with project overview and setup instructions
- Add .env.example with all required environment variables
- Configure Prettier for consistent code formatting

All acceptance criteria met:
 Git repository initialized with appropriate .gitignore
 Directory structure matches Technical Assumptions
 README.md created with project overview and setup docs
 .env.example file with all required environment variables
 Prettier config files added for code formatting consistency

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 15:12:30 +01:00

2.1 KiB

Monitoring and Observability

Monitoring Stack

  • Frontend Monitoring: Browser console errors (dev), future: Sentry for production error tracking
  • Backend Monitoring: Winston structured logging, health check endpoint for uptime
  • Error Tracking: Console logs (dev), future: Sentry or LogRocket
  • Performance Monitoring: Lighthouse audits (manual), future: Web Vitals reporting

Key Metrics

Frontend Metrics:

  • Core Web Vitals:
    • LCP (Largest Contentful Paint): <2.5s
    • FID (First Input Delay): <100ms
    • CLS (Cumulative Layout Shift): <0.1
  • JavaScript errors: Track with Error Boundaries
  • API response times: Log slow requests (>1s)
  • User interactions: Button clicks, form submissions

Backend Metrics:

  • Request rate: Requests per second
  • Error rate: 4xx/5xx responses per minute
  • Response time: P50, P95, P99 latency
  • Database query performance: Slow queries (>100ms)
  • Open Library API: Success rate, response times

Health Check Endpoint:

// GET /api/health
app.get('/api/health', async (req, res) => {
  try {
    // Check database connection
    await prisma.$queryRaw`SELECT 1`;

    res.json({
      status: 'ok',
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      database: 'connected',
    });
  } catch (error) {
    res.status(503).json({
      status: 'error',
      timestamp: new Date().toISOString(),
      database: 'disconnected',
    });
  }
});

Logging (Winston):

// utils/logger.js
const winston = require('winston');

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple(),
    }),
    // Add file transport for production
    // new winston.transports.File({ filename: 'error.log', level: 'error' }),
  ],
});

module.exports = logger;

// Usage:
logger.info('Book created', { bookId: 123, title: 'Test Book' });
logger.error('API error', { error: err.message, stack: err.stack });