Visual Computing Library  devel
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_BASE_LOGGER_LOGGER_H
24#define VCL_BASE_LOGGER_LOGGER_H
25
26#include "abstract_logger.h"
27
28#include <vclib/base/timer.h>
29
30#include <cassert>
31#include <cmath>
32#include <mutex>
33#include <stack>
34
35namespace vcl {
36
37template<typename Stream>
38class Logger : public AbstractLogger
39{
41 {
42 std::string message;
43 uint step;
44 uint perc;
45 uint percStep;
46 uint size;
47 uint lastProgress;
48 bool isActive = false;
49 };
50
51 enum InternalLogLevel { START = DEBUG_LOG + 1, END };
52
53 static const uint TIMER_MAX_CHAR_NUMBER = 12;
54
55 uint mPercPrecision = 0;
56
57 // on top of the stack, we save the interval percentages of the current task
58 // values are between 0 and 100
59 std::stack<std::pair<double, double>> mIntervals;
60
61 // actual percentage (0 - 100), that is in the interval in top of the stack
62 double mGlobalPercProgress = 0;
63
64 double mStep = 1; // the value that corresponds to 1% on the current task
65
66 uint mLineWidth = 80;
67
68 Timer mTimer;
69
70 LogLevel mPrintLevel = PROGRESS_LOG;
71
72 // progress status members
73 ProgressStatus mProgress;
74
75 // settings
76 bool mPrintPerc = true;
77 bool mPrintMsgDuringProgress = true;
78 bool mIndent = true;
79 bool mPrintTimer = false;
80
81 std::mutex mMutex;
82
83public:
84 Logger()
85 {
86 mIntervals.push({0, 100});
87 updateStep();
88 }
89
90 void enableIndentation() override final { mIndent = true; }
91
92 void disableIndentation() override final { mIndent = false; }
93
94 void enablePrintPercentage() override final { mPrintPerc = true; }
95
96 void disablePrintPercentage() override final { mPrintPerc = false; }
97
98 void setPrintLevel(LogLevel level) override final { mPrintLevel = level; }
99
100 void enablePrintMessageDuringProgress() override final
101 {
102 mPrintMsgDuringProgress = true;
103 }
104
105 void disablePrintMessageDuringProgress() override final
106 {
107 mPrintMsgDuringProgress = false;
108 }
109
110 void enablePrintTimer() override final { mPrintTimer = true; }
111
112 void disablePrintTimer() override final { mPrintTimer = false; }
113
114 void reset() override final
115 {
116 while (!mIntervals.empty())
117 mIntervals.pop();
118 mIntervals.push({0, 100});
119 updateStep();
120 }
121
122 void setMaxLineWidth(uint w) override final { mLineWidth = w; }
123
124 void startTimer() override final { mTimer.start(); }
125
126 void stopTimer() override final { mTimer.stop(); }
127
128 double time() const override final { return mTimer.delay(); }
129
130 void startNewTask(double fromPerc, double toPerc, const std::string& action)
131 override final
132 {
133 printLine(action, START);
134
135 assert(fromPerc >= 0);
136 assert(toPerc <= 100);
137 std::pair<double, double> actualP = mIntervals.top();
138 std::pair<double, double> newP;
139 newP.first =
140 actualP.first + (actualP.second - actualP.first) * (fromPerc / 100);
141 newP.second = (actualP.second - actualP.first) * (toPerc / 100);
142 mGlobalPercProgress = newP.first;
143 mIntervals.push(newP);
144 updateStep();
145 }
146
147 void endTask(const std::string& action) override final
148 {
149 mGlobalPercProgress = mIntervals.top().second;
150 if (mIntervals.size() > 1) {
151 mIntervals.pop();
152 updateStep();
153
154 printLine(action, END);
155 }
156 }
157
158 double percentage() const override final
159 {
160 double k = std::pow(10, mPercPrecision);
161 uint c = mGlobalPercProgress * k;
162 return c / k;
163 }
164
165 virtual void setPercentage(uint newPerc) override
166 {
167 if (newPerc >= 0 && newPerc <= 100) {
168 mGlobalPercProgress = (mIntervals.top().first) + mStep * newPerc;
169 }
170 }
171
172 void log(const std::string& msg) const override final
173 {
174 printLine(msg, PROGRESS_LOG);
175 }
176
177 void log(const std::string& msg, LogLevel lvl) const override final
178 {
179 printLine(msg, lvl);
180 }
181
182 void log(uint perc, const std::string& msg) override final
183 {
184 log(perc, msg, PROGRESS_LOG);
185 }
186
187 void log(uint perc, const std::string& msg, LogLevel lvl) override final
188 {
189 if (perc >= 0 && perc <= 100)
190 setPercentage(perc);
191
192 printLine(msg, lvl);
193 }
194
196 const std::string& msg,
197 uint progressSize,
198 uint percPrintProgress = 10,
199 uint startPerc = 0,
200 uint endPerc = 100) override final
201 {
203 assert((endPerc - startPerc) > 0);
204 mProgress.isActive = true;
205 mProgress.message = msg;
206 mProgress.size = progressSize;
207 mProgress.perc = startPerc;
208 mProgress.percStep = percPrintProgress;
209 mProgress.step =
211 if (mProgress.step == 0)
212 mProgress.step = progressSize;
213 mProgress.lastProgress = 0;
214 }
215
217 {
218 progress(mProgress.size);
219 mProgress.isActive = false;
220 }
221
222 void progress(uint n) override final
223 {
224 mMutex.lock();
225 assert(mProgress.isActive);
226 uint progress = n / mProgress.step;
227 if (mProgress.lastProgress < progress) {
228 mProgress.perc = progress * mProgress.percStep;
229 if (mPrintMsgDuringProgress)
230 log(mProgress.perc, mProgress.message, PROGRESS_LOG);
231 else
232 setPercentage(mProgress.perc);
233 mProgress.lastProgress = progress;
234 }
235 mMutex.unlock();
236 }
237
238protected:
247 virtual Stream* levelStream(LogLevel lvl) const = 0;
248
249 virtual void alignLeft(Stream& o) const {}
250
251 virtual void alignRight(Stream& o) const {}
252
253 virtual void setWidth(Stream& o, uint w) const {}
254
255 virtual void flush(Stream& o) const {}
256
257private:
258 void updateStep()
259 {
260 mStep = (mIntervals.top().second - mIntervals.top().first) / 100;
261 }
262
263 void printLine(const std::string& msg, uint lvl) const
264 {
265 if (!mPrintPerc && msg.empty())
266 return;
267
268 // lvl could be also InternalLogLevel BEGIN or END
269 LogLevel l = PROGRESS_LOG;
270 if (lvl <= DEBUG_LOG) {
271 l = (LogLevel) lvl;
272 }
273 if (l > mPrintLevel)
274 return;
275 Stream* stream = levelStream(l);
276
277 if (stream) {
278 uint s = 0;
279
280 if (mPrintPerc) {
281 s = printPercentage(*stream);
282 }
283 s += printIndentation(*stream);
284 printMessage(*stream, msg, lvl, s);
285 printElapsedTime(*stream);
286 *stream << "\n";
287 }
288 flush(*stream);
289 }
290
291 uint printPercentage(Stream& o) const
292 {
293 uint size = 3;
294 if (mPercPrecision > 0)
295 size += 1 + mPercPrecision;
296
297 o << "[";
298 alignRight(o);
299 setWidth(o, size);
300 o << percentage() << "%]";
301 return size + 3;
302 }
303
304 uint printIndentation(Stream& o) const
305 {
306 uint s = 0;
307 if (mIndent) {
308 uint n = mIntervals.size() - 1;
309 for (uint i = 0; i < n; i++) {
310 o << " ";
311 s += 2;
312 }
313 }
314 return s;
315 }
316
317 void printMessage(Stream& o, const std::string& msg, uint lvl, uint n) const
318 {
319 uint maxMsgSize = mLineWidth - n;
320 if (mPrintTimer)
321 maxMsgSize -= TIMER_MAX_CHAR_NUMBER;
322 switch (lvl) {
323 case LogLevel::ERROR_LOG:
324 maxMsgSize -= 8;
325 o << " ERROR: ";
326 break;
327 case LogLevel::WARNING_LOG:
328 maxMsgSize -= 10;
329 o << " WARNING: ";
330 break;
331 case LogLevel::PROGRESS_LOG:
332 maxMsgSize -= 1;
333 o << " ";
334 break;
335 case LogLevel::DEBUG_LOG:
336 maxMsgSize -= 9;
337 o << " (debug) ";
338 break;
339 case InternalLogLevel::START:
340 maxMsgSize -= 7;
341 o << " Start ";
342 break;
343 case InternalLogLevel::END:
344 maxMsgSize -= 5;
345 o << " End ";
346 break;
347 }
348 setWidth(o, maxMsgSize);
349 alignLeft(o);
350 o << msg.c_str();
351 }
352
353 void printElapsedTime(Stream& o) const
354 {
355 if (mPrintTimer) {
356 o << "[";
357 setWidth(o, TIMER_MAX_CHAR_NUMBER - 3);
358 alignRight(o);
359 o << mTimer.delay() << "s]";
360 }
361 }
362};
363
364} // namespace vcl
365
366#endif // VCL_BASE_LOGGER_LOGGER_H
The AbstractLogger class is used as common ancestor class for all the logger types in the library.
Definition abstract_logger.h:40
A class representing a box in N-dimensional space.
Definition box.h:46
PointT size() const
Computes the size of the box.
Definition box.h:267
Definition logger.h:39
void setPrintLevel(LogLevel level) override final
Sets the maximum print level of the logger.
Definition logger.h:98
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:172
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:177
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:187
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:195
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:128
void progress(uint n) override final
Allows to easily manage progresses with the logger, along with the startProgress and endProgress memb...
Definition logger.h:222
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:182
void endProgress() override final
Allows to easily manage progresses with the logger, along with the startProgress and progress member ...
Definition logger.h:216
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:147
void start()
Starts the timer.
Definition timer.h:93
void stop()
Stops the timer.
Definition timer.h:111
Definition logger.h:41