Visual Computing Library
Loading...
Searching...
No Matches
logger.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_MISC_LOGGER_LOGGER_H
24#define VCL_MISC_LOGGER_LOGGER_H
25
26#include "abstract_logger.h"
27
28#include <vclib/misc/timer.h>
29#include <vclib/types.h>
30
31#include <cassert>
32#include <cmath>
33#include <mutex>
34#include <stack>
35
36namespace vcl {
37
38template<typename Stream>
39class Logger : public AbstractLogger
40{
41 enum InternalLogLevel { START = DEBUG_LOG + 1, END };
42
43 static const uint TIMER_MAX_CHAR_NUMBER = 12;
44
45 uint mPercPrecision = 0;
46
47 // on top of the stack, we save the interval percentages of the current task
48 // values are between 0 and 100
49 std::stack<std::pair<double, double>> mIntervals;
50
51 // actual percentage (0 - 100), that is in the interval in top of the stack
52 double mGlobalPercProgress = 0;
53
54 double mStep = 1; // the value that corresponds to 1% on the current task
55
56 uint mLineWidth = 80;
57
58 Timer mTimer;
59
60 // progress status members
61 std::string mProgressMessage;
62 LogLevel mPrintLevel = PROGRESS_LOG;
63 uint mProgressStep;
64 uint mProgressPerc;
65 uint mProgressPercStep;
66 uint mProgressSize;
67 uint mLastProgress;
68 bool mIsProgressActive = false;
69
70 // settings
71 bool mPrintPerc = true;
72 bool mPrintMsgDuringProgress = true;
73 bool mIndent = true;
74 bool mPrintTimer = false;
75
76 std::mutex mMutex;
77
78public:
79 Logger()
80 {
81 mIntervals.push({0, 100});
82 updateStep();
83 }
84
85 void enableIndentation() override final { mIndent = true; }
86
87 void disableIndentation() override final { mIndent = false; }
88
89 void enablePrintPercentage() override final { mPrintPerc = true; }
90
91 void disablePrintPercentage() override final { mPrintPerc = false; }
92
93 void setPrintLevel(LogLevel level) override final { mPrintLevel = level; }
94
95 void enablePrintMessageDuringProgress() override final
96 {
97 mPrintMsgDuringProgress = true;
98 }
99
100 void disablePrintMessageDuringProgress() override final
101 {
102 mPrintMsgDuringProgress = false;
103 }
104
105 void enablePrintTimer() override final { mPrintTimer = true; }
106
107 void disablePrintTimer() override final { mPrintTimer = false; }
108
109 void reset() override final
110 {
111 while (!mIntervals.empty())
112 mIntervals.pop();
113 mIntervals.push({0, 100});
114 updateStep();
115 }
116
117 void setMaxLineWidth(uint w) override final { mLineWidth = w; }
118
119 void startTimer() override final { mTimer.start(); }
120
121 void stopTimer() override final { mTimer.stop(); }
122
123 double time() const override final { return mTimer.delay(); }
124
125 void startNewTask(double fromPerc, double toPerc, const std::string& action)
126 override final
127 {
128 printLine(action, START);
129
130 assert(fromPerc >= 0);
131 assert(toPerc <= 100);
132 std::pair<double, double> newP;
133 newP.first = mIntervals.top().first +
134 (mIntervals.top().second - mIntervals.top().first) *
135 (fromPerc / 100);
136 newP.second =
137 (mIntervals.top().second - mIntervals.top().first) * (toPerc / 100);
138 mGlobalPercProgress = newP.first;
139 mIntervals.push(newP);
140 updateStep();
141 }
142
143 void endTask(const std::string& action) override final
144 {
145 mGlobalPercProgress = mIntervals.top().second;
146 if (mIntervals.size() > 1) {
147 mIntervals.pop();
148 updateStep();
149
150 printLine(action, END);
151 }
152 }
153
154 double percentage() const override final
155 {
156 double k = std::pow(10, mPercPrecision);
157 uint c = mGlobalPercProgress * k;
158 return c / k;
159 }
160
161 virtual void setPercentage(uint newPerc) override
162 {
163 if (newPerc >= 0 && newPerc <= 100) {
164 mGlobalPercProgress = (mIntervals.top().first) + mStep * newPerc;
165 }
166 }
167
168 void log(const std::string& msg) const override final
169 {
170 printLine(msg, PROGRESS_LOG);
171 }
172
173 void log(const std::string& msg, LogLevel lvl) const override final
174 {
175 printLine(msg, lvl);
176 }
177
178 void log(uint perc, const std::string& msg) override final
179 {
180 log(perc, msg, PROGRESS_LOG);
181 }
182
183 void log(uint perc, const std::string& msg, LogLevel lvl) override final
184 {
185 if (perc >= 0 && perc <= 100)
186 setPercentage(perc);
187
188 printLine(msg, lvl);
189 }
190
192 const std::string& msg,
193 uint progressSize,
194 uint percPrintProgress = 10,
195 uint startPerc = 0,
196 uint endPerc = 100) override final
197 {
199 assert((endPerc - startPerc) > 0);
200 mIsProgressActive = true;
201 mProgressMessage = msg;
202 mProgressSize = progressSize;
203 mProgressPerc = startPerc;
204 mProgressPercStep = percPrintProgress;
205 mProgressStep =
207 if (mProgressStep == 0)
208 mProgressStep = progressSize;
209 mLastProgress = 0;
210 }
211
213 {
214 progress(mProgressSize);
215 mIsProgressActive = false;
216 }
217
218 void progress(uint n) override final
219 {
220 mMutex.lock();
221 assert(mIsProgressActive);
222 uint progress = n / mProgressStep;
223 if (mLastProgress < progress) {
224 mProgressPerc = progress * mProgressPercStep;
225 if (mPrintMsgDuringProgress)
226 log(mProgressPerc, mProgressMessage, PROGRESS_LOG);
227 else
228 setPercentage(mProgressPerc);
229 mLastProgress = progress;
230 }
231 mMutex.unlock();
232 }
233
234protected:
243 virtual Stream* levelStream(LogLevel lvl) const = 0;
244
245 virtual void alignLeft(Stream& o) const {}
246
247 virtual void alignRight(Stream& o) const {}
248
249 virtual void setWidth(Stream& o, uint w) const {}
250
251 virtual void flush(Stream& o) const {}
252
253private:
254 void updateStep()
255 {
256 mStep = (mIntervals.top().second - mIntervals.top().first) / 100;
257 }
258
259 void printLine(const std::string& msg, uint lvl) const
260 {
261 if (!mPrintPerc && msg.empty())
262 return;
263
264 // lvl could be also InternalLogLevel BEGIN or END
265 LogLevel l = PROGRESS_LOG;
266 if (lvl <= DEBUG_LOG) {
267 l = (LogLevel) lvl;
268 }
269 if (l > mPrintLevel)
270 return;
271 Stream* stream = levelStream(l);
272
273 if (stream) {
274 uint s = 0;
275
276 if (mPrintPerc) {
277 s = printPercentage(*stream);
278 }
279 s += printIndentation(*stream);
280 printMessage(*stream, msg, lvl, s);
281 printElapsedTime(*stream);
282 *stream << "\n";
283 }
284 flush(*stream);
285 }
286
287 uint printPercentage(Stream& o) const
288 {
289 uint size = 3;
290 if (mPercPrecision > 0)
291 size += 1 + mPercPrecision;
292
293 o << "[";
294 alignRight(o);
295 setWidth(o, size);
296 o << percentage() << "%]";
297 return size + 3;
298 }
299
300 uint printIndentation(Stream& o) const
301 {
302 uint s = 0;
303 if (mIndent) {
304 uint n = mIntervals.size() - 1;
305 for (uint i = 0; i < n; i++) {
306 o << " ";
307 s += 2;
308 }
309 }
310 return s;
311 }
312
313 void printMessage(Stream& o, const std::string& msg, uint lvl, uint n) const
314 {
315 uint maxMsgSize = mLineWidth - n;
316 if (mPrintTimer)
317 maxMsgSize -= TIMER_MAX_CHAR_NUMBER;
318 switch (lvl) {
319 case LogLevel::ERROR_LOG:
320 maxMsgSize -= 8;
321 o << " ERROR: ";
322 break;
323 case LogLevel::WARNING_LOG:
324 maxMsgSize -= 10;
325 o << " WARNING: ";
326 break;
327 case LogLevel::PROGRESS_LOG:
328 maxMsgSize -= 1;
329 o << " ";
330 break;
331 case LogLevel::DEBUG_LOG:
332 maxMsgSize -= 9;
333 o << " (debug) ";
334 break;
335 case InternalLogLevel::START:
336 maxMsgSize -= 7;
337 o << " Start ";
338 break;
339 case InternalLogLevel::END:
340 maxMsgSize -= 5;
341 o << " End ";
342 break;
343 }
344 setWidth(o, maxMsgSize);
345 alignLeft(o);
346 o << msg.c_str();
347 }
348
349 void printElapsedTime(Stream& o) const
350 {
351 if (mPrintTimer) {
352 o << "[";
353 setWidth(o, TIMER_MAX_CHAR_NUMBER - 3);
354 alignRight(o);
355 o << mTimer.delay() << "s]";
356 }
357 }
358};
359
360} // namespace vcl
361
362#endif // VCL_MISC_LOGGER_LOGGER_H
The AbstractLogger class is used as common ancestor class for all the logger types in the library.
Definition abstract_logger.h:39
Definition logger.h:40
void setPrintLevel(LogLevel level) override final
Sets the maximum print level of the logger.
Definition logger.h:93
void log(const std::string &msg) const override final
Prints a message to the logger, with level LogLevel::PROGRESS and without modifying the current perce...
Definition logger.h:168
void log(const std::string &msg, LogLevel lvl) const override final
Prints a message to the logger, with the given level and without modifying the current percentage.
Definition logger.h:173
void log(uint perc, const std::string &msg, LogLevel lvl) override final
Prints a message to the logger, with the given level and with the given percentage.
Definition logger.h:183
void startProgress(const std::string &msg, uint progressSize, uint percPrintProgress=10, uint startPerc=0, uint endPerc=100) override final
Allows to easily manage progresses with the logger, along with the progress and endProgress member fu...
Definition logger.h:191
virtual Stream * levelStream(LogLevel lvl) const =0
Returns the stream corresponding to the given LogLevel.
double time() const override final
Returns the time passed since the last call to startTimer member function, or the time passed between...
Definition logger.h:123
void progress(uint n) override final
Allows to easily manage progresses with the logger, along with the startProgress and endProgress memb...
Definition logger.h:218
void log(uint perc, const std::string &msg) override final
Prints a message to the logger, with the level LogLevel::PROGRESS and with the given percentage.
Definition logger.h:178
void endProgress() override final
Allows to easily manage progresses with the logger, along with the startProgress and progress member ...
Definition logger.h:212
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
The Timer class allows to instantiate simple Timer objects that can be used everywhere.
Definition timer.h:42
double delay() const
Returns the time passed between the call of start() and this member function. Works also if the timer...
Definition timer.h:144
void start()
Starts the timer.
Definition timer.h:93
void stop()
Stops the timer.
Definition timer.h:108