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

Loopback API全局错误触发自动邮件方案咨询

在LoopBack中实现全局API错误自动发送邮件的方案

我之前也遇到过类似的困扰——LoopBack项目越来越大,每个方法加catch完全不现实,尤其是自动生成的CRUD方法根本没法逐个改。下面给你两种针对不同LoopBack版本的全局解决方案,一次配置就能覆盖所有API错误:

针对LoopBack 3的方案:全局远程钩子(Remote Hooks)

LoopBack 3提供了afterError全局远程钩子,能捕获所有远程方法(包括自动生成的CRUD方法)抛出的错误,完美解决你的问题。

步骤1:安装邮件依赖

先安装常用的邮件发送工具nodemailer:

npm install nodemailer --save

步骤2:配置全局错误钩子

在server/server.js中添加以下代码,实现全局错误捕获和邮件发送:

const nodemailer = require('nodemailer');
const app = require('./server');

// 配置邮件传输器(建议用环境变量存储敏感信息,不要硬编码)
const transporter = nodemailer.createTransport({
  service: 'Gmail', // 也可以用SendGrid、AWS SES等其他服务商
  auth: {
    user: process.env.ALERT_EMAIL_USER,
    pass: process.env.ALERT_EMAIL_PASS
  }
});

// 全局afterError钩子:捕获所有远程方法的错误
app.remotes().afterError(function(ctx, next) {
  // 可选:过滤客户端错误(比如404、401),只处理服务器端5xx错误
  if (ctx.error.statusCode && ctx.error.statusCode < 500) {
    return next();
  }

  // 构建邮件内容
  const mailOptions = {
    from: 'LoopBack Error Alert <your-alert-email@example.com>',
    to: 'admin-team@example.com',
    subject: `API Error: ${ctx.error.name} - ${ctx.req.path}`,
    html: `
      <h2>🚨 LoopBack API 错误告警</h2>
      <table style="border-collapse: collapse; width: 100%;">
        <tr><th style="border:1px solid #ddd; padding:8px;">错误类型</th><td style="border:1px solid #ddd; padding:8px;">${ctx.error.name}</td></tr>
        <tr><th style="border:1px solid #ddd; padding:8px;">请求路径</th><td style="border:1px solid #ddd; padding:8px;">${ctx.req.path}</td></tr>
        <tr><th style="border:1px solid #ddd; padding:8px;">请求方法</th><td style="border:1px solid #ddd; padding:8px;">${ctx.req.method}</td></tr>
        <tr><th style="border:1px solid #ddd; padding:8px;">错误信息</th><td style="border:1px solid #ddd; padding:8px;">${ctx.error.message}</td></tr>
        <tr><th style="border:1px solid #ddd; padding:8px;">堆栈跟踪</th><td style="border:1px solid #ddd; padding:8px;"><pre>${ctx.error.stack}</pre></td></tr>
        <tr><th style="border:1px solid #ddd; padding:8px;">请求参数</th><td style="border:1px solid #ddd; padding:8px;">${JSON.stringify(ctx.req.query)}</td></tr>
        <tr><th style="border:1px solid #ddd; padding:8px;">请求体</th><td style="border:1px solid #ddd; padding:8px;">${JSON.stringify(ctx.req.body)}</td></tr>
      </table>
    `
  };

  // 发送邮件(异步执行,不阻塞请求处理流程)
  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      console.error('发送错误邮件失败:', error);
    } else {
      console.log('错误邮件已发送:', info.response);
    }
    // 继续执行默认错误处理流程
    next();
  });
});

关键说明

  • 这个钩子会拦截所有远程方法的错误,不管是你自定义的还是LoopBack自动生成的
  • 通过statusCode过滤可以避免把客户端的错误(比如用户输入错误)也发邮件给管理员
  • 敏感信息(邮箱账号、密码)一定要用环境变量存储,不要提交到代码仓库

针对LoopBack 4的方案:全局异常过滤器

LoopBack 4采用了基于异常过滤器的错误处理机制,我们可以创建一个全局过滤器来捕获所有HTTP请求中的异常。

步骤1:创建全局异常过滤器

用LoopBack CLI生成一个过滤器:

lb4 filter --name GlobalErrorFilter

然后修改生成的src/filters/global-error.filter.ts文件:

import { Catch, ExceptionFilter, ArgumentsHost, HttpException, HttpStatus } from '@loopback/rest';
import { Logger, inject } from '@loopback/core';
import nodemailer from 'nodemailer';

// @Catch() 不加参数表示捕获所有类型的异常
@Catch()
export class GlobalErrorFilter implements ExceptionFilter {
  constructor(@inject('logger') private logger: Logger) {}

  async catch(exception: unknown, host: ArgumentsHost) {
    const httpCtx = host.getHttpContext();
    if (!httpCtx) return;

    const request = httpCtx.request;
    let statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
    let errorMessage = '服务器内部错误';
    let stackTrace = '';

    // 区分HTTP异常和普通Error
    if (exception instanceof HttpException) {
      statusCode = exception.statusCode;
      errorMessage = exception.message;
      stackTrace = exception.stack || '';
    } else if (exception instanceof Error) {
      errorMessage = exception.message;
      stackTrace = exception.stack || '';
    }

    // 过滤客户端错误,只处理5xx服务器错误
    if (statusCode < 500) {
      // 交给LoopBack默认的错误处理逻辑
      throw exception;
    }

    // 配置邮件传输器
    const transporter = nodemailer.createTransport({
      service: 'Gmail',
      auth: {
        user: process.env.ALERT_EMAIL_USER,
        pass: process.env.ALERT_EMAIL_PASS
      }
    });

    const mailOptions = {
      from: 'LoopBack 4 Error Alert <your-alert-email@example.com>',
      to: 'admin-team@example.com',
      subject: `API Error [${statusCode}]: ${request.path}`,
      html: `
        <h2>🚨 LoopBack 4 API 错误告警</h2>
        <table style="border-collapse: collapse; width: 100%; margin-top: 10px;">
          <tr><th style="border:1px solid #ddd; padding:8px;">状态码</th><td style="border:1px solid #ddd; padding:8px;">${statusCode}</td></tr>
          <tr><th style="border:1px solid #ddd; padding:8px;">请求路径</th><td style="border:1px solid #ddd; padding:8px;">${request.path}</td></tr>
          <tr><th style="border:1px solid #ddd; padding:8px;">请求方法</th><td style="border:1px solid #ddd; padding:8px;">${request.method}</td></tr>
          <tr><th style="border:1px solid #ddd; padding:8px;">错误信息</th><td style="border:1px solid #ddd; padding:8px;">${errorMessage}</td></tr>
          <tr><th style="border:1px solid #ddd; padding:8px;">堆栈跟踪</th><td style="border:1px solid #ddd; padding:8px;"><pre>${stackTrace}</pre></td></tr>
          <tr><th style="border:1px solid #ddd; padding:8px;">请求参数</th><td style="border:1px solid #ddd; padding:8px;">${JSON.stringify(request.query)}</td></tr>
          <tr><th style="border:1px solid #ddd; padding:8px;">请求体</th><td style="border:1px solid #ddd; padding:8px;">${JSON.stringify(request.body)}</td></tr>
        </table>
      `
    };

    try {
      await transporter.sendMail(mailOptions);
      this.logger.info('错误告警邮件发送成功');
    } catch (emailErr) {
      this.logger.error('发送错误告警邮件失败:', emailErr);
    }

    // 继续抛出异常,让LoopBack处理后续响应
    throw exception;
  }
}

步骤2:注册全局过滤器

在src/application.ts中注册这个全局过滤器:

import { GlobalErrorFilter } from './filters/global-error.filter';

export class YourApplication extends BootMixin(ServiceMixin(RepositoryMixin(RestApplication))) {
  constructor(options: ApplicationConfig = {}) {
    super(options);

    // ...其他配置

    // 注册全局异常过滤器
    this.globalInterceptor(GlobalErrorFilter, { scope: BindingScope.SINGLETON });
  }
}

关键说明

  • 全局过滤器会捕获所有进入HTTP管道的异常,包括自动生成的CRUD控制器的错误
  • 可以根据业务需求调整邮件内容,比如添加环境标识(开发/生产)、请求ID等信息
  • 建议集成日志系统,同时记录错误日志和邮件发送状态

通用优化建议

  • 错误去重:可以用Redis或内存缓存记录最近发送的错误,避免短时间内相同错误重复发送邮件
  • 邮件模板:把邮件HTML模板抽成单独的文件,方便维护和修改
  • 服务商选择:如果是生产环境,建议用专业的邮件服务商(如SendGrid、Mailgun),比Gmail更稳定
  • 环境变量:所有敏感配置(邮箱账号、密码、收件人列表)都用环境变量管理,不要硬编码

内容的提问来源于stack exchange,提问作者Varun Sukheja

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:36:11