| 19 | std::function<void(std::vector<std::string>)> Logger::m_message_callback; |
| 20 | |
| 21 | void Logger::Initialize(const LoggerConfiguration& configuration) { |
| 22 | const auto current_directoy = std::filesystem::current_path(); |
| 23 | const auto log_directory = fmt::format("{0}/{1}", current_directoy.string(), configuration.OutputDirectory); |
| 24 | auto log_directory_path = std::filesystem::path(log_directory); |
| 25 | if (!std::filesystem::exists(log_directory_path)) { |
| 26 | auto dir_created = std::filesystem::create_directory(log_directory_path); |
| 27 | if (!dir_created) { |
| 28 | ZENGINE_CORE_ERROR("failed to create Logs directory"); |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | spdlog::init_thread_pool(8192, 1); |
| 33 | |
| 34 | m_sink_collection.push_back( |
| 35 | std::make_shared<spdlog::sinks::rotating_file_sink_mt>(fmt::format("{0}/{1}", configuration.OutputDirectory, configuration.EngineLogFile), 1024 * 1024, 5, false)); |
| 36 | m_sink_collection.push_back( |
| 37 | std::make_shared<spdlog::sinks::rotating_file_sink_mt>(fmt::format("{0}/{1}", configuration.OutputDirectory, configuration.EditorLogFile), 1024 * 1024, 5, false)); |
| 38 | m_sink_collection.push_back(std::make_shared<spdlog::sinks::ringbuffer_sink_mt>(200)); |
| 39 | |
| 40 | m_engine_logger = std::make_shared<spdlog::async_logger>(configuration.EngineLoggerName, m_sink_collection[0], spdlog::thread_pool()); |
| 41 | m_editor_logger = std::make_shared<spdlog::async_logger>(configuration.EditorLoggerName, m_sink_collection[1], spdlog::thread_pool()); |
| 42 | m_aggregate_logger = std::make_shared<spdlog::async_logger>("Logger", m_sink_collection[2], spdlog::thread_pool()); |
| 43 | |
| 44 | m_engine_logger->info("Engine logger initialized"); |
| 45 | m_editor_logger->info("Editor logger initialized"); |
| 46 | m_aggregate_logger->info("Aggregate logger initialized"); |
| 47 | |
| 48 | spdlog::register_logger(m_engine_logger); |
| 49 | spdlog::register_logger(m_editor_logger); |
| 50 | spdlog::register_logger(m_aggregate_logger); |
| 51 | |
| 52 | spdlog::flush_every(configuration.PeriodicFlush); |
| 53 | |
| 54 | m_is_invoker_running = true; |
| 55 | m_periodic_invoke_callback_interval = configuration.PeriodicInvokeCallbackInterval; |
| 56 | m_message_callback = configuration.MessageCallback; |
| 57 | |
| 58 | std::thread::id empty_id; |
| 59 | if (m_callback_invoker.get_id() == empty_id) { |
| 60 | m_callback_invoker = std::thread([&]() { |
| 61 | auto current_time = std::chrono::system_clock::now(); |
| 62 | |
| 63 | while (m_is_invoker_running) { |
| 64 | auto elapsed_time = std::chrono::system_clock::now() - current_time; |
| 65 | auto elapsed_time_second = std::chrono::duration_cast<std::chrono::seconds>(elapsed_time); |
| 66 | |
| 67 | if (elapsed_time_second.count() >= m_periodic_invoke_callback_interval.count()) { |
| 68 | current_time = std::chrono::system_clock::now(); |
| 69 | auto& current_sink_ptr = m_aggregate_logger->sinks().at(0); |
| 70 | auto ringbuffer_sink = reinterpret_cast<spdlog::sinks::ringbuffer_sink_mt*>(current_sink_ptr.get()); |
| 71 | if (m_message_callback) { |
| 72 | auto message = ringbuffer_sink->last_formatted(200); |
| 73 | current_sink_ptr.reset(new spdlog::sinks::ringbuffer_sink_mt{200}); |
| 74 | m_message_callback(message); |
| 75 | } |
| 76 | } |
| 77 | } |
| 78 | }); |
nothing calls this directly
no outgoing calls
no test coverage detected