| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- #include "logger.h"
- #include <iostream>
- #include <ctime>
- Logger& Logger::getInstance() {
- static Logger instance;
- return instance;
- }
- Logger::~Logger() {
- close();
- }
- void Logger::initialize(bool enableFileLogging, const std::string& logFilePath, LogLevel minLevel) {
- std::lock_guard<std::mutex> lock(m_mutex);
- m_fileLoggingEnabled = enableFileLogging;
- m_logFilePath = logFilePath;
- m_minLevel = minLevel;
- if (m_fileLoggingEnabled && !m_logFilePath.empty()) {
- m_logFile.open(m_logFilePath, std::ios::app);
- if (!m_logFile.is_open()) {
- std::cerr << "<3>ERROR: Failed to open log file: " << m_logFilePath << std::endl;
- m_fileLoggingEnabled = false;
- } else {
- // Write startup marker
- m_logFile << "\n=== Log started at " << getCurrentTimestamp() << " ===" << std::endl;
- m_logFile.flush();
- }
- }
- }
- void Logger::close() {
- std::lock_guard<std::mutex> lock(m_mutex);
- if (m_logFile.is_open()) {
- m_logFile << "=== Log closed at " << getCurrentTimestamp() << " ===" << std::endl;
- m_logFile.close();
- }
- }
- std::string Logger::getCurrentTimestamp() {
- auto now = std::chrono::system_clock::now();
- auto time_t_now = std::chrono::system_clock::to_time_t(now);
- auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
- now.time_since_epoch()) % 1000;
- std::tm tm_buf;
- localtime_r(&time_t_now, &tm_buf);
- std::ostringstream oss;
- oss << std::put_time(&tm_buf, "%Y-%m-%d %H:%M:%S");
- oss << '.' << std::setfill('0') << std::setw(3) << ms.count();
- return oss.str();
- }
- std::string Logger::levelToString(LogLevel level) {
- switch (level) {
- case LogLevel::DEBUG: return "DEBUG";
- case LogLevel::INFO: return "INFO";
- case LogLevel::WARNING: return "WARNING";
- case LogLevel::ERROR: return "ERROR";
- default: return "UNKNOWN";
- }
- }
- std::string Logger::levelToSystemdPriority(LogLevel level) {
- // systemd journal priority levels:
- // 0=emerg, 1=alert, 2=crit, 3=err, 4=warning, 5=notice, 6=info, 7=debug
- switch (level) {
- case LogLevel::DEBUG: return "<7>"; // debug
- case LogLevel::INFO: return "<6>"; // info
- case LogLevel::WARNING: return "<4>"; // warning
- case LogLevel::ERROR: return "<3>"; // error
- default: return "<6>";
- }
- }
- void Logger::log(LogLevel level, const std::string& message) {
- if (level < m_minLevel) {
- return;
- }
- std::lock_guard<std::mutex> lock(m_mutex);
- std::string timestamp = getCurrentTimestamp();
- std::string levelStr = levelToString(level);
- std::string priority = levelToSystemdPriority(level);
- // Console output with systemd priority prefix
- std::cout << priority << "[" << timestamp << "] "
- << levelStr << ": " << message << std::endl;
- // File output (without systemd priority)
- if (m_fileLoggingEnabled && m_logFile.is_open()) {
- m_logFile << "[" << timestamp << "] "
- << levelStr << ": " << message << std::endl;
- m_logFile.flush();
- }
- }
|