eggjs使用kafka上报日志

503 阅读1分钟

kafka插件选择

由于使用的是egg,因此最先考虑的是有没有egg kafka的插件,在gthub中找到了egg-kafka-node, 但是此插件在node v16版本以上无法使用。因此以下的两个插件可以自由选择,我使用的是kafkajs。

1. kafka-node
2. kafkajs 

如何获取到egg的各种日志

egg的文档中找到了高级自定义日志,按照文档创建自定义的transport文件,再将kafkajs中的producer示例代码结合一下:

const util = require('util');
const Transport = require('egg-logger').Transport;
const { Kafka } = require('kafkajs');

class KafkaTransport extends Transport {
  // 定义 log 方法,在此方法中把日志上报给远端服务
  log(level, args) {
    let log;
    if (args[0] instanceof Error) {
      const err = args[0];
      log = util.format(
        '%s: %s\n%s\npid: %s\n',
        err.name,
        err.message,
        err.stack,
        process.pid,
      );
    } else {
      log = util.format(...args);
    }

    const kafka = new Kafka({
        brokers:['此处是kafka的地址']
    });
    const producer = kafka.producer();
    producer.connect().then(()=>{
        producer.send({
            topic:'',
            message:[{value:JSON.stringify(log)}]
        }).catch(err=>{
            console.log("kafka send message error", err);
        })
    }).catch(err=>{
        console.log("kafka connect error", err);
    });
  }
}

module.exports = KafkaTransport;

还需要在app.js中添加下面代码,让自定义transport生效

    const {app} = this;
    app.getLogger('logger').set('名字随便',new KafkaTransport({ level:'ALL',app}));

现在启动项目,所有通过app.logger或者ctx.logger产生的日志都可以从自定义的transport发送到kafka了。在实际使用中不同环境可能对应不同的kafka地址或topic,因此可以将对应环境的kafka配置写在config.[env].js文件中,例如:

    // config.dev.js
    ...
    config.kafkaConfig = {
        host:['地址1','地址2'],
        topic:'xxxx'
    }
    ...

然后对transport.js进行小小的改动:

    ...
    const { app } = this.options;
    
     const kafka = new Kafka({
        brokers: app.config.kafkaConfig.host
    });
    const producer = kafka.producer();
    producer.connect().then(()=>{
        producer.send({
            topic: app.config.kafkaConfig.topic,
            message: [{value:JSON.stringify(log)}]
        }).catch(err=>{
            console.log("kafka send message error", err);
        })
    }).catch(err=>{
        console.log("kafka connect error", err);
    })
    ...

这样就可以根据不同的环境将日志发往对应的kafka了,有疑问或者建议欢迎在评论区交流。