|
|
@@ -1,6 +1,7 @@
|
|
|
#include "logger.h"
|
|
|
#include <iostream>
|
|
|
#include <ctime>
|
|
|
+#include <fstream>
|
|
|
|
|
|
Logger& Logger::getInstance() {
|
|
|
static Logger instance;
|
|
|
@@ -19,6 +20,12 @@ void Logger::initialize(bool enableFileLogging, const std::string& logFilePath,
|
|
|
m_internalMinLevel = minLevel;
|
|
|
m_httpMinLevel = minLevel;
|
|
|
|
|
|
+ // Perform systemd detection once during initialization
|
|
|
+ if (!m_systemdDetected) {
|
|
|
+ m_isRunningUnderSystemd = detectSystemd();
|
|
|
+ m_systemdDetected = true;
|
|
|
+ }
|
|
|
+
|
|
|
if (m_fileLoggingEnabled && !m_logFilePath.empty()) {
|
|
|
m_logFile.open(m_logFilePath, std::ios::app);
|
|
|
if (!m_logFile.is_open()) {
|
|
|
@@ -124,3 +131,78 @@ void Logger::log(LogLevel level, const std::string& message, LoggerType type) {
|
|
|
m_logFile.flush();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+bool Logger::isRunningUnderSystemd() {
|
|
|
+ std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
+
|
|
|
+ // Perform detection if not already done
|
|
|
+ if (!m_systemdDetected) {
|
|
|
+ m_isRunningUnderSystemd = detectSystemd();
|
|
|
+ m_systemdDetected = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return m_isRunningUnderSystemd;
|
|
|
+}
|
|
|
+
|
|
|
+bool Logger::detectSystemd() {
|
|
|
+ // Method 1: Try sd_booted() if systemd development libraries are available
|
|
|
+ // This is the most reliable method when available
|
|
|
+ #ifdef HAVE_SYSTEMD
|
|
|
+ // If we have systemd development libraries, we could use sd_booted()
|
|
|
+ // But we'll implement fallback methods for broader compatibility
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // Method 2: Check for NOTIFY_SOCKET environment variable
|
|
|
+ // This is set by systemd when using sd_notify()
|
|
|
+ const char* notifySocket = std::getenv("NOTIFY_SOCKET");
|
|
|
+ if (notifySocket && notifySocket[0] != '\0') {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Method 3: Check for JOURNAL_STREAM environment variable
|
|
|
+ // This is set by systemd for services with StandardOutput=journal
|
|
|
+ const char* journalStream = std::getenv("JOURNAL_STREAM");
|
|
|
+ if (journalStream && journalStream[0] != '\0') {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Method 4: Check cgroup filesystem for systemd
|
|
|
+ // Look for systemd-specific cgroup paths
|
|
|
+ std::ifstream cgroupFile("/proc/1/cgroup");
|
|
|
+ if (cgroupFile.is_open()) {
|
|
|
+ std::string line;
|
|
|
+ while (std::getline(cgroupFile, line)) {
|
|
|
+ if (line.find("systemd") != std::string::npos) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ cgroupFile.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Method 5: Check if /sys/fs/cgroup/systemd exists
|
|
|
+ struct stat sb;
|
|
|
+ if (stat("/sys/fs/cgroup/systemd", &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Method 6: Check PID 1 command line for "systemd"
|
|
|
+ std::ifstream cmdlineFile("/proc/1/cmdline");
|
|
|
+ if (cmdlineFile.is_open()) {
|
|
|
+ std::string cmdline;
|
|
|
+ std::getline(cmdlineFile, cmdline);
|
|
|
+ cmdlineFile.close();
|
|
|
+
|
|
|
+ // cmdline contains null-separated arguments, replace nulls with spaces for searching
|
|
|
+ for (size_t i = 0; i < cmdline.length(); ++i) {
|
|
|
+ if (cmdline[i] == '\0') {
|
|
|
+ cmdline[i] = ' ';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmdline.find("systemd") != std::string::npos) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|