spdLog的使用

spdLog的使用以下为收集到或者个人测试的内容,侵权删一.优点非常快使用自带的例子测试写log,利用次数/时钟周期衡量结果*******************************************************************************Singlethread,1,000,000iteration

大家好,又见面了,我是你们的朋友全栈君。

以下为收集到或者个人测试的内容,侵权删

一.优点

  • 非常快

    使用自带的例子测试写log,利用 次数/时钟周期 衡量结果
    *******************************************************************************
    Single thread, 1,000,000 iterations
    *******************************************************************************
    rotating_st...        1,464,366/sec
    daily_st...           1,377,742/sec
    null_st...            1,621,649/sec
    *******************************************************************************
    10 threads sharing same logger, 1,000,000 iterations
    *******************************************************************************
    rotating_mt...        1,165,635/sec
    daily_mt...           1,151,680/sec
    null_mt...            1,512,478/sec
    *******************************************************************************
    async logging.. 10 threads sharing same logger, 1,000,000 iterations
    *******************************************************************************
    as...                 3,901,457/sec
    as...                 6,977,551/sec
    as...                 7,005,095/sec

  • 只包含头文件
     (spdlog/spdlog.h —> spdlog , spdlog/fmt/bundled/format.h —> pattern_formatter)
  • 无需依赖第三方库
  • 支持跨平台 – Linux / Windows on 32/64 bits
  • 支持多线程

    单线程和多线程主要在锁的定义上不一样
    typedefrotating_file_sink<std::mutex> rotating_file_sink_mt;
    typedefrotating_file_sink<details::null_mutex>rotating_file_sink_st;
    其中 details::null_mutex 定义为:
    structnull_mutex
    {
        voidlock() {}
        voidunlock() {}
        booltry_lock()
        {
            returntrue;
        }
    };

  • 可对日志文件进行循环输出
     (指的是可以用 rotating_file_sink结构在 log_1,log_2,log_3 等几个文件中循环迭代,在不产生新的文件的情况下更新后面的文件)

    // Rotate files:
    // log.txt -> log.1.txt
    // log.1.txt -> log2.txt
    // log.2.txt -> log3.txt
    // log.3.txt -> delete

  • 可每日生成日志文件
    daily_file_sink 每天定时产生文件日志
  • 支持控制台日志输出
  • 可选的异步日志
  • 支持日志输出级别
  • 可自定义日志格式

二.基本使用

1.直接打印日志到console

auto console1 = spd::stdout_logger_mt("console1");
console1->error("Some error message with arg{}..", 1);
 
//console2 的module 名字不可以和以前的重复,创建的日志名字为 basic_log
auto console2 = spd::basic_logger_mt("basic_logger","./basic_log");
console2->info("Some log message");
 
//通过module名字获取到对应的log指针
spd::get("console2")->info("get console by name");
 
//设置日志等级
spd::set_level(spd::level::info);//Set global log level to info
console1->debug("This message shold not be displayed!");
console1->set_level(spd::level::debug);// Set specific logger's log level
console1->debug("This message shold be displayed..");

2.每天更新一个log文件(带秒数)

//创建文件名类似于: daily_log_2018-01-17_10-27.txt,如果程序不退出的话,就是每天2:30 am创建新的文件       
auto console3 =  spd::daily_logger_mt("daily_logger","./daily_log", 2, 30);
console3->flush_on(spd::level::debug);
console3->info("test daily info");
console3->error("test daily error")

        如果想在文件名里只关心天数,可以使用这个,这样的好处是,同一天多次运行一个程序,可以把log写到同一个文件里面去,测试了不会覆盖以前的内容

//创建文件名类似于: log_2018-01-17.txt
typedefspdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::dateonly_daily_file_name_calculator> dateonly_daily_file_sink_mt;
auto m_logger = spdlog::create<dateonly_daily_file_sink_mt>("logger","log","txt", 0, 0);
m_logger->info("test daily info");
m_logger->error("test daily error");

3.日志太多的时候,当前文件重命名_1,_2,_3.再写新的文件

//日志文件名为
//-rw-rw-r-- 1 ski ski    962 Jan 17 10:48 mylogfile_log.1.txt
//-rw-rw-r-- 1 ski ski    962 Jan 17 10:48 mylogfile_log.2.txt
//-rw-rw-r-- 1 ski ski    962 Jan 17 10:48 mylogfile_log.3.txt
//-rw-rw-r-- 1 ski ski    370 Jan 17 10:48 mylogfile_log.txt
 
auto rotating_logger = spd::rotating_logger_mt("rotate_log","./mylogfile_log", 1024, 3);
for (int i = 0; i < 1000; ++i)
    rotating_logger->info("{} * {} equals {:>10}", i, i, i*i);

4.flush_on命令

//遇到错误及以上级别会立马将缓存的buffer写到文件中,底层调用是std::fflush(_fd)
m_logger->flush_on(spd::level::err);

5.关闭所有的log handler

// Release and close all loggers 把所有的log对象智能指针放置到unordered_map中去,然后调用clear函数
spdlog::drop_all();

 三.源码阅读

spdlog支持多线程的,想看看其中是怎么控制同步的,实现多线程的一个接口:
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);

点进去:

inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
{
    return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
}

继续:

typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;

所有的sinks类都是继承sinks类的,这里是从rotating_file_sink->base_sink->sink继承而来的。

template<class Mutex>
class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex >

看看base_sinks类中的两个关键log函数:

template<class Mutex>
class base_sink:public sink
{
    void log(const details::log_msg& msg) SPDLOG_FINAL override
    {
        std::lock_guard<Mutex> lock(_mutex);
        _sink_it(msg);
    }
    void flush() SPDLOG_FINAL override
    {
        std::lock_guard<Mutex> lock(_mutex);
        _flush();
    }
在这里是根据锁的类型不同而实现多线程和单线程的区别,多线程的锁可以使用正常的锁机制来使用,那么,单线程的使用呢? 开始查看details::null_mutex的定义:
struct null_mutex
{
    void lock() {}
    void unlock() {}
    bool try_lock()
    {
        return true;
    }
};

其实,他是使用了一个类去模拟锁的函数,但是里面什么也不做,这样就可以与多线程情况下使用同样的代码了,提升了代码效率。值得借鉴


其他:

参考网址:

1.spdLog官网

2.spdLog源码阅读

 主要包括三页内容:

        sink介绍(base_sink, rotating_file_sink,另外还有 daily_file_sink)

        sink创建和使用(稍微介绍了下单例模式)

        log_msg的原理介绍(缓冲区存储日志内容)

3.spdLog使用example

        这是spdLog自带的一个example,教你如何使用sink去写log

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152329.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql修改数据类型_MySQL修改字段类型[通俗易懂]

    mysql修改数据类型_MySQL修改字段类型[通俗易懂]mysql>altertable表名modifycolumn字段名类型。数据库中address表city字段是varchar(30),修改类型可以用(谨慎修改类型,可能会导致原有数据出错)。mysql>altertableaddressmodifycolumncitychar(30);修改长度可以用(修改长度,要保证不短与已有数据,以保证原有数据不出错)m…

    2022年6月11日
    45
  • touchstart与click同时触发

    touchstart与click同时触发产生冲突的原因我们可以给某个元素同时绑定touchstart和click事件,但这将会导致本篇文章解决的问题–这两个事件在移动设备上会发生冲突。由于移动设备能够同时识别touchstart和click事件,因此当用户点击目标元素时,绑定在目标元素上的touchstart事件与click事件(约300ms后)会依次被触发,也就是说,我们所绑定的回调函数会被执行两次!。…

    2022年6月19日
    120
  • docker镜像操作_docker 本地镜像

    docker镜像操作_docker 本地镜像前言Docker的三大核心概念:镜像、容器、仓库。初学者对镜像和容器往往分不清楚,学过面向对象的应该知道类和实例,这跟面向对象里面的概念很相似我们可以把镜像看作类,把容器看作类实例化后的对象。|

    2022年7月31日
    10
  • 数据库的简介与类型

    数据库的简介与类型数据库的简介与类型

    2022年4月22日
    38
  • Handler、HandlerThread理解

    Handler、HandlerThread理解Handler在android线程编程中非常常见。线程中的handler使用原理:每个线程只有一个Looper来管理消息队列,handler在使用的时候需要绑定到对应的Looper上。Handler给自己绑定的Looper不断的发送消息,Looper来做死循环来不断读取MessageQueue队列中的消息,发送给handler来进行处理。 Android的UI是运行在主线程中,主线程是用MainL…

    2022年7月14日
    20
  • redis主从复制原理是同步还是异步_kubernetes高可用架构

    redis主从复制原理是同步还是异步_kubernetes高可用架构史上最全的MySQL高可用架构之【主从复制】【故障转移】【读写分离】【负载均衡】

    2022年8月13日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号