File indexing completed on 2025-11-05 09:55:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RLogger
0015 #define ROOT_RLogger
0016
0017 #include <atomic>
0018 #include <list>
0019 #include <memory>
0020 #include <mutex>
0021 #include <sstream>
0022 #include <string>
0023 #include <utility>
0024
0025 namespace ROOT {
0026
0027 class RLogEntry;
0028 class RLogManager;
0029
0030
0031
0032
0033 enum class ELogLevel : unsigned char {
0034 kUnset,
0035 kFatal,
0036 kError,
0037 kWarning,
0038 kInfo,
0039 kDebug
0040 };
0041
0042 inline ELogLevel operator+(ELogLevel severity, int offset)
0043 {
0044 return static_cast<ELogLevel>(static_cast<int>(severity) + offset);
0045 }
0046
0047
0048
0049
0050 class RLogDiagCount {
0051 protected:
0052 std::atomic<long long> fNumWarnings{0ll};
0053 std::atomic<long long> fNumErrors{0ll};
0054 std::atomic<long long> fNumFatalErrors{0ll};
0055
0056 public:
0057
0058 long long GetNumWarnings() const { return fNumWarnings; }
0059
0060
0061 long long GetNumErrors() const { return fNumErrors; }
0062
0063
0064 long long GetNumFatalErrors() const { return fNumFatalErrors; }
0065
0066
0067 void Increment(ELogLevel severity)
0068 {
0069 switch (severity) {
0070 case ELogLevel::kFatal: ++fNumFatalErrors; break;
0071 case ELogLevel::kError: ++fNumErrors; break;
0072 case ELogLevel::kWarning: ++fNumWarnings; break;
0073 default:;
0074 }
0075 }
0076 };
0077
0078
0079
0080
0081
0082 class RLogHandler {
0083 public:
0084 virtual ~RLogHandler();
0085
0086
0087
0088
0089
0090
0091 virtual bool Emit(const RLogEntry &entry) = 0;
0092 };
0093
0094
0095
0096
0097
0098 class RLogChannel : public RLogDiagCount {
0099
0100 std::string fName;
0101
0102
0103 ELogLevel fVerbosity = ELogLevel::kUnset;
0104
0105 public:
0106
0107 RLogChannel() = default;
0108
0109
0110 explicit RLogChannel(ELogLevel verbosity) : fVerbosity(verbosity) {}
0111
0112
0113 RLogChannel(const std::string &name) : fName(name) {}
0114
0115 ELogLevel SetVerbosity(ELogLevel verbosity)
0116 {
0117 std::swap(fVerbosity, verbosity);
0118 return verbosity;
0119 }
0120 ELogLevel GetVerbosity() const { return fVerbosity; }
0121 ELogLevel GetEffectiveVerbosity(const RLogManager &mgr) const;
0122
0123 const std::string &GetName() const { return fName; }
0124 };
0125
0126
0127
0128
0129
0130
0131
0132
0133 class RLogManager : public RLogChannel, public RLogHandler {
0134 std::mutex fMutex;
0135 std::list<std::unique_ptr<RLogHandler>> fHandlers;
0136
0137 public:
0138
0139 RLogManager(std::unique_ptr<RLogHandler> lh) : RLogChannel(ELogLevel::kWarning)
0140 {
0141 fHandlers.emplace_back(std::move(lh));
0142 }
0143
0144 static RLogManager &Get();
0145
0146
0147 void PushFront(std::unique_ptr<RLogHandler> handler) { fHandlers.emplace_front(std::move(handler)); }
0148
0149
0150 void PushBack(std::unique_ptr<RLogHandler> handler) { fHandlers.emplace_back(std::move(handler)); }
0151
0152
0153 std::unique_ptr<RLogHandler> Remove(RLogHandler *handler);
0154
0155
0156
0157 bool Emit(const RLogEntry &entry) override;
0158 };
0159
0160
0161
0162
0163 struct RLogLocation {
0164 std::string fFile;
0165 std::string fFuncName;
0166 int fLine;
0167 };
0168
0169
0170
0171
0172
0173
0174
0175 class RLogEntry {
0176 public:
0177 RLogLocation fLocation;
0178 std::string fMessage;
0179 RLogChannel *fChannel = nullptr;
0180 ELogLevel fLevel = ELogLevel::kFatal;
0181
0182 RLogEntry(ELogLevel level, RLogChannel &channel) : fChannel(&channel), fLevel(level) {}
0183 RLogEntry(ELogLevel level, RLogChannel &channel, const RLogLocation &loc)
0184 : fLocation(loc), fChannel(&channel), fLevel(level)
0185 {
0186 }
0187
0188 bool IsDebug() const { return fLevel >= ELogLevel::kDebug; }
0189 bool IsInfo() const { return fLevel == ELogLevel::kInfo; }
0190 bool IsWarning() const { return fLevel == ELogLevel::kWarning; }
0191 bool IsError() const { return fLevel == ELogLevel::kError; }
0192 bool IsFatal() const { return fLevel == ELogLevel::kFatal; }
0193 };
0194
0195 namespace Detail {
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 class RLogBuilder : public std::ostringstream {
0211
0212 RLogEntry fEntry;
0213
0214 public:
0215 RLogBuilder(ELogLevel level, RLogChannel &channel) : fEntry(level, channel) {}
0216 RLogBuilder(ELogLevel level, RLogChannel &channel, const std::string &filename, int line,
0217 const std::string &funcname)
0218 : fEntry(level, channel, {filename, funcname, line})
0219 {
0220 }
0221
0222
0223 ~RLogBuilder()
0224 {
0225 fEntry.fMessage = str();
0226 RLogManager::Get().Emit(fEntry);
0227 }
0228 };
0229 }
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 class RLogScopedVerbosity {
0241 RLogChannel *fChannel;
0242 ELogLevel fPrevLevel;
0243
0244 public:
0245 RLogScopedVerbosity(RLogChannel &channel, ELogLevel verbosity)
0246 : fChannel(&channel), fPrevLevel(channel.SetVerbosity(verbosity))
0247 {
0248 }
0249 explicit RLogScopedVerbosity(ELogLevel verbosity) : RLogScopedVerbosity(RLogManager::Get(), verbosity) {}
0250 ~RLogScopedVerbosity() { fChannel->SetVerbosity(fPrevLevel); }
0251 };
0252
0253
0254
0255
0256
0257 class RLogScopedDiagCount {
0258 RLogDiagCount *fCounter = nullptr;
0259
0260 long long fInitialWarnings = 0;
0261
0262 long long fInitialErrors = 0;
0263
0264 long long fInitialFatalErrors = 0;
0265
0266 public:
0267
0268
0269 explicit RLogScopedDiagCount(RLogDiagCount &cnt)
0270 : fCounter(&cnt), fInitialWarnings(cnt.GetNumWarnings()), fInitialErrors(cnt.GetNumErrors()),
0271 fInitialFatalErrors(cnt.GetNumFatalErrors())
0272 {
0273 }
0274
0275
0276 RLogScopedDiagCount() : RLogScopedDiagCount(RLogManager::Get()) {}
0277
0278
0279 long long GetAccumulatedWarnings() const { return fCounter->GetNumWarnings() - fInitialWarnings; }
0280
0281
0282 long long GetAccumulatedErrors() const { return fCounter->GetNumErrors() - fInitialErrors; }
0283
0284
0285 long long GetAccumulatedFatalErrors() const { return fCounter->GetNumFatalErrors() - fInitialFatalErrors; }
0286
0287
0288 bool HasWarningOccurred() const { return GetAccumulatedWarnings(); }
0289
0290
0291 bool HasErrorOccurred() const { return GetAccumulatedErrors() + GetAccumulatedFatalErrors(); }
0292
0293
0294 bool HasErrorOrWarningOccurred() const { return HasWarningOccurred() || HasErrorOccurred(); }
0295 };
0296
0297 namespace Internal {
0298
0299 inline RLogChannel &GetChannelOrManager()
0300 {
0301 return RLogManager::Get();
0302 }
0303 inline RLogChannel &GetChannelOrManager(RLogChannel &channel)
0304 {
0305 return channel;
0306 }
0307
0308 }
0309
0310 inline ELogLevel RLogChannel::GetEffectiveVerbosity(const RLogManager &mgr) const
0311 {
0312 if (fVerbosity == ELogLevel::kUnset)
0313 return mgr.GetVerbosity();
0314 return fVerbosity;
0315 }
0316
0317 }
0318
0319 #if defined(_MSC_VER)
0320 #define R__LOG_PRETTY_FUNCTION __FUNCSIG__
0321 #else
0322 #define R__LOG_PRETTY_FUNCTION __PRETTY_FUNCTION__
0323 #endif
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340 #define R__LOG_TO_CHANNEL(SEVERITY, CHANNEL) \
0341 ((SEVERITY < ROOT::ELogLevel::kInfo + 0) || \
0342 ROOT::Internal::GetChannelOrManager(CHANNEL).GetEffectiveVerbosity(ROOT::RLogManager::Get()) >= SEVERITY) && \
0343 ROOT::Detail::RLogBuilder(SEVERITY, ROOT::Internal::GetChannelOrManager(CHANNEL), __FILE__, __LINE__, \
0344 R__LOG_PRETTY_FUNCTION)
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 #define R__LOG_FATAL(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kFatal, __VA_ARGS__)
0357 #define R__LOG_ERROR(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kError, __VA_ARGS__)
0358 #define R__LOG_WARNING(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kWarning, __VA_ARGS__)
0359 #define R__LOG_INFO(...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kInfo, __VA_ARGS__)
0360 #define R__LOG_DEBUG(DEBUGLEVEL, ...) R__LOG_TO_CHANNEL(ROOT::ELogLevel::kDebug + DEBUGLEVEL, __VA_ARGS__)
0361
0362
0363 #endif