如何快速的把日志输出到磁盘上

不管是做客户端业务,还是做服务端业务,日志子系统都是非常重要的一个组件。

日志系统的输出目的地可以是disk,也可以是tty,更可以是network。

我的日志系统可以输出到tty,不同log level可以有不同的color,这样看日志非常的醒目,当然这里着重谈的是如何快速的把log内容写到磁盘上。

其实,如何快速的把log内容写到磁盘上,网上文章已经汗牛充栋,真正高质量的没多少,本篇可能也是狗尾续貂之作。不过,我的log子系统能够达到106M/s的输出速率。

详细介绍我的log系统之前,推荐大家看看陈硕大牛的《Linux 多线程服务端编程:使用 muduo C++ 网络库》一书中关于muduo log的实现,muduo的log的思路和实现都是非常漂亮的。网上还有相关的ppt,这里面有很多的干货。

log系统如何快速的把log内容写到磁盘上?其关键就在于写log时要进行顺序写,即每次写log的大小要为4k或者4k的倍数。

鉴于语言描述非本人强项,下面先呈上关键代码,然后再详述之。

struct log_t {

int                            file;

pthread_mutex_t mutex;

int                           buf_cursor;

char                       buf[4 * 1024];

struct iovec           iovec_[2];

};

int log_write(log_t* log, char* buf, int len)

{

int ret = 0;

pthread_mutex_lock(&log->mutex);

do  {

size = log->buf_cursor + len;

if (size < sizeof(log->buf))  {

memcpy(log->buf + log->buf_cursor, buf, len);

log->buf_cursor = size;

break;

}

log->iovec_[0].iov_base = log->buf;

log->iovec_[0].iov_len = log->buf_cursor;

log->iovec_[1].iov_base = buf;

log->iovec_[1].iov_len = len;

ret = (int)writev(log->file, log->iovec_, 2);

if (IS_NEQ(ret, size))  {

ret = -2;

}

log->cursor += size;

log->buf_cursor = 0;

} while(0);

pthread_mutex_unlock(&log->mutex);

return ret;

}

看上面这段代码的,log有一个4k的buf,如果本次输出的内容能够放到buf里面,那么就把内容拷贝进去,然后退出,否则就调用writev函数把内容写进log文件。

其思路跟陈硕大牛的muduo的log比起来当然是云泥之别,没那么高大上。其方法的关键就是减小锁的粒度、合并多次write为一次write以进行顺序写log内容至磁盘上。

log系统有同步和异步两种区别,上面的实现方式本质是一种同步方式。

所谓的异步输出log就是专门启动一个日志线程,它可以有一个log队列,其他线程作为生产者把内容输出至队列,日志线程就作为消费者从队列中取出log内容,然后把它写到磁盘上。

我现在西二旗一家公司工作,我最近为公司实现了一种异步log系统,其关键流程当然就是上面一段的思路。但是,仅仅靠上面的这种方法是无法实现快速地进行异步log输出的。除了log线程的队列外,参考陈硕的muduo log的思路,我还添加了一个log buf(struct log_buf {  int cursor;  char buf[1 * 1024 * 1024];  };),其思路跟同步方式一样,先把log内容放到这个log_buf中,待log_buf快溢出的时候,把log_buf放入队列中。

由于代码的版权归公司所有,所以这里就不贴代码了。异步log的最终效果能达到140M/s的输出速率。

最近不顺心之事甚多,有离去之意,不过咱还没有到homeless的地步,我就不学某个自视甚高的人去乞讨工作了。

不过,如果你觉得你的公司能给本人合适的发展空间,鄙人非常欢迎的,本人qq3028038055。

如何快速的把日志输出到磁盘上,布布扣,bubuko.com

时间: 2024-10-11 01:16:04

如何快速的把日志输出到磁盘上的相关文章

Log4Qt快速入门——Log4Qt日志输出重定向源码解析

Log4Qt快速入门--Log4Qt日志输出重定向源码解析 一.Appender简介 1.Appender简介 Appender是所有Appender的抽象类,是对记录日志形式的抽象.Log4Qt(Qt4版本)中Appender继承体系如下: 2.Appender接口 virtual Filter *filter() const = 0; virtual QString name() const = 0; virtual Layout *layout() const = 0; virtual b

【原创】日志输出到串口设备导致的问题

问题场景: 测试人员报告,业务 modb 作为 RabbitMQ 的消费者,消费消息的速度非常慢,慢到大约每秒 2 条左右,从而导致 RabbitMQ 的队列中积压了 4000+ 条消息. 排查过程: 先通过 top 命令定位一下 [[email protected]_1 ~]# top -Hp 8177 top - 09:50:33 up 34 min, 8 users, load average: 4.76, 4.32, 3.65 Tasks: 2 total, 0 running, 2 s

Snort日志输出插件详解

Snort是一款老牌的开源入侵检测工具,本文主要讨论他作为日志分析时的各种插件的应用.Snort的日志一般位于:/var/log/snort/目录下.可以通过修改配置文件来设置Snort的报警形式.基于文本的格式.Libpcap格式和数据库是Snort最重要的三种报警形式.本文主要对每种报警形式及其配置进行介绍. 1工作模式及输出插件 Snort拥有3种工作模式,分别为嗅探器模式.分组日志模式与网络入侵检测模式. (1)嗅探器模式 Snort使用Libpcap包捕获库,即TCPDUMP使用的库.

Log4j将不同Package的日志输出到不同的文件

转自:http://www.crazyant.net/1931.html 随着项目规模的越来越大,会不断的引入新的模块,不同的模块都会打印自己的日志,最后就造成日志根本没法查看,比如我自己的项目中,就存在以下这些日志: 接收外界消息的日志.对外发送消息的日志: 后台常驻线程的处理日志: 外部接口访问的参数.返回结果等接口日志: Service访问数据库产生的SQL日志: 这其中,消息日志和后台线程的日志数据量非常庞大,如果所有日志打印在一个文件中,使用tail -f log.log文件,会发现日

log4j日志输出到web项目指定文件夹

感谢 eric2500 的这篇文章:http://www.cxyclub.cn/n/27860/ 摘要:尝试将log4j的文件日志输出到web工程制定目录,遇到了很多问题,最终在eric2500的指导下搞定,下面是记录. 其原理在于log4j的配置文件支持服务器的vm的环境变量,如${oss.log4j.path},在log4j加载配置文件之前,先用 System.setProperty("","")设置好日志文件路径,这一操作通过一个初始的servlet来实现.

Qt之日志输出文件

来源:http://blog.sina.com.cn/s/blog_a6fb6cc90101guc5.html 在Qt开发过程当中经常使用qDebug等一些输出来调试程序,但是到了正式发布的时候,都会被注释或者删除,采用日志输出来代替. 做过项目的童鞋可能都使用过日志功能,以便有异常错误能够快速跟踪.定位,Qt也提供的类似的机制.之前用Qt4做项目时使用的是Qt::qInstallMsgHandler(),到了Qt5,使用了新的Qt::qInstallMessageHandler()来替代,详情

理解正确的日志输出级别

原文链接:http://macrochen.iteye.com/blog/1399082 很多程序员都忽略了日志输出级别, 甚至不知道如何指定日志的输出级别. 相对于System.out来说, 日志框架有两个最大的优点就是可以指定输出类别(category)和级别(level). 对于日志输出级别来说, 下面是我们应该记住的一些原则:ERROR:系统发生了严重的错误, 必须马上进行处理, 否则系统将无法继续运行. 比如, NPE, 数据库不可用等. WARN:系统能继续运行, 但是必须引起关注.

Android 项目Log日志输出优化

概述 Android开发过程中经常需要向控制台输出日志信息,有些人还在用Log.i(tag,msg)的形式或者system.out.println(msg)方式吗?本篇文章对日志信息输出进行优化,以达到快速定位输出日志位置及输出规范日志的效果.日志输出行展示调用输出日志信息在哪个文件的第几行,并且可以和点击跳转到对应位置的作用. 输出日志的一般形式 1.在项目中直接调用Log.i(tag,msg)或者println函数,这是初级开发者的做法,不便于后期维护与统一控制. 2.在项目中对输出操作进行

Log4Qt快速入门——Log4Qt日志格式化源码解析

Log4Qt快速入门--Log4Qt日志格式化源码解析 一.Layout 1.Layout简介 Log4Qt提供了多种Layout对象,用于格式化日志输出,指定日志级别.线程名称.Logger名称.日期时间等信息.Layout类是Log4Qt API中的抽象类.PatternLayout:根据一个模式字符串输出日志事件:SimpleLayout:输出日志事件的级别和消息:TTCCLayout:输出日志事件的时间.线程名称.Logger名称和嵌套的诊断上下文信息.PatternLayout和TTC