You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js(Express多模块项目)的规范错误日志记录方案

Got it, let's break down a robust error logging solution tailored to your multi-module Express project. Based on your folder structure and need for actionable logs that support manual intervention, here's a step-by-step implementation:

1. Start with a Custom Error Class for Consistent Context

First, create a reusable error class to standardize error metadata across all services. This ensures every error includes critical details for debugging.

// utils/ServiceError.js (create this new file)
class ServiceError extends Error {
  constructor(errorCode, message, context = {}) {
    super(message);
    this.name = 'ServiceError';
    this.errorCode = errorCode; // Unique identifier (e.g., "PAYMENT_TRANSACTION_FAILED")
    this.context = context; // Extra details: user ID, transaction ID, service name
    Error.captureStackTrace(this, this.constructor); // Preserve stack trace
  }
}

module.exports = ServiceError;
2. Wrap Service Gateways to Capture Errors

Since each service's index.js acts as the external gateway, use it to catch errors from the service's routes and wrap them in your custom error class.

For example, in payment_service/index.js:

const express = require('express');
const router = require('./routes');
const ServiceError = require('../utils/ServiceError');

// Gateway wrapper to catch route errors
const paymentGateway = (req, res, next) => {
  router(req, res, (err) => {
    if (err) {
      // Wrap raw errors into our standardized format
      const standardizedError = new ServiceError(
        err.errorCode || 'PAYMENT_UNKNOWN_ERROR',
        err.message || 'Payment service encountered an unexpected error',
        { 
          service: 'payment_service',
          requestPath: req.path,
          ...err.context // Merge any existing context from the route error
        }
      );
      next(standardizedError); // Pass to global error handler
    }
  });
};

module.exports = paymentGateway;
3. Add a Global Express Error Handling Middleware

This middleware will be the single point to log all errors and send consistent responses to clients. We'll use a structured logging library like winston (no external links needed—just npm install it) for machine-readable logs.

First, set up the logger:

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

const logger = winston.createLogger({
  level: 'error',
  format: winston.format.combine(
    winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
    winston.format.json() // Structured format for easy filtering/searching
  ),
  transports: [
    new winston.transports.File({ filename: 'critical-errors.log' }), // Persist to file
    new winston.transports.Console() // Also log to console for development
  ]
});

module.exports = logger;

Then add the global error middleware to app.js:

const express = require('express');
const requestId = require('express-request-id')(); // Adds unique request ID for tracing
const logger = require('./utils/logger');
const paymentGateway = require('./payment_service');
const ServiceError = require('./utils/ServiceError');

const app = express();

// Add request ID to track full request lifecycle
app.use(requestId);

// Mount your service gateways
app.use('/payment', paymentGateway);

// Global error handler (must have 4 parameters)
app.use((err, req, res, next) => {
  // Standardize any non-ServiceError errors
  const error = err instanceof ServiceError 
    ? err 
    : new ServiceError(
        'GENERAL_SERVER_ERROR',
        'An internal server error occurred',
        { service: 'unknown', requestPath: req.path }
      );

  // Log structured error with request context
  logger.error({
    requestId: req.id,
    service: error.context.service,
    errorCode: error.errorCode,
    errorMessage: error.message,
    stackTrace: error.stack,
    context: error.context
  });

  // Send consistent response to client
  res.status(500).json({
    success: false,
    message: 'We encountered an issue. Please reference request ID: ' + req.id,
    requestId: req.id
  });

  // Trigger alerts for errors requiring manual intervention
  const criticalErrors = [
    'PAYMENT_TRANSACTION_FAILED',
    'DB_CONNECTION_LOST',
    'INSUFFICIENT_FUNDS'
  ];
  if (criticalErrors.includes(error.errorCode)) {
    // Add your alert logic here (e.g., email to admins, Slack notification)
    // alertAdmin(`Critical Error: ${error.errorCode} - Request ID: ${req.id}`);
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));
4. Throw Standardized Errors in Routes/Models

In your service routes and models, throw ServiceError instances with specific context to make logs actionable.

Example in payment_service/routes.js:

const express = require('express');
const router = express.Router();
const PaymentModel = require('../models/model_1');
const ServiceError = require('../utils/ServiceError');

router.post('/charge', async (req, res, next) => {
  try {
    const { userId, amount, transactionId } = req.body;
    const paymentResult = await PaymentModel.chargeUser(userId, amount);
    
    if (!paymentResult.success) {
      throw new ServiceError(
        'PAYMENT_INSUFFICIENT_FUNDS',
        'User has insufficient funds for transaction',
        { userId, transactionId, amount }
      );
    }

    res.json({ success: true, transactionId });
  } catch (dbErr) {
    throw new ServiceError(
      'PAYMENT_DB_ERROR',
      'Failed to process payment in database',
      { userId: req.body.userId, dbErrorMessage: dbErr.message }
    );
  }
});

module.exports = router;
Key Benefits of This Setup
  • Structured Logs: JSON format makes it easy to search/filter errors by service, error code, or request ID.
  • Actionable Context: Every log includes details like user IDs, transaction IDs, and service names to speed up manual fixes.
  • Centralized Control: All errors flow through one middleware, so you can update logging/alerts without touching every service.
  • Request Tracing: The request ID lets you track a single request across all modules, perfect for debugging cross-service issues.

内容的提问来源于stack exchange,提问作者Krrish Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:08:50