windows 平台上日志文件监控

需求

最近遇到一个需求,要将终端运行的日志集中到指定位置。我们之前研究过 filebeat,这是一个比较成熟的产品,可以支持将日志传输到多种不同的中间件上。测试下来发现似乎不支持 http,而我们的需求场景都是 http。当然,确实可以先传到诸如 redis、kafka 这些中间件上,再转给后端,不过这就拉长了整个链路。

我们的场景是这样的:

终端运行时,会不停向日志文件追加内容;之前各个级别有各自的日志文件,但排查问题以及应对这个需求有点儿鸡肋,所以所有日志都追加到同一个文件中;
使用的日志框架会根据配置,将文件按照大小进行切割;当前写入的永远都是配置的那个文件名,而回滚的日志会被编号,会定时清除;
终端会部署在不同的平台上,windows、linux 都有;
需求中希望日志上传越快越好;这就导致我们不能等一个文件写完毕后才上传;
其实原本还有更简单的方案,我们可以直接更改日志框架,即日志内容除了写到文件中外,还往指定位置发送一份;但是这样的话,日志库就变重了(不过写这篇文章的时候,越来越觉得这样也挺合理的)。

最终,为了不怎么侵入原来的代码(因为日志收集功能是在终端程序在需要的情况下才会启动,所以还是需要做一些改动的),我们单独开发了一个程序,专门监控日志文件。

但这里最让人郁闷的问题是,不同平台的文件逻辑并不相同……

linux

linux 对文件处理的逻辑是非常棒的。当我们 open 一个文件时,linux 返回给我们的是这个文件的句柄,而所谓句柄其实就是一个编号。对于一个文件最重要的属性是 innode,根据 innode 就能读取到一个文件的内容,而写入也一样。至于文件名称反而不重要,我们完全可以在一个进程中打开一个文件,然后用其它进程将该文件重命名,甚至删除。所以在 linux 上,可以由主进程以追加方式写入文件,再启动一个进程不停从这个文件中读取日志内容;当主进程判断需要新建立一个日志文件时,可以直接将该文件对象关闭,然后将其重命名成别的,再新建一个同名文件;而读取日志的进程在发现没有内容可读时,只要检查一下日志文件的名称,就知道该日志文件是不是已经写完毕了。
在这里插入图片描述

windows

windows 的文件机制似乎比较死板,一个文件在进程 A 中以只读模式打开,而进程 B 哪怕对该文件进行重命名,都是不允许的,这也正是我们在 windows 上经常遇到的想删除一个文件却一直删不掉的原因,甚至都不知道哪个进程在占着该文件。这导致一个情况,当主进程在往日志文件里边追加内容时,读取日志的进程不能一直 open 着该文件,否则会导致主进程因为重命名失败而阻塞甚至崩溃,所以只能按照偏移量一段一段读,读了以后立马关闭。

经过一番逻辑上的研究,要在 windows 上实现该功能基本就是下面的逻辑流。
在这里插入图片描述

每次接收到读取一段日志的要求时,需要先判断日志文件还在不在,即使在,也需要能确定当前同名的这个文件确实是上次读取的文件,因为很有可能已经发生了日志切换;而最保险的依据只能是创建时间,所以读取日志的进程必须记录当前追踪的日志文件的创建时间;当再次读取时,要判断两个文件的创建时间是否一致,只有一致才表示文件还没有被切换,否则必须遍历所有文件找到原来那个文件,当然为了更快找到,可以引入日志回滚的文件命名规则,比方说所有日志叫 info,log.[0-9],甚至还可以引入日志编号,这样更快,不过这会导致日志监控进程与日志框架耦合严重。另外,上面查找文件的逻辑也要求存储日志的文件夹比较干净,可别什么东西都往里边塞。windows 上文件创建的时间戳精度是秒,不过一般这个时间也够了,除非配置的回滚大小太小。

最后的一点,这样的方式依然可能会有问题,就是当日志监控进程正在从日志中读取时,主进程发现要切了,执行重命名,然后因为前面的进程还没读完,结果重命名失败,主进程如果没有相应的机制,极可能会崩溃;这个需要实际测一下效果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值