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 <spdlog/async.h> 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 1 : LoggerBridge::QueueSink::QueueSink(LoggerBridge *parent) : parent(parent) {} 21 : 22 0 : void LoggerBridge::QueueSink::sink_it_(const spdlog::details::log_msg &msg) { 23 0 : spdlog::memory_buf_t buf; 24 0 : this->formatter_->format(msg, buf); 25 0 : std::string text = fmt::to_string(buf); 26 0 : LogEntry entry; 27 0 : switch (msg.level) { 28 0 : case spdlog::level::trace: 29 0 : entry.level = 0; 30 0 : break; 31 0 : case spdlog::level::debug: 32 0 : entry.level = 10; 33 0 : break; 34 0 : case spdlog::level::info: 35 0 : entry.level = 20; 36 0 : break; 37 0 : case spdlog::level::warn: 38 0 : entry.level = 30; 39 0 : 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 0 : entry.message = text; 50 0 : parent->log_queue.push(std::move(entry)); 51 0 : } 52 : 53 0 : void LoggerBridge::QueueSink::flush_() {} 54 : 55 1 : LoggerBridge::LoggerBridge() { 56 1 : std::filesystem::path logdir = paths::get_cache_directory() / "logs"; 57 1 : if (!std::filesystem::exists(logdir)) { 58 1 : std::filesystem::create_directories(logdir); 59 0 : } else if (!std::filesystem::is_directory(logdir)) { 60 0 : throw std::runtime_error("Log path is not a directory."); 61 : } 62 1 : std::filesystem::path logfile = logdir / "cpp.log"; 63 : 64 1 : spdlog::init_thread_pool(8192, 1); 65 : 66 1 : auto queue_sink = std::make_shared<QueueSink>(this); 67 1 : queue_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e %t] [%s:%#] %v"); 68 : 69 : auto file_sink = 70 1 : std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logfile.string(), 1048576 * 5, 10); 71 1 : file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e %t] [%^%l%$] [%s:%#] %v"); 72 : 73 3 : std::vector<spdlog::sink_ptr> sinks{queue_sink, file_sink}; 74 1 : auto logger = std::make_shared<spdlog::async_logger>("logger", sinks.begin(), sinks.end(), 75 1 : spdlog::thread_pool(), 76 2 : spdlog::async_overflow_policy::block); 77 1 : logger->set_level(spdlog::level::trace); 78 1 : spdlog::set_default_logger(logger); 79 2 : } 80 : 81 1 : LoggerBridge::~LoggerBridge() { 82 1 : spdlog::shutdown(); 83 1 : logger.reset(); 84 1 : } 85 : 86 0 : std::vector<LoggerBridge::LogEntry> LoggerBridge::get_pending_logs() { 87 0 : std::vector<LogEntry> entries; 88 0 : LogEntry entry; 89 0 : while (log_queue.try_pop(entry)) { 90 0 : entries.push_back(std::move(entry)); 91 : } 92 0 : return entries; 93 0 : }