spdlog使用
2020-08-03 09:25:20 # cpp

logger.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#pragma once

#include <memory>
#include <string_view>

#include "singleton.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"

#define LOG_INFO(...) Sky::Logger::instance().log(spdlog::level::level_enum::info, ##__VA_ARGS__)
#define LOG_WARN(...) Sky::Logger::instance().log(spdlog::level::level_enum::warn, ##__VA_ARGS__)
#define LOG_DEBUG(...) Sky::Logger::instance().log(spdlog::level::level_enum::debug, ##__VA_ARGS__)
#define LOG_ERROR(...) Sky::Logger::instance().log(spdlog::level::level_enum::err, ##__VA_ARGS__)

namespace Sky {
class Logger final : public Singleton<Logger> {
friend class Singleton<Logger>;

~Logger() override {
if (m_logger) {
spdlog::shutdown();
m_logger = nullptr;
}
}

private:
Logger() {
spdlog::set_pattern("%C-%m-%d %T %t %^%l%$ [not init Logger] %v");
};

public:
bool start(std::string_view fileName, std::string_view pattern, uint16_t file_level, uint16_t console_level,
uint16_t timer_flush_sec = 0);

template <typename... Args>
void log(spdlog::level::level_enum level, Args &&... args) {
if (m_logger) {
m_logger->log(level, std::forward<Args>(args)...);
} else {
SPDLOG_ERROR(std::forward<Args>(args)...);
}
}

void setLogLevel(spdlog::level::level_enum level) {
if (m_logger) {
m_logger->set_level(level);
}
}

private:
template <typename T, typename... Args>
spdlog::sink_ptr createLogger(uint8_t level, Args &&... args) {
auto lv = static_cast<spdlog::level::level_enum>(level);
auto log = std::make_shared<T>(std::forward<Args>(args)...);
log->set_level(lv);
return log;
};

private:
std::shared_ptr<spdlog::logger> m_logger{};
};
} // namespace Sky

logger.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include "logger.h"

#include <string>

#include "comm_func.h"
#include "define.h"

namespace Sky {
bool Logger::start(std::string_view fileName, std::string_view pattern, uint16_t file_level, uint16_t console_level,
uint16_t timer_flush_sec) {
bool ret{};
try {
if (fileName.empty()) {
LOG_ERROR("Logger::start fileName is empty");
return ret;
}

std::string file_name_path = CommFunc::getCurrentExeDir().append(SLASH_STR).append(fileName.data());
std::vector<spdlog::sink_ptr> sinks;
// file Logger
sinks.push_back(createLogger<spdlog::sinks::daily_file_sink_mt>(file_level, file_name_path, 0, 0));

// console Logger
sinks.push_back(createLogger<spdlog::sinks::stdout_color_sink_mt>(console_level));

auto log = std::make_shared<spdlog::logger>(file_name_path, sinks.begin(), sinks.end());
log->set_level(spdlog::level::trace);
spdlog::register_logger(log);

// set option
log->set_pattern(pattern.data());
m_logger = log;

spdlog::set_error_handler([](const std::string& msg) {
LOG_ERROR("Logger error handler:{}", msg);
});

if (timer_flush_sec > 0) {
spdlog::flush_every(std::chrono::seconds(timer_flush_sec));
}

ret = true;
} catch (spdlog::spdlog_ex& e) {
LOG_ERROR("Logger::start exception message:{}", e.what());
} catch (...) {
LOG_ERROR("Logger::start other exception");
}

return ret;
}
} // namespace Sky