trace-hook

0.2.17 • Public • Published

trace-hook

还在开发中, 有任何问题和bug欢迎发给邮箱: ruanchuhao7455@gmail.com

Description

一个轻量化的全链路追踪中间件, 可生成TraceID, 并将TraceID注入到各种请求中, 以便于在日志中查看请求的完整链路

配置逻辑简介

这个模块, 用于生成traceId, 以及解析traceId
必须有生产TraceID的模块才能使用其余所有功能\

产生TraceID的模块有:

  • koaTrace
  • amqplibTrace
  • transByAmqplib
  • 自定义模块

简介

  • koaTrace 用于koa框架
  • amqplibTrace 用于amqplib框架 一般不单独使用
  • transByAmqplib 用于amqplib框架 (集成了amqplibTrace 所以也属于生产者)
  • 自定义模块(todo)

使用ID的模块有:

  • logger
  • loggerTrace
  • koaLogger
  • transByAxios

简介

  • logger, loggerTrace 用于记录日志
  • koaLogger 用于请求信息记录日志
  • transByAxios 用于axios请求传递traceId (解析traceId的是由koaTrace处理的)
  • transByAmqplib 用于amqplib生成和解析以及请求传递traceId (生成traceId的是由amqplibTrace处理的)

KOA配置

最小配置

1. 在KOA中配置中间件

const Koa = require('koa');
const {koaHookMiddleware} = require('server/middleware/koa-hook');

let koa = new Koa();
koa.use(koaHookMiddleware());  // call ruanchuhao 全链路hook

2. 使用框架提供的日志方法, 或者在自己的日志中添加traceID

2.1. 使用自定义的方法

// 引入核心包
const {hookCore} = require('trace-hook'); 

// 获取当前请求的TraceID
const traceId = hookCore.getRootIdx();

// 在日志中添加TraceID
...你的核心logger逻辑
return `[traceID-${traceId}] ${level}:${module}${category} ${info.message ? info.message : JSON.stringify(info)}`;

2.2. 使用框架提供的方法

const logger = require("trace-hook").logger.logger(config).child({ module: "server:router:basic" });
logger.info(`[${process.env.NODE_ENV}]MeetingPadService works! start at ${_now} [1]`);

2.1或2.2可以得到日志

[traceID-3002] info: [Token] path [/api] token [undefined] state [{}]
[traceID-3002] info:server:router:basic [development]MeetingPadService works! start at Thu Aug 17 2023 15:27:43 GMT+0800 (China Standard Time) [1]

更多配置

1. 为KOA请求官方的KOA-logger中间件添加traceID

const { koaLogger } = require('trace-hook');

let koa = new Koa();
koa.use(koaLogger()); // 这样就可以生效了
可以得到日志
[traceID-3002]  <-- GET /api
.....
[traceID-3002]  --> GET /api 200 1,018ms 137b

2. axios请求中添加traceID

const axios = require('axios');
const {transByAxios} = require("trace-hook");
transByAxios(axios);// 初始化axios, 使得axios可以自动注入traceID 全局只需执行一次 请勿执行多次

// 使用axios 正常使用即可
const axios = require('axios');
axios.get('http://localhost:3000/api')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
可以得到日志
# 调用方日志 传出traceID
[traceID-6002]  <-- GET /api
......

# 背调方日志 获得traceID
[traceID-T-6002]  --> GET /api 200 1,004ms 137b
......

3. amqplib 添加日志

目前支持三个方法的日志

  • publish
  • sendToQueue
  • addSetup中的channel.consume
// amqp 依赖包
const amqp = require('amqp-connection-manager');

// 连接MQ配置
const connection = amqp.connect(['amqp://localhost:5672']);

// 使用初始化方法令amqp支持traceID
const {transByAmqplib} = require('trace-hook');
transByAmqplib(this.connection);
配置完成后正常使用amqp即可(可以不看下面的例子)
// 正常使用amqp即可
const channelWrapper = this.connection.createChannel({
    json: true, setup: function (channel) {
        return channel.assertQueue('rxQueueName', {durable: true});
    },
});
// sendToQueue
channelWrapper.sendToQueue('rxQueueName', {hello: 'world'});

// publish
await channelWrapper.assertExchange('any', 'direct', {durable: false});

await channelWrapper.publish('any', '', {hello: 'world'}).then(() => {
    logger.info('publish success');
});

// addSetup中的channel.consume
await channelWrapper.addSetup(function (channel) {
    return channel.consume('rxQueueName', function (msg) {
        logger.info('Rx msg' + msg.content.toString());
        setTimeout(() => {
            logger.info('2Rx msg' + msg.content.toString());
        }, 1000);
    });
});
可以得到日志
# 调用方日志 传出traceID
[traceID-1409] info:infra:rabbitmq publish success
# 消费方日志 获得traceID
[traceID-T-1409] info:infra:rabbitmq 2Rx msg{"hello":"world","traceId":"T-1409"}

# 若生产者没有传入traceID, 则消费者日志会生成自己的traceID
[traceID-1037] info:infra:rabbitmq 2Rx msg{"hello":"world"}

4. mqtt

目前支持mqtt包中的两个方法

  • on('message', ....)
  • publish
使用方法
// mqtt 依赖包
const mqtt = require('mqtt');

// 连接MQ配置
this.client = mqtt.connect(...);

// 使用初始化方法令mqtt支持traceID
traceByMqtt(this.client);

// === 配置完成 以下为正常使用mqtt ===
// 使用mqtt
this.client.on('message', function (topic, message) {
    // message is Buffer
    logger.info(message.toString());
});

this.client.publish('presence', {msg: 'Hello mqtt'});
可以得到日志
# 生产者日志
[traceID-65582] info:infra:mqtt send ...  

# 消费者日志
[traceID-T-65582] info:infra:mqtt {"msg": "Hello mqtt","traceId":"T-65582"}
5. 自定义模块

可以自定义模块, 用于生成traceID, 以及解析traceID

// 引入核心包 创建自己的模块
let mqttTraceHook = new CustomTraceHook();

// [重要] 使用入口函数, 只有入口函数及其子函数可以获得traceID
mqttTraceHook.entrance(
    msg.traceId, // 外部传入的traceID 可以指定rootId(根traceID) 也可以不指定, 不指定则自动生成
    (_outerTraceId, _innerTraceId)=>{ `...`}, // 传入的traceID, 以及生成的traceID 可以自定义上下文记录
    ()=>{return callback(topic, Buffer.from(JSON.stringify(msg)));} // 子函数(callback\ next) 在这里执行你的业务逻辑 可以使用traceID的全部能力
);

还有一些附加能力

mqttTraceHook.getRootIdx() // 获取当前的根节点 (traceId)
mqttTraceHook.getCurrentIdx() // 获取当前的 async id  在没有根节点的情况下充当TraceId

未完待续...

Package Sidebar

Install

npm i trace-hook

Weekly Downloads

5

Version

0.2.17

License

ISC

Unpacked Size

33.9 kB

Total Files

12

Last publish

Collaborators

  • chrischuhao