Chi-Tech
chi_log.h
Go to the documentation of this file.
1#ifndef CHI_LOG_H
2#define CHI_LOG_H
3
4#include "chi_logstream.h"
6#include "TimingLog.h"
7
8#include <utility>
9#include <vector>
10#include <memory>
11
12// ###################################################################
13namespace chi
14{
15/**Object for controlling logging.
16 *
17 * ## Part A: Output logs
18 * There are three levels of verbosity in ChiTech: Zero(Default), One and Two.
19 * These can be set on the command line via the switch -v followed by a
20 * space and the number for the verbosity (0,1 or 2).
21 *
22 * \code
23 * ./bin/ChiTech InputFile.lua -v 1
24 * \endcode
25 *
26 * The lua command `chiLogSetVerbosity(int_level)` achieves the same.\n\n
27 *
28 * Printing a log under the auspices of a verbosity level again has
29 * numerous options. Firstly, any log can be a normal log, a warning
30 * or an error. Secondly, a log can be either location 0 or all the locations
31 * in a parallel process environment. The log option enums defined under
32 * LOG_LVL are
33 - LOG_0, Used only for location 0
34 - LOG_0WARNING, Warning only for location 0
35 - LOG_0ERROR, Error only for location 0
36 - LOG_0VERBOSE_0, Default verbosity level
37 - LOG_0VERBOSE_1, Used only if verbosity level equals 1
38 - LOG_0VERBOSE_2, Used only if verbosity level equals 2
39 - LOG_ALL, Verbose level 0 all locations
40 - LOG_ALLWARNING, Warning for any location
41 - LOG_ALLERROR, Error for any location
42 - LOG_ALLVERBOSE_0, Default verbosity level
43 - LOG_ALLVERBOSE_1, Used only if verbosity level equals 1
44 - LOG_ALLVERBOSE_2, Used only if verbosity level equals 2
45
46 * A log can be made by first connecting code with the logger. This is done
47 * by including the log header and then defining an extern reference to the
48 * global object.
49 *
50 * \code
51 * #include <chi::log.h>
52 * extern ChiLog& chi::log;
53 * \endcode
54 *
55 * A log is then written inside a piece of code as follows:
56 *
57 * \code
58 * void PrintSomethingToLog()
59 * {
60 * chi::log.Log() << "This is printed on location 0 only";
61 * chi::log.Log0Warning() << "This is a warning";
62 * chi::log.Log0Error() << "This is an error";
63 * }
64 * \endcode
65 *
66 \verbatim
67 [0] This is printed on location 0 only
68 [0] **WARNING** This is a warning
69 [0] **!**ERROR**!** This is an error
70 \endverbatim
71 *
72 * ## Part B: Repeating events log
73 * Suppose a routine or segment of code gets called multiple times. Now
74 suppose
75 * we want to know how many times this routine was called, how long it ran
76 * (total and on-avg), or we want to know at which timestamp it ran every
77 time.
78 * We do this by using a repeating event. A repeating event is identified
79 * by a tag. Therefore the first step is to obtain a unique id for the event
80 using
81 * ChiLog::GetRepeatingEventTag.
82 *
83 * \code
84 * size_t tag = chi::log.GetRepeatingEventTag(std::string("Sweep Timing"))
85 * \endcode
86 *
87 * Events can now be logged using
88 * ChiLog::LogEvent(size_t ev_tag, ChiLog::EventType ev_type). As an example,
89 * consider we want to count the number of occurrences of an event. We trigger
90 * multiple occurences using
91 *
92 * \code
93 * chi::log.LogEvent(tag,ChiLog::EventType::SINGLE_OCCURRENCE);
94 * \endcode
95 *
96 * At the end of the block for which you wanted to log these events we can now
97 * extract the number of occurrences using
98 *
99 * \code
100 * double number_of_occ =
101 chi::log.ProcessEvent(tag,ChiLog::EventOperation::NUMBER_OF_OCCURRENCES);
102 *\endcode
103 *
104 * Below is a complete example:
105 *
106 \code
107 size_t tag = chi::log.GetRepeatingEventTag(std::string());
108
109 for (int i=0; i<5; ++i)
110 chi::log.LogEvent(tag,ChiLog::EventType::SINGLE_OCCURRENCE);
111
112 chi::log.LogAll()
113 << chi::log.ProcessEvent(tag,
114 ChiLog::EventOperation::NUMBER_OF_OCCURRENCES); \endcode \verbatim
115 6
116 \endverbatim
117
118 * Since chi::log is a global object this functionality is really powerful for
119 * use in modules or class objects where multiple methods can contribute to
120 * the same event track. For example an object can have an event tag as a
121 member
122 * and initialize it at construction then all of the objects methods can
123 * contribute to the event.
124 *
125 * ### Supplying event information
126 * In addition to the ChiLog::EventType the user can also supply a reference
127 to
128 * a ChiLog::EventInfo structure. Be cautious with this though because each
129 * event stored a double and a string which can look like a memory leak if
130 * multiple events are pushed up with event information. Developers can supply
131 * either a double or a string or both to an event info constructor to
132 * instantiate an instance. The event arb_value is by default 0.0 and the
133 event
134 * arb_info is by default an empty string. An example is shown below:
135 *
136 \code
137 size_t tag = chi::log.GetRepeatingEventTag(std::string());
138
139 for (int i=0; i<5; ++i)
140 {
141 auto ev_info = std::make_shared<ChiLog::EventInfo>(i*2.0);
142 chi::log.LogEvent(tag,ChiLog::EventType::SINGLE_OCCURRENCE,ev_info);
143 }
144
145 chi::log.LogAll()
146 << chi::log.ProcessEvent(tag, ChiLog::EventOperation::AVERAGE_VALUE);
147 \endcode
148 \verbatim
149 4.0
150 \endverbatim
151 *
152 * Event information can also be supplied by string values but then the
153 * average value is meaningless unless the average value is also supplied.
154 * For example:
155 *
156 \code
157 size_t tag = chi::log.GetRepeatingEventTag(std::string());
158
159 chi::log.LogEvent(tag,
160 ChiLog::EventType::SINGLE_OCCURRENCE,
161 std::make_shared<ChiLog::EventInfo>(std::string("A"),2.0));
162 chi::log.LogEvent(tag,
163 ChiLog::EventType::SINGLE_OCCURRENCE,
164 std::make_shared<ChiLog::EventInfo>(std::string("B")));
165 chi::log.LogEvent(tag,
166 ChiLog::EventType::SINGLE_OCCURRENCE,
167 std::make_shared<ChiLog::EventInfo>(std::string("C"),2.0));
168
169 chi::log.LogAll()
170 << chi::log.ProcessEvent(tag, ChiLog::EventOperation::AVERAGE_VALUE);
171 \endcode
172 \verbatim
173 1.33333
174 \endverbatim
175 *
176 * To get a string value of the event history developers can use
177 * ChiLog::PrintEventHistory along with the event tag. Just note that it will
178 * automatically be formatted for each location so no need to use chi::log to
179 * print it. Also, each event will be prepended with a program timestamp
180 * in seconds.
181 *
182 \code
183 std::cout << chi::log.PrintEventHistory(tag);
184 \endcode
185 \verbatim
186 1.33333
187 [0] 3.813119000 EVENT_CREATED
188 [0] 3.813120000 SINGLE_OCCURRENCE A
189 [0] 3.813121000 SINGLE_OCCURRENCE B
190 [0] 3.813122000 SINGLE_OCCURRENCE C
191 \endverbatim
192 * */
193class ChiLog : public TimingLog
194{
195public:
196 /**Logging level*/
198 {
199 LOG_0 = 1, ///< Used only for location 0
200 LOG_0WARNING = 2, ///< Warning only for location 0
201 LOG_0ERROR = 3, ///< Error only for location 0
202 LOG_0VERBOSE_0 = 4, ///< Default verbosity level
203 LOG_0VERBOSE_1 = 5, ///< Used only if verbosity level equals 1
204 LOG_0VERBOSE_2 = 6, ///< Used only if verbosity level equals 2
205 LOG_ALL = 7, ///< Verbose level 0 all locations
206 LOG_ALLWARNING = 8, ///< Warning for any location
207 LOG_ALLERROR = 9, ///< Error for any location
208 LOG_ALLVERBOSE_0 = 10, ///< Default verbosity level
209 LOG_ALLVERBOSE_1 = 11, ///< Used only if verbosity level equals 1
211 }; ///< Used only if verbosity level equals 2
212
213private:
216
217public:
218 static ChiLog& GetInstance() noexcept;
219
220private:
221 // 00
222 ChiLog() noexcept;
223
224public:
225 // 01
226 LogStream Log(LOG_LVL level = LOG_0);
227 void SetVerbosity(int int_level);
228 int GetVerbosity() const;
229
230 LogStream Log0() { return Log(LOG_0); }
236
243
244private:
245 class RepeatingEvent;
246
247public:
249 {
250 MAX_MEMORY_USAGE = 0 ///< Tag reserved for logging process memory
251 };
252 enum class EventType
253 {
254 EVENT_CREATED = 0, ///< Automatically signalled when event is created
255 SINGLE_OCCURRENCE = 1, ///< Signals a single occurrence
256 EVENT_BEGIN = 2, ///< Signals the begin of an event
257 EVENT_END = 3 ///< Signals the end of an event
258 };
259 enum class EventOperation
260 {
261 NUMBER_OF_OCCURRENCES =
262 0, ///< Counts creation events, single occurrences and begins
263 TOTAL_DURATION = 1, ///< Integrates times between begins and ends
264 AVERAGE_DURATION = 2, ///< Computes average time between begins and ends
265 MAX_VALUE = 3, ///< Computes the maximum of the EventInfo arb_value
266 AVERAGE_VALUE = 4 ///< Computes the average of the EventInfo arb_value
267 };
268 struct EventInfo;
269 struct Event;
270
271private:
272 std::vector<RepeatingEvent> repeating_events;
273
274public:
275 size_t GetRepeatingEventTag(std::string event_name);
276 size_t GetExistingRepeatingEventTag(std::string event_name);
277 void LogEvent(size_t ev_tag,
278 EventType ev_type,
279 const std::shared_ptr<EventInfo>& ev_info);
280 void LogEvent(size_t ev_tag, EventType ev_type);
281 std::string PrintEventHistory(size_t ev_tag);
282 double ProcessEvent(size_t ev_tag, EventOperation ev_operation);
283};
284} // namespace chi
285
286// ###################################################################
287/** */
289{
290 std::string arb_info;
291 double arb_value = 0.0;
292 EventInfo() : arb_info(std::string()) {}
293
294 explicit EventInfo(std::string in_string) : arb_info(std::move(in_string)) {}
295 explicit EventInfo(double in_value) : arb_value(in_value) {}
296 explicit EventInfo(std::string in_string, double in_value)
297 : arb_info(std::move(in_string)), arb_value(in_value)
298 {
299 }
300
301 virtual ~EventInfo() = default;
302
303 virtual std::string GetString() { return arb_info; }
304};
305
306// ###################################################################
307/** Object used by repeating events.*/
309{
310 const double ev_time = 0.0;
312 std::shared_ptr<EventInfo> ev_info;
313
314 Event(double in_time,
315 EventType in_ev_type,
316 std::shared_ptr<EventInfo> in_event_info)
317 : ev_time(in_time), ev_type(in_ev_type), ev_info(std::move(in_event_info))
318 {
319 }
320};
321
322// ###################################################################
323/**Repeating event object.*/
325{
326public:
327 explicit RepeatingEvent(std::string& name) : name_(name) {}
328
329 const std::string& Name() const { return name_; }
330
331 std::vector<Event>& Events() { return events_; }
332 const std::vector<Event>& Events() const { return events_; }
333
334 bool operator==(const RepeatingEvent& other)
335 {
336 return this->name_ == other.name_;
337 }
338
339private:
340 const std::string name_;
341 std::vector<Event> events_;
342
343};
344
345#endif // CHI_LOG_H
std::vector< Event > events_
Definition: chi_log.h:341
const std::string & Name() const
Definition: chi_log.h:329
const std::string name_
Definition: chi_log.h:340
bool operator==(const RepeatingEvent &other)
Definition: chi_log.h:334
const std::vector< Event > & Events() const
Definition: chi_log.h:332
RepeatingEvent(std::string &name)
Definition: chi_log.h:327
std::vector< Event > & Events()
Definition: chi_log.h:331
LogStream LogAllVerbose1()
Definition: chi_log.h:241
double ProcessEvent(size_t ev_tag, EventOperation ev_operation)
Definition: chi_log.cc:275
LogStream LogAllError()
Definition: chi_log.h:239
int verbosity_
Definition: chi_log.h:215
DummyStream dummy_stream_
Definition: chi_log.h:214
int GetVerbosity() const
Definition: chi_log.cc:172
LogStream Log0Warning()
Definition: chi_log.h:231
std::vector< RepeatingEvent > repeating_events
Definition: chi_log.h:269
@ MAX_MEMORY_USAGE
Tag reserved for logging process memory.
Definition: chi_log.h:250
LogStream Log0Error()
Definition: chi_log.h:232
void SetVerbosity(int int_level)
Definition: chi_log.cc:165
size_t GetExistingRepeatingEventTag(std::string event_name)
Definition: chi_log.cc:191
LogStream Log0()
Definition: chi_log.h:230
LogStream LogAllVerbose0()
Definition: chi_log.h:240
LogStream Log0Verbose0()
Definition: chi_log.h:233
LogStream Log0Verbose2()
Definition: chi_log.h:235
static ChiLog & GetInstance() noexcept
Definition: chi_log.cc:12
LogStream LogAll()
Definition: chi_log.h:237
LogStream LogAllVerbose2()
Definition: chi_log.h:242
@ SINGLE_OCCURRENCE
Signals a single occurrence.
std::string PrintEventHistory(size_t ev_tag)
Definition: chi_log.cc:234
LogStream Log(LOG_LVL level=LOG_0)
Definition: chi_log.cc:35
size_t GetRepeatingEventTag(std::string event_name)
Definition: chi_log.cc:176
@ LOG_ALLVERBOSE_2
Definition: chi_log.h:210
@ LOG_0VERBOSE_2
Used only if verbosity level equals 2.
Definition: chi_log.h:204
@ LOG_0
Used only for location 0.
Definition: chi_log.h:199
@ LOG_ALLERROR
Error for any location.
Definition: chi_log.h:207
@ LOG_0VERBOSE_0
Default verbosity level.
Definition: chi_log.h:202
@ LOG_ALLVERBOSE_1
Used only if verbosity level equals 1.
Definition: chi_log.h:209
@ LOG_0WARNING
Warning only for location 0.
Definition: chi_log.h:200
@ LOG_ALLVERBOSE_0
Default verbosity level.
Definition: chi_log.h:208
@ LOG_0VERBOSE_1
Used only if verbosity level equals 1.
Definition: chi_log.h:203
@ LOG_0ERROR
Error only for location 0.
Definition: chi_log.h:201
@ LOG_ALLWARNING
Warning for any location.
Definition: chi_log.h:206
@ LOG_ALL
Verbose level 0 all locations.
Definition: chi_log.h:205
void LogEvent(size_t ev_tag, EventType ev_type, const std::shared_ptr< EventInfo > &ev_info)
Definition: chi_log.cc:204
LogStream LogAllWarning()
Definition: chi_log.h:238
LogStream Log0Verbose1()
Definition: chi_log.h:234
Event(double in_time, EventType in_ev_type, std::shared_ptr< EventInfo > in_event_info)
Definition: chi_log.h:314
std::shared_ptr< EventInfo > ev_info
Definition: chi_log.h:312
const EventType ev_type
Definition: chi_log.h:311
const double ev_time
Definition: chi_log.h:310
EventInfo(std::string in_string)
Definition: chi_log.h:294
EventInfo(double in_value)
Definition: chi_log.h:295
EventInfo(std::string in_string, double in_value)
Definition: chi_log.h:296
virtual ~EventInfo()=default
virtual std::string GetString()
Definition: chi_log.h:303
std::string arb_info
Definition: chi_log.h:290