Line data Source code
1 : // SPDX-FileCopyrightText: 2025 PairInteraction Developers 2 : // SPDX-License-Identifier: LGPL-3.0-or-later 3 : 4 : #include "./LoggerBridge.hpp" 5 : 6 : #include "pairinteraction/utils/paths.hpp" 7 : 8 : #include <filesystem> 9 : #include <fmt/core.h> 10 : #include <fmt/format.h> 11 : #include <memory> 12 : #include <mutex> 13 : #include <spdlog/sinks/base_sink.h> 14 : #include <spdlog/sinks/rotating_file_sink.h> 15 : #include <spdlog/spdlog.h> 16 : #include <string> 17 : #include <vector> 18 : 19 : using namespace pairinteraction; 20 : 21 2 : LoggerBridge::QueueSink::QueueSink(LoggerBridge *parent) : parent(parent) {} 22 : 23 2199 : void LoggerBridge::QueueSink::sink_it_(const spdlog::details::log_msg &msg) { 24 2199 : spdlog::memory_buf_t buf; 25 2199 : this->formatter_->format(msg, buf); 26 2199 : std::string text = fmt::to_string(buf); 27 2199 : LogEntry entry; 28 2199 : switch (msg.level) { 29 0 : case spdlog::level::trace: 30 0 : entry.level = 0; 31 0 : break; 32 2014 : case spdlog::level::debug: 33 2014 : entry.level = 10; 34 2014 : break; 35 135 : case spdlog::level::info: 36 135 : entry.level = 20; 37 135 : break; 38 50 : case spdlog::level::warn: 39 50 : entry.level = 30; 40 50 : break; 41 0 : case spdlog::level::err: 42 0 : entry.level = 40; 43 0 : break; 44 0 : case spdlog::level::critical: 45 0 : entry.level = 50; 46 0 : break; 47 0 : default: 48 0 : break; 49 : } 50 2199 : entry.message = text; 51 2199 : std::scoped_lock lock(parent->log_queue_mtx); 52 2199 : parent->log_queue.push_back(std::move(entry)); 53 2199 : } 54 : 55 0 : void LoggerBridge::QueueSink::flush_() {} 56 : 57 2 : LoggerBridge::LoggerBridge() { 58 2 : std::filesystem::path logdir = paths::get_cache_directory() / "logs"; 59 2 : if (!std::filesystem::exists(logdir)) { 60 1 : std::filesystem::create_directories(logdir); 61 1 : } else if (!std::filesystem::is_directory(logdir)) { 62 0 : throw std::runtime_error("Log path is not a directory."); 63 : } 64 2 : std::filesystem::path logfile = logdir / "cpp.log"; 65 : 66 2 : auto queue_sink = std::make_shared<QueueSink>(this); 67 2 : queue_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e %t] [%s:%#] %v"); 68 : 69 : auto file_sink = 70 2 : std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logfile.string(), 1048576 * 5, 10); 71 2 : file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e %t] [%^%l%$] [%s:%#] %v"); 72 : 73 6 : std::vector<spdlog::sink_ptr> sinks{queue_sink, file_sink}; 74 2 : logger = std::make_shared<spdlog::logger>("logger", sinks.begin(), sinks.end()); 75 2 : logger->set_level(spdlog::level::trace); 76 2 : spdlog::set_default_logger(logger); 77 4 : } 78 : 79 2 : LoggerBridge::~LoggerBridge() { 80 2 : spdlog::shutdown(); 81 2 : logger.reset(); 82 2 : } 83 : 84 2312859 : std::vector<LoggerBridge::LogEntry> LoggerBridge::get_pending_logs() { 85 2312859 : std::deque<LogEntry> log_queue_local; 86 : { 87 2312859 : std::scoped_lock lock(log_queue_mtx); 88 2312859 : log_queue_local.swap(log_queue); 89 2312859 : } 90 : 91 2312859 : return {std::make_move_iterator(log_queue_local.begin()), 92 4625718 : std::make_move_iterator(log_queue_local.end())}; 93 2312859 : }