Nx C++程序使用spdlog库进行日志存储
创始人
2024-03-17 14:22:17
0

1 spdlog简介

spdlog是一个开源的日志库,在github上有。代码见这里,文档这里

C++语言的,支持Linux、windows等系统。
csdn上也有许多介绍,这里列举两个:1、2

2 使用

2.1下载编译链接

有多种使用方式,这里介绍下,将源代码直接链接编译的方式:代码见这里
下载后,在Nx的QtCreator中,将Include中的代码放到代码下,然后,在pro文件中加入定义:SPDLOG_COMPILED_LIB,如下图所示。
在这里插入图片描述

2.2 使用的例子

官方的一个使用的例子,这里贴出来,可以参考。
ps:在下载文件的example文件下有。

//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)// spdlog usage example#include 
#include void load_levels_example();
void stdout_logger_example();
void basic_example();
void rotating_example();
void daily_example();
void async_example();
void binary_example();
void vector_example();
void stopwatch_example();
void trace_example();
void multi_sink_example();
void user_defined_example();
void err_handler_example();
void syslog_example();
void udp_example();
void custom_flags_example();
void file_events_example();
void replace_default_logger_example();#include "spdlog/spdlog.h"
#include "spdlog/cfg/env.h"  // support for loading levels from the environment variable
#include "spdlog/fmt/ostr.h" // support for user defined typesint main(int, char *[])
{// Log levels can be loaded from argv/env using "SPDLOG_LEVEL"load_levels_example();spdlog::info("Welcome to spdlog version {}.{}.{}  !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH);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("{:>8} aligned, {:<8} aligned", "right", "left");// Runtime log levelsspdlog::set_level(spdlog::level::info); // Set global log level to infospdlog::debug("This message should not be displayed!");spdlog::set_level(spdlog::level::trace); // Set specific logger's log levelspdlog::debug("This message should be displayed..");// Customize msg format for all loggersspdlog::set_pattern("[%H:%M:%S %z] [%^%L%$] [thread %t] %v");spdlog::info("This an info message with custom format");spdlog::set_pattern("%+"); // back to default formatspdlog::set_level(spdlog::level::info);// Backtrace support// Loggers can store in a ring buffer all messages (including debug/trace) for later inspection.// When needed, call dump_backtrace() to see what happened:spdlog::enable_backtrace(10); // create ring buffer with capacity of 10  messagesfor (int i = 0; i < 100; i++){spdlog::debug("Backtrace message {}", i); // not logged..}// e.g. if some error happened:spdlog::dump_backtrace(); // log them now!try{stdout_logger_example();basic_example();rotating_example();daily_example();async_example();binary_example();vector_example();multi_sink_example();user_defined_example();err_handler_example();trace_example();stopwatch_example();udp_example();custom_flags_example();file_events_example();replace_default_logger_example();// Flush all *registered* loggers using a worker thread every 3 seconds.// note: registered loggers *must* be thread safe for this to work correctly!spdlog::flush_every(std::chrono::seconds(3));// Apply some function on all registered loggersspdlog::apply_all([&](std::shared_ptr l) { l->info("End of example."); });// Release all spdlog resources, and drop all loggers in the registry.// This is optional (only mandatory if using windows + async log).spdlog::shutdown();}// Exceptions will only be thrown upon failed logger or sink construction (not during logging).catch (const spdlog::spdlog_ex &ex){std::printf("Log initialization failed: %s\n", ex.what());return 1;}
}#include "spdlog/sinks/stdout_color_sinks.h"
// or #include "spdlog/sinks/stdout_sinks.h" if no colors needed.
void stdout_logger_example()
{// Create color multi threaded logger.auto console = spdlog::stdout_color_mt("console");// or for stderr:// auto console = spdlog::stderr_color_mt("error-logger");
}#include "spdlog/sinks/basic_file_sink.h"
void basic_example()
{// Create basic file logger (not rotated).auto my_logger = spdlog::basic_logger_mt("file_logger", "logs/basic-log.txt", true);
}#include "spdlog/sinks/rotating_file_sink.h"
void rotating_example()
{// Create a file rotating logger with 5mb size max and 3 rotated files.auto rotating_logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
}#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 daily_logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
}#include "spdlog/cfg/env.h"
void load_levels_example()
{// Set the log level to "info" and mylogger to "trace":// SPDLOG_LEVEL=info,mylogger=trace && ./examplespdlog::cfg::load_env_levels();// or from command line:// ./example SPDLOG_LEVEL=info,mylogger=trace// #include "spdlog/cfg/argv.h" // for loading levels from argv// spdlog::cfg::load_argv_levels(args, argv);
}#include "spdlog/async.h"
void async_example()
{// Default thread pool settings can be modified *before* creating the async logger:// spdlog::init_thread_pool(32768, 1); // queue with max 32k items 1 backing thread.auto async_file = spdlog::basic_logger_mt("async_file_logger", "logs/async_log.txt");// alternatively:// auto async_file = spdlog::create_async("async_file_logger", "logs/async_log.txt");for (int i = 1; i < 101; ++i){async_file->info("Async message #{}", i);}
}// Log binary data as hex.
// Many types of std::container types can be used.
// Iterator ranges are supported too.
// Format flags:
// {:X} - print in uppercase.
// {:s} - don't separate each byte with space.
// {:p} - don't print the position on each line start.
// {:n} - don't split the output to lines.#include "spdlog/fmt/bin_to_hex.h"
void binary_example()
{std::vector buf(80);for (int i = 0; i < 80; i++){buf.push_back(static_cast(i & 0xff));}spdlog::info("Binary example: {}", spdlog::to_hex(buf));spdlog::info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10));// more examples:// logger->info("uppercase: {:X}", spdlog::to_hex(buf));// logger->info("uppercase, no delimiters: {:Xs}", spdlog::to_hex(buf));// logger->info("uppercase, no delimiters, no position info: {:Xsp}", spdlog::to_hex(buf));// logger->info("hexdump style: {:a}", spdlog::to_hex(buf));// logger->info("hexdump style, 20 chars per line {:a}", spdlog::to_hex(buf, 20));
}// Log a vector of numbers
#ifndef SPDLOG_USE_STD_FORMAT
#    include "spdlog/fmt/ranges.h"
void vector_example()
{std::vector vec = {1, 2, 3};spdlog::info("Vector example: {}", vec);
}#else
void vector_example() {}
#endif// ! DSPDLOG_USE_STD_FORMAT// Compile time log levels.
// define SPDLOG_ACTIVE_LEVEL to required level (e.g. SPDLOG_LEVEL_TRACE)
void trace_example()
{// trace from default loggerSPDLOG_TRACE("Some trace message.. {} ,{}", 1, 3.23);// debug from default loggerSPDLOG_DEBUG("Some debug message.. {} ,{}", 1, 3.23);// trace from logger objectauto logger = spdlog::get("file_logger");SPDLOG_LOGGER_TRACE(logger, "another trace message");
}// stopwatch example
#include "spdlog/stopwatch.h"
#include 
void stopwatch_example()
{spdlog::stopwatch sw;std::this_thread::sleep_for(std::chrono::milliseconds(123));spdlog::info("Stopwatch: {} seconds", sw);
}#include "spdlog/sinks/udp_sink.h"
void udp_example()
{spdlog::sinks::udp_sink_config cfg("127.0.0.1", 11091);auto my_logger = spdlog::udp_logger_mt("udplog", cfg);my_logger->set_level(spdlog::level::debug);my_logger->info("hello world");
}// A logger with multiple sinks (stdout and file) - each with a different format and log level.
void multi_sink_example()
{auto console_sink = std::make_shared();console_sink->set_level(spdlog::level::warn);console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");auto file_sink = std::make_shared("logs/multisink.txt", true);file_sink->set_level(spdlog::level::trace);spdlog::logger logger("multi_sink", {console_sink, file_sink});logger.set_level(spdlog::level::debug);logger.warn("this should appear in both console and file");logger.info("this message should not appear in the console, only in the file");
}// User defined types logging
struct my_type
{int i = 0;explicit my_type(int i): i(i){};
};#ifndef SPDLOG_USE_STD_FORMAT // when using fmtlib
template<>
struct fmt::formatter : fmt::formatter
{auto format(my_type my, format_context &ctx) -> decltype(ctx.out()){return format_to(ctx.out(), "[my_type i={}]", my.i);}
};#else // when using std::format
template<>
struct std::formatter : std::formatter
{auto format(my_type my, format_context &ctx) -> decltype(ctx.out()){return format_to(ctx.out(), "[my_type i={}]", my.i);}
};
#endifvoid user_defined_example()
{spdlog::info("user defined type: {}", my_type(14));
}// Custom error handler. Will be triggered on log failure.
void err_handler_example()
{// can be set globally or per logger(logger->set_error_handler(..))spdlog::set_error_handler([](const std::string &msg) { printf("*** Custom log error handler: %s ***\n", msg.c_str()); });
}// syslog example (linux/osx/freebsd)
#ifndef _WIN32
#    include "spdlog/sinks/syslog_sink.h"
void syslog_example()
{std::string ident = "spdlog-example";auto syslog_logger = spdlog::syslog_logger_mt("syslog", ident, LOG_PID);syslog_logger->warn("This is warning that will end up in syslog.");
}
#endif// Android example.
#if defined(__ANDROID__)
#    include "spdlog/sinks/android_sink.h"
void android_example()
{std::string tag = "spdlog-android";auto android_logger = spdlog::android_logger_mt("android", tag);android_logger->critical("Use \"adb shell logcat\" to view this message.");
}
#endif// Log patterns can contain custom flags.
// this will add custom flag '%*' which will be bound to a  instance
#include "spdlog/pattern_formatter.h"
class my_formatter_flag : public spdlog::custom_flag_formatter
{
public:void format(const spdlog::details::log_msg &, const std::tm &, spdlog::memory_buf_t &dest) override{std::string some_txt = "custom-flag";dest.append(some_txt.data(), some_txt.data() + some_txt.size());}std::unique_ptr clone() const override{return spdlog::details::make_unique();}
};void custom_flags_example()
{using spdlog::details::make_unique; // for pre c++14auto formatter = make_unique();formatter->add_flag('*').set_pattern("[%n] [%*] [%^%l%$] %v");// set the new formatter using spdlog::set_formatter(formatter) or logger->set_formatter(formatter)// spdlog::set_formatter(std::move(formatter));
}void file_events_example()
{// pass the spdlog::file_event_handlers to file sinks for open/close log file notificationsspdlog::file_event_handlers handlers;handlers.before_open = [](spdlog::filename_t filename) { spdlog::info("Before opening {}", filename); };handlers.after_open = [](spdlog::filename_t filename, std::FILE *fstream) {spdlog::info("After opening {}", filename);fputs("After opening\n", fstream);};handlers.before_close = [](spdlog::filename_t filename, std::FILE *fstream) {spdlog::info("Before closing {}", filename);fputs("Before closing\n", fstream);};handlers.after_close = [](spdlog::filename_t filename) { spdlog::info("After closing {}", filename); };auto file_sink = std::make_shared("logs/events-sample.txt", true, handlers);spdlog::logger my_logger("some_logger", file_sink);my_logger.info("Some log line");
}void replace_default_logger_example()
{// store the old logger so we don't break other examples.auto old_logger = spdlog::default_logger();auto new_logger = spdlog::basic_logger_mt("new_default_logger", "logs/new-default-log.txt", true);spdlog::set_default_logger(new_logger);spdlog::set_level(spdlog::level::info);spdlog::debug("This message should not be displayed!");spdlog::set_level(spdlog::level::trace);spdlog::debug("This message should be displayed..");spdlog::set_default_logger(old_logger);
}

2.3 我的一个例子

    auto console_sink = std::make_shared();console_sink->set_level(spdlog::level::warn);console_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e %^%l%$] %v");//循环日志文件,每个10M,最多10个文件auto file_sink = std::make_shared("logs/Log.txt", 1048576 * 10, 10);file_sink->set_level(spdlog::level::trace);file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e %L] %v");spdlog::logger * pLogger = new spdlog::logger("multi_sink", {console_sink, file_sink});pLogger->set_level(spdlog::level::debug);// Flush all *registered* loggers using a worker thread every 3 seconds.// note: registered loggers *must* be thread safe for this to work correctly!spdlog::flush_every(std::chrono::seconds(3));			//定时刷新

2.4 关于循环日志文件

上面的文件中有了,补充下多个文件时候的关系。
当前写的文件为Log.txt,一旦写满后,将其更名为Log.1.txt。再新建一个Log.txt,写入
如果新Log.txt再次满后,将Log.1.txt更名为Log.2.txt。将Log.txt更名为Log.1.txt,然后再新建一个Log.txt写入。

2.5 关于设置日志格式

这里有官方说明:https://github.com/gabime/spdlog/wiki/3.-Custom-formatting

2.6 关于头文件

这里面有很多头文件,使用不同功能需要引入不同的功能,见上面的例子吧,这点确实麻烦。

2.7 关于输出

保存的日志文件时,有一个刷新的机制。可以设置定时更新。如下。这里实际使用时候,除了定时外,貌似跟数据量也有关系,如果数据量少时候,也不输出!
具体见:https://github.com/gabime/spdlog/wiki/7.-Flush-policy

spdlog::flush_every(std::chrono::seconds(3));			//定时刷新

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...