C++ log library combat-spdlog, do you feel that log4cxx is a bit cumbersome, might as well try spdlog

background

Under the recommendation of a new colleague recently, the author has learned and used spdlog in a small tool, and it has been posted to run online. The following is the learning record.

What is spdlog


According to the official introduction, Fast C++ logging library is a high-performance C++ logging component that supports cross-platform and is compatible with C++11. Log4cxx was used in the original project, I felt a little cumbersome, and I haven't updated it for a long time.

In a new project, I only need a lightweight log component that can:

  • Save file
  • Divide according to the number of days

I quickly browsed the spdlog and met my needs, so I started!

Quick start with spdlog

githubhttps://github.com/gabime/spdlog

The following content is from the README of spdlog

Compile

$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && make -j

PS: Use cmake to compile, cmake command will generate makefile. If there is no cmake on the machine, please install it first, my cmake3.14.5 , macos 10.15 ,

meki-mac-pro:~ xuyc$ cmake -version
cmake version 3.14.5

CMake suite maintained and supported by Kitware (kitware.com/cmake).

use

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

int main() 
{
    
    
    spdlog::info("Welcome to spdlog!");
    spdlog::error("Some error message with arg: {}", 1);
    
    spdlog::warn("Easy padding in numbers like {:08d}", 12);
    spdlog::critical("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);
    spdlog::info("Support for floats {:03.2f}", 1.23456);
    spdlog::info("Positional args are {1} {0}..", "too", "supported");
    spdlog::info("{:<30}", "left aligned");
    
    spdlog::set_level(spdlog::level::debug); // Set global log level to debug
    spdlog::debug("This message should be displayed..");    
    
    // change log pattern
    spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
    
    // Compile time log levels
    // define SPDLOG_ACTIVE_LEVEL to desired level
    SPDLOG_TRACE("Some trace message with param {}", 42);
    SPDLOG_DEBUG("Some debug message");
    
    // Set the default logger to file logger
    auto file_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
    spdlog::set_default_logger(file_logger);            
}

The official code probably knows how to use spdlog, please give me a thumbs up. However, some problems may be encountered. The following is a record of the problems encountered by the author.

common problem

Print line number

// 先设置日志输出格式
// %s:文件名,my_file.cpp
// %#:行号,123
// %!:函数名,my_func
spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");

// 使用宏才会有行号
SPDLOG_DEBUG("Some debug message");

spdlog::info("Welcome to spdlog!");

For details, see: https://github.com/gabime/spdlog/wiki/3.-Custom-formatting

Recommended writing :

#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__)

DEBUG("debug");
LOG("info");

Why can't the console see log

Just set the default logger as the console

// 设置默认logger,这里是控制台,所以spdlog::info的内容会输出到控制台
auto console = spdlog::stdout_color_mt("console");
spdlog::set_default_logger(console);

Official code

#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
void stdout_example()
{
    
    
    // create color multi threaded logger
    auto console = spdlog::stdout_color_mt("console");    
    //auto err_logger = spdlog::stderr_color_mt("stderr");    
    spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
}

Output console and file at the same time

  1. Register first
// 每天2:30 am 新建一个日志文件
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
// 遇到warn flush日志,防止丢失
logger->flush_on(spdlog::level::warn);
  1. Use the macro to output the console and file at the same time, pay attention to the logger name and the above corresponding.
// spd 带行号的打印,同时输出console和文件
#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_DEBUG(spdlog::get("daily_logger"), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_INFO(spdlog::get("daily_logger"), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_WARN(spdlog::get("daily_logger"), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_ERROR(spdlog::get("daily_logger"), __VA_ARGS__)

File is divided by day

#include "spdlog/sinks/daily_file_sink.h"
void daily_example()
{
    
    
    // Create a daily logger - a new file is created every day on 2:30am
    auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
}

Stop debugging log without writing files?

In order to improve performance and reduce write operations to disks, spdlog uses the flush mechanism to write logs to files for persistence at one time. So if there is no proper configuration , there will be a log loss problem when debugging is stopped or the process crashes.

Flush to the file regularly:

//每三秒刷新一次
spdlog::flush_every(std::chrono::seconds(3));

When the error level is encountered, flush to the file immediately:

enum level_enum
{
    
    
    trace = SPDLOG_LEVEL_TRACE, // 最低
    debug = SPDLOG_LEVEL_DEBUG,
    info = SPDLOG_LEVEL_INFO,
    warn = SPDLOG_LEVEL_WARN,
    err = SPDLOG_LEVEL_ERROR,
    critical = SPDLOG_LEVEL_CRITICAL, // 最高
    off = SPDLOG_LEVEL_OFF,
    n_levels
};

auto logger = spdlog::daily_logger_mt("daily_logger", "log/daily.txt", 2, 30);
// 遇到warn或者更高级别,比如err,critical 立即flush日志,防止丢失
logger->flush_on(spdlog::level::warn);

Complete code

// spdlog
#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include <iostream>
#include <memory>

// spd 带行号的打印,同时输出console和文件
#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_DEBUG(spdlog::get("daily_logger"), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_INFO(spdlog::get("daily_logger"), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_WARN(spdlog::get("daily_logger"), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_ERROR(spdlog::get("daily_logger"), __VA_ARGS__)

int main(int argc, char *argv[]) {
    
    
    // 按文件大小
    //auto file_logger = spdlog::rotating_logger_mt("file_log", "log/log.log", 1024 * 1024 * 100, 3);
    // 每天2:30 am 新建一个日志文件
    auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
    // 遇到warn flush日志,防止丢失
    logger->flush_on(spdlog::level::warn);
    //每三秒刷新一次
    spdlog::flush_every(std::chrono::seconds(3));
    
    // Set the default logger to file logger
    auto console = spdlog::stdout_color_mt("console");
    spdlog::set_default_logger(console);
    spdlog::set_level(spdlog::level::debug); // Set global log level to debug

    // change log pattern
    // %s:文件名
    // %#:行号
    // %!:函数名
    spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");

    LOG("test info");
    ERROR("test error");
    
    // Release and close all loggers
    spdlog::drop_all();
}

Console output

/Users/xuyc/repo/sd_linux/cmake-build-debug/sd_linux
[2020-04-30 16:14:41.816] [console] [info] [main.cpp:608] test info
[2020-04-30 16:14:41.816] [console] [error] [main.cpp:609] test error

Process finished with exit code 0

file
Insert picture description here

appendix

It is said that only the header file is needed on the Internet, but I still link it. . .

CMakeList.txt

cmake_minimum_required(VERSION 3.15)
project(sd_linux)

set(CMAKE_CXX_STANDARD 14)
AUX_SOURCE_DIRECTORY(./ SRC_LIST)
AUX_SOURCE_DIRECTORY(./jsoncpp SRC_LIST)

// 包含spdlog的头文件
INCLUDE_DIRECTORIES(./jsoncpp ./spdlog/include)
// 包含spdlog的动态库目录
LINK_DIRECTORIES(./ ./spdlog/build)

add_executable(sd_linux ${
    
    SRC_LIST})

// 链接spdlog动态库
TARGET_LINK_LIBRARIES(sd_linux curl iconv spdlog)

on

Recommend your own open source IM, written in pure Golang:

CoffeeChat:
https://github.com/xmcy0011/CoffeeChat
opensource im with server(go) and client(flutter+swift)

Refer to well-known projects such as TeamTalk and Guazi IM, including server (go) and client (flutter), single chat and robot (Xiaowei, Turing, Sizhi) chat functions have been completed, and group chat functions are currently being developed. Welcome Star, who is interested in golang and cross-platform development of flutter technology, pay more attention.

————————————————
Copyright statement: This article is the original article of CSDN blogger "Xu Fei", and it follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this for reprinting. statement.
Original link: https://blog.csdn.net/xmcy001122/article/details/105665732

Guess you like

Origin blog.csdn.net/xmcy001122/article/details/105864473