Cbeam
Loading...
Searching...
No Matches
logging_impl.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
28namespace cbeam::concurrency
29{
30 template <typename Derived, typename MessageType>
31 class threaded_object;
32
33 template <typename Message>
34 class message_manager;
35}
36
38#include <cbeam/concurrency/thread.hpp> // for cbeam::concurrency::get_thread_name, cbeam::concurrency::thread_id_type, cbeam::concurrency::to_string, CBEAM:CONCURRENCY::GET_CURRENT_THREAD_ID, CBEAM_DEFAULT_THREAD_ID
39#include <cbeam/convert/string.hpp> // for cbeam::convert::from_string, cbeam::convert::to_string
40
41#include <cassert> // for assert
42
43#include <chrono> // for std::chrono::system_clock
44#include <exception> // for std::exception
45#include <filesystem> // for std::filesystem::path, std::filesystem::remove
46#include <fstream> // for std::operator<<, std::basic_ostream, std::endl, std::basic_ofstream, std::ofstream, std::wofstream, std::wstringstream
47#include <iostream> // for std::wcerr
48#include <memory> // for std::unique_ptr, std::make_unique
49#include <mutex> // for std::mutex, std::lock_guard
50#include <string> // for std::char_traits, std::operator<<, std::wstring, std::string_literals::operator""s, std::operator+, std::string_literals, std::string
51
53{
60 class log
61 {
62 public:
71 explicit log(const std::filesystem::path& log_path)
72 {
73 using namespace std::string_literals;
74 _log_path = log_path;
75
76 std::filesystem::create_directories(log_path.parent_path());
77
78 try
79 {
80 std::filesystem::remove(_log_path);
81 }
82 catch (const std::exception& ex)
83 {
84 do_append(convert::from_string<std::wstring>("Could not delete old log file: "s + ex.what()));
85 }
86
87 do_append(L"-------------------------------- start of log --------------------------------"s);
88 }
89
95 ~log() noexcept
96 {
97 try
98 {
99 using namespace std::string_literals;
100 std::lock_guard<std::mutex> lock(_mtx);
101 do_append(L"-------------------------------- end of log --------------------------------"s);
102 }
103 catch (const std::system_error& ex)
104 {
105 std::wcerr << "cbeam::logging::~log: Could not lock the mutex. This indicates a serious (unexpected) bug that must be fixed during development phase: "
106 << ex.what() << std::endl;
107 assert(false);
108 }
109 }
110
118 void append(const std::wstring& str) noexcept
119 {
120 try
121 {
122 std::wstring header;
124 if (!_mtx.try_lock())
125 {
126 // We just try to lock to optimize performance. If locking fails, we postpone the creation of the header
127 header = create_header(thread_id);
128 _mtx.lock();
129 }
130
131 do_append(str, thread_id, header);
132 }
133 catch (const std::exception& ex)
134 {
135 std::wcerr << "cbeam::logging::append: " << ex.what() << std::endl;
136 assert(false);
137 }
138
139 _mtx.unlock();
140 }
141
147 void append(const std::string& str) noexcept
148 {
149 append(std::wstring(str.begin(), str.end()));
150 }
151
152 private:
153 struct message
154 {
155 std::wstring text;
157 };
158
166 void do_append(const std::wstring& str, concurrency::thread_id_type thread_id = {}, std::wstring time = {}) const noexcept
167 {
168 try
169 {
170 if (thread_id == cbeam::concurrency::thread_id_type{})
172 if (time.empty())
173 time = create_header(thread_id);
174
175 std::wofstream(_log_path, std::ofstream::app) << time << str << std::endl;
176 }
177 catch (const std::exception& ex)
178 {
179 std::wcerr << str << " " << ex.what() << std::endl;
180 }
181 }
182
189 static std::wstring create_header(concurrency::thread_id_type thread_id)
190 {
191 std::wstringstream stream;
192 stream << current_time_to_wstring() << L" ("
193 << concurrency::to_string(thread_id, 0xFFFF) << L" "
194 << concurrency::get_thread_name(thread_id)
195 << L"): ";
196 return stream.str();
197 }
198
204 static std::wstring current_time_to_wstring()
205 {
206 return convert::from_string<std::wstring>(convert::to_string(std::chrono::system_clock::now()));
207 }
208
209 std::unique_ptr<concurrency::message_manager<message>> _message_manager;
210 std::filesystem::path _log_path;
211 std::mutex _mtx;
212 };
213}
Definition message_manager.hpp:102
Definition threaded_object.hpp:97
void append(const std::wstring &str) noexcept
Appends a wide-string message to the log, along with thread and timestamp information.
Definition logging_impl.hpp:118
log(const std::filesystem::path &log_path)
Constructs a log object that manages logging to a file.
Definition logging_impl.hpp:71
void append(const std::string &str) noexcept
Appends a narrow-string message to the log (converted internally to wide-string).
Definition logging_impl.hpp:147
~log() noexcept
Destructor writes a final footer line before the log object is destroyed.
Definition logging_impl.hpp:95
Provides concurrency primitives and abstractions for multithreaded programming. It features the power...
Definition message_manager.hpp:47
HANDLE thread_id_type
Definition thread.hpp:50
thread_id_type get_current_thread_id()
Retrieves the current thread's native identifier.
Definition thread.hpp:63
std::wstring to_string(concurrency::thread_id_type id, std::size_t mask=(std::size_t) -1)
Returns a hexadecimal string representation of the given thread ID.
Definition thread.hpp:214
std::wstring get_thread_name(thread_id_type id)
Retrieves the name of the specified thread.
Definition thread.hpp:184
std::string to_string(const container::buffer &b)
Creates a std::string from the contents of a container::buffer.
Definition buffer.hpp:42
T from_string(const std::string &str)
Converts a given std::string to a specified type.
Definition string.hpp:171
std::wstring from_string< std::wstring >(const std::string &str)
Converts the given std::string to std::wstring using UTF-8 to UTF-16 encoding.
Definition string.hpp:196
Offers flexible logging mechanisms to record messages with timestamps and thread information....
Definition logging_impl.hpp:53