Error Logging
ByteHide Logger provides specialized methods for handling errors: error
and critical
. Both methods can accept an Error
parameter to automatically capture exception details like stack traces and error types.
Error Logging Methods
Error Method
Use error
for exceptions that affect functionality but allow the application to continue:
// Method signature
Log.error(message, options, error)
// Basic error logging
try {
await processOrder(orderId);
} catch (error) {
Log.error('Failed to process order', {}, error);
}
// Error with context
try {
await processPayment(paymentRequest);
} catch (error) {
Log.error('Payment processing failed', {
context: {
transactionId: paymentRequest.transactionId,
amount: paymentRequest.amount
},
tags: ['payment', 'error']
}, error);
}
Critical Method
Use critical
for critical errors that may cause application termination:
// Method signature
Log.critical(message, options, error)
// Critical system failures
try {
await initializeDatabase();
} catch (error) {
Log.critical('Database initialization failed - application cannot continue', {
context: { connectionString: '***' }
}, error);
process.exit(1);
}
// Critical configuration errors
try {
await loadConfiguration();
} catch (error) {
Log.critical('Invalid configuration detected - shutting down', {
tags: ['config', 'critical']
}, error);
throw error;
}
Error Information Captured
When you pass an Error
to error
or critical
methods, ByteHide Logger automatically captures:
- Error Name: The error's name/type
- Error Message: The error's message
- Stack Trace: Complete stack trace for debugging
- Error Properties: Additional properties attached to the error
try {
const result = await callExternalApi();
} catch (error) {
// All error details are automatically captured
Log.error('External API call failed', {
context: { endpoint: '/api/payments' }
}, error);
// Logged information includes:
// - Error name: TypeError, ReferenceError, etc.
// - Message: "Network request failed"
// - Stack trace: Full call stack
// - Additional error properties
}
Common Error Scenarios
API Calls
try {
const response = await fetch('/api/orders', {
method: 'POST',
body: JSON.stringify(orderData)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
} catch (error) {
Log.error('API request failed', {
context: {
endpoint: '/api/orders',
method: 'POST',
status: error.status
},
tags: ['api', 'error']
}, error);
throw error;
}
Database Operations
try {
const orders = await database.query('SELECT * FROM orders WHERE customer_id = ?', [customerId]);
return orders;
} catch (error) {
Log.error('Database query failed', {
context: {
customerId,
query: 'getOrdersByCustomer'
},
metadata: { timeout: 30000 },
tags: ['database', 'error']
}, error);
throw error;
}
File Operations
try {
const content = await fs.readFile(filePath, 'utf8');
return JSON.parse(content);
} catch (error) {
if (error.code === 'ENOENT') {
Log.error('Configuration file not found', {
context: { filePath },
tags: ['config', 'file']
}, error);
} else if (error instanceof SyntaxError) {
Log.critical('Invalid JSON configuration', {
context: { filePath },
tags: ['config', 'json', 'critical']
}, error);
} else {
Log.error('File operation failed', {
context: { filePath, operation: 'read' }
}, error);
}
throw error;
}
Business Logic Errors
class OrderService {
async validateAndProcessOrder(order) {
try {
await this.validateOrder(order);
return await this.processOrder(order);
} catch (error) {
if (error instanceof ValidationError) {
Log.error('Order validation failed', {
context: {
orderId: order.id,
validationErrors: error.errors
},
tags: ['validation', 'orders']
}, error);
} else if (error instanceof InsufficientStockError) {
Log.error('Insufficient stock for order', {
context: {
orderId: order.id,
productId: error.productId,
requestedQuantity: error.requestedQuantity,
availableStock: error.availableStock
},
tags: ['inventory', 'orders']
}, error);
} else {
Log.critical('Unexpected error in order processing', {
context: { orderId: order.id },
tags: ['orders', 'critical']
}, error);
}
throw error;
}
}
}
Error Handling Patterns
Catch and Log
async function getOrder(orderId) {
try {
return await orderRepository.findById(orderId);
} catch (error) {
Log.error('Failed to retrieve order', {
context: { orderId },
tags: ['repository', 'orders']
}, error);
throw error; // Re-throw to preserve original error
}
}
Catch, Log, and Transform
async function getOrderSafely(orderId) {
try {
const order = await orderRepository.findById(orderId);
return { success: true, data: order };
} catch (error) {
if (error.name === 'NotFoundError') {
Log.error('Order not found', {
context: { orderId }
}, error);
return { success: false, error: 'Order not found' };
} else {
Log.critical('Unexpected error retrieving order', {
context: { orderId }
}, error);
return { success: false, error: 'Internal server error' };
}
}
}
Critical Failure Handling
async function startApplication() {
try {
await initializeDatabase();
await loadConfiguration();
await startServices();
} catch (error) {
if (error.name === 'DatabaseConnectionError') {
Log.critical('Database initialization failed', {
tags: ['startup', 'database']
}, error);
process.exit(1);
} else if (error.name === 'ConfigurationError') {
Log.critical('Configuration loading failed', {
tags: ['startup', 'config']
}, error);
process.exit(1);
} else {
Log.critical('Application startup failed', {
tags: ['startup', 'critical']
}, error);
process.exit(1);
}
}
}
Express.js Integration
Route Error Handling
app.get('/api/orders/:id', async (req, res) => {
try {
const order = await orderService.getOrder(req.params.id);
res.json(order);
} catch (error) {
if (error.name === 'NotFoundError') {
Log.error('Order not found', {
context: {
orderId: req.params.id,
requestId: req.id
},
tags: ['api', 'orders']
}, error);
res.status(404).json({ error: 'Order not found' });
} else {
Log.critical('Unexpected error in getOrder endpoint', {
context: {
orderId: req.params.id,
requestId: req.id
},
tags: ['api', 'orders', 'critical']
}, error);
res.status(500).json({ error: 'Internal server error' });
}
}
});
Global Error Handler
app.use((error, req, res, next) => {
const requestInfo = {
requestId: req.id,
path: req.path,
method: req.method,
query: req.query
};
if (error.status && error.status < 500) {
Log.error('Client error', {
context: requestInfo,
metadata: { statusCode: error.status },
tags: ['http', 'client-error']
}, error);
res.status(error.status);
} else {
Log.critical('Server error', {
context: requestInfo,
tags: ['http', 'server-error']
}, error);
res.status(500);
}
res.json({ error: 'An error occurred' });
});
Best Practices
Error Logging Best Practices
- Always pass the Error: Include the
Error
parameter to capture full details - Add relevant context: Include business context like IDs, operation names, and state
- Use appropriate levels:
error
for recoverable issues,critical
for system failures - Don't swallow errors: Log and re-throw or transform appropriately
- Include correlation IDs: Use correlation IDs for request tracking
- Avoid sensitive data: Don't log passwords, tokens, or PII in error context
Common Mistakes to Avoid
// ❌ Don't lose error details
try {
await processOrder(order);
} catch (error) {
Log.error('Something went wrong'); // Missing error parameter
throw new Error('Operation failed'); // Lost original error
}
// ✅ Capture full error details
try {
await processOrder(order);
} catch (error) {
Log.error('Order processing failed', {
context: { orderId: order.id }
}, error);
throw error; // Preserve original error
}
// ❌ Don't log and swallow
try {
await processOrder(order);
} catch (error) {
Log.error('Error occurred', {}, error);
return null; // Swallowing error
}
// ✅ Log and handle appropriately
try {
await processOrder(order);
} catch (error) {
Log.error('Error occurred', {}, error);
throw error; // Or return appropriate error response
}
Next Steps
- Basic Logging - Learn the fundamental logging methods
- Correlation IDs - Track errors across service calls
- Data Masking - Protect sensitive data in error logs
- Tags - Organize error logs with tags