使用spdlog写一个宏定义,输出error,info灯
时间: 2024-04-30 19:21:24 浏览: 77
以下是使用spdlog库定义输出error和info灯的宏定义:
```cpp
#include "spdlog/spdlog.h"
#define LOG_ERROR(msg) spdlog::error("[ERROR] {}", msg)
#define LOG_INFO(msg) spdlog::info("[INFO] {}", msg)
```
使用方法:
```cpp
int main()
{
LOG_ERROR("Something went wrong!");
LOG_INFO("The program has started.");
return 0;
}
```
输出结果:
```
[2021-09-25 15:38:32.350] [error] [logger_example.cpp:5] [ERROR] Something went wrong!
[2021-09-25 15:38:32.350] [info] [logger_example.cpp:6] [INFO] The program has started.
```
注意:要在程序中先初始化spdlog库,可以参考spdlog的官方文档进行初始化。
相关问题
#ifndef MYSPDLOG_H #define MYSPDLOG_H #include <fstream> #include <iostream> #define SPDLOG_HEADER_ONLY #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #include "spdlog/spdlog.h" #include "spdlog/logger.h" #include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/sinks/stdout_color_sinks.h" #include "spdlog/sinks/daily_file_sink.h" class MySpdlog { public: static MySpdlog*getInstace() { static MySpdlog MySpdlogStatic; return &MySpdlogStatic; } int init() { std::string formatStr="%Y-%m-%dT%H:%M:%S.%e[%l][%s:%#][%!]%v"; // auto myLogger1 = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("spdlog", "logs/myspdlog.log", 1024 * 1024 * 10, 10); // auto myLogger1 = std::make_shared<spdlog::sinks::daily_file_sink>("spdlog", "logs/log.txt", 0, 0); auto myLogger1 = spdlog::daily_logger_mt("spdlog", "logs/log.txt", 0, 0); // myLogger1 = spdlog::rotating_logger_mt("spdlog", "logs/myspdlog.log", 1024 * 1024 * 10, 10); spdlog::set_default_logger(myLogger1); myLogger1->set_level(spdlog::level::debug); myLogger1->set_pattern(formatStr); myLogger2 = spdlog::stdout_color_mt("baseLogger2"); spdlog::set_default_logger(myLogger2); myLogger2->set_level(spdlog::level::debug); myLogger2->set_pattern(formatStr); return 0; } void uninit() { } std::shared_ptr<spdlog::logger> myLogger1; std::shared_ptr<spdlog::logger> myLogger2; private: MySpdlog() {} ~MySpdlog() {} }; #define SPLOG_INIT() MySpdlog::getInstace()->init() #define SPLOG_UNINIT() MySpdlog::getInstace()->uninit() #define SPLOG_DEBUG(...) do {SPDLOG_LOGGER_DEBUG(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\ SPDLOG_LOGGER_DEBUG(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0) #define SPLOG_INFO(...) do {SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\ SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0) #define SPLOG_ERROR(...) do {SPDLOG_LOGGER_ERROR(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\ SPDLOG_LOGGER_ERROR(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0) #define SPDLOG_CLRAR(a) do{std::fstream fout((a),std::ios::out|std::ios::trunc);fout.close();}while(0); #endif // MYSPDLOG_H运行之后调用SPLOG_INFO时报错
根据您提供的代码,我看到您定义了一个名为`SPLOG_INFO`的宏,其实现方式为:
```
#define SPLOG_INFO(...) do {SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger1, __VA_ARGS__);\
SPDLOG_LOGGER_INFO(MySpdlog::getInstace()->myLogger2, __VA_ARGS__);}while(0)
```
这个宏展开后会调用`SPDLOG_LOGGER_INFO`来输出日志信息,而`SPDLOG_LOGGER_INFO`需要传入一个有效的logger对象作为第一个参数。在您的代码中,您定义了一个名为`myLogger1`的logger对象,但是您没有在宏中使用它,而是在`MySpdlog`类中以成员变量的形式定义。因此,当您调用`SPLOG_INFO`时,会找不到有效的logger对象,从而导致编译错误。
要解决这个问题,您可以将`myLogger1`和`myLogger2`定义为静态成员变量,并在`MySpdlog`类外初始化它们。然后,在宏中使用这两个静态成员变量。
例如,您可以将`MySpdlog`类的定义改为:
```
class MySpdlog {
public:
static MySpdlog*getInstace()
{
static MySpdlog MySpdlogStatic;
return &MySpdlogStatic;
}
int init()
{
std::string formatStr="%Y-%m-%dT%H:%M:%S.%e[%l][%s:%#][%!]%v";
auto myLogger1 = spdlog::daily_logger_mt("spdlog", "logs/log.txt", 0, 0);
spdlog::set_default_logger(myLogger1);
myLogger1->set_level(spdlog::level::debug);
myLogger1->set_pattern(formatStr);
auto myLogger2 = spdlog::stdout_color_mt("baseLogger2");
spdlog::set_default_logger(myLogger2);
myLogger2->set_level(spdlog::level::debug);
myLogger2->set_pattern(formatStr);
return 0;
}
void uninit()
{
}
static std::shared_ptr<spdlog::logger> myLogger1;
static std::shared_ptr<spdlog::logger> myLogger2;
private:
MySpdlog() {}
~MySpdlog() {}
};
std::shared_ptr<spdlog::logger> MySpdlog::myLogger1;
std::shared_ptr<spdlog::logger> MySpdlog::myLogger2;
```
然后,您可以在代码的其他地方使用这两个静态成员变量。例如,在`SPLOG_INFO`中,您可以这样使用:
```
#define SPLOG_INFO(...) \
do { \
SPDLOG_LOGGER_INFO(MySpdlog::myLogger1, __VA_ARGS__); \
SPDLOG_LOGGER_INFO(MySpdlog::myLogger2, __VA_ARGS__); \
} while(0)
```
这样,当您调用`SPLOG_INFO`时,就会使用正确的logger对象输出日志信息,从而避免编译错误。
spdlog 封装一层
### 封装 `spdlog` 日志库
为了简化 `spdlog` 的使用并增强其功能,可以将其核心组件封装在一个统一的头文件中。这不仅减少了重复代码的数量,也使得配置更加集中化和易于维护。
#### 创建全局日志初始化函数
通过创建一个名为 `Log.h` 的头文件,在其中定义必要的宏和初始化函数,可以在项目启动时自动加载预设的日志设置:
```cpp
#ifndef LOG_H_
#define LOG_H_
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
class Log {
public:
static void Init() {
auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
consoleSink->set_pattern("%^[%T] %n: %v%$");
spdlog::init_thread_pool(8192, 1);
auto asyncLogger = std::make_shared<spdlog::async_logger>("console", consoleSink, spdlog::thread_pool(), spdlog::async_overflow_policy::block_retry);
spdlog::register_logger(asyncLogger);
spdlog::flush_on(spdlog::level::info);
spdlog::set_default_logger(asyncLogger);
spdlog::set_level(spdlog::level::debug); // Set global log level to debug.
}
};
#endif /* LOG_H_ */
```
此部分实现了基本的日志记录器初始化工作,并设置了异步模式下的线程池大小以及阻塞策略[^1]。
#### 定义便捷宏以便于调用
为了让开发人员更轻松地访问日志接口,还可以引入一系列简便易记的宏定义:
```cpp
// Add these lines after the previous code block inside Log.h file.
#ifdef NDEBUG
#define LOG_TRACE(...) ((void)0)
#else
#define LOG_TRACE(...) SPDLOG_TRACE(__VA_ARGS__)
#endif
#define LOG_DEBUG(...) SPDLOG_DEBUG(__VA_ARGS__)
#define LOG_INFO(...) SPDLOG_INFO(__VA_ARGS__)
#define LOG_WARN(...) SPDLOG_WARN(__VA_ARGS__)
#define LOG_ERROR(...) SPDLOG_ERROR(__VA_ARGS__)
#define LOG_CRITICAL(...) SPDLOG_CRITICAL(__VA_ARGS__)
```
这些宏允许用户根据不同的编译选项调整最低级别的消息输出级别,从而优化性能或增加调试信息量[^3]。
#### 扩展自定义 Sink 实现特定需求
对于某些特殊应用场景,比如将日志数据保存至数据库或是推送到第三方服务,可以通过继承 `base_sink<T>` 来构建自己的 sink 类型。例如,这里展示了一个简单的例子——向 MySQL 数据库存储日志条目:
```cpp
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/statement.h>
namespace custom {
template<typename MutexType>
class MysqlSink : public spdlog::sinks::base_sink<MutexType> {
private:
sql::Connection* con;
protected:
void _sink_it(const spdlog::details::log_msg& msg) override {
try {
sql::Statement *stmt = this->con->createStatement();
stmt->execute(
"INSERT INTO logs (timestamp,message,severity)"
"VALUES('" +
boost::posix_time::to_iso_string(msg.time) +
"','" +
escapeStringForSQL(msg.payload.data()) +
"'," +
std::to_string(static_cast<int>(msg.level)) + ");"
);
delete stmt;
} catch(sql::SQLException &e){
throw e.what();
}
}
void flush() override {}
public:
explicit MysqlSink(std::string host="localhost",
unsigned int port=3306,
std::string user="root",
std::string password="") :
base_sink<MutexType>() {
sql::Driver *driver = get_driver_instance();
con = driver->connect(host.c_str(), user.c_str(), password.c_str());
con->setSchema("my_database");
}
};
} // namespace custom
```
上述代码片段展示了如何利用 C++ Connector 和 Boost 库来处理 SQL 注入风险的同时完成对 MySQL 表格的操作[^2]。
阅读全文
相关推荐














