Cbeam
Loading...
Searching...
No Matches
log_manager.hpp
Go to the documentation of this file.
1/*
2Copyright (c) 2025 acrion innovations GmbH
3Authors: Stefan Zipproth, s.zipproth@acrion.ch
4
5This file is part of Cbeam, see https://github.com/acrion/cbeam and https://cbeam.org
6
7Cbeam is offered under a commercial and under the AGPL license.
8For commercial licensing, contact us at https://acrion.ch/sales. For AGPL licensing, see below.
9
10AGPL licensing:
11
12Cbeam is free software: you can redistribute it and/or modify
13it under the terms of the GNU Affero General Public License as published by
14the Free Software Foundation, either version 3 of the License, or
15(at your option) any later version.
16
17Cbeam is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU Affero General Public License for more details.
21
22You should have received a copy of the GNU Affero General Public License
23along with Cbeam. If not, see <https://www.gnu.org/licenses/>.
24*/
25
26#pragma once
27
28#include <cassert> // for assert
29
30#include <atomic> // for std::atomic
31#include <filesystem> // for std::filesystem::operator/, std::filesystem::temp_directory_path, std::filesystem::path
32#include <iostream> // for std::operator<<, std::endl, std::basic_ostream, std::cerr
33#include <memory> // for std::shared_ptr, std::make_shared, std::__shared_ptr_access
34#include <mutex> // for std::recursive_mutex, std::lock_guard
35#include <string> // for std::char_traits, std::wstring, std::string
36
37namespace cbeam::logging
38{
39 class log;
40
48 class log_manager
49 {
50 public:
51 virtual ~log_manager() noexcept;
52
62 static inline void create_logfile(const std::filesystem::path& path, log_manager* instance = nullptr);
63
71 static inline void log_append(const std::wstring& str);
72
80 static inline void log_append(const std::string& str);
81
82 private:
83 log_manager() = default;
84 static inline log_manager* Instance();
85
91 static inline bool is_operational_for_logging();
92
93 std::shared_ptr<log> _log;
94 std::recursive_mutex _log_mutex;
95 static inline std::atomic<bool> _shutting_down{false};
96 static inline std::recursive_mutex _shutting_down_mutex;
97 };
98}
99
110#ifndef CBEAM_DEBUG_LOGGING
111 #ifdef _DEBUG
112 #define CBEAM_DEBUG_LOGGING 1
113 #else
114 #define CBEAM_DEBUG_LOGGING 0
115 #endif
116#endif
117
124#define CBEAM_LOG(s) ::cbeam::logging::log_manager::log_append(s);
125
135#if CBEAM_DEBUG_LOGGING
136 #define CBEAM_LOG_DEBUG(s) ::cbeam::logging::log_manager::log_append(s);
137#else
138 #define CBEAM_LOG_DEBUG(s)
139#endif
140
141#include "detail/logging_impl.hpp" // for cbeam::logging::log
142#include <cbeam/convert/string.hpp> // for cbeam::convert::from_string, cbeam::convert
143
144namespace cbeam::logging
145{
146 namespace convert = ::cbeam::convert;
147
149 {
150 try
151 {
152 std::lock_guard<std::recursive_mutex> lock(_shutting_down_mutex);
153 _shutting_down = true;
154 }
155 catch (const std::system_error& ex)
156 {
157 std::cerr << "cbeam::logging::log_manager::~log_manager: Could not lock the mutex. This indicates a serious (unexpected) bug that must be fixed during development phase." << std::endl;
158 assert(false);
159 }
160 }
161
162 inline void log_manager::create_logfile(const std::filesystem::path& path, log_manager* instance)
163 {
164 if (!_shutting_down_mutex.try_lock() && instance)
165 {
166 // An instance of LogManager has been created without locking _shutting_down_mutex, which should be impossible
167 assert(false);
168 }
169
170 if (!instance)
171 {
172 instance = Instance();
173 }
174
175 if (is_operational_for_logging())
176 {
177 std::lock_guard<std::recursive_mutex> lock(instance->_log_mutex);
178 if (!instance->_log)
179 {
180 instance->_log = std::make_shared<log>(path);
181 }
182 }
183
184 _shutting_down_mutex.unlock();
185 }
186
187 inline void log_manager::log_append(const std::wstring& str)
188 {
189 std::lock_guard<std::recursive_mutex> lockShuttingDown(_shutting_down_mutex);
190 auto instance = Instance();
191
192 if (is_operational_for_logging())
193 {
194 std::lock_guard<std::recursive_mutex> lockLog(instance->_log_mutex);
195 if (!instance->_log)
196 {
197 create_logfile(std::filesystem::temp_directory_path() / "Cbeam.log", instance);
198 }
199 instance->_log->append(str);
200 }
201 }
202
203 inline void log_manager::log_append(const std::string& str)
204 {
205 std::lock_guard<std::recursive_mutex> lockShuttingDown(_shutting_down_mutex);
206 if (is_operational_for_logging())
207 {
209 }
210 }
211
212 inline log_manager* log_manager::Instance()
213 {
214 static log_manager instance;
215 return &instance;
216 }
217
218 inline bool log_manager::is_operational_for_logging()
219 {
220 if (_shutting_down)
221 {
222 std::cerr << "Error: The main function returned or the shared library is being unloaded, but a logging attempt has been made." << std::endl
223 << std::endl
224 << "This condition indicates a serious issue that must be resolved during the development phase." << std::endl
225 << "The static cbeam::logging::log_manager instance has been correctly destroyed by the C++ runtime" << std::endl
226 << "due to the termination of the main application or the unloading of a shared library. However," << std::endl
227 << "another thread is still attempting to perform logging operations. It is crucial to ensure that" << std::endl
228 << "all threads are joined before the main application exits or before the shared library is unloaded." << std::endl;
229 assert(false);
230 }
231
232 return !_shutting_down;
233 }
234}
The log_manager class provides a global logging facility that can be used throughout the application.
Definition log_manager.hpp:49
virtual ~log_manager() noexcept
Definition log_manager.hpp:148
static void log_append(const std::wstring &str)
Appends a wide-string message to the current global log.
Definition log_manager.hpp:187
static void create_logfile(const std::filesystem::path &path, log_manager *instance=nullptr)
Creates or re-initializes the global log file at the specified path.
Definition log_manager.hpp:162
The log class provides basic file-based logging functionality.
Definition logging_impl.hpp:61
Contains conversion utilities to transform data between different formats and types....
Definition buffer.hpp:35
T from_string(const std::string &str)
Converts a given std::string to a specified type.
Definition string.hpp:171
Offers flexible logging mechanisms to record messages with timestamps and thread information....
Definition logging_impl.hpp:53