Skip to content

Commit

Permalink
improve
Browse files Browse the repository at this point in the history
  • Loading branch information
beats-dh committed Aug 20, 2024
1 parent 88a4db9 commit 5418917
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 40 deletions.
61 changes: 57 additions & 4 deletions src/lib/logging/log_with_spd_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,47 @@
* Contributors: https://github.com/opentibiabr/canary/graphs/contributors
* Website: https://docs.opentibiabr.com/
*/

#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>

Check warning on line 11 in src/lib/logging/log_with_spd_log.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

restrict-system-libc-headers

system include spdlog/sinks/basic_file_sink.h not allowed
#include <spdlog/sinks/stdout_color_sinks.h>

Check warning on line 12 in src/lib/logging/log_with_spd_log.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

restrict-system-libc-headers

system include spdlog/sinks/stdout_color_sinks.h not allowed

#include "pch.hpp"
#include "lib/di/container.hpp"

LogWithSpdLog::LogWithSpdLog() {
setLevel("info");
spdlog::set_pattern("[%Y-%d-%m %H:%M:%S.%e] [%^%l%$] %v ");

#ifdef DEBUG_LOG
spdlog::set_pattern("[%Y-%d-%m %H:%M:%S.%e] [thread %t] [%^%l%$] %v ");
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [thread %t] [%^%l%$] %v ");
#else
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v ");
#endif

const std::tm local_tm = get_local_time();

std::ostringstream oss;
oss << std::put_time(&local_tm, "%Y-%m-%d_%H-%M-%S");
std::string filename = "log/server_log_" + oss.str() + ".txt";

try {
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);

const auto combined_logger = std::make_shared<spdlog::logger>(
"",
spdlog::sinks_init_list { console_sink, file_sink }
);

combined_logger->set_level(spdlog::get_level());
combined_logger->flush_on(spdlog::level::info);

set_default_logger(combined_logger);

spdlog::info("Logger initialized and configured for console and file output.");
} catch (const spdlog::spdlog_ex &ex) {
std::cerr << "Log initialization failed: " << ex.what() << std::endl;

Check warning on line 48 in src/lib/logging/log_with_spd_log.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

avoid-endl

do not use 'std::endl' with streams; use '\n' instead
}
}

Logger &LogWithSpdLog::getInstance() {
Expand All @@ -26,15 +55,39 @@ Logger &LogWithSpdLog::getInstance() {

void LogWithSpdLog::setLevel(const std::string &name) {
debug("Setting log level to: {}.", name);
auto level = spdlog::level::from_str(name);
const auto level = spdlog::level::from_str(name);
spdlog::set_level(level);
}

std::string LogWithSpdLog::getLevel() const {
auto level = spdlog::level::to_string_view(spdlog::get_level());
const auto level = spdlog::level::to_string_view(spdlog::get_level());
return std::string { level.begin(), level.end() };
}

void LogWithSpdLog::log(const std::string &lvl, const fmt::basic_string_view<char> msg) const {
spdlog::log(spdlog::level::from_str(lvl), msg);
}

bool LogWithSpdLog::shouldLog(const std::string &lvl) const {
const auto currentLevel = spdlog::get_level();
const auto messageLevel = spdlog::level::from_str(lvl);
return messageLevel >= currentLevel;
}

void LogWithSpdLog::logProfile(const std::string &name, double duration_ms) const {
std::string filename = "log/profile_log-" + name + ".txt";

const auto it = profile_loggers_.find(filename);
if (it == profile_loggers_.end()) {
try {
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto profile_logger = std::make_shared<spdlog::logger>("profile_logger_" + name, file_sink);
profile_loggers_[filename] = profile_logger;
profile_logger->info("Function {} executed in {} ms", name, duration_ms);
} catch (const spdlog::spdlog_ex &ex) {
std::cerr << "Profile log initialization failed: " << ex.what() << std::endl;

Check warning on line 88 in src/lib/logging/log_with_spd_log.cpp

View workflow job for this annotation

GitHub Actions / Qodana for C/C++

avoid-endl

do not use 'std::endl' with streams; use '\n' instead
}
} else {
it->second->info("Function {} executed in {} ms", name, duration_ms);
}
}
10 changes: 10 additions & 0 deletions src/lib/logging/log_with_spd_log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

#include "lib/logging/logger.hpp"

namespace spdlog {
class logger; // Forward declaration
}

class LogWithSpdLog final : public Logger {
public:
LogWithSpdLog();
Expand All @@ -19,8 +23,14 @@ class LogWithSpdLog final : public Logger {

void setLevel(const std::string &name) override;
std::string getLevel() const override;
bool shouldLog(const std::string &lvl) const override;
void logProfile(const std::string &name, double duration_ms) const override;
void setupLogger() const;

void log(const std::string &lvl, fmt::basic_string_view<char> msg) const override;

private:
mutable std::unordered_map<std::string, std::shared_ptr<spdlog::logger>> profile_loggers_;
};

constexpr auto g_logger = LogWithSpdLog::getInstance;
109 changes: 73 additions & 36 deletions src/lib/logging/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,12 @@
#include <fmt/format.h>
#endif

#define LOG_LEVEL_TRACE \
std::string { \
"trace" \
}
#define LOG_LEVEL_DEBUG \
std::string { \
"debug" \
}
#define LOG_LEVEL_INFO \
std::string { \
"info" \
}
#define LOG_LEVEL_WARNING \
std::string { \
"warning" \
}
#define LOG_LEVEL_ERROR \
std::string { \
"error" \
}
#define LOG_LEVEL_CRITICAL \
std::string { \
"critical" \
}
#define LOG_LEVEL_TRACE "trace"
#define LOG_LEVEL_DEBUG "debug"
#define LOG_LEVEL_INFO "info"
#define LOG_LEVEL_WARNING "warning"
#define LOG_LEVEL_ERROR "error"
#define LOG_LEVEL_CRITICAL "critical"

class Logger {
public:
Expand All @@ -50,63 +32,118 @@ class Logger {
[[nodiscard]] virtual std::string getLevel() const = 0;
virtual void log(const std::string &lvl, fmt::basic_string_view<char> msg) const = 0;

virtual bool shouldLog(const std::string &lvl) const = 0;
virtual void logProfile(const std::string &name, double duration_ms) const = 0;

std::tm get_local_time() const {
const auto now = std::chrono::system_clock::now();
std::time_t now_time = std::chrono::system_clock::to_time_t(now);
std::tm local_tm {};

#if defined(_WIN32) || defined(_WIN64)
localtime_s(&local_tm, &now_time);
#else
localtime_r(&now_time, &local_tm);
#endif

return local_tm;
}

template <typename Func>
auto profile(const std::string &name, Func func) -> decltype(func()) {
const auto start = std::chrono::high_resolution_clock::now();
auto result = func();
const auto end = std::chrono::high_resolution_clock::now();

const std::chrono::duration<double, std::milli> duration = end - start;
info("Function {} executed in {} ms", name, duration.count());

logProfile(name, duration.count());

return result;
}

template <typename... Args>
void trace(const fmt::format_string<Args...> &fmt, Args &&... args) {
trace(fmt::format(fmt, std::forward<Args>(args)...));
if (shouldLog(LOG_LEVEL_TRACE)) {
trace(fmt::format(fmt, std::forward<Args>(args)...));
}
}

template <typename... Args>
void debug(const fmt::format_string<Args...> &fmt, Args &&... args) {
debug(fmt::format(fmt, std::forward<Args>(args)...));
if (shouldLog(LOG_LEVEL_DEBUG)) {
debug(fmt::format(fmt, std::forward<Args>(args)...));
}
}

template <typename... Args>
void info(fmt::format_string<Args...> fmt, Args &&... args) {
info(fmt::format(fmt, std::forward<Args>(args)...));
if (shouldLog(LOG_LEVEL_INFO)) {
info(fmt::format(fmt, std::forward<Args>(args)...));
}
}

template <typename... Args>
void warn(const fmt::format_string<Args...> &fmt, Args &&... args) {
warn(fmt::format(fmt, std::forward<Args>(args)...));
if (shouldLog(LOG_LEVEL_WARNING)) {
warn(fmt::format(fmt, std::forward<Args>(args)...));
}
}

template <typename... Args>
void error(const fmt::format_string<Args...> fmt, Args &&... args) {
error(fmt::format(fmt, std::forward<Args>(args)...));
if (shouldLog(LOG_LEVEL_ERROR)) {
error(fmt::format(fmt, std::forward<Args>(args)...));
}
}

template <typename... Args>
void critical(const fmt::format_string<Args...> fmt, Args &&... args) {
critical(fmt::format(fmt, std::forward<Args>(args)...));
if (shouldLog(LOG_LEVEL_CRITICAL)) {
critical(fmt::format(fmt, std::forward<Args>(args)...));
}
}

template <typename T>
void trace(const T &msg) {
log(LOG_LEVEL_TRACE, msg);
if (shouldLog(LOG_LEVEL_TRACE)) {
log(LOG_LEVEL_TRACE, msg);
}
}

template <typename T>
void debug(const T &msg) {
log(LOG_LEVEL_DEBUG, msg);
if (shouldLog(LOG_LEVEL_DEBUG)) {
log(LOG_LEVEL_DEBUG, msg);
}
}

template <typename T>
void info(const T &msg) {
log(LOG_LEVEL_INFO, msg);
if (shouldLog(LOG_LEVEL_INFO)) {
log(LOG_LEVEL_INFO, msg);
}
}

template <typename T>
void warn(const T &msg) {
log(LOG_LEVEL_WARNING, msg);
if (shouldLog(LOG_LEVEL_WARNING)) {
log(LOG_LEVEL_WARNING, msg);
}
}

template <typename T>
void error(const T &msg) {
log(LOG_LEVEL_ERROR, msg);
if (shouldLog(LOG_LEVEL_ERROR)) {
log(LOG_LEVEL_ERROR, msg);
}
}

template <typename T>
void critical(const T &msg) {
log(LOG_LEVEL_CRITICAL, msg);
if (shouldLog(LOG_LEVEL_CRITICAL)) {
log(LOG_LEVEL_CRITICAL, msg);
}
}
};

0 comments on commit 5418917

Please sign in to comment.