跳到正文
山月行
返回

结构化日志

结构化日志

在一个健壮的项目中,日志是必不可少的。而格式化的日志更有助于我们快速检索日志,更快的找到性能瓶颈,更快的解决线上故障。

如果在 nodejs 环境中,推荐 winston 作为日志库

level

在所有关于日志的组件/函数库中都会有 level 的属性。它表示日志的紧急程度。一般会分为以下几个等级

在平常使用中,还是 error,warn,info 三者较多。另外,error 与 warn 一般会接入异常监控系统,如 Sentry

const winston = require("winston");

const logger = createLogger();

logger.info("hello, world");
logger.warn("hello, warn");
logger.error("hello, error");

label

日志会在不同的地方产生,如 db,redis,function,request, response。在不同地方产生的日志,则含有不同的信息

如在数据库产生的日志会有以下信息

{
  label: 'db',
  sql: 'select * from todo',
  timing: 180,
  tables: ['todo'],
  type: 'SELECT',
  timestamp: '2019-09-13T12:55:16.061Z',
  requestId: '1a83de48-6b80-4558-a587-5be4c87449c2'
}

如在一个 graphql 的 query 中产生的日志会有以下信息

{
  label: 'query',
  query: 'query TODOS { todos { id, title } }',
  operationName: 'TODOS'
  variables: {},
  user: {
    id: 10086,
    role: 'ADMIN'
  },
  ip: '::1',
  timestamp: '2019-09-13T12:55:16.061Z',
  requestId: '1a83de48-6b80-4558-a587-5be4c87449c2'
}

生成结构化与易读的日志

一般来说,关于日志

  1. 生产环境的日志需要 machine readable,使用 json 进行数据结构化,方便在 ELK 或其它日志系统进行检索
  2. 本地环境的日志需要 human readable,方便开发人员在本地开发时阅读

那如何设计一个简单的 logger,既能够 machine readable,又 human readable 呢

  1. 把日志存储为 jsonl 格式文件,即每行都是一个 json,来满足 machine readable
  2. 使用 jq 来做 human readable,可以对日志进行筛选,并展示所需字段
// 把日志存储使用 jsonl 格式存到文件中
const logger = winston.createLogger({
  transports: [
    new winston.transports.File({
      dirname: "./logs",
      filename: `db.log`,
    }),
  ],
});
$ tail -f -n 2 logs/db.log | jq '{ message, requestId }'
{
  "message": "Executing (default): SELECT \"id\", \"name\" FROM \"todo\" AS \"Todo\";",
  "requestId": "4ab7525d-dbae-4243-b833-490a9b7268b5"
}
{
  "message": "Executing (default): SELECT \"id\" FROM \"todo\" AS \"Todo\";",
  "requestId": "390b158b-23aa-443d-9dc9-03abfc56e750"
}

分享本文:

上一篇
Body Parse / Raw Body
下一篇
异常监控