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