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