Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
RLogger.hxx
Go to the documentation of this file.
1/// \file ROOT/RLogger.hxx
2/// \ingroup Base ROOT7
3/// \author Axel Naumann <axel@cern.ch>
4/// \date 2015-03-29
5
6/*************************************************************************
7 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#ifndef ROOT_RLogger
15#define ROOT_RLogger
16
17#include <atomic>
18#include <list>
19#include <memory>
20#include <mutex>
21#include <sstream>
22#include <string>
23#include <utility>
24
25namespace ROOT {
26
27class RLogEntry;
28class RLogManager;
29
30/**
31 Kinds of diagnostics.
32 */
33enum class ELogLevel : unsigned char {
34 kUnset,
35 kFatal, ///< An error which causes further processing to be unreliable
36 kError, ///< An error
37 kWarning, ///< Warnings about likely unexpected behavior
38 kInfo, ///< Informational messages; used for instance for tracing
39 kDebug ///< Debug information; only useful for developers; can have added verbosity up to 255-kDebug.
40};
41
42inline ELogLevel operator+(ELogLevel severity, int offset)
43{
44 return static_cast<ELogLevel>(static_cast<int>(severity) + offset);
45}
46
47/**
48 Keep track of emitted errors and warnings.
49 */
51protected:
52 std::atomic<long long> fNumWarnings{0ll}; /// Number of warnings.
53 std::atomic<long long> fNumErrors{0ll}; /// Number of errors.
54 std::atomic<long long> fNumFatalErrors{0ll}; /// Number of fatal errors.
55
56public:
57 /// Returns the current number of warnings.
58 long long GetNumWarnings() const { return fNumWarnings; }
59
60 /// Returns the current number of errors.
61 long long GetNumErrors() const { return fNumErrors; }
62
63 /// Returns the current number of fatal errors.
64 long long GetNumFatalErrors() const { return fNumFatalErrors; }
65
66 /// Increase warning or error count.
67 void Increment(ELogLevel severity)
68 {
69 switch (severity) {
71 case ELogLevel::kError: ++fNumErrors; break;
72 case ELogLevel::kWarning: ++fNumWarnings; break;
73 default:;
74 }
75 }
76};
77
78/**
79 Abstract RLogHandler base class. ROOT logs everything from info to error
80 to entities of this class.
81 */
83public:
84 virtual ~RLogHandler();
85 /// Emit a log entry.
86 /// \param entry - the RLogEntry to be emitted.
87 /// \returns false if further emission of this Log should be suppressed.
88 ///
89 /// \note This function is called concurrently; log emission must be locked
90 /// if needed. (The default log handler using ROOT's DefaultErrorHandler is locked.)
91 virtual bool Emit(const RLogEntry &entry) = 0;
92};
93
94/**
95 A log configuration for a channel, e.g. "RHist".
96 Each ROOT module has its own log, with potentially distinct verbosity.
97 */
98class RLogChannel : public RLogDiagCount {
99 /// Name as shown in diagnostics
100 std::string fName;
101
102 /// Verbosity of this channel. By default, use the global verbosity.
104
105public:
106 /// Construct an anonymous channel.
107 RLogChannel() = default;
108
109 /// Construct an anonymous channel with a default verbosity.
111
112 /// Construct a log channel given its name, which is part of the diagnostics.
113 RLogChannel(const std::string &name) : fName(name) {}
114
116 {
117 std::swap(fVerbosity, verbosity);
118 return verbosity;
119 }
122
123 const std::string &GetName() const { return fName; }
124};
125
126/**
127 A RLogHandler that multiplexes diagnostics to different client `RLogHandler`s
128 and keeps track of the sum of `RLogDiagCount`s for all channels.
129
130 `RLogHandler::Get()` returns the process's (static) log manager.
131 */
132
133class RLogManager : public RLogChannel, public RLogHandler {
134 std::mutex fMutex;
135 std::list<std::unique_ptr<RLogHandler>> fHandlers;
136
137public:
138 /// Initialize taking a RLogHandler.
139 RLogManager(std::unique_ptr<RLogHandler> lh) : RLogChannel(ELogLevel::kWarning)
140 {
141 fHandlers.emplace_back(std::move(lh));
142 }
143
144 static RLogManager &Get();
145
146 /// Add a RLogHandler in the front - to be called before all others.
147 void PushFront(std::unique_ptr<RLogHandler> handler) { fHandlers.emplace_front(std::move(handler)); }
148
149 /// Add a RLogHandler in the back - to be called after all others.
150 void PushBack(std::unique_ptr<RLogHandler> handler) { fHandlers.emplace_back(std::move(handler)); }
151
152 /// Remove and return the given log handler. Returns `nullptr` if not found.
153 std::unique_ptr<RLogHandler> Remove(RLogHandler *handler);
154
155 // Emit a `RLogEntry` to the RLogHandlers.
156 // Returns false if further emission of this Log should be suppressed.
157 bool Emit(const RLogEntry &entry) override;
158};
159
160/**
161 A diagnostic location, part of an RLogEntry.
162 */
164 std::string fFile;
165 std::string fFuncName;
166 int fLine; // C++11 forbids "= 0" for braced-init-list initialization.
167};
168
169/**
170 A diagnostic that can be emitted by the RLogManager.
171 One can construct a RLogEntry through RLogBuilder, including streaming into
172 the diagnostic message and automatic emission.
173 */
174
176public:
178 std::string fMessage;
181
182 RLogEntry(ELogLevel level, RLogChannel &channel) : fChannel(&channel), fLevel(level) {}
184 : fLocation(loc), fChannel(&channel), fLevel(level)
185 {
186 }
187
188 bool IsDebug() const { return fLevel >= ELogLevel::kDebug; }
189 bool IsInfo() const { return fLevel == ELogLevel::kInfo; }
190 bool IsWarning() const { return fLevel == ELogLevel::kWarning; }
191 bool IsError() const { return fLevel == ELogLevel::kError; }
192 bool IsFatal() const { return fLevel == ELogLevel::kFatal; }
193};
194
195namespace Detail {
196/**
197 Builds a diagnostic entry, emitted by the static RLogManager upon destruction of this builder,
198 where - by definition - the RLogEntry has been completely built.
199
200 This builder can be used through the utility preprocessor macros R__LOG_ERROR,
201 R__LOG_WARNING etc like this:
202~~~ {.cpp}
203 R__LOG_INFO(ROOT::Experimental::HistLog()) << "all we know is " << 42;
204 const int decreasedInfoLevel = 5;
205 R__LOG_XDEBUG(ROOT::WebGUILog(), decreasedInfoLevel) << "nitty-gritty details";
206~~~
207 This will automatically capture the current class and function name, the file and line number.
208 */
209
210class RLogBuilder : public std::ostringstream {
211 /// The log entry to be built.
213
214public:
215 RLogBuilder(ELogLevel level, RLogChannel &channel) : fEntry(level, channel) {}
216 RLogBuilder(ELogLevel level, RLogChannel &channel, const std::string &filename, int line,
217 const std::string &funcname)
218 : fEntry(level, channel, {filename, funcname, line})
219 {
220 }
221
222 /// Emit the log entry through the static log manager.
224 {
225 fEntry.fMessage = str();
226 RLogManager::Get().Emit(fEntry);
227 }
228};
229} // namespace Detail
230
231/**
232 Change the verbosity level (global or specific to the RLogChannel passed to the
233 constructor) for the lifetime of this object.
234 Example:
235~~~ {.cpp}
236 RLogScopedVerbosity debugThis(gFooLog, ELogLevel::kDebug);
237 Foo::SomethingToDebug();
238~~~
239 */
252
253/**
254 Object to count the number of warnings and errors emitted by a section of code,
255 after construction of this type.
256 */
259 /// The number of the RLogDiagCount's emitted warnings at construction time of *this.
260 long long fInitialWarnings = 0;
261 /// The number of the RLogDiagCount's emitted errors at construction time.
262 long long fInitialErrors = 0;
263 /// The number of the RLogDiagCount's emitted fatal errors at construction time.
264 long long fInitialFatalErrors = 0;
265
266public:
267 /// Construct the scoped count given a counter (e.g. a channel or RLogManager).
268 /// The counter's lifetime must exceed the lifetime of this object!
270 : fCounter(&cnt), fInitialWarnings(cnt.GetNumWarnings()), fInitialErrors(cnt.GetNumErrors()),
271 fInitialFatalErrors(cnt.GetNumFatalErrors())
272 {
273 }
274
275 /// Construct the scoped count for any diagnostic, whatever its channel.
277
278 /// Get the number of warnings that the RLogDiagCount has emitted since construction of *this.
280
281 /// Get the number of errors that the RLogDiagCount has emitted since construction of *this.
282 long long GetAccumulatedErrors() const { return fCounter->GetNumErrors() - fInitialErrors; }
283
284 /// Get the number of errors that the RLogDiagCount has emitted since construction of *this.
286
287 /// Whether the RLogDiagCount has emitted a warnings since construction time of *this.
289
290 /// Whether the RLogDiagCount has emitted an error (fatal or not) since construction time of *this.
292
293 /// Whether the RLogDiagCount has emitted an error or a warning since construction time of *this.
295};
296
297namespace Internal {
298
300{
301 return RLogManager::Get();
302}
304{
305 return channel;
306}
307
308} // namespace Internal
309
311{
313 return mgr.GetVerbosity();
314 return fVerbosity;
315}
316
317} // namespace ROOT
318
319#if defined(_MSC_VER)
320#define R__LOG_PRETTY_FUNCTION __FUNCSIG__
321#else
322#define R__LOG_PRETTY_FUNCTION __PRETTY_FUNCTION__
323#endif
324
325/*
326 Some implementation details:
327
328 - The conditional `RLogBuilder` use prevents stream operators from being called if
329 verbosity is too low, i.e.:
330 ~~~
331 RLogScopedVerbosity silence(RLogLevel::kFatal);
332 R__LOG_DEBUG(7) << WillNotBeCalled();
333 ~~~
334 - To update counts of warnings / errors / fatal errors, those RLogEntries must
335 always be created, even if in the end their emission will be silenced. This
336 should be fine, performance-wise, as they should not happen frequently.
337 - Use `(condition) && RLogBuilder(...)` instead of `if (condition) RLogBuilder(...)`
338 to prevent "ambiguous else" in invocations such as `if (something) R__LOG_DEBUG()...`.
339 */
340#define R__LOG_TO_CHANNEL(SEVERITY, CHANNEL) \
341 ((SEVERITY < ROOT::ELogLevel::kInfo + 0) || \
342 ROOT::Internal::GetChannelOrManager(CHANNEL).GetEffectiveVerbosity(ROOT::RLogManager::Get()) >= SEVERITY) && \
343 ROOT::Detail::RLogBuilder(SEVERITY, ROOT::Internal::GetChannelOrManager(CHANNEL), __FILE__, __LINE__, \
344 R__LOG_PRETTY_FUNCTION)
345
346/// \name LogMacros
347/// Macros to log diagnostics.
348/// ~~~ {.cpp}
349/// R__LOG_INFO(ROOT::HistLog()) << "all we know is " << 42;
350///
351/// RLogScopedVerbosity verbose(kDebug + 5);
352/// const int decreasedInfoLevel = 5;
353/// R__LOG_DEBUG(ROOT::WebGUILog(), decreasedInfoLevel) << "nitty-gritty details";
354/// ~~~
355///\{
356#define R__LOG_FATAL(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kFatal, __VA_ARGS__)
357#define R__LOG_ERROR(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kError, __VA_ARGS__)
358#define R__LOG_WARNING(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kWarning, __VA_ARGS__)
359#define R__LOG_INFO(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kInfo, __VA_ARGS__)
360#define R__LOG_DEBUG(DEBUGLEVEL, ...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kDebug + DEBUGLEVEL, __VA_ARGS__)
361///\}
362
363#endif
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
char name[80]
Definition TGX11.cxx:110
Builds a diagnostic entry, emitted by the static RLogManager upon destruction of this builder,...
Definition RLogger.hxx:210
RLogBuilder(ELogLevel level, RLogChannel &channel)
Definition RLogger.hxx:215
RLogBuilder(ELogLevel level, RLogChannel &channel, const std::string &filename, int line, const std::string &funcname)
Definition RLogger.hxx:216
RLogEntry fEntry
The log entry to be built.
Definition RLogger.hxx:212
~RLogBuilder()
Emit the log entry through the static log manager.
Definition RLogger.hxx:223
A log configuration for a channel, e.g.
Definition RLogger.hxx:98
std::string fName
Name as shown in diagnostics.
Definition RLogger.hxx:100
RLogChannel(ELogLevel verbosity)
Construct an anonymous channel with a default verbosity.
Definition RLogger.hxx:110
const std::string & GetName() const
Definition RLogger.hxx:123
ELogLevel fVerbosity
Verbosity of this channel. By default, use the global verbosity.
Definition RLogger.hxx:103
RLogChannel()=default
Construct an anonymous channel.
ELogLevel GetVerbosity() const
Definition RLogger.hxx:120
ELogLevel SetVerbosity(ELogLevel verbosity)
Definition RLogger.hxx:115
RLogChannel(const std::string &name)
Construct a log channel given its name, which is part of the diagnostics.
Definition RLogger.hxx:113
ELogLevel GetEffectiveVerbosity(const RLogManager &mgr) const
Definition RLogger.hxx:310
Keep track of emitted errors and warnings.
Definition RLogger.hxx:50
long long GetNumFatalErrors() const
Returns the current number of fatal errors.
Definition RLogger.hxx:64
void Increment(ELogLevel severity)
Increase warning or error count.
Definition RLogger.hxx:67
std::atomic< long long > fNumWarnings
Definition RLogger.hxx:52
std::atomic< long long > fNumFatalErrors
Number of errors.
Definition RLogger.hxx:54
std::atomic< long long > fNumErrors
Number of warnings.
Definition RLogger.hxx:53
long long GetNumWarnings() const
Number of fatal errors.
Definition RLogger.hxx:58
long long GetNumErrors() const
Returns the current number of errors.
Definition RLogger.hxx:61
A diagnostic that can be emitted by the RLogManager.
Definition RLogger.hxx:175
bool IsFatal() const
Definition RLogger.hxx:192
bool IsError() const
Definition RLogger.hxx:191
bool IsInfo() const
Definition RLogger.hxx:189
RLogChannel * fChannel
Definition RLogger.hxx:179
RLogEntry(ELogLevel level, RLogChannel &channel)
Definition RLogger.hxx:182
std::string fMessage
Definition RLogger.hxx:178
bool IsDebug() const
Definition RLogger.hxx:188
RLogEntry(ELogLevel level, RLogChannel &channel, const RLogLocation &loc)
Definition RLogger.hxx:183
ELogLevel fLevel
Definition RLogger.hxx:180
bool IsWarning() const
Definition RLogger.hxx:190
RLogLocation fLocation
Definition RLogger.hxx:177
Abstract RLogHandler base class.
Definition RLogger.hxx:82
virtual ~RLogHandler()
Definition RLogger.cxx:26
virtual bool Emit(const RLogEntry &entry)=0
Emit a log entry.
A RLogHandler that multiplexes diagnostics to different client RLogHandlers and keeps track of the su...
Definition RLogger.hxx:133
std::list< std::unique_ptr< RLogHandler > > fHandlers
Definition RLogger.hxx:135
void PushBack(std::unique_ptr< RLogHandler > handler)
Add a RLogHandler in the back - to be called after all others.
Definition RLogger.hxx:150
RLogManager(std::unique_ptr< RLogHandler > lh)
Initialize taking a RLogHandler.
Definition RLogger.hxx:139
std::unique_ptr< RLogHandler > Remove(RLogHandler *handler)
Remove and return the given log handler. Returns nullptr if not found.
Definition RLogger.cxx:66
bool Emit(const RLogEntry &entry) override
Emit a log entry.
Definition RLogger.cxx:80
void PushFront(std::unique_ptr< RLogHandler > handler)
Add a RLogHandler in the front - to be called before all others.
Definition RLogger.hxx:147
std::mutex fMutex
Definition RLogger.hxx:134
static RLogManager & Get()
Definition RLogger.cxx:60
Object to count the number of warnings and errors emitted by a section of code, after construction of...
Definition RLogger.hxx:257
bool HasWarningOccurred() const
Whether the RLogDiagCount has emitted a warnings since construction time of *this.
Definition RLogger.hxx:288
RLogDiagCount * fCounter
Definition RLogger.hxx:258
bool HasErrorOccurred() const
Whether the RLogDiagCount has emitted an error (fatal or not) since construction time of *this.
Definition RLogger.hxx:291
RLogScopedDiagCount(RLogDiagCount &cnt)
Construct the scoped count given a counter (e.g.
Definition RLogger.hxx:269
long long GetAccumulatedFatalErrors() const
Get the number of errors that the RLogDiagCount has emitted since construction of *this.
Definition RLogger.hxx:285
long long GetAccumulatedWarnings() const
Get the number of warnings that the RLogDiagCount has emitted since construction of *this.
Definition RLogger.hxx:279
long long fInitialErrors
The number of the RLogDiagCount's emitted errors at construction time.
Definition RLogger.hxx:262
long long GetAccumulatedErrors() const
Get the number of errors that the RLogDiagCount has emitted since construction of *this.
Definition RLogger.hxx:282
bool HasErrorOrWarningOccurred() const
Whether the RLogDiagCount has emitted an error or a warning since construction time of *this.
Definition RLogger.hxx:294
long long fInitialWarnings
The number of the RLogDiagCount's emitted warnings at construction time of *this.
Definition RLogger.hxx:260
long long fInitialFatalErrors
The number of the RLogDiagCount's emitted fatal errors at construction time.
Definition RLogger.hxx:264
RLogScopedDiagCount()
Construct the scoped count for any diagnostic, whatever its channel.
Definition RLogger.hxx:276
Change the verbosity level (global or specific to the RLogChannel passed to the constructor) for the ...
Definition RLogger.hxx:240
RLogScopedVerbosity(ELogLevel verbosity)
Definition RLogger.hxx:249
RLogScopedVerbosity(RLogChannel &channel, ELogLevel verbosity)
Definition RLogger.hxx:245
TLine * line
RLogChannel & GetChannelOrManager()
Definition RLogger.hxx:299
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
ELogLevel
Kinds of diagnostics.
Definition RLogger.hxx:33
@ kInfo
Informational messages; used for instance for tracing.
@ kDebug
Debug information; only useful for developers; can have added verbosity up to 255-kDebug.
@ kError
An error.
@ kFatal
An error which causes further processing to be unreliable.
@ kWarning
Warnings about likely unexpected behavior.
ELogLevel operator+(ELogLevel severity, int offset)
Definition RLogger.hxx:42
A diagnostic location, part of an RLogEntry.
Definition RLogger.hxx:163
std::string fFile
Definition RLogger.hxx:164
std::string fFuncName
Definition RLogger.hxx:165