我正在实现一个库,并且想提供简单的日志记录工具,而不使用日志记录框架。
我已经看到了这一小段代码,但它的作用比我预期的要多一些:
// logging.h
#ifndef LOGGING_H
#define LOGGING_H
#include <iostream>
enum LogLevel {
// no log is the default
NoLog = 0,
// written to stderr
Err = 1,
Warning = 2,
// written to stdout
Info = 3,
Debug = 4
};
void initLogger(LogLevel level);
LogLevel loggerLevel();
#define LOG(level, msg) \
do { \
if (level > NoLog && level <= loggerLevel()) { \
if (level <= Warning) \
std::cerr << __FILE__ << "(" << __LINE__ << ") " << msg << std::endl; \
else \
std::cout << __FILE__ << "(" << __LINE__ << ") " << msg << std::endl; \
} \
} while (0)
#define LOG_ERR(msg) LOG(Err, msg)
#define LOG_WARN(msg) LOG(Warning, msg)
#define LOG_INFO(msg) LOG(Info, msg)
#define LOG_DEBUG(msg) LOG(Debug, msg)
#endif // LOGGING_H
和
// logging.cpp
include "logging.h"
static LogLevel logLevel = NoLog;
void initLogger(LogLevel level)
{
logLevel = level;
}
LogLevel loggerLevel()
{
return logLevel;
}
在这里,用户可以在运行时更改我不想要的日志记录级别:
initLogger(Err);
// not printed
LOG_INFO("info");
initLogger(Info);
// printed
LOG_INFO("info");
我更愿意让用户选择一劳永逸地初始化日志记录级别,或者完全跳过此步骤并回退到默认级别。我心里有一个单例,但是如何处理默认情况呢? (跳过初始化步骤)
我想应该有更直接的东西。 实现这一目标的最佳方法是什么?
谢谢你。
例如像这样的东西:
#include <string_view>
#include <iostream>
namespace your_library
{
struct reporting_itf
{
virtual ~reporting_itf() = default;
virtual void report_method_called(const std::string_view method_name) const noexcept = 0;
// add more report options here...
// virtual void report_internal_error() const noexcept = 0;
};
struct no_reporting_t : public reporting_itf
{
void report_method_called(const std::string_view method_name) const noexcept override {};
//void report_internal_error() const noexcept override {};
};
no_reporting_t no_reporting;
const reporting_itf* g_reporting = &no_reporting;
void set_reporting(const reporting_itf& reporting)
{
g_reporting = &reporting;
}
void some_function()
{
g_reporting->report_method_called(__FUNCTION__);
}
}
namespace client_code
{
struct client_logger_t : public your_library::reporting_itf
{
void report_method_called(const std::string_view method_name) const noexcept override
{
std::cout << "called : " << method_name << "\n";
// should be something like LOG(Informational....)
};
// Internal logger classes
// Logger m_log;
};
}
int main()
{
client_code::client_logger_t client_logger;
your_library::set_reporting(client_logger);
your_library::some_function();
}