如何将自定义记录器与websocketpp一起使用?
How to use custom logger with websocketpp?
我正在使用websocketpp创建一个遥测服务器,并遵循了此处的示例。我的应用程序将作为在启动时启动的 linux 守护程序运行,因此我将无法将日志写入标准输出。因此,我想使用 spdlog 添加一个客户记录器,并了解可以根据此页面上的内容来完成。看起来我需要使用websocketpp::log::stub
界面来创建我自己的客户记录器。问题是,有关日志记录的文档非常有限,我不确定从哪里开始以及如何将其合并到上面链接的遥测服务器示例的上下文中。我不确定在定义服务器时如何指定记录器:typedef websocketpp::server<websocketpp::config::asio> server;
.
如何扩展stub
类,以及如何使用此客户记录器初始化服务器?
我能找到的唯一示例代码是这里的这个线程,但根据链接的注释,该代码在V 0.3.x+
后不再相关。
对于任何想要使用 spdlog 作为客户记录器的示例代码的人来说,这里是:
创建一个包含以下内容的新文件customerLogger.hpp
:
#pragma once
#include <websocketpp/logger/basic.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/logger/levels.hpp>
#include "spdlog/logger.h"
#include "spdlog/sinks/rotating_file_sink.h"
namespace websocketpp {
namespace log {
/// Basic logger that outputs to syslog
template <typename concurrency, typename names>
class myLogger : public basic<concurrency, names> {
public:
typedef basic<concurrency, names> base;
/// Construct the logger
/**
* @param hint A channel type specific hint for how to construct the logger
*/
myLogger<concurrency,names>(channel_type_hint::value hint =
channel_type_hint::access)
: basic<concurrency,names>(hint), m_channel_type_hint(hint) {
auto max_size = 1048576 * 5;
auto max_files = 3;
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt> ("/var/logs/my_logger.log", max_size, max_files);
m_logger = std::make_shared<spdlog::logger>("my_logger", rotating_sink);
m_logger->flush_on(spdlog::level::info);
m_logger->set_level(spdlog::level::level_enum::info);
}
/// Construct the logger
/**
* @param channels A set of channels to statically enable
* @param hint A channel type specific hint for how to construct the logger
*/
myLogger<concurrency,names>(level channels, channel_type_hint::value hint =
channel_type_hint::access)
: basic<concurrency,names>(channels, hint), m_channel_type_hint(hint) {
auto max_size = 1048576 * 5;
auto max_files = 3;
auto rotating_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt> ("/var/logs/my_logger.log", max_size, max_files);
m_logger = std::make_shared<spdlog::logger>("my_logger", rotating_sink);
m_logger->flush_on(spdlog::level::info);
m_logger->set_level(spdlog::level::level_enum::info);
}
/// Write a string message to the given channel
/**
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level channel, std::string const & msg) {
write(channel, msg.c_str());
}
/// Write a cstring message to the given channel
/**
* @param channel The channel to write to
* @param msg The message to write
*/
void write(level channel, char const * msg) {
scoped_lock_type lock(base::m_lock);
if (!this->dynamic_test(channel)) { return; }
if (m_channel_type_hint == channel_type_hint::access) {
m_logger->info(msg);
} else {
if (channel == elevel::devel) {
m_logger->debug(msg);
} else if (channel == elevel::library) {
m_logger->debug(msg);
} else if (channel == elevel::info) {
m_logger->info(msg);
} else if (channel == elevel::warn) {
m_logger->warn(msg);
} else if (channel == elevel::rerror) {
m_logger->error(msg);
} else if (channel == elevel::fatal) {
m_logger->critical(msg);
}
}
}
private:
std::shared_ptr<spdlog::logger> m_logger;
typedef typename base::scoped_lock_type scoped_lock_type;
channel_type_hint::value m_channel_type_hint;
};
} // log
} // websocketpp
接下来,创建另一个文件,customConfig.hpp
其中包含以下内容:
#pragma once
#include "./customLogger.hpp"
#include <websocketpp/logger/syslog.hpp>
#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
// Custom server config based on bundled asio config
struct my_config : public websocketpp::config::asio {
// Replace default stream logger with the custom logger
typedef websocketpp::log::myLogger<concurrency_type, websocketpp::log::elevel> elog_type;
typedef websocketpp::log::myLogger<concurrency_type, websocketpp::log::alevel> alog_type;
};
typedef websocketpp::server<my_config> my_server;
最后,当您想要创建服务器时,您只需执行my_server endpoint;
构建自定义记录器有两个步骤。首先,使用适当的接口编写策略类,然后创建使用该策略的自定义配置。
编写策略类websocketpp::log::stub
是一个最小的实现,它实际上不做任何事情(它主要用于在单元测试中存根日志记录(,但它演示并记录了日志记录类需要实现的接口。日志记录类不需要是websocketpp::log::stub
的子类。您可以查看websocketpp/logger/*
文件夹中的其他示例。特别是系统日志记录器作为输出到标准输出以外的其他内容的日志记录策略的示例可能很有趣。
要设置自定义配置,您将创建一个配置类。它可以是独立的,也可以是标准类之一的子类,如websocketpp::config::asio
,只是覆盖了少量的东西。例如,您的配置可能只覆盖记录器。创建后,您将配置类传递到端点模板参数中,而不是websocketpp::config::asio
。
有关在编译时可以通过此配置系统覆盖的内容的更多详细信息,请参阅 https://docs.websocketpp.org/reference_8config.html。此页面上有一个示例,显示了替换默认记录器的自定义配置(以及其他更改(。
- 如何将enable-if与模板参数和参数包一起使用
- 如何将PERF_AMPLE_READ与mmap一起使用
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 如何将C++中的库和头与MinGW一起使用
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 为什么我不能将 rand() 与数组的大小一起使用?
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 将fold表达式与std::一起用于两个元组
- spdlog标头仅与外部fmt一起使用.spdlog错误:'内部':不是'fmt'
- 将 std::allocate_shared 与多态资源分配器一起使用
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- 将 exprtk 与自定义类的对象一起使用
- 将 std::set 与基于键的比较器一起使用
- 将 C++ 类与 Rcpp 一起使用,从 C 或 R 修改它
- 如何将 Eigen::Ref 与 pybind11 一起使用?
- 如何将AERT_Allocate与 std:vector 一起使用
- 如何使我的 sizeof sum 结构与空参数包一起工作
- 如何将自定义记录器与websocketpp一起使用?