【nodejs高可用】日志管理

227 阅读4分钟

日志的意义是什么

(1)Debug(调试):用来记录某个程序运行了那些代码,变量的逻辑是什么,方便找问题。

(2)问题定位:帮助开发者快速的定位程序错误位置。

(3)用户行为:如分析,监控,推荐这种系统需要协助其他团队分析,开发者需要按照格式约定去执行。

(4)现场记录(甩锅):出现问题了,直接甩出日志打脸

image.png

Console.log发生了什么

Console底层其实调用了process.stdout.write,stdin,stdout,stderr称之为“标准输入”,“标准输出”,“标准错误”等。

例如打Log是这么实现的

Console.prototype.log = function(){
  this._stdout.write(util.format.apply(this,arguments)+'\n')
}

Process.stdout.write有可能是同步的,也有可能是异步的,在win和mac上的表现各不相同。

文件输出日志

有的做法可能会考虑,fs.writeFile去打印日志.

const fs = require("fs"); // 导入 file system 模块
 
// 异步写入文件
fs.writeFile("./files/log.log", "日志内容", (err) => {
  if (err) {
    console.log(err.message); // 输出错误信息
    return;
  } else {
    console.log("成功写入文件./files/log.log");
  }
});

但是这种,每次使用的时候都会替换文件数据,应该做那种追加行的形式。

一般使用fs.aapendfile去追加。



var fs = require("fs"); 

fs.appendFile('log.log', 'data:content', function (err) {

  if (err) throw err;

  console.log('The "data to append" was appended to file!');

});


这种方式也会有一个缺陷,高并发场景下不使用,因为他会不断的创建文件句柄出来,操作系统针对文件句柄的可操作数,是有一定限制的,会直接报错。

fd的操作和释放在操作系统里都有限制。

image.png

一般采用流式的方式

const fs = require('fs');  
const readStream = fs.createReadStream('log.log'); 

这也是现在比较推荐的方式,对内存的占用更少,也不会有fd(文件句柄)创建的问题,分块处理数据的。

服务器应用日志

客户端请求:accesslog,客户端请求到达服务层面,需要记录请求日志。

Nginx等支持这种操作

服务端请求:一般用框架的请求库负责打日志。

异常获取:比如try-catch,出现了err后,打印日志,出现异常了。

业务记录:比如生成了一个订单号等,保证业务是的逻辑可查的到的。

建议使用框架自带的logger,比如egg-logger,Winston,log4j等。。。。

什么样是一份好的日志

日志级别的介绍:

INFO:一些日常的信息,create xxx sucess这种

DEBUG:排查问题去用的,一般情况下不出现在线上环境。

WARN:用户错误的输入,重试等。

ERROR:出现错误,比如try-catch,调用某个接口超时了之类的。需要进行错误处理。

可以参考下eggjs自带的日志。

带有时间戳,计算机服务器的IP(分布式系统下便于识别是那台机器发出来的)等,进程ID,消息,报错等,上下和堆栈。

www.eggjs.org/zh-CN/core/…

打日志需要注意的问题

一般来说日志,不要携带任何敏感信息,用户密码,银行卡,手机号之类的。

当然一般是拿不到的,但是为了绝对的安全,一般不建议打出来这种。

然后需要做日志切割,随着时间的积累,磁盘里的文件越来越大了,磁盘占满了,日志文件是写入不进去,会导致报错。

这里的方案就比较多了,pm2,eggjs都有这样的插件支持!这边就不再讲述,感兴趣的去找文档,一般框架也都内置了这些功能。

ELK通用日志系统

ELK - 日志分析系统。

支持可视化查看日志。

搭建方式:

gitee.com/node-apm/el…

参考这个demo

ELK的安装:

使用命令:

git clone https://github.com/deviantony/docker-elk.git

然后用docker的形式运行起来。

安装好之后,做配置。

log4js.configure({
  appenders: {
    console: { type: "console" },
    // file: { type: "file", filename: "all-the-logs.log" },
    // https://github.com/Aigent/log4js-logstash-tcp
    elk_learn: {
      type: "log4js-logstash-tcp",
      host: "127.0.0.1",
      port: 5000
    }
  },
  categories: {
    default: { appenders: ["elk_learn"], level: "debug" }
  }
});

可以把log4j的日志直接收集到elk当中,els像个回收站一样,这个过程是被动的。

Elk支持日志收集,Apm,告警等能力。

Sentry - 错误日志收集

这个和Elk的区别是,Sentry只能收集错误日志。

Sentry对各个端的支持很好,前后端的日志都可以进行收集。

其他的语言,Nodejs,php,Java,React等都可以用

ELk是全量的日志收集。

Sentry分为SDK,和平台。

搭建流程:

直接用git拉代码:

git clone https://github.com/getsentry/onpremise.git

./install.sh

再把SDK集成到自己的应用里配置好即可。。。

过程比较简单。