日志的意义是什么
(1)Debug(调试):用来记录某个程序运行了那些代码,变量的逻辑是什么,方便找问题。
(2)问题定位:帮助开发者快速的定位程序错误位置。
(3)用户行为:如分析,监控,推荐这种系统需要协助其他团队分析,开发者需要按照格式约定去执行。
(4)现场记录(甩锅):出现问题了,直接甩出日志打脸
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的操作和释放在操作系统里都有限制。
一般采用流式的方式
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,消息,报错等,上下和堆栈。
打日志需要注意的问题
一般来说日志,不要携带任何敏感信息,用户密码,银行卡,手机号之类的。
当然一般是拿不到的,但是为了绝对的安全,一般不建议打出来这种。
然后需要做日志切割,随着时间的积累,磁盘里的文件越来越大了,磁盘占满了,日志文件是写入不进去,会导致报错。
这里的方案就比较多了,pm2,eggjs都有这样的插件支持!这边就不再讲述,感兴趣的去找文档,一般框架也都内置了这些功能。
ELK通用日志系统
ELK - 日志分析系统。
支持可视化查看日志。
搭建方式:
参考这个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集成到自己的应用里配置好即可。。。
过程比较简单。