-
Notifications
You must be signed in to change notification settings - Fork 184
/
Copy pathLogger.hpp
741 lines (661 loc) · 25.6 KB
/
Logger.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
// This file is part of the ACTS project.
//
// Copyright (C) 2016 CERN for the benefit of the ACTS project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
#pragma once
// STL include(s)
#include <ctime>
#include <iomanip>
#include <iostream>
#include <memory>
#include <optional>
#include <sstream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <thread>
#include <utility>
/// @defgroup Logging Logging
// clang-format off
/// @brief macro to use a local Acts::Logger object
/// @ingroup Logging
///
/// @param log_object logger instance of type
// <tt>std::unique_ptr<const Acts::Logger></tt>
///
/// @pre In the current scope, the symbol @c logger is not yet defined.
/// @post The ownership of the given @c log_object is transferred and
/// @c log_object should not be used directly any more.
///
/// This macro allows to use a locally defined logging object with the ACTS_*
/// logging macros. The envisaged usage is the following:
///
/// @code{.cpp}
/// void myFunction() {
/// std::unique_ptr<const Acts::Logger> myLogger
/// = /* .. your initialization .. */;
/// ACTS_LOCAL_LOGGER(std::move(myLogger));
///
/// ACTS_VERBOSE("hello world!");
/// }
/// @endcode
#define ACTS_LOCAL_LOGGER(log_object) \
struct __local_acts_logger \
{ \
explicit __local_acts_logger(std::unique_ptr<const ::Acts::Logger> logger): \
m_logger(std::move(logger)) \
{} \
\
const ::Acts::Logger& operator()() const \
{ \
return *m_logger; \
} \
\
std::unique_ptr<const ::Acts::Logger> m_logger; \
}; \
__local_acts_logger logger(log_object);
// Debug level agnostic implementation of the ACTS_XYZ logging macros
#define ACTS_LOG(level, x) \
do { \
if (logger().doPrint(level)) { \
std::ostringstream os; \
os << x; \
logger().log(level, os.str()); \
} \
} \
while(0)
/// @brief macro for verbose debug output
/// @ingroup Logging
///
/// @param x debug message
///
/// @pre @c logger() must be a valid expression in the scope where this
/// macro is used and it must return a Acts::Logger object.
///
/// The debug message is printed if the current Acts::Logging::Level <=
/// Acts::Logging::VERBOSE.
#define ACTS_VERBOSE(x) ACTS_LOG(Acts::Logging::VERBOSE, x)
/// @brief macro for debug debug output
/// @ingroup Logging
///
/// @param x debug message
///
/// @pre @c logger() must be a valid expression in the scope where this
/// macro is used and it must return a Acts::Logger object.
///
/// The debug message is printed if the current Acts::Logging::Level <=
/// Acts::Logging::DEBUG.
#define ACTS_DEBUG(x) ACTS_LOG(Acts::Logging::DEBUG, x)
/// @brief macro for info debug output
/// @ingroup Logging
///
/// @param x debug message
///
/// @pre @c logger() must be a valid expression in the scope where this
/// macro is used and it must return a Acts::Logger object.
///
/// The debug message is printed if the current Acts::Logging::Level <=
/// Acts::Logging::INFO.
#define ACTS_INFO(x) ACTS_LOG(Acts::Logging::INFO, x)
/// @brief macro for warning debug output
/// @ingroup Logging
///
/// @param x debug message
///
/// @pre @c logger() must be a valid expression in the scope where this
/// macro is used and it must return a Acts::Logger object.
///
/// The debug message is printed if the current Acts::Logging::Level <=
/// Acts::Logging::WARNING.
#define ACTS_WARNING(x) ACTS_LOG(Acts::Logging::WARNING, x)
/// @brief macro for error debug output
/// @ingroup Logging
///
/// @param x debug message
///
/// @pre @c logger() must be a valid expression in the scope where this
/// macro is used and it must return a Acts::Logger object.
///
/// The debug message is printed if the current Acts::Logging::Level <=
/// Acts::Logging::ERROR.
#define ACTS_ERROR(x) ACTS_LOG(Acts::Logging::ERROR, x)
/// @brief macro for fatal debug output
/// @ingroup Logging
///
/// @param x debug message
///
/// @pre @c logger() must be a valid expression in the scope where this
/// macro is used and it must return a Acts::Logger object.
///
/// The debug message is printed if the current Acts::Logging::Level <=
/// Acts::Logging::FATAL.
#define ACTS_FATAL(x) ACTS_LOG(Acts::Logging::FATAL, x)
// clang-format on
namespace Acts {
/// @brief debug output related helper classes and functions
/// @ingroup Logging
namespace Logging {
/// @brief constants steering the debug output
///
/// All messages with a debug level equal or higher than the currently set
/// debug output level will be printed.
enum Level {
VERBOSE = 0, ///< VERBOSE level
DEBUG, ///< DEBUG level
INFO, ///< INFO level
WARNING, ///< WARNING level
ERROR, ///< ERROR level
FATAL, ///< FATAL level
MAX ///< Must be kept above the maximum supported debug level
};
inline std::string_view levelName(Level level) {
switch (level) {
case Level::VERBOSE:
return "VERBOSE";
case Level::DEBUG:
return "DEBUG";
case Level::INFO:
return "INFO";
case Level::WARNING:
return "WARNING";
case Level::ERROR:
return "ERROR";
case Level::FATAL:
return "FATAL";
case Level::MAX:
return "MAX";
default:
throw std::invalid_argument{"Unknown level"};
}
}
#ifdef DOXYGEN
/// @brief Get debug level above which an exception will be thrown after logging
///
/// All messages with a debug level equal or higher than the return value of
/// this function will cause an exception to be thrown after log emission.
///
/// @note Depending on preprocessor settings @c ACTS_ENABLE_LOG_FAILURE_THRESHOLD
/// and @c ACTS_LOG_FAILURE_THRESHOLD, this operations is either constexpr
/// or a runtime operation.
Level getFailureThreshold();
#else
#ifdef ACTS_ENABLE_LOG_FAILURE_THRESHOLD
#ifdef ACTS_LOG_FAILURE_THRESHOLD
// We have a fixed compile time log failure threshold
constexpr Level getFailureThreshold() {
return Level::ACTS_LOG_FAILURE_THRESHOLD;
}
#else
Level getFailureThreshold();
#endif
#else
constexpr Level getFailureThreshold() {
// Default "NO" failure threshold
return Level::MAX;
}
#endif
#endif
/// @brief Set debug level above which an exception will be thrown after logging
///
/// All messages with a debug level equal or higher than @p level will
/// cause an exception to be thrown after log emission.
///
/// @warning The runtime log failure threshold is **global state**, therefore
/// this function is **not threadsafe**. The intention is that this
/// level is set once, before multi-threaded execution begins, and then
/// not modified before the end of the job.
/// @note This function is only available if @c ACTS_LOG_FAILURE_THRESHOLD is
/// unset, i.e. no compile-time threshold is used. Otherwise an
/// exception is thrown.
void setFailureThreshold(Level level);
/// Custom exception class so threshold failures can be caught
class ThresholdFailure : public std::runtime_error {
using std::runtime_error::runtime_error;
};
/// Helper class that changes the failure threshold for the duration of its
/// lifetime.
class ScopedFailureThreshold {
public:
explicit ScopedFailureThreshold(Level level) { setFailureThreshold(level); }
ScopedFailureThreshold(const ScopedFailureThreshold&) = delete;
ScopedFailureThreshold& operator=(const ScopedFailureThreshold&) = delete;
ScopedFailureThreshold(ScopedFailureThreshold&&) = delete;
ScopedFailureThreshold& operator=(ScopedFailureThreshold&&) = delete;
~ScopedFailureThreshold() noexcept;
private:
Level m_previousLevel{getFailureThreshold()};
};
/// @brief abstract base class for printing debug output
///
/// Implementations of this interface need to define how and where to @a print
/// debug messages (e.g. to a file, to a stream into a database etc).
class OutputPrintPolicy {
public:
/// virtual default destructor
virtual ~OutputPrintPolicy() = default;
/// @brief handle output of debug message
///
/// @param [in] lvl debug output level of message
/// @param [in] input text of debug message
virtual void flush(const Level& lvl, const std::string& input) = 0;
/// Return the name of the print policy
/// @return the name
virtual const std::string& name() const = 0;
/// Make a copy of this print policy with a new name
/// @param name the new name
/// @return the copy
virtual std::unique_ptr<OutputPrintPolicy> clone(
const std::string& name) const = 0;
};
/// @brief abstract base class for filtering debug output
///
/// Implementations of this interface need to define whether a debug message
/// with a certain debug level is processed or filtered out.
class OutputFilterPolicy {
public:
/// virtual default destructor
virtual ~OutputFilterPolicy() = default;
/// @brief decide whether a debug message should be processed
///
/// @param [in] lvl debug level of debug message
///
/// @return @c true of debug message should be processed, @c false if debug
/// message should be skipped
virtual bool doPrint(const Level& lvl) const = 0;
/// Get the level of this filter policy
/// @return the levele
virtual Level level() const = 0;
/// Make a copy of this filter policy with a new level
/// @param level the new level
/// @return the new copy
virtual std::unique_ptr<OutputFilterPolicy> clone(Level level) const = 0;
};
/// @brief default filter policy for debug messages
///
/// All debug messages with a debug level equal or larger to the specified
/// threshold level are processed.
class DefaultFilterPolicy final : public OutputFilterPolicy {
public:
/// @brief constructor
///
/// @param [in] lvl threshold debug level
explicit DefaultFilterPolicy(Level lvl) : m_level(lvl) {
if (lvl > getFailureThreshold()) {
throw ThresholdFailure(
"Requested debug level is incompatible with "
"the ACTS_LOG_FAILURE_THRESHOLD=" +
std::string{levelName(getFailureThreshold())} +
" configuration. See "
"https://acts.readthedocs.io/en/latest/core/misc/"
"logging.html#logging-thresholds");
}
}
/// virtual default destructor
~DefaultFilterPolicy() override = default;
/// @brief decide whether a debug message should be processed
///
/// @param [in] lvl debug level of debug message
///
/// @return @c true if @p lvl >= #m_level, otherwise @c false
bool doPrint(const Level& lvl) const override { return m_level <= lvl; }
/// Get the level of this filter policy
/// @return the levele
Level level() const override { return m_level; }
/// Make a copy of this filter policy with a new level
/// @param level the new level
/// @return the new copy
std::unique_ptr<OutputFilterPolicy> clone(Level level) const override {
return std::make_unique<DefaultFilterPolicy>(level);
}
private:
/// threshold debug level for messages to be processed
Level m_level;
};
/// @brief base class for decorating the debug output
///
/// Derived classes may augment the debug message with additional information.
/// Chaining different decorators is possible to customize the output to your
/// needs.
class OutputDecorator : public OutputPrintPolicy {
public:
/// @brief constructor wrapping actual output print policy
///
/// @param [in] wrappee output print policy object which is wrapped by this
/// decorator object
explicit OutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee)
: m_wrappee(std::move(wrappee)) {}
/// @brief flush the debug message to the destination stream
///
/// @param [in] lvl debug level of debug message
/// @param [in] input text of debug message
///
/// This function delegates the flushing of the debug message to its wrapped
/// object.
void flush(const Level& lvl, const std::string& input) override {
m_wrappee->flush(lvl, input);
}
/// Return the name of the output decorator (forwards to wrappee)
/// @return the name
const std::string& name() const override { return m_wrappee->name(); }
protected:
/// wrapped object for printing the debug message
std::unique_ptr<OutputPrintPolicy> m_wrappee;
};
/// @brief decorate debug message with a name
///
/// The debug message is complemented with a name.
class NamedOutputDecorator final : public OutputDecorator {
public:
/// @brief constructor
///
/// @param [in] wrappee output print policy object to be wrapped
/// @param [in] name name to be added to debug message
/// @param [in] maxWidth maximum width of field used for name
NamedOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee,
const std::string& name, unsigned int maxWidth = 15)
: OutputDecorator(std::move(wrappee)),
m_name(name),
m_maxWidth(maxWidth) {}
/// @brief flush the debug message to the destination stream
///
/// @param [in] lvl debug level of debug message
/// @param [in] input text of debug message
///
/// This function prepends the given name to the debug message and then
/// delegates the flushing of the whole message to its wrapped object.
void flush(const Level& lvl, const std::string& input) override {
std::ostringstream os;
os << std::left << std::setw(m_maxWidth) << m_name.substr(0, m_maxWidth - 3)
<< input;
OutputDecorator::flush(lvl, os.str());
}
/// Make a copy of this print policy with a new name
/// @param name the new name
/// @return the copy
std::unique_ptr<OutputPrintPolicy> clone(
const std::string& name) const override {
return std::make_unique<NamedOutputDecorator>(m_wrappee->clone(name), name,
m_maxWidth);
}
/// Get this named output decorators name
/// @return the name
const std::string& name() const override { return m_name; }
private:
/// name to be prepended
std::string m_name;
/// maximum width of field for printing the name
unsigned int m_maxWidth;
};
/// @brief decorate debug message with a time stamp
///
/// The debug message is complemented with a time stamp.
class TimedOutputDecorator final : public OutputDecorator {
public:
/// @brief constructor
///
/// @param [in] wrappee output print policy object to be wrapped
/// @param [in] format format of time stamp (see std::strftime)
explicit TimedOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee,
const std::string& format = "%X")
: OutputDecorator(std::move(wrappee)), m_format(format) {}
/// @brief flush the debug message to the destination stream
///
/// @param [in] lvl debug level of debug message
/// @param [in] input text of debug message
///
/// This function prepends a time stamp to the debug message and then
/// delegates the flushing of the whole message to its wrapped object.
void flush(const Level& lvl, const std::string& input) override {
std::ostringstream os;
os << std::left << std::setw(12) << now() << input;
OutputDecorator::flush(lvl, os.str());
}
/// Make a copy of this print policy with a new name
/// @param name the new name
/// @return the copy
std::unique_ptr<OutputPrintPolicy> clone(
const std::string& name) const override {
return std::make_unique<TimedOutputDecorator>(m_wrappee->clone(name),
m_format);
}
private:
/// @brief get current time stamp
///
/// @return current time stamp as string
std::string now() const {
char buffer[20];
time_t t{};
std::time(&t);
struct tm tbuf {};
std::strftime(buffer, sizeof(buffer), m_format.c_str(),
localtime_r(&t, &tbuf));
return buffer;
}
/// format of the time stamp (see std::strftime for details)
std::string m_format;
};
/// @brief decorate debug message with a thread ID
///
/// The debug message is complemented with a thread ID.
class ThreadOutputDecorator final : public OutputDecorator {
public:
/// @brief constructor
///
/// @param [in] wrappee output print policy object to be wrapped
explicit ThreadOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee)
: OutputDecorator(std::move(wrappee)) {}
/// @brief flush the debug message to the destination stream
///
/// @param [in] lvl debug level of debug message
/// @param [in] input text of debug message
///
/// This function prepends the thread ID to the debug message and then
/// delegates the flushing of the whole message to its wrapped object.
void flush(const Level& lvl, const std::string& input) override {
std::ostringstream os;
os << std::left << std::setw(20) << std::this_thread::get_id() << input;
OutputDecorator::flush(lvl, os.str());
}
/// Make a copy of this print policy with a new name
/// @param name the new name
/// @return the copy
std::unique_ptr<OutputPrintPolicy> clone(
const std::string& name) const override {
return std::make_unique<ThreadOutputDecorator>(m_wrappee->clone(name));
}
};
/// @brief decorate debug message with its debug level
///
/// The debug message is complemented with its debug level.
class LevelOutputDecorator final : public OutputDecorator {
public:
/// @brief constructor
///
/// @param [in] wrappee output print policy object to be wrapped
explicit LevelOutputDecorator(std::unique_ptr<OutputPrintPolicy> wrappee)
: OutputDecorator(std::move(wrappee)) {}
/// @brief flush the debug message to the destination stream
///
/// @param [in] lvl debug level of debug message
/// @param [in] input text of debug message
///
/// This function prepends the debug level to the debug message and then
/// delegates the flushing of the whole message to its wrapped object.
void flush(const Level& lvl, const std::string& input) override {
std::ostringstream os;
os << std::left << std::setw(10) << toString(lvl) << input;
OutputDecorator::flush(lvl, os.str());
}
/// Make a copy of this print policy with a new name
/// @param name the new name
/// @return the copy
std::unique_ptr<OutputPrintPolicy> clone(
const std::string& name) const override {
return std::make_unique<LevelOutputDecorator>(m_wrappee->clone(name));
}
private:
/// @brief convert debug level to string
///
/// @param [in] lvl debug level
///
/// @return string representation of debug level
std::string toString(const Level& lvl) const {
static const char* const buffer[] = {"VERBOSE", "DEBUG", "INFO",
"WARNING", "ERROR", "FATAL"};
return buffer[lvl];
}
};
/// @brief default print policy for debug messages
///
/// This class allows to print debug messages without further modifications to
/// a specified output stream.
class DefaultPrintPolicy final : public OutputPrintPolicy {
public:
/// @brief constructor
///
/// @param [in] out pointer to output stream object
///
/// @pre @p out is non-zero
explicit DefaultPrintPolicy(std::ostream* out = &std::cout) : m_out(out) {}
/// @brief flush the debug message to the destination stream
///
/// @param [in] lvl debug level of debug message
/// @param [in] input text of debug message
void flush(const Level& lvl, const std::string& input) final {
(*m_out) << input << std::endl;
if (lvl >= getFailureThreshold()) {
throw ThresholdFailure(
"Previous debug message exceeds the "
"ACTS_LOG_FAILURE_THRESHOLD=" +
std::string{levelName(getFailureThreshold())} +
" configuration, bailing out. See "
"https://acts.readthedocs.io/en/latest/core/misc/"
"logging.html#logging-thresholds");
}
}
/// Fulfill @c OutputPrintPolicy interface. This policy doesn't actually have a
/// name, so the assumption is that somewhere in the decorator hierarchy,
/// there is something that returns a name without delegating to a wrappee,
/// before reaching this overload.
/// @note This method will throw an exception
/// @return the name, but it never returns
const std::string& name() const override {
throw std::runtime_error{
"Default print policy doesn't have a name. Is there no named output in "
"the decorator chain?"};
};
/// Make a copy of this print policy with a new name
/// @return the copy
std::unique_ptr<OutputPrintPolicy> clone(
const std::string& /*name*/) const override {
return std::make_unique<DefaultPrintPolicy>(m_out);
};
private:
/// pointer to destination output stream
std::ostream* m_out;
};
} // namespace Logging
/// @brief class for printing debug output
///
/// This class provides the user interface for printing debug messages with
/// different levels of severity.
///
/// @ingroup Logging
class Logger {
public:
/// @brief construct from output print and filter policy
///
/// @param [in] pPrint policy for printing debug messages
/// @param [in] pFilter policy for filtering debug messages
Logger(std::unique_ptr<Logging::OutputPrintPolicy> pPrint,
std::unique_ptr<Logging::OutputFilterPolicy> pFilter)
: m_printPolicy(std::move(pPrint)), m_filterPolicy(std::move(pFilter)) {}
/// @brief decide whether a message with a given debug level has to be printed
///
/// @param [in] lvl debug level of debug message
///
/// @return @c true if debug message should be printed, otherwise @c false
bool doPrint(const Logging::Level& lvl) const {
return m_filterPolicy->doPrint(lvl);
}
/// @brief log a debug message
///
/// @param [in] lvl debug level of debug message
/// @param [in] input text of debug message
void log(const Logging::Level& lvl, const std::string& input) const {
if (doPrint(lvl)) {
m_printPolicy->flush(lvl, input);
}
}
/// Return the print policy for this logger
/// @return the print policy
const Logging::OutputPrintPolicy& printPolicy() const {
return *m_printPolicy;
}
/// Return the filter policy for this logger
/// @return the filter policy
const Logging::OutputFilterPolicy& filterPolicy() const {
return *m_filterPolicy;
}
/// Return the level of the filter policy of this logger
/// @return the level
Logging::Level level() const { return m_filterPolicy->level(); }
/// Return the name of the print policy of this logger
/// @return the name
const std::string& name() const { return m_printPolicy->name(); }
/// Make a copy of this logger, optionally changing the name or the level
/// @param _name the optional new name
/// @param _level the optional new level
std::unique_ptr<Logger> clone(
const std::optional<std::string>& _name = std::nullopt,
const std::optional<Logging::Level>& _level = std::nullopt) const {
return std::make_unique<Logger>(
m_printPolicy->clone(_name.value_or(name())),
m_filterPolicy->clone(_level.value_or(level())));
}
/// Make a copy of the logger, with a new level. Convenience function for
/// if you only want to change the level but not the name.
/// @param _level the new level
/// @return the new logger
std::unique_ptr<Logger> clone(Logging::Level _level) const {
return clone(std::nullopt, _level);
}
/// Make a copy of the logger, with a suffix added to the end of it's
/// name. You can also optionally supply a new level
/// @param suffix the suffix to add to the end of the name
/// @param _level the optional new level
std::unique_ptr<Logger> cloneWithSuffix(
const std::string& suffix,
std::optional<Logging::Level> _level = std::nullopt) const {
return clone(name() + suffix, _level.value_or(level()));
}
/// Helper function so a logger reference can be used as is with the logging
/// macros
const Logger& operator()() const { return *this; }
private:
/// policy object for printing debug messages
std::unique_ptr<Logging::OutputPrintPolicy> m_printPolicy;
/// policy object for filtering debug messages
std::unique_ptr<Logging::OutputFilterPolicy> m_filterPolicy;
};
/// @brief get default debug output logger
///
/// @param [in] name name of the logger instance
/// @param [in] lvl debug threshold level
/// @param [in] log_stream output stream used for printing debug messages
///
/// This function returns a pointer to a Logger instance with the following
/// decorations enabled:
/// - time stamps
/// - name of logging instance
/// - debug level
///
/// @return pointer to logging instance
std::unique_ptr<const Logger> getDefaultLogger(
const std::string& name, const Logging::Level& lvl,
std::ostream* log_stream = &std::cout);
const Logger& getDummyLogger();
} // namespace Acts