Error Handling Integration Guide - pacificnm/wiki-ai GitHub Wiki
This guide will help you integrate the error handling and logging system into your wiki-ai application.
# Install server-side dependencies
npm install winston zod
# Install client-side dependencies (if not already installed)
cd client
npm install notistack
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
mkdir -p logs
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);
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);
}));
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');
}
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');
}
};
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>
);
}
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();
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>
);
}
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>
);
}
# 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
// 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>
);
}
# Check log files
cat logs/combined.log
cat logs/error.log
# Watch logs in real-time
tail -f logs/combined.log
- 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
andSnackbarProvider
- Update API service layer
- Update React components to use error hooks
- Test error handling in development
- Configure production error monitoring
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
}
Choose and integrate an error monitoring service:
- Sentry (recommended)
- LogRocket
- Bugsnag
- Datadog
- Set appropriate log levels for production (
warn
orerror
) - Implement error rate limiting
- Consider log aggregation services (ELK stack, Splunk)
- Monitor disk space usage for log files
- Don't log sensitive information
- Sanitize user input in error messages
- Rate limit error reporting endpoints
- Implement authentication for admin endpoints
-
"Cannot find module" errors
- Ensure all dependencies are installed
- Check import paths
-
Snackbar not showing
- Ensure
SnackbarProvider
wraps your app - Check console for JavaScript errors
- Ensure
-
Logs not writing to file
- Check logs directory permissions
- Verify LOG_DIR environment variable
-
Error boundary not catching errors
- Ensure it wraps the component that might error
- Check that errors are thrown, not just logged
Enable debug mode for detailed logging:
NODE_ENV=development
DEBUG=*
LOG_LEVEL=debug
If you encounter issues with the error handling system:
- Check the logs for detailed error information
- Ensure all dependencies are correctly installed
- Verify environment variables are set
- Test with the provided test endpoints
- 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.