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 2 : LoggerBridge::QueueSink::QueueSink(LoggerBridge *parent) : parent(parent) {} 21 : 22 629 : void LoggerBridge::QueueSink::sink_it_(const spdlog::details::log_msg &msg) { 23 629 : spdlog::memory_buf_t buf; 24 629 : this->formatter_->format(msg, buf); 25 629 : std::string text = fmt::to_string(buf); 26 629 : LogEntry entry; 27 629 : switch (msg.level) { 28 0 : case spdlog::level::trace: 29 0 : entry.level = 0; 30 0 : break; 31 435 : case spdlog::level::debug: 32 435 : entry.level = 10; 33 435 : break; 34 194 : case spdlog::level::info: 35 194 : entry.level = 20; 36 194 : 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 629 : entry.message = text; 50 629 : parent->log_queue.push(std::move(entry)); 51 629 : } 52 : 53 0 : void LoggerBridge::QueueSink::flush_() {} 54 : 55 2 : LoggerBridge::LoggerBridge() { 56 2 : std::filesystem::path logdir = paths::get_cache_directory() / "logs"; 57 2 : if (!std::filesystem::exists(logdir)) { 58 1 : std::filesystem::create_directories(logdir); 59 1 : } else if (!std::filesystem::is_directory(logdir)) { 60 0 : throw std::runtime_error("Log path is not a directory."); 61 : } 62 2 : std::filesystem::path logfile = logdir / "cpp.log"; 63 : 64 2 : spdlog::init_thread_pool(8192, 1); 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 : auto logger = std::make_shared<spdlog::async_logger>("logger", sinks.begin(), sinks.end(), 75 2 : spdlog::thread_pool(), 76 4 : spdlog::async_overflow_policy::block); 77 2 : logger->set_level(spdlog::level::trace); 78 2 : spdlog::set_default_logger(logger); 79 4 : } 80 : 81 2 : LoggerBridge::~LoggerBridge() { 82 2 : spdlog::shutdown(); 83 2 : logger.reset(); 84 2 : } 85 : 86 2571 : std::vector<LoggerBridge::LogEntry> LoggerBridge::get_pending_logs() { 87 2571 : std::vector<LogEntry> entries; 88 2571 : LogEntry entry; 89 3200 : while (log_queue.try_pop(entry)) { 90 629 : entries.push_back(std::move(entry)); 91 : } 92 5142 : return entries; 93 2571 : }