c++ 高性能日志库(muduo_AsyncLogging)

实现一个高效的网络日志库要解决那些问题?

首先明确一下问题的模型,这是一个典型的多生产者 单消费者问题,对于前端的日志库使用者来说,应该做到非阻塞添加,作为后端的文件写入,应该注意磁盘IO的瓶颈。

功能需求

  1. 日志的级别分级
  2. 发生时间和具体线程信息
  3. 线程安全

实现思路

多个线程共有一个前端,通过后端写入磁盘文件

异步日志是必须的,所以需要一个缓冲区,在这里我们使用的是多缓冲技术,基本思路是准备多块Buffer,前端负责向Buffer中填数据,后端负责将Buffer中数据取出来写入文件,这种实现的好处在于在新建日志消息的时候不必等待磁盘IO操作,前端写的时候也不会阻塞。

实现结构

LogStream 负责写入消息的格式化

LogFile 负责文件写入

AsyncLogging 负责实现 多缓冲技术 协调前后端

LogFile

LogStream

AsyncLogging

是及实现采用了四个缓冲区,这样可以进一步减少前端等待,数据结构

typedef boost::ptr_vector<LargeBuffer> BufferVector;
typedef BufferVector::auto_type BufferPtr;
MutexLock lock;
Condition cond;
BufferPtr nextBuffer;
BufferVector buffers_;

append的具体实现

在当前的缓冲区和备用缓冲区中选择一个足够使用的进行写入。

void AsynLogging::append(const char* logline, int len){
    LockGuard(mutex);
    if(curbuf->avail() > len){//当前缓冲区足够
        curbuf->append(logline,len);
    }
    else{
        buffers.push_back(curbuf->release());
        if(nextbuf){
            curbuf = std::move(nextbuf);
        }
        else{
            curbuf.reset(new LargeBuffer);
        }
        curbuf->append(logline, len);
        cond.notify();
    }
}
  • 接收方的后端实现

    首先准备好两块空闲的buffer,已备在临界区内交换,等待条件标量出发的条件又两个,超时或者是前端写满了一个或者多个Buffer,当条件满足时,先将当前缓冲移入buffer,并且立刻将空闲的newBuffer1作为当前缓冲,接下来将buffers和buffersToWrite交换,随后将buffersToWrite写入文件,重新设计设置Buffer。

void AsyncLogging::threadFunc(){
    BufferPtr nweBuffer1(new LargeBuffer);
    BufferPtr newBuffer2(new LargeBuffer);
    BufferVector bufferToWrite;
    while(running_){
    {
        MutexLockGuard lock(mutex);
        if(buffers.empty()){
            cond.wait_for(muted,flushInterval_);
        }
        buffers.push_back(currentBuffer_.release());
        currentBuffer = move(newBuffer1);
        buffersTowrite.swap(buffers_);
        if(!nextBuf){
            nextBuf = std::move(newBuffer2);
        }
    }
    }
}

原文地址:https://www.cnblogs.com/joeylee97/p/8886326.html

时间: 2024-12-18 23:36:23

c++ 高性能日志库(muduo_AsyncLogging)的相关文章

golang高性能日志库zap配置示例

zap是uber开源的Go高性能日志库,gitlab地址 安装 go get -u go.uber.org/zap 请注意,zap仅支持两个最新的Go版本. 示例 简单示例 格式化输出 package main import ( "go.uber.org/zap" "time" ) func main() { // zap.NewDevelopment 格式化输出 logger, _ := zap.NewDevelopment() defer logger.Sync

使用SeasLog打造PHP项目中的高性能日志组件(一)

云智慧(北京)科技有限公司 高驰涛 什么是SeasLog SeasLog是一个C语言编写的PHP扩展,提供一组规范标准的功能函数,在PHP项目中方便.规范.高效地写日志,以及快速地读取和查询日志. 为什么使用SeasLog 无论在什么应用中,log日志都是架构中不可缺少的一个重要组成部分,它通常是系统或软件.应用的运行记录.通过log的分析,可以方便用户了解系统或软件.应用的运行情况:如果你的应用log足够丰富,也可以分析以往用户的操作行为.类型喜好.地域分布或其他更多信息:如果一个应用的log

Logan:美团点评的开源移动端基础日志库

前言 Logan是美团点评集团移动端基础日志组件,这个名称是Log和An的组合,代表个体日志服务.同时Logan也是"金刚狼"大叔的名号,当然我们更希望这个产品能像金刚狼大叔一样犀利. Logan已经稳定迭代了一年多的时间.目前美团点评绝大多数App已经接入并使用Logan进行日志收集.上传.分析.近日,我们决定开源Logan生态体系中的存储SDK部分(Android/iOS),希望能够帮助更多开发者合理的解决移动端日志存储收集的相关痛点,也欢迎更多社区的开发者和我们一起共建Logan

Python日志库的用法

日志不管对于开发或者运维都是一项非常重要的东西,它可以用来排错,解决故障,统计分析等. 本文介绍python中的日志库的用法. 日志库:import logging 要用日志需要先定义以下东西: 获取日志名,比如 logging.getLogger(__name__) 定义Handler,比如 logging.FileHandler('/var/log/messages') 设置级别,比如 fh.setLevel(logging.DEBUG) 定义格式,比如 formatter = loggin

YxdJSON - Delphi 高性能 JSON 库(支持RTTI和序列化操作)

Delphi 高性能 JSON 库(支持RTTI和序列化操作) 支持平台: Windows, Android, iOS, Mac OS https://github.com/yangyxd/YxdJson

爆料喽!!!开源日志库Logger的使用秘籍

导读 日志对于开发来说是非常重要的,不管是调试数据查看.bug问题追踪定位.数据信息收集统计,日常工作运行维护等等,都大量的使用到.今天介绍著名开源日志库Logger的使用,库的地址:https://github.com/orhanobut/logger 在Android Studio中的gradle中加入,就可以引用依赖logger库: dependencies { compile 'com.orhanobut:logger:1.15' } Logger库能提供的功能: 线程的信息 类的信息

C++的开源跨平台日志库glog学习研究(一)

作为C++领域中为数不多的好用.高效的.跨平台的日志工具,Google的开源日志库glog也算是凤毛麟角了.glog 是一个C++实现的应用级日志记录框架,提供了C++风格的流操作. 恰巧趁着五一我也学习研究了这个glog库,写个总结如下.走过路过的的各位牛人.高手可以忽略这篇文章了. 从code.google.com下载源码(在这里),在Visual Studio 2010中打开工程,如下: 可见只有四个工程,其中libglog和libglog_static分别是Windows下的动态库和静态

C++的开源跨平台日志库glog学习研究(二)--宏的使用

上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. 日志输出宏 这里我们以一条最简单的日至输出为例说明: LOG(WARNING) << "This is a warning message"; 这里LOG是一个宏,其定义如下(logging.h line 487): #define LOG(severity) COMPACT

Android 开源日志库 Logger 使用教程

转载请注明出处: http://blog.csdn.net/like_program/article/details/52986553 1.Logger 是什么 在我们日常的开发中,肯定是少不了要和 Log 打交道,回想一下我们是怎么使用 Log 的:先定义一个静态常量 TAG,TAG 的值通常是当前类的类名,然后在需要打印 Log 的地方,调用 Log.d(TAG, "要打印的内容").每次新写一个类,都要写一个 TAG,这也就算了,最苦逼的是,项目一上线,还要手动去把每个 Log