/******************************************************************************** * Copyright (c) 2025-2026 ZF Friedrichshafen AG * * This program and the accompanying materials are made available under the * terms of the Apache License Version 2.0 which is available at * https://www.apache.org/licenses/LICENSE-2.0 * * SPDX-License-Identifier: Apache-2.0 * * Contributors: * Erik Verhoeven - initial API and implementation ********************************************************************************/ #include "logger.h" #include #include "../../global/exec_dir_helper.h" #ifdef __unix__ #include #endif #ifdef __GNUC__ #include // for getpid #endif CLogger& GetDefaultLogger() { static CLogger default_logger; return default_logger; } CLogger::~CLogger() { #ifdef __unix__ if (m_bLogOpen) closelog(); #endif } void CLogger::Log(sdv::core::ELogSeverity eSeverity, /*in*/ const sdv::u8string& ssSrcFile, /*in*/ uint32_t uiSrcLine, /*in*/ sdv::process::TProcessID tProcessID, /*in*/ const sdv:: u8string& ssObjectName, /*in*/ const sdv::u8string& ssMessage) { if (static_cast(eSeverity) >= static_cast(m_eViewFilter)) { if (tProcessID) std::clog << "[PID#" << static_cast(tProcessID) << "] "; if (!ssObjectName.empty()) std::clog << ssObjectName << " "; switch (eSeverity) { case sdv::core::ELogSeverity::debug: std::clog << "Debug: " << ssMessage << std::endl; break; case sdv::core::ELogSeverity::trace: std::clog << "Trace: " << ssMessage << std::endl; break; case sdv::core::ELogSeverity::info: std::clog << "Info: " << ssMessage << std::endl; break; case sdv::core::ELogSeverity::warning: std::clog << "Warning: " << ssMessage << std::endl; break; case sdv::core::ELogSeverity::error: std::clog << "Error: " << ssMessage << std::endl; break; case sdv::core::ELogSeverity::fatal: std::clog << "Fatal: " << ssMessage << std::endl; break; default: break; } } // Apply the log filter if (static_cast(eSeverity) < static_cast(m_eFilter)) return; std::unique_lock lock(m_mtxLogger); if (m_ssProgramtag.empty()) m_ssProgramtag = std::string("SDV_LOG_") + std::to_string(getpid()); sdv::u8string ssExtendedMessage; ssExtendedMessage += ssSrcFile + "(" + std::to_string(uiSrcLine) + "): " + ssMessage; #ifdef _WIN32 if (!m_ptrWriter) { std::string logFileName = m_ssProgramtag + "_" + GetDateTime(std::chrono::system_clock::now()) + ".log"; auto path = GetExecDirectory() / logFileName; auto stream = std::make_shared(path, std::ios_base::out | std::ios_base::app); if (!stream->is_open()) { std::cerr << "ERROR: Log file cannot be created!" << std::endl; return; } m_ptrWriter = std::move(std::make_unique(stream)); if (!m_ptrWriter) { std::cerr << "ERROR: Cannot create CSV write object!" << std::endl; return; } } m_ptrWriter->Write(ssExtendedMessage, eSeverity, std::chrono::system_clock::now()); #elif defined __unix__ if (!m_bLogOpen) openlog(m_ssProgramtag.c_str(), LOG_PID | LOG_CONS, LOG_USER); m_bLogOpen = true; switch(eSeverity) { case sdv::core::ELogSeverity::trace : syslog(LOG_NOTICE, "%s", ssExtendedMessage.c_str()); break; case sdv::core::ELogSeverity::debug : syslog(LOG_DEBUG, "%s", ssExtendedMessage.c_str()); break; case sdv::core::ELogSeverity::info : syslog(LOG_INFO, "%s", ssExtendedMessage.c_str()); break; case sdv::core::ELogSeverity::warning : syslog(LOG_WARNING, "%s", ssExtendedMessage.c_str()); break; case sdv::core::ELogSeverity::error : syslog(LOG_ERR, "%s", ssExtendedMessage.c_str()); break; case sdv::core::ELogSeverity::fatal : syslog(LOG_CRIT, "%s", ssExtendedMessage.c_str()); break; default: std::cerr << "ERROR: Logging level is undefined!"; break; } #else #error OS not supported! #endif } void CLogger::SetProgramTag(const sdv::u8string& ssTag) { std::unique_lock lock(m_mtxLogger); if (m_ssProgramtag.empty()) m_ssProgramtag = ssTag; } sdv::u8string CLogger::GetProgramTag() const { return m_ssProgramtag; } void CLogger::SetLogFilter(/*in*/ sdv::core::ELogSeverity eSeverity, /*in*/ sdv::core::ELogSeverity eViewSeverity) { m_eFilter = eSeverity; m_eViewFilter = eViewSeverity; } sdv::core::ELogSeverity CLogger::GetLogFilter() const { return m_eFilter; } sdv::core::ELogSeverity CLogger::GetViewFilter() const { return m_eViewFilter; } std::string CLogger::GetDateTime(std::chrono::time_point timestamp) { using namespace std::chrono; std::stringstream output; microseconds micros = duration_cast(timestamp.time_since_epoch()); std::string timeFormat = "_%Y.%m.%d_%H-%M-%S"; std::time_t time = system_clock::to_time_t(timestamp); output << std::put_time(std::localtime(&time), timeFormat.c_str()); return output.str(); }