FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
logging.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2024-present FERS Contributors (see AUTHORS.md).
4//
5// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
6
7/**
8 * @file logging.cpp
9 * @brief Implementation of the logging system.
10 */
11
12#include "logging.h"
13
14#include <chrono>
15#include <ctime>
16#include <filesystem>
17#include <iomanip>
18#include <iostream>
19#include <sstream>
20
21namespace logging
22{
24
25 void Logger::setLevel(const Level level) noexcept { _log_level.store(level, std::memory_order_relaxed); }
26
27 Level Logger::getLevel() const noexcept { return _log_level.load(std::memory_order_relaxed); }
28
29 std::string Logger::getCurrentTimestamp() noexcept
30 {
31 const auto now = std::chrono::system_clock::now();
32 const std::time_t time = std::chrono::system_clock::to_time_t(now);
33 std::tm tm{};
34#ifdef _WIN32
35 localtime_s(&tm, &time);
36#else
37 localtime_r(&time, &tm);
38#endif
39
40 std::ostringstream oss;
41 oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
42 return oss.str();
43 }
44
45 void Logger::log(const Level level, const std::string& message, const std::source_location& location) noexcept
46 {
47 if (level != Level::OFF && level >= getLevel())
48 {
49 Callback callback = nullptr;
50 void* callback_user_data = nullptr;
51 std::string line;
52
53 {
54 std::scoped_lock lock(_log_mutex);
55
56 const std::string filename = std::filesystem::path(location.file_name()).filename().string();
57 const std::string file_line = filename + ":" + std::to_string(location.line());
58
59 std::ostringstream oss;
60 oss << "[" << getCurrentTimestamp() << "] " << "[" << std::setw(7) << std::left << getLevelString(level)
61 << "] " << "[" << std::setw(30) << std::left << file_line << "] " << message;
62 line = oss.str();
63
64 std::cerr << line << '\n';
65
66 if (_log_file && _log_file->is_open())
67 {
68 *_log_file << line << '\n';
69 _log_file->flush();
70 }
71
72 callback = _callback;
73 callback_user_data = _callback_user_data;
74 }
75
76 if (callback != nullptr)
77 {
78 callback(level, line, callback_user_data);
79 }
80 }
81 }
82
83 void Logger::setCallback(Callback callback, void* user_data) noexcept
84 {
85 std::scoped_lock lock(_log_mutex);
86 _callback = callback;
87 _callback_user_data = user_data;
88 }
89
90 std::expected<void, std::string> Logger::logToFile(const std::string& filePath) noexcept
91 {
92 std::scoped_lock lock(_log_mutex);
93
94 std::ofstream file(filePath, std::ios::out | std::ios::trunc);
95 if (!file)
96 {
97 return std::unexpected("Unable to open log file: " + filePath);
98 }
99
100 _log_file = std::move(file);
101 return {};
102 }
103}
Enum class representing the log levels.
Thread-safe logger class for handling logging operations.
Definition logging.h:53
void log(Level level, const std::string &message, const std::source_location &location=std::source_location::current()) noexcept
Logs a message with a specific log level and source location.
Definition logging.cpp:45
std::expected< void, std::string > logToFile(const std::string &filePath) noexcept
Sets the log file path to log messages to a file.
Definition logging.cpp:90
void setCallback(Callback callback, void *user_data) noexcept
Sets an optional callback that receives each formatted log line.
Definition logging.cpp:83
void setLevel(Level level) noexcept
Sets the logging level.
Definition logging.cpp:25
void(*)(Level level, const std::string &line, void *user_data) Callback
Definition logging.h:55
Level getLevel() const noexcept
Gets the current logging level.
Definition logging.cpp:27
Header file for the logging system.
@ OFF
Special level to disable all logging.
std::string getLevelString(const Level level) noexcept
Converts a log level enum value to its string representation.
Definition logging.h:143
Logger logger
Externally available logger object.
Definition logging.cpp:23