TypeScript 应用中的日志记录:最佳实践与工具

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么在 TypeScript 中日志记录很重要

日志记录不仅仅是把事件写入文件。在现代 TypeScript 应用程序中,配置良好的日志记录是调试、监控和性能分析的基础。没有高质量的日志,开发者会花费数小时重现错误,而运维团队也无法快速定位瓶颈。

TypeScript 作为 JavaScript 的超集,提供了严格的类型检查,使得创建更可预测、更安全的日志系统成为可能。然而,在生产环境中使用简单的 console.log() 是一种反模式,会导致信息噪音和重要数据的丢失。

在本文中,我们将探讨 TypeScript 中日志记录的最佳实践:从库的选择到日志的结构化以及上下文处理。

选择日志记录库

在 TypeScript/Node.js 生态系统中,有几个流行的库。我们来看三个主要选项:

  • Winston — 最流行的库,具有灵活的传输配置(输出到控制台、文件、数据库)。支持日志级别和格式化。
  • Pino — 一个现代库,专注于性能。非常适合高负载系统。
  • Bunyan — 一个不太流行但稳定的选项。所有日志记录器都以 JSON 格式输出数据。

对于典型的 TypeScript 应用程序,我们推荐 Winston 或 Pino。使用 TypeScript 配置 Winston 的示例:

import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
  ],
});

logger.info('服务器已启动', { port: 3000 });

与 TypeScript 集成:类型和接口

为了充分利用类型检查,使用接口为日志记录器创建一个包装器:

interface LoggerOptions {
  level?: string;
  service?: string;
}

interface ILogger {
  info(message: string, meta?: unknown): void;
  error(message: string, error?: Error): void;
  warn(message: string, meta?: unknown): void;
}

这将允许您严格控制传递数据的类型,并在编译阶段避免错误。

日志级别及其正确使用

标准日志级别(从最严重到最不严重):error、warn、info、debug、trace。重要的是遵循统一的语义:

  • error — 仅用于需要开发者关注的不可恢复的错误。
  • warn — 用于潜在的问题情况,这些情况不会破坏应用程序的运行。
  • info — 用于关键事件:服务器启动、请求处理、成功授权。
  • debug — 用于开发过程中的调试。不要在生产环境中启用此级别。

根据环境动态更改级别的示例:

const logLevel = process.env.NODE_ENV === 'production' ? 'warn' : 'debug';
const logger = winston.createLogger({ level: logLevel });

结构化日志和上下文

使用 JSON 格式的结构化日志代替字符串消息。这使得可以使用 ELK 栈(Elasticsearch、Logstash、Kibana)或其他系统轻松解析日志。

务必添加上下文信息:请求 ID、用户名、服务名称、时间戳。使用 Pino 的示例:

import pino from 'pino';

const logger = pino({
  level: 'info',
  mixin() {
    return { service: 'my-api' };
  },
});

// 添加上                

博客

书籍推荐