TypeScript Logging

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。

本文缩写(英文全称与中文含义)
缩写 英文全称/名称 中文含义
ACK Alibaba Cloud Container Service for Kubernetes 阿里云容器服务 Kubernetes 版
AKS Azure Kubernetes Service Azure 托管 Kubernetes 服务
AWS Amazon Web Services 亚马逊云服务
ECS Elastic Container Service AWS 容器编排服务
EKS Elastic Kubernetes Service AWS 托管 Kubernetes 服务
GCP Google Cloud Platform Google 云平台
GKE Google Kubernetes Engine Google 托管 Kubernetes 服务
HTTP Hypertext Transfer Protocol 超文本传输协议
JSON JavaScript Object Notation 一种结构化数据格式
PM2 PM2 process manager Node.js 进程管理工具名称
VM Virtual Machine 虚拟机
https://github.com/pinojs/pino
https://getpino.io/
https://kubernetes.io/docs/concepts/cluster-administration/logging/
https://pm2.io/docs/runtime/guide/log-management/
https://man7.org/linux/man-pages/man8/logrotate.8.html

1. Important Points#

日志脱敏覆盖 Authorization、cookie、token 和 Secret;TypeScript 类型声明不会替你移除运行时敏感字段。

logging rules:
    production logs should be structured JSON
    container app should write to stdout/stderr
    log should include service / env / request_id / trace_id
    do not log password / token / cookie / authorization header
    error log should include stack
    log level must be configurable
    log rotation should be done by runtime platform when possible
recommended:
    local:
        pretty logs for humans

    Docker / K8S / cloud:
        JSON logs to stdout/stderr
        collector handles storage, search, retention, rotation

    VM + systemd:
        stdout to journald, or file + logrotate

2. Log Levels#

Level Use Case
trace very detailed debug, usually disabled
debug local/dev troubleshooting
info important business/runtime events
warn recoverable abnormal condition
error request failed / dependency failed
fatal process cannot continue
rules:
    info:
        service started
        order created
        job completed

    warn:
        retrying dependency call
        slow request
        invalid but handled state

    error:
        request failed
        database query failed
        message processing failed

    fatal:
        config invalid
        cannot connect critical dependency during startup

3. Pino Setup#

install#

npm install pino
npm install -D pino-pretty

logger.ts#

import pino from "pino";

const isLocal = process.env.NODE_ENV === "local";

export const logger = pino({
  level: process.env.LOG_LEVEL ?? "info",
  base: {
    service: process.env.SERVICE_NAME ?? "order-api",
    env: process.env.NODE_ENV ?? "local"
  },
  redact: {
    paths: [
      "req.headers.authorization",
      "req.headers.cookie",
      "password",
      "token",
      "*.password",
      "*.token"
    ],
    censor: "[REDACTED]"
  },
  transport: isLocal
    ? {
        target: "pino-pretty",
        options: {
          colorize: true,
          translateTime: "SYS:standard"
        }
      }
    : undefined
});
why:
    pino writes JSON by default
    pino-pretty only for local human-friendly output
    redact prevents common secret fields from leaking

4. Request Logging#

import { randomUUID } from "node:crypto";
import type { NextFunction, Request, Response } from "express";
import { logger } from "./logger.js";

export function requestLogger(req: Request, res: Response, next: NextFunction) {
  const start = Date.now();
  const requestId = req.header("x-request-id") ?? randomUUID();

  res.setHeader("x-request-id", requestId);

  const childLogger = logger.child({
    request_id: requestId,
    method: req.method,
    path: req.path
  });

  req.log = childLogger;

  res.on("finish", () => {
    childLogger.info({
      status_code: res.statusCode,
      duration_ms: Date.now() - start
    }, "request completed");
  });

  next();
}
declare global {
  namespace Express {
    interface Request {
      log: import("pino").Logger;
    }
  }
}
fields:
    request_id:
        join logs of one request

    method / path / status_code:
        HTTP dimension

    duration_ms:
        latency troubleshooting

5. Error Logging#

import type { ErrorRequestHandler } from "express";
import { AppError } from "./AppError.js";

export const errorHandler: ErrorRequestHandler = (error, req, res, next) => {
  if (error instanceof AppError) {
    req.log.warn({
      error_code: error.code,
      status_code: error.statusCode
    }, error.message);

    res.status(error.statusCode).json({
      error: {
        code: error.code,
        message: error.message
      }
    });
    return;
  }

  req.log.error({
    err: error
  }, "unexpected error");

  res.status(500).json({
    error: {
      code: "INTERNAL_ERROR",
      message: "internal server error"
    }
  });
};
rules:
    expected business error:
        warn

    unexpected error:
        error with stack

    response:
        do not return raw stack to client

6. Log Format#

{
  "level": 30,
  "time": 1790599200000,
  "service": "order-api",
  "env": "prod",
  "request_id": "req-1001",
  "method": "POST",
  "path": "/orders",
  "status_code": 201,
  "duration_ms": 18,
  "msg": "request completed"
}
recommended fields:
    time
    level
    msg
    service
    env
    version
    request_id
    trace_id
    user_id, only when safe
    method
    path / route
    status_code
    duration_ms
    error_code

7. Sensitive Data#

never log:
    password
    token
    authorization header
    cookie
    session id
    private key
    credit card
    raw personal data
safe pattern:
    log user_id only when necessary
    log order_id / tenant_id for debugging
    mask email / phone if needed
    log error code instead of raw external response body

8. Docker#

container logging:
    write application logs to stdout/stderr
    do not write rotating log files inside container by default
    Docker logging driver / runtime handles collection and rotation
docker logs -f order-api
services:
  order-api:
    image: order-api:1.0.0
    environment:
      NODE_ENV: production
      LOG_LEVEL: info
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "5"

9. Kubernetes#

K8S logging:
    app writes stdout/stderr
    kubelet/container runtime stores container logs on node
    kubectl logs reads container logs
    cluster-level logging needs separate backend
kubectl logs deploy/order-api
kubectl logs deploy/order-api --previous
kubectl logs pod/order-api-xxxxx -c order-api
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-api
spec:
  template:
    spec:
      containers:
        - name: order-api
          image: order-api:1.0.0
          env:
            - name: NODE_ENV
              value: prod
            - name: LOG_LEVEL
              value: info
rotation:
    kubelet manages container log rotation
    common kubelet settings:
        containerLogMaxSize
        containerLogMaxFiles

collection:
    Fluent Bit / Fluentd / Vector / OpenTelemetry Collector
    send to Elasticsearch / Loki / CloudWatch Logs / Google Cloud Logging / Azure Monitor

10. VM / systemd#

stdout to journald#

[Unit]
Description=order-api
After=network.target

[Service]
User=app
WorkingDirectory=/opt/order-api
Environment=NODE_ENV=prod
Environment=LOG_LEVEL=info
ExecStart=/usr/bin/node /opt/order-api/dist/main.js
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
journalctl -u order-api -f
journalctl -u order-api --since "1 hour ago"

file log#

[Service]
StandardOutput=append:/var/log/order-api/app.log
StandardError=append:/var/log/order-api/error.log
file log:
    use only when required by VM operation model
    configure logrotate
    make sure app user can write log directory

11. logrotate#

use logrotate when:
    app writes to files
    PM2 writes file logs
    systemd redirects stdout/stderr to files

do not need app-level logrotate when:
    app writes stdout/stderr in container
    platform log driver already rotates logs
/var/log/order-api/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    copytruncate
    create 0640 app app
}
directives:
    daily:
        rotate daily

    rotate 14:
        keep 14 rotated files

    compress:
        gzip old logs

    copytruncate:
        copy current log then truncate original file
        useful when process cannot reopen log file

    create:
        create new log file with mode/user/group
sudo logrotate -d /etc/logrotate.d/order-api
sudo logrotate -f /etc/logrotate.d/order-api

12. PM2#

npm install -g pm2
pm2 start dist/main.js --name order-api
pm2 logs order-api
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 100M
pm2 set pm2-logrotate:retain 14
pm2 set pm2-logrotate:compress true
PM2 notes:
    default logs are under $HOME/.pm2/logs
    pm2-logrotate rotates PM2-managed log files
    for containers, prefer one process and stdout/stderr instead of PM2

13. Cloud Logging#

Platform Common Target
AWS ECS / EKS CloudWatch Logs / FireLens
GCP GKE / Cloud Run Cloud Logging
Azure AKS / App Service Azure Monitor / Log Analytics
Alibaba ACK Simple Log Service
Self-managed K8S Loki / Elasticsearch / OpenSearch
cloud logging checklist:
    JSON logs
    service/env labels
    retention policy
    access control
    sensitive data redaction
    dashboard and alert links

14. Production Checklist#

application:
    structured JSON logs
    request_id / trace_id included
    log level configurable
    secrets redacted
    unexpected errors include stack

runtime:
    container writes stdout/stderr
    VM file logs use logrotate
    K8S log rotation understood
    centralized log backend configured

operation:
    retention policy defined
    log volume monitored
    error rate alert
    slow request logs queryable
    access to logs restricted

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭