如何将自定义记录器与websocketpp一起使用?

How to use custom logger with websocketpp?

本文关键字:一起 websocketpp 自定义 记录器      更新时间:2023-10-16

我正在使用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。此页面上有一个示例,显示了替换默认记录器的自定义配置(以及其他更改(。