You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
702 lines
21 KiB
702 lines
21 KiB
//
|
|
// Created by zhaohe on 19-5-31.
|
|
//
|
|
|
|
#include "logger_factory.hpp"
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <mutex>
|
|
#include <thread>
|
|
|
|
#include "default_logger_config.hpp"
|
|
#include "nlohmann/json.hpp"
|
|
#include "spdlog/sinks/basic_file_sink.h"
|
|
#include "spdlog/sinks/daily_file_sink.h"
|
|
#include "spdlog/sinks/rotating_file_sink.h"
|
|
#include "spdlog/sinks/stdout_sinks.h"
|
|
// #include "zwtimecpp/core/utils/compliler.h"
|
|
using namespace std;
|
|
using namespace iflytop;
|
|
using namespace core;
|
|
using namespace nlohmann;
|
|
using namespace spdlog;
|
|
|
|
const static char* kRootLogerName = "root";
|
|
// const static char* kSpdDefaultConfigPaths[] = {"spd_logger_cfg.json"};
|
|
const static char* kDefaultPattern = "[%C-%m-%d %H:%M:%S.%e] [%-30n] [%^%L%$] %v";
|
|
// const static string kDefaultPattern = "";
|
|
|
|
// const string WEAK spdLoggerConfig() { return ""; }
|
|
|
|
// const static string kDefaultLoggerBeforeConfig = "DefaultLoggerBeforeConfig";
|
|
|
|
// {
|
|
// "name": "LoggerName",
|
|
// "level": 2,
|
|
// "type":"daily_logger_mt",
|
|
// "filename":"fileName",
|
|
// "hour":0,
|
|
// "minute":0,
|
|
// "truncate":false
|
|
// }
|
|
|
|
// {
|
|
// "name": "LoggerName",
|
|
// "level": 2,
|
|
// "type":"rotating_logger_mt",
|
|
// "filename":"fileName",
|
|
// "max_file_size":1000,
|
|
// "max_files":100,
|
|
// "rotate_on_open":true
|
|
// }
|
|
// Rotate files:
|
|
// log.txt -> log.1.txt
|
|
// log.1.txt -> log.2.txt
|
|
// log.2.txt -> log.3.txt
|
|
// log.3.txt -> delete
|
|
|
|
// 1. 没设置type,统统被当做logger处理
|
|
// 2. 所有的logger,sink loggerAndSink,name都不能重复
|
|
// 3.
|
|
|
|
/**
|
|
* @brief
|
|
*loggerSupportList:
|
|
*
|
|
*-->: daily_logger_mt
|
|
*-->: basic_logger_mt
|
|
*-->: logger
|
|
*-->: daily_file_sink_mt
|
|
*-->: stderr_color_sink_mt
|
|
*-->: stdout_color_sink_mt
|
|
*
|
|
* rotating_logger_mt
|
|
* rotating_file_sink_mt
|
|
*
|
|
*/
|
|
|
|
#define ASSININ_VALUE(value) \
|
|
if (config_item.key() == #value) item.at(#value).get_to(config.value);
|
|
|
|
#if 0
|
|
static bool c_daily_logger_mt(json j) {
|
|
try {
|
|
string type = j.at("type").get<string>();
|
|
if (type == "daily_logger_mt") {
|
|
GET(string, name);
|
|
GET(string, filename);
|
|
mkdirIfNotExist(filename);
|
|
|
|
TRY_GET(int, hour, 0);
|
|
TRY_GET(int, minute, 0);
|
|
TRY_GET(bool, truncate, false);
|
|
|
|
auto var_logger =
|
|
spdlog::daily_logger_mt(name, filename, hour, minute, truncate);
|
|
logger_common_config(var_logger, j);
|
|
insertLogger(var_logger);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} catch (const std::exception& e) {
|
|
spdlog::critical("c_daily_logger_mt fail {} reason {}", j.dump(1),
|
|
e.what());
|
|
exit(-1);
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#if 0
|
|
static bool c_daily_file_sink_mt(json j) {
|
|
try {
|
|
string type = j.at("type").get<string>();
|
|
if (type == "daily_file_sink_mt") {
|
|
GET(string, name);
|
|
GET(string, filename);
|
|
mkdirIfNotExist(filename);
|
|
TRY_GET(int, hour, 0);
|
|
TRY_GET(int, minute, 0);
|
|
TRY_GET(bool, truncate, false);
|
|
|
|
auto sink = make_shared<sinks::daily_file_sink_mt>(filename, hour, minute,
|
|
truncate);
|
|
|
|
sink_common_config(sink, j);
|
|
insertSink(name, sink);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} catch (const std::exception& e) {
|
|
spdlog::critical("c_daily_file_sink_mt fail {} reason {}", j.dump(1),
|
|
e.what());
|
|
exit(-1);
|
|
}
|
|
};
|
|
#endif
|
|
// 10485760 == 10M
|
|
static string default_config = R"(
|
|
[
|
|
{
|
|
"name": "info-sink",
|
|
"type": "rotating_file_sink_mt",
|
|
"filename": "logs/infolog.log",
|
|
"max_file_size":10485760,
|
|
"max_files": 3,
|
|
"rotate_on_open": true,
|
|
"level" : 2
|
|
},
|
|
{
|
|
"name": "debug-sink",
|
|
"type": "rotating_file_sink_mt",
|
|
"filename": "logs/debuglog.log",
|
|
"max_file_size":10485760,
|
|
"max_files": 3,
|
|
"rotate_on_open": true,
|
|
"level": 0
|
|
},
|
|
{
|
|
"name": "terminal-sink",
|
|
"type": "stdout_color_sink_mt"
|
|
},
|
|
{
|
|
"name": "root",
|
|
"type": "logger",
|
|
"level": 2,
|
|
"sinks": [
|
|
"terminal-sink",
|
|
"debug-sink",
|
|
"info-sink"
|
|
]
|
|
}
|
|
]
|
|
)";
|
|
#define LOGGER_ENABLE_BEGIN(_name) \
|
|
static bool c_##_name(json j) { \
|
|
logger_t var_logger; \
|
|
try { \
|
|
string type = j.at("type").get<string>(); \
|
|
if (type == #_name) { \
|
|
GET(string, name);
|
|
|
|
#define LOGGER_ENABLE_END(name) \
|
|
logger_common_config(var_logger, j); \
|
|
insertLogger(var_logger); \
|
|
return true; \
|
|
} \
|
|
else { \
|
|
return false; \
|
|
} \
|
|
} \
|
|
catch (const std::exception& e) { \
|
|
spdlog::critical("c_{} fail {} reason {}", #name, j.dump(1), e.what()); \
|
|
exit(-1); \
|
|
} \
|
|
} \
|
|
;
|
|
|
|
#define SINK_DEFINE_BEGIN(var_name) \
|
|
static bool c_##var_name(json j) { \
|
|
sink_ptr sink; \
|
|
try { \
|
|
string type = j.at("type").get<string>(); \
|
|
if (type == #var_name) { \
|
|
GET(string, name);
|
|
|
|
#define SINK_DEFINE_END(var_name) \
|
|
sink_common_config(sink, j); \
|
|
insertSink(name, sink); \
|
|
return true; \
|
|
} \
|
|
else { \
|
|
return false; \
|
|
} \
|
|
} \
|
|
catch (const std::exception& e) { \
|
|
spdlog::critical("c_" #var_name " fail {} reason {}", j.dump(1), e.what()); \
|
|
exit(-1); \
|
|
} \
|
|
} \
|
|
;
|
|
|
|
template <class type>
|
|
type tryGet(json j, string value_name, type defaultValue) {
|
|
try {
|
|
if (j.find(value_name) == j.end()) {
|
|
return defaultValue;
|
|
}
|
|
type value = j.at(value_name).get<type>();
|
|
return value;
|
|
} catch (const std::exception& e) {
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
static bool exist(const string& path) {
|
|
struct stat statInfo;
|
|
if (stat(path.c_str(), &statInfo) == 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
static bool mkdirIfNotExist(const string& path) {
|
|
string::size_type sepPos = path.find_last_of("/");
|
|
if (sepPos == string::npos) {
|
|
return false;
|
|
}
|
|
string dirPath = path.substr(0, sepPos);
|
|
if (exist(dirPath)) {
|
|
return true;
|
|
}
|
|
int ret = mkdir(dirPath.c_str(), S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
|
|
|
return 0 == ret ? true : false;
|
|
}
|
|
|
|
class LoggerAndSinks {
|
|
public:
|
|
string loggerName;
|
|
set<string> sinkNames;
|
|
};
|
|
/****************************************************************************************************/
|
|
|
|
static map<string, sink_ptr> s_sinks = {};
|
|
static map<string, shared_ptr<logger>> s_loggers = {};
|
|
static set<shared_ptr<LoggerAndSinks>> s_loggerAndSinks = {};
|
|
|
|
static void insertLogger(shared_ptr<logger> var_logger) {
|
|
if (s_loggers.find(var_logger->name()) == s_loggers.end()) {
|
|
s_loggers[var_logger->name()] = var_logger;
|
|
} else {
|
|
spdlog::critical("Add the logger {} fail", var_logger->name());
|
|
exit(-1);
|
|
}
|
|
};
|
|
|
|
static void insertSink(string name, sink_ptr sink) {
|
|
if (s_sinks.find(name) == s_sinks.end()) {
|
|
s_sinks[name] = sink;
|
|
} else {
|
|
spdlog::critical("Add the sink {} fail", name);
|
|
exit(-1);
|
|
}
|
|
};
|
|
|
|
static level::level_enum to_level(int value) {
|
|
switch (value) {
|
|
case SPDLOG_LEVEL_TRACE:
|
|
return level::trace;
|
|
case SPDLOG_LEVEL_DEBUG:
|
|
return level::debug;
|
|
case SPDLOG_LEVEL_INFO:
|
|
return level::info;
|
|
case SPDLOG_LEVEL_WARN:
|
|
return level::warn;
|
|
case SPDLOG_LEVEL_ERROR:
|
|
return level::err;
|
|
case SPDLOG_LEVEL_CRITICAL:
|
|
return level::critical;
|
|
default:
|
|
spdlog::critical("level is out of range {} level must in [{},{}]", value, SPDLOG_LEVEL_TRACE, SPDLOG_LEVEL_CRITICAL);
|
|
exit(-1);
|
|
break;
|
|
}
|
|
return level::info;
|
|
}
|
|
|
|
// #define GET(type,value,error_msg,...)
|
|
#define TRY_GET(type, value_name, default_value) type value_name = tryGet<type>(j, #value_name, default_value)
|
|
#define GET(T, value_name) T value_name = j.at(#value_name).get<T>();
|
|
|
|
static void logger_common_config(logger_t var_logger, json j) {
|
|
TRY_GET(int, level, 2);
|
|
TRY_GET(string, pattern, kDefaultPattern);
|
|
TRY_GET(set<string>, sinks, {});
|
|
|
|
var_logger->set_level(to_level(level));
|
|
if (!sinks.empty()) {
|
|
shared_ptr<LoggerAndSinks> las(new LoggerAndSinks());
|
|
las->loggerName = var_logger->name();
|
|
las->sinkNames = sinks;
|
|
s_loggerAndSinks.insert(las);
|
|
}
|
|
}
|
|
|
|
static void sink_common_config(sink_ptr sink, json j) {
|
|
TRY_GET(int, level, 0);
|
|
TRY_GET(string, pattern, kDefaultPattern);
|
|
TRY_GET(set<string>, sinks, {});
|
|
sink->set_level(to_level(level));
|
|
if (!pattern.empty()) sink->set_pattern(pattern);
|
|
}
|
|
|
|
/**
|
|
* logger-----------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
LOGGER_ENABLE_BEGIN(daily_logger_mt) {
|
|
GET(string, filename);
|
|
mkdirIfNotExist(filename);
|
|
TRY_GET(int, hour, 0);
|
|
TRY_GET(int, minute, 0);
|
|
TRY_GET(bool, truncate, false);
|
|
TRY_GET(int, max_files, 100);
|
|
var_logger = spdlog::daily_logger_mt(name, filename, hour, minute, truncate, max_files);
|
|
}
|
|
LOGGER_ENABLE_END(daily_logger_mt)
|
|
|
|
LOGGER_ENABLE_BEGIN(rotating_logger_mt) {
|
|
GET(string, filename);
|
|
mkdirIfNotExist(filename);
|
|
TRY_GET(int, max_file_size, 10 * 1024 * 1024);
|
|
TRY_GET(int, max_files, 3);
|
|
TRY_GET(bool, rotate_on_open, true);
|
|
var_logger = spdlog::rotating_logger_mt(name, filename, max_file_size, max_files, rotate_on_open);
|
|
}
|
|
LOGGER_ENABLE_END(rotating_logger_mt)
|
|
|
|
LOGGER_ENABLE_BEGIN(basic_logger_mt) {
|
|
GET(string, filename);
|
|
mkdirIfNotExist(filename);
|
|
var_logger = spdlog::basic_logger_mt(name, filename);
|
|
}
|
|
LOGGER_ENABLE_END(basic_logger_mt)
|
|
|
|
static bool c_logger(json j) {
|
|
try {
|
|
string type = j.at("type").get<string>();
|
|
if (type == "logger") {
|
|
GET(string, name);
|
|
GET(set<string>, sinks);
|
|
auto var_logger = make_shared<logger>(name, sinks_init_list{});
|
|
if (sinks.empty()) {
|
|
spdlog::critical("c_logger fail {} reason {}", j.dump(1), "Not set sink");
|
|
exit(-1);
|
|
}
|
|
|
|
logger_common_config(var_logger, j);
|
|
insertLogger(var_logger);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} catch (const std::exception& e) {
|
|
spdlog::critical("c_logger fail {} reason {}", j.dump(1), e.what());
|
|
exit(-1);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* sinks-----------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
SINK_DEFINE_BEGIN(daily_file_sink_mt) {
|
|
GET(string, filename);
|
|
mkdirIfNotExist(filename);
|
|
TRY_GET(int, hour, 0);
|
|
TRY_GET(int, minute, 0);
|
|
TRY_GET(bool, truncate, false);
|
|
TRY_GET(int, max_files, 100);
|
|
// printf("filename:%s,max_files %d\n", filename.c_str(), max_files);
|
|
sink = make_shared<sinks::daily_file_sink_mt>(filename, hour, minute, truncate, max_files);
|
|
}
|
|
SINK_DEFINE_END(daily_file_sink_mt)
|
|
|
|
SINK_DEFINE_BEGIN(rotating_file_sink_mt) {
|
|
GET(string, filename);
|
|
mkdirIfNotExist(filename);
|
|
TRY_GET(int, max_file_size, 10 * 1024 * 1024);
|
|
TRY_GET(int, max_files, 5);
|
|
TRY_GET(bool, rotate_on_open, true);
|
|
sink = make_shared<sinks::rotating_file_sink_mt>(filename, max_file_size, max_files, rotate_on_open);
|
|
}
|
|
SINK_DEFINE_END(rotating_file_sink_mt)
|
|
|
|
SINK_DEFINE_BEGIN(stdout_color_sink_mt) { sink = make_shared<sinks::stdout_color_sink_mt>(); }
|
|
SINK_DEFINE_END(stdout_color_sink_mt)
|
|
|
|
SINK_DEFINE_BEGIN(stderr_color_sink_mt) { sink = make_shared<sinks::stderr_color_sink_mt>(); }
|
|
SINK_DEFINE_END(stderr_color_sink_mt)
|
|
|
|
/**
|
|
* default_root_logger-----------------------------------------------------------------------------------------------------
|
|
*/
|
|
static logger_t createRootLogger() {
|
|
if (!get(kRootLogerName)) {
|
|
auto rootLogger = spdlog::stdout_color_mt(kRootLogerName);
|
|
if (!string(kDefaultPattern).empty()) {
|
|
rootLogger->set_pattern(kDefaultPattern);
|
|
}
|
|
return rootLogger;
|
|
}
|
|
|
|
// auto stdoutsink = make_shared<sinks::stderr_color_sink_mt>();
|
|
// stdoutsink->set_level(level::debug);
|
|
// if (!kDefaultPattern.empty()) {
|
|
// stdoutsink->set_pattern(kDefaultPattern);
|
|
// }
|
|
// auto rootLogger =
|
|
// make_shared<logger>(kRootLogerName, sinks_init_list{stdoutsink});
|
|
// rootLogger->set_level(level::info);
|
|
// rootLogger->set_pattern(kDefaultPattern);
|
|
return get(kRootLogerName);
|
|
}
|
|
/**
|
|
* @brief
|
|
*/
|
|
/**
|
|
* @brief 当使用 daily_logger_mt时候会自动注册logger, 而使用make_shared<logger>
|
|
* 则不会自动注册logger
|
|
* @param var_logger
|
|
*/
|
|
static void myRegLogger(logger_t var_logger) {
|
|
if (var_logger->name() == kRootLogerName) {
|
|
spdlog::set_default_logger(var_logger);
|
|
}
|
|
|
|
if (!get(var_logger->name())) {
|
|
register_logger(var_logger);
|
|
}
|
|
if (!get(var_logger->name())) {
|
|
spdlog::critical("reg root logger fail {}");
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
static void __parseSphLogConfig(json var) {
|
|
if (c_daily_logger_mt(var)) {
|
|
} else if (c_rotating_logger_mt(var)) {
|
|
} else if (c_basic_logger_mt(var)) {
|
|
} else if (c_daily_file_sink_mt(var)) {
|
|
} else if (c_logger(var)) {
|
|
} else if (c_stderr_color_sink_mt(var)) {
|
|
} else if (c_stdout_color_sink_mt(var)) {
|
|
} else if (c_rotating_file_sink_mt(var)) {
|
|
} else {
|
|
spdlog::critical("no such type {}", var.dump());
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
static logger_t createLoggerWithoutType(json j) {
|
|
TRY_GET(int, level, 2);
|
|
GET(string, name);
|
|
TRY_GET(string, pattern, kDefaultPattern);
|
|
auto rootLogger = get(kRootLogerName);
|
|
if (!rootLogger) {
|
|
spdlog::critical("func: createLoggerWithoutType,can't find rootLogger");
|
|
exit(-1);
|
|
}
|
|
auto newLogger = rootLogger->clone(name);
|
|
newLogger->set_level(to_level(level));
|
|
if (!pattern.empty()) newLogger->set_pattern(pattern);
|
|
return newLogger;
|
|
}
|
|
|
|
/**
|
|
* @brief
|
|
*
|
|
* 构造logger思路
|
|
* 1. 首先找到所有定义了type了的logger和sink
|
|
* 2. 绑定所有的logger和对应的sink
|
|
* 3. 查看是否创建rootLogger,没有则创建rootLogger
|
|
* 4. 遍历所有没有定义type的logger,继承于rootLogger,并为其设置level
|
|
* @param path
|
|
*/
|
|
void core::SpdLoggerFactory::parseSphLogConfig(string path) {
|
|
try {
|
|
// 这里必须清空,因为这个方法可能在main函数之前启动,所以数量可能未初始化
|
|
s_sinks.clear();
|
|
s_loggers.clear();
|
|
s_loggerAndSinks.clear();
|
|
|
|
fstream infile(path, ios::binary | ios::in);
|
|
stringstream sstream;
|
|
sstream << infile.rdbuf();
|
|
infile.close();
|
|
|
|
string jsonStr(sstream.str());
|
|
sstream.clear();
|
|
|
|
json configjson = json::parse(jsonStr);
|
|
for (auto& j : configjson) {
|
|
TRY_GET(string, type, "");
|
|
if (!type.empty()) {
|
|
__parseSphLogConfig(j);
|
|
}
|
|
}
|
|
|
|
// 组装logger and sink
|
|
for (auto& las : s_loggerAndSinks) {
|
|
logger_t logger = s_loggers[las->loggerName];
|
|
if (logger == nullptr) {
|
|
spdlog::critical("can't find logger", las->loggerName);
|
|
exit(-1);
|
|
}
|
|
set<sink_ptr> sinks;
|
|
for (auto& sinkname : las->sinkNames) {
|
|
auto result = s_sinks.find(sinkname);
|
|
if (result == s_sinks.end()) {
|
|
spdlog::critical("can't find sink {} ??", sinkname);
|
|
exit(-1);
|
|
}
|
|
sinks.insert(result->second);
|
|
}
|
|
for (auto& sink : sinks) logger->sinks().push_back(sink);
|
|
}
|
|
for (auto& var : s_loggers) myRegLogger(var.second);
|
|
|
|
// 如果没有rootLogger,构造rootLogger
|
|
if (!get(kRootLogerName)) {
|
|
for (auto& j : configjson) {
|
|
GET(string, name);
|
|
TRY_GET(string, type, "");
|
|
if (name == kRootLogerName) {
|
|
if (type.empty()) {
|
|
TRY_GET(int, level, 2);
|
|
TRY_GET(string, pattern, kDefaultPattern);
|
|
auto rootLogger = createRootLogger();
|
|
rootLogger->set_level(to_level(level));
|
|
if (!pattern.empty()) rootLogger->set_pattern(pattern);
|
|
myRegLogger(rootLogger);
|
|
} else {
|
|
spdlog::critical("shouldn't go here");
|
|
exit(-1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// 如果依然没有构造rootLogger则构造默认logger
|
|
if (!get(kRootLogerName)) myRegLogger(createRootLogger());
|
|
|
|
// 构造没有type的logger
|
|
for (auto& j : configjson) {
|
|
TRY_GET(string, type, "");
|
|
GET(string, name);
|
|
if (type.empty() && name != kRootLogerName) {
|
|
auto newlogger = createLoggerWithoutType(j);
|
|
myRegLogger(newlogger);
|
|
}
|
|
}
|
|
|
|
// spdlog::info("Logger initialize ok");
|
|
} catch (const exception& e) {
|
|
spdlog::critical("parse logger config fail {}", e.what());
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
static string getConfigFilePath() {
|
|
if (spdLoggerConfig) {
|
|
if (exist(spdLoggerConfig())) {
|
|
return spdLoggerConfig();
|
|
} else {
|
|
spdlog::warn("can't find spdLoggerConfig file {},use deafult config", spdLoggerConfig());
|
|
}
|
|
}
|
|
return "spd_logger_cfg.json";
|
|
}
|
|
|
|
class MonitoringSpdLoggerConfigTask {
|
|
unique_ptr<thread> wthread;
|
|
|
|
public:
|
|
MonitoringSpdLoggerConfigTask() {
|
|
wthread.reset(new thread([]() {
|
|
|
|
}));
|
|
}
|
|
~MonitoringSpdLoggerConfigTask() { wthread->join(); }
|
|
};
|
|
void SpdLoggerFactory::initialize() {
|
|
if (!initializeLogger) {
|
|
string configFilePath = getConfigFilePath();
|
|
if (!configFilePath.empty() && exist(configFilePath)) {
|
|
parseSphLogConfig(configFilePath);
|
|
} else {
|
|
spdlog::warn("can't find logger config file use default config {}", configFilePath);
|
|
// 写字符串default_config到文件中configFilePath
|
|
ofstream outfile(configFilePath);
|
|
outfile << default_config;
|
|
outfile.close();
|
|
parseSphLogConfig(configFilePath);
|
|
}
|
|
initializeLogger = true;
|
|
}
|
|
}
|
|
|
|
shared_ptr<logger> SpdLoggerFactory::createLogger(string loggerName) {
|
|
lock_guard<mutex> lock_gu(createLogger_lock);
|
|
if (!loggerName.empty()) {
|
|
if (s_loggerNames.size() == 0) {
|
|
s_loggerNames.insert(loggerName);
|
|
} else {
|
|
if (s_loggerNames.find(loggerName) == s_loggerNames.end()) {
|
|
s_loggerNames.insert(loggerName);
|
|
}
|
|
}
|
|
}
|
|
// TODO:当使用gtest进行单元测试的时候,logger似乎会被清空,原因未知
|
|
if (!get(kRootLogerName)) {
|
|
initializeLogger = false;
|
|
if (!string(kDefaultPattern).empty()) {
|
|
spdlog::set_pattern(kDefaultPattern);
|
|
}
|
|
}
|
|
|
|
if (!initializeLogger) {
|
|
string configFilePath = getConfigFilePath();
|
|
if (!configFilePath.empty() && exist(configFilePath)) {
|
|
parseSphLogConfig(configFilePath);
|
|
} else {
|
|
spdlog::warn("can't find logger config file use default config {}", configFilePath);
|
|
// 写字符串default_config到文件中configFilePath
|
|
ofstream outfile(configFilePath);
|
|
outfile << default_config;
|
|
outfile.close();
|
|
parseSphLogConfig(configFilePath);
|
|
}
|
|
initializeLogger = true;
|
|
}
|
|
|
|
logger_t ret_logger = get(loggerName);
|
|
if (ret_logger) {
|
|
return ret_logger;
|
|
} else {
|
|
logger_t rootLogger = get(kRootLogerName);
|
|
if (!rootLogger) {
|
|
spdlog::critical("can't find root logger ?????");
|
|
exit(-1);
|
|
}
|
|
logger_t newLogger = rootLogger->clone(loggerName);
|
|
myRegLogger(newLogger);
|
|
return newLogger;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
set<string> SpdLoggerFactory::loggerNames() { return s_loggerNames; }
|
|
sink_ptr SpdLoggerFactory::getSink(string name) {
|
|
auto result = s_sinks.find(name);
|
|
if (result == s_sinks.end()) {
|
|
return nullptr;
|
|
}
|
|
return result->second;
|
|
}
|
|
|
|
shared_ptr<logger> SpdLoggerFactory::createRotatingFileLogger(const std::string& logger_name, size_t max_file_size, size_t max_files, bool bindTerminal,
|
|
bool bindDebug, bool bindInfo) {
|
|
auto newlogger = spdlog::rotating_logger_mt(logger_name, fmt::format("logs/{}.log", logger_name), 5 * 1024 * 1024 /*5M*/, 3 /*times*/);
|
|
newlogger->set_level(spdlog::level::info);
|
|
if (bindTerminal && GET_SINK("terminal-sink")) newlogger->sinks().push_back(GET_SINK("terminal-sink"));
|
|
if (bindDebug && GET_SINK("debug-sink")) newlogger->sinks().push_back(GET_SINK("debug-sink"));
|
|
if (bindInfo && GET_SINK("info-sink")) newlogger->sinks().push_back(GET_SINK("info-sink"));
|
|
myRegLogger(newlogger);
|
|
return newlogger;
|
|
}
|