Error Handling Integration Guide - pacificnm/wiki-ai GitHub Wiki

Error Handling Integration Guide

This guide will help you integrate the error handling and logging system into your wiki-ai application.

Installation

1. Install Dependencies

# Install server-side dependencies
npm install winston zod

# Install client-side dependencies (if not already installed)
cd client
npm install notistack

2. Environment Setup

Add the following environment variables to your .env file:

# Logging Configuration
LOG_LEVEL=info
LOG_DIR=./logs
NODE_ENV=development

# Error Reporting
ERROR_REPORTING_ENABLED=true

3. Create Log Directory

mkdir -p logs

Backend Integration

1. Update Server Entry Point

Your server/index.js should already include the error handling middleware:

import { errorHandler, AppError } from './middleware/error.js';

// Add error handling middleware after routes
app.use(errorHandler);

2. Update Existing Route Handlers

Wrap your existing async route handlers with asyncHandler:

import { asyncHandler } from './middleware/error.js';

// Before
router.get('/users', async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// After
router.get('/users', asyncHandler(async (req, res) => {
  const users = await User.find();
  res.json(users);
}));

3. Replace Generic Errors

Replace generic Error instances with custom error classes:

import { AppError, ValidationError, NotFoundError } from './middleware/error.js';

// Before
if (!user) {
  throw new Error('User not found');
}

// After
if (!user) {
  throw new NotFoundError('User not found');
}

4. Update Authentication Middleware

If you have authentication middleware, update it to use error classes:

import { AuthenticationError } from './middleware/error.js';

export const authenticateToken = (req, res, next) => {
  const token = req.header('Authorization')?.replace('Bearer ', '');
  
  if (!token) {
    throw new AuthenticationError('Access token required');
  }
  
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    throw new AuthenticationError('Invalid access token');
  }
};

Frontend Integration

1. Wrap Your App with ErrorBoundary

Update your main App component:

// client/src/App.js
import ErrorBoundary from './components/ErrorBoundary';
import { SnackbarProvider } from 'notistack';

function App() {
  return (
    <SnackbarProvider 
      maxSnack={3}
      anchorOrigin={{
        vertical: 'top',
        horizontal: 'center'
      }}
    >
      <ErrorBoundary>
        <YourExistingAppComponents />
      </ErrorBoundary>
    </SnackbarProvider>
  );
}

2. Update API Service Layer

Create or update your API service to use error handling:

// client/src/services/api.js
import { useApiError } from '../hooks/useError';

class ApiService {
  constructor() {
    this.baseURL = process.env.REACT_APP_API_URL || '/api';
  }

  async request(endpoint, options = {}) {
    const url = `${this.baseURL}${endpoint}`;
    const config = {
      headers: {
        'Content-Type': 'application/json',
        ...options.headers
      },
      ...options
    };

    // Add auth token if available
    const token = localStorage.getItem('authToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    const response = await fetch(url, config);
    
    if (!response.ok) {
      throw response; // Let useApiError handle this
    }

    return response.json();
  }

  // Example API methods
  async getUsers() {
    return this.request('/users');
  }

  async createUser(userData) {
    return this.request('/users', {
      method: 'POST',
      body: JSON.stringify(userData)
    });
  }
}

export const api = new ApiService();

3. Update React Components

Update your components to use the error handling hooks:

// Before
import { useState, useEffect } from 'react';

function UserList() {
  const [users, setUsers] = useState([]);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('/api/users')
      .then(res => res.json())
      .then(data => {
        setUsers(data);
        setLoading(false);
      })
      .catch(err => {
        setError(err.message);
        setLoading(false);
      });
  }, []);

  if (error) return <div>Error: {error}</div>;
  if (loading) return <div>Loading...</div>;

  return (
    <div>
      {users.map(user => (
        <div key={user.id}>{user.name}</div>
      ))}
    </div>
  );
}
// After
import { useState, useEffect } from 'react';
import { useError, useApiError } from '../hooks/useError';
import { api } from '../services/api';

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const { showSuccess } = useError();
  const { handleApiError } = useApiError();

  useEffect(() => {
    loadUsers();
  }, []);

  const loadUsers = async () => {
    try {
      setLoading(true);
      const data = await api.getUsers();
      setUsers(data);
      showSuccess('Users loaded successfully');
    } catch (error) {
      handleApiError(error, 'Load users');
    } finally {
      setLoading(false);
    }
  };

  if (loading) return <div>Loading...</div>;

  return (
    <div>
      {users.map(user => (
        <div key={user.id}>{user.name}</div>
      ))}
    </div>
  );
}

4. Add Error Handling to Forms

import { useState } from 'react';
import { useError, useApiError } from '../hooks/useError';
import { api } from '../services/api';

function UserForm() {
  const [formData, setFormData] = useState({ name: '', email: '' });
  const [loading, setLoading] = useState(false);
  const { showSuccess } = useError();
  const { handleApiError } = useApiError();

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    try {
      setLoading(true);
      await api.createUser(formData);
      showSuccess('User created successfully!');
      setFormData({ name: '', email: '' });
    } catch (error) {
      handleApiError(error, 'Create user');
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Your form fields */}
      <button type="submit" disabled={loading}>
        {loading ? 'Creating...' : 'Create User'}
      </button>
    </form>
  );
}

Testing the Integration

1. Test Backend Error Handling

# Start your server
npm run server

# Test health check
curl http://localhost:5000/

# Test API health
curl http://localhost:5000/api/health

# Test error endpoint (if in development)
curl http://localhost:5000/api/errors/test

2. Test Frontend Error Handling

// Add a test component to trigger errors
function ErrorTest() {
  const { showError, showSuccess } = useError();

  return (
    <div>
      <button onClick={() => showError('Test error message')}>
        Test Error
      </button>
      <button onClick={() => showSuccess('Test success message')}>
        Test Success
      </button>
      <button onClick={() => { throw new Error('Test boundary error'); }}>
        Test Error Boundary
      </button>
    </div>
  );
}

3. Check Logs

# Check log files
cat logs/combined.log
cat logs/error.log

# Watch logs in real-time
tail -f logs/combined.log

Migration Checklist

  • Install required dependencies (winston, zod, notistack)
  • Add environment variables
  • Create logs directory
  • Update server entry point with error middleware
  • Wrap async route handlers with asyncHandler
  • Replace generic errors with custom error classes
  • Wrap React app with ErrorBoundary and SnackbarProvider
  • Update API service layer
  • Update React components to use error hooks
  • Test error handling in development
  • Configure production error monitoring

Production Considerations

1. Log Rotation

Install log rotation for production:

# Install logrotate (Ubuntu/Debian)
sudo apt-get install logrotate

# Create logrotate config for your app
sudo nano /etc/logrotate.d/wiki-ai
/path/to/your/app/logs/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    copytruncate
}

2. Error Monitoring Service

Choose and integrate an error monitoring service:

  • Sentry (recommended)
  • LogRocket
  • Bugsnag
  • Datadog

3. Performance Considerations

  • Set appropriate log levels for production (warn or error)
  • Implement error rate limiting
  • Consider log aggregation services (ELK stack, Splunk)
  • Monitor disk space usage for log files

4. Security

  • Don't log sensitive information
  • Sanitize user input in error messages
  • Rate limit error reporting endpoints
  • Implement authentication for admin endpoints

Troubleshooting

Common Issues

  1. "Cannot find module" errors

    • Ensure all dependencies are installed
    • Check import paths
  2. Snackbar not showing

    • Ensure SnackbarProvider wraps your app
    • Check console for JavaScript errors
  3. Logs not writing to file

    • Check logs directory permissions
    • Verify LOG_DIR environment variable
  4. Error boundary not catching errors

    • Ensure it wraps the component that might error
    • Check that errors are thrown, not just logged

Debug Mode

Enable debug mode for detailed logging:

NODE_ENV=development
DEBUG=*
LOG_LEVEL=debug

Support

If you encounter issues with the error handling system:

  1. Check the logs for detailed error information
  2. Ensure all dependencies are correctly installed
  3. Verify environment variables are set
  4. Test with the provided test endpoints
  5. Review the Error Handling and Logging documentation

The system is designed to be robust and fail gracefully, so even if error logging fails, your application should continue to function normally.

⚠️ **GitHub.com Fallback** ⚠️