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 2237 : void LoggerBridge::QueueSink::sink_it_(const spdlog::details::log_msg &msg) { 24 2237 : spdlog::memory_buf_t buf; 25 2237 : this->formatter_->format(msg, buf); 26 2237 : std::string text = fmt::to_string(buf); 27 2237 : LogEntry entry; 28 2237 : switch (msg.level) { 29 0 : case spdlog::level::trace: 30 0 : entry.level = 0; 31 0 : break; 32 1979 : case spdlog::level::debug: 33 1979 : entry.level = 10; 34 1979 : break; 35 219 : case spdlog::level::info: 36 219 : entry.level = 20; 37 219 : break; 38 39 : case spdlog::level::warn: 39 39 : entry.level = 30; 40 39 : 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 2237 : entry.message = text; 51 2237 : std::scoped_lock lock(parent->log_queue_mtx); 52 2237 : parent->log_queue.push_back(std::move(entry)); 53 2237 : } 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 2549394 : std::vector<LoggerBridge::LogEntry> LoggerBridge::get_pending_logs() { 85 2549394 : std::deque<LogEntry> log_queue_local; 86 : { 87 2549394 : std::scoped_lock lock(log_queue_mtx); 88 2549394 : log_queue_local.swap(log_queue); 89 2549394 : } 90 : 91 2549394 : return {std::make_move_iterator(log_queue_local.begin()), 92 5098788 : std::make_move_iterator(log_queue_local.end())}; 93 2549394 : }