comparison Utils/Log.h @ 1:0b3630a29ad8

Initial version based on previous repository. Project was ported to QT6 and in now cmake based.
author Ideenmodellierer <tiefenrauscher@web.de>
date Thu, 27 Nov 2025 18:40:28 +0100
parents
children
comparison
equal deleted inserted replaced
0:76ccd6ce50c0 1:0b3630a29ad8
1 //////////////////////////////////////////////////////////////////////////////
2 /// \file Log.h
3 /// \brief Basic logging tool
4 /// \author JD Gascuel.
5 /// \copyright (c) 2011-2016 JD Gascuel. All rights reserved.
6 /// $Id$
7 //////////////////////////////////////////////////////////////////////////////
8 //
9 // BSD 2-Clause License:
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions
13 // are met:
14 //
15 // 1. Redistributions of source code must retain the above copyright notice,
16 // this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright notice,
19 // this list of conditions and the following disclaimer in the documentation
20 // and/or other materials provided with the distribution.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 // THE POSSIBILITY OF SUCH DAMAGE.
33 //
34 //////////////////////////////////////////////////////////////////////////////
35 // HISTORY
36 // 2013-07-01 jDG: Creation.
37 // 2016-05-24 jDG: BSD-2 version.
38
39 #ifndef LOG_H
40 #define LOG_H
41
42 #include <QString>
43 #include <QStringList>
44 #include <QByteArray>
45
46 //class QStringList;
47 //class QByteArray;
48
49 #define LOG_MAX_MESSAGE_LENGTH 2048
50
51 //////////////////////////////////////////////////////////////////////////////
52 /// \brief Basic logging tool
53 ///
54 ///
55 /// Provides easy and centralized log messages for the application.
56 /// Typical usage:
57 /// \code
58 /// main(int argc, char* argv[])
59 /// {
60 /// Log::autoLoad(argc, argv); // Read XML configuration.
61 /// LOG_TRACE("... "); // Just a tick where we are.
62 ///
63 /// LOG_INFO("Main started"); // Visible message (users can see it).
64 /// LOG_TRACE("Now argc=" << argc);
65 /// LOG_TRACE("Invisible message, only for log files");
66 /// LOG_DEBUG("Invisible, and logged only if run with a "-d" argument");
67 /// }
68 /// \endcode
69 ///
70 /// \note that message destination can be multiple, and are the responsability
71 /// of the LogAppender class hierarchy.
72 ///
73 /// \sa LogAppender, LogConsole, LogFile.
74 class Log
75 {
76 /// Application's reference.
77 static QString _applicationPath;
78 static QString _applicationName;
79
80 public:
81 //////////////////////////////////////////////////////////////////////////
82 /// \{
83 /// \name Record message and context
84
85 //------------------------------------------------------------------------
86 /// \brief Log level: severity scale.
87 enum Level {
88 LEVEL_NOERROR = 0,
89 LEVEL_DEBUG, ///< The most verbose one, used only during debug session.
90 LEVEL_TRACE, ///< Messages to be put in silent log files, for post-mortem analysis.
91 LEVEL_INFO, ///< General information send to the final user.
92 LEVEL_WARNING, ///< Error reported to the user (eg. with a Qt warning box. \sa LogAppenderWindow).
93 LEVEL_THROW, ///< Error that is mean to be catched, and corrected automatically.
94 LEVEL_ERROR ///< Fatal error that cannot be recovered. The program should halt.
95 };
96
97 //------------------------------------------------------------------------
98 const Level level; ///< Event's log level.
99 const QString file; ///< Source file that fired the log event.
100 const int line; ///< Source line that fired the log event.
101 const QString function; ///< Function (and class) that fired the event.
102 QString message; ///< The log message itself.
103
104 /// \}
105 //////////////////////////////////////////////////////////////////////////
106 /// \{
107 /// \name Global services
108
109 //------------------------------------------------------------------------
110 /// \brief Minimal error level to log.
111 ///
112 /// Defaults to LEVEL_TRACE.
113 static Level minLevel;
114
115 //------------------------------------------------------------------------
116 /// \brief Initialize the log system, by loading some XML config.
117 ///
118 /// Might be used to change logging configuration of installed
119 /// applications.
120 //------------------------------------------------------------------------
121 /// Initialize the log system, by loading some XML config.
122 static void autoLoad(int argc, char *argv[]);
123
124 //------------------------------------------------------------------------
125 /// \brief Initialize the log system, without configurations.
126 ///
127 /// Then one can instanciate LogAppender classes in a static way.
128 static void init(int& argc, char* argv[]);
129
130 //------------------------------------------------------------------------
131 /// \brief End the log systems, closing all appenders.
132 static void close();
133
134 //------------------------------------------------------------------------
135 /// \brief Utility to retrieve where the executable was installed.
136 static inline QString applicationPath();
137
138 /// \brief Utility to retrieve the executable's name.
139 static inline QString applicationName();
140
141 /// \}
142
143 protected:
144 /// \brief Constructor
145 ///
146 /// All message are to be created by a LogAction instance, responsible
147 /// to build-up the message, and to send it to LogAppender instances.
148 Log(Level level, const char *file, int line, const char *function);
149 };
150
151 inline QString Log::applicationPath() { return _applicationPath; }
152 inline QString Log::applicationName() { return _applicationName; }
153
154 //////////////////////////////////////////////////////////////////////////////
155 /// \brief Creates a Log event.
156 ///
157 /// Uses object's destructor to send the Log into all registered log appenders.
158 class LogAction
159 : public Log
160 {
161 public:
162 /// Starts a log line, with timestamp and source-stamp.
163 LogAction(Level level, const char* file, int line, const char* function);
164
165 /// Finish (and print) a log line.
166 ~LogAction();
167
168 /// Appends a single char to the log line.
169 LogAction& operator<<(char msg);
170 /// Appends a single char to the log line.
171 LogAction& operator<<(unsigned char msg);
172
173 /// Appends a C string to the log line.
174 LogAction& operator<<(const char* msg);
175 /// Appends a Qt's wide-char string to the log line, converted to Latin1.
176 LogAction& operator<<(const QString& msg);
177 /// Appends a list of Qt's wide-char strings.
178 LogAction& operator<<(const QStringList& msg);
179 /// Appends a Qt's single-byte-string to the log line.
180 LogAction& operator<<(const QByteArray& msg);
181
182 /// Appends a float/double to the log line.
183 LogAction& operator<<(double value);
184 /// Appends a signed int/short/byte to the log line.
185 LogAction& operator<<(int value);
186 /// Appends an unsigned int/short/byte to the log line.
187 LogAction& operator<<(unsigned int value);
188
189 // Resole ambiguities for the C++ compiler.
190 /// Appends a signed long to the log line.
191 LogAction& operator<<(long value);
192 /// Appends an unsigned long to the log line.
193 LogAction& operator<<(unsigned long value);
194 /// Appends a signed long long to the log line.
195 LogAction& operator<<(long long value);
196 /// Appends an unsigned long long to the log line.
197 LogAction& operator<<(unsigned long long value);
198
199 /// Print any pointer as an Hex address:
200 LogAction& operator<<(const void* ptr);
201 };
202
203 #ifndef LOG_FUNCTION_
204 # if defined __PRETTY_FUNCTION__
205 # define LOG_FUNCTION_ __PRETTY_FUNCTION__
206 # elif defined __FUNCSIG__
207 # define LOG_FUNCTION_ __FUNCSIG__
208 # elif defined __FUNCTION__
209 # define LOG_FUNCTION_ __FUNCTION__
210 # elif defined __func__
211 # define LOG_FUNCTION_ __func__
212 # elif defined LINUX
213 # define LOG_FUNCTION_ __PRETTY_FUNCTION__
214 # else
215 # define LOG_FUNCTION_ __FILE__
216 # endif
217 #endif
218
219 #define LOG_DEBUG(msg) do { if( Log::minLevel <= Log::LEVEL_DEBUG ) LogAction(Log::LEVEL_DEBUG, __FILE__, __LINE__, LOG_FUNCTION_ ) << msg; } while(0)
220 #define LOG_TRACE(msg) do { if( Log::minLevel <= Log::LEVEL_TRACE ) LogAction(Log::LEVEL_TRACE, __FILE__, __LINE__, LOG_FUNCTION_ ) << msg; } while(0)
221 #define LOG_INFO(msg) do { if( Log::minLevel <= Log::LEVEL_INFO ) LogAction(Log::LEVEL_INFO, __FILE__, __LINE__, LOG_FUNCTION_ ) << msg; } while(0)
222 #define LOG_WARNING(msg) do { if( Log::minLevel <= Log::LEVEL_WARNING) LogAction(Log::LEVEL_WARNING, __FILE__, __LINE__, LOG_FUNCTION_ ) << msg; } while(0)
223 #define LOG_ERROR(msg) do { if( Log::minLevel <= Log::LEVEL_ERROR ) LogAction(Log::LEVEL_ERROR, __FILE__, __LINE__, LOG_FUNCTION_ ) << msg; } while(0)
224
225 #include <sstream> // Für std::ostringstream
226 #include "Exception.h"
227
228 // Hilfsmakros für stringification
229 #define STRINGIFY(x) #x
230 #define TOSTRING(x) STRINGIFY(x)
231
232 #define LOG_THROW_E(EXCEPTION, msg) \
233 do { \
234 LogAction log(Log::LEVEL_THROW, __FILE__, __LINE__, LOG_FUNCTION_ ); \
235 log << msg; \
236 throw EXCEPTION(log.message); \
237 } while(0)
238
239 #define LOG_THROW(msg) \
240 do { \
241 LogAction log(Log::LEVEL_THROW, __FILE__, __LINE__, LOG_FUNCTION_ ); \
242 log << msg; \
243 throw ::Exception(log.message); \
244 } while(0)
245
246 #define assert(e) \
247 do { if( !(e) ) \
248 LOG_THROW("Assert: " #e); \
249 } while(0)
250
251 #endif // LOG_H