1 // 2 // Bismillah ar-Rahmaan ar-Raheem 3 // 4 // Easylogging++ v9.96.4 5 // Single-header only, cross-platform logging library for C++ applications 6 // 7 // Copyright (c) 2012-2018 Muflihun Labs 8 // Copyright (c) 2012-2018 @abumusamq 9 // 10 // This library is released under the MIT Licence. 11 // https://github.com/muflihun/easyloggingpp/blob/master/LICENSE 12 // 13 // https://github.com/muflihun/easyloggingpp 14 // https://muflihun.github.io/easyloggingpp 15 // http://muflihun.com 16 // 17 18 #ifndef EASYLOGGINGPP_H 19 #define EASYLOGGINGPP_H 20 // Compilers and C++0x/C++11 Evaluation 21 #if __cplusplus >= 201103L 22 # define ELPP_CXX11 1 23 #endif // __cplusplus >= 201103L 24 #if (defined(__GNUC__)) 25 # define ELPP_COMPILER_GCC 1 26 #else 27 # define ELPP_COMPILER_GCC 0 28 #endif 29 #if ELPP_COMPILER_GCC 30 # define ELPP_GCC_VERSION (__GNUC__ * 10000 \ 31 + __GNUC_MINOR__ * 100 \ 32 + __GNUC_PATCHLEVEL__) 33 # if defined(__GXX_EXPERIMENTAL_CXX0X__) 34 # define ELPP_CXX0X 1 35 # endif 36 #endif 37 // Visual C++ 38 #if defined(_MSC_VER) 39 # define ELPP_COMPILER_MSVC 1 40 #else 41 # define ELPP_COMPILER_MSVC 0 42 #endif 43 #define ELPP_CRT_DBG_WARNINGS ELPP_COMPILER_MSVC 44 #if ELPP_COMPILER_MSVC 45 # if (_MSC_VER == 1600) 46 # define ELPP_CXX0X 1 47 # elif(_MSC_VER >= 1700) 48 # define ELPP_CXX11 1 49 # endif 50 #endif 51 // Clang++ 52 #if (defined(__clang__) && (__clang__ == 1)) 53 # define ELPP_COMPILER_CLANG 1 54 #else 55 # define ELPP_COMPILER_CLANG 0 56 #endif 57 #if ELPP_COMPILER_CLANG 58 # if __has_include(<thread>) 59 # include <cstddef> // Make __GLIBCXX__ defined when using libstdc++ 60 # if !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 61 # define ELPP_CLANG_SUPPORTS_THREAD 62 # endif // !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 63 # endif // __has_include(<thread>) 64 #endif 65 #if (defined(__MINGW32__) || defined(__MINGW64__)) 66 # define ELPP_MINGW 1 67 #else 68 # define ELPP_MINGW 0 69 #endif 70 #if (defined(__CYGWIN__) && (__CYGWIN__ == 1)) 71 # define ELPP_CYGWIN 1 72 #else 73 # define ELPP_CYGWIN 0 74 #endif 75 #if (defined(__INTEL_COMPILER)) 76 # define ELPP_COMPILER_INTEL 1 77 #else 78 # define ELPP_COMPILER_INTEL 0 79 #endif 80 // Operating System Evaluation 81 // Windows 82 #if (defined(_WIN32) || defined(_WIN64)) 83 # define ELPP_OS_WINDOWS 1 84 #else 85 # define ELPP_OS_WINDOWS 0 86 #endif 87 // Linux 88 #if (defined(__linux) || defined(__linux__)) 89 # define ELPP_OS_LINUX 1 90 #else 91 # define ELPP_OS_LINUX 0 92 #endif 93 #if (defined(__APPLE__)) 94 # define ELPP_OS_MAC 1 95 #else 96 # define ELPP_OS_MAC 0 97 #endif 98 #if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) 99 # define ELPP_OS_FREEBSD 1 100 #else 101 # define ELPP_OS_FREEBSD 0 102 #endif 103 #if (defined(__sun)) 104 # define ELPP_OS_SOLARIS 1 105 #else 106 # define ELPP_OS_SOLARIS 0 107 #endif 108 #if (defined(_AIX)) 109 # define ELPP_OS_AIX 1 110 #else 111 # define ELPP_OS_AIX 0 112 #endif 113 #if (defined(__NetBSD__)) 114 # define ELPP_OS_NETBSD 1 115 #else 116 # define ELPP_OS_NETBSD 0 117 #endif 118 // Unix 119 #if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_NETBSD || ELPP_OS_SOLARIS || ELPP_OS_AIX) && (!ELPP_OS_WINDOWS)) 120 # define ELPP_OS_UNIX 1 121 #else 122 # define ELPP_OS_UNIX 0 123 #endif 124 #if (defined(__ANDROID__)) 125 # define ELPP_OS_ANDROID 1 126 #else 127 # define ELPP_OS_ANDROID 0 128 #endif 129 // Evaluating Cygwin as *nix OS 130 #if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN 131 # undef ELPP_OS_UNIX 132 # undef ELPP_OS_LINUX 133 # define ELPP_OS_UNIX 1 134 # define ELPP_OS_LINUX 1 135 #endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN 136 #if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO) 137 # define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout 138 #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) 139 #if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR) 140 # define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr 141 #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) 142 #if !defined(ELPP_INTERNAL_DEBUGGING_ENDL) 143 # define ELPP_INTERNAL_DEBUGGING_ENDL std::endl 144 #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) 145 #if !defined(ELPP_INTERNAL_DEBUGGING_MSG) 146 # define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg 147 #endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) 148 // Internal Assertions and errors 149 #if !defined(ELPP_DISABLE_ASSERT) 150 # if (defined(ELPP_DEBUG_ASSERT_FAILURE)) 151 # define ELPP_ASSERT(expr, msg) if (!(expr)) { \ 152 std::stringstream internalInfoStream; internalInfoStream << msg; \ 153 ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ 154 << "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \ 155 << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \ 156 "ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); } 157 # else 158 # define ELPP_ASSERT(expr, msg) if (!(expr)) { \ 159 std::stringstream internalInfoStream; internalInfoStream << msg; \ 160 ELPP_INTERNAL_DEBUGGING_OUT_ERROR\ 161 << "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \ 162 << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \ 163 << ELPP_INTERNAL_DEBUGGING_ENDL; } 164 # endif // (defined(ELPP_DEBUG_ASSERT_FAILURE)) 165 #else 166 # define ELPP_ASSERT(x, y) 167 #endif //(!defined(ELPP_DISABLE_ASSERT) 168 #if ELPP_COMPILER_MSVC 169 # define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ 170 { char buff[256]; strerror_s(buff, 256, errno); \ 171 ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0 172 #else 173 # define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ 174 ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0 175 #endif // ELPP_COMPILER_MSVC 176 #if defined(ELPP_DEBUG_ERRORS) 177 # if !defined(ELPP_INTERNAL_ERROR) 178 # define ELPP_INTERNAL_ERROR(msg, pe) { \ 179 std::stringstream internalInfoStream; internalInfoStream << "<ERROR> " << msg; \ 180 ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ 181 << "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \ 182 << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \ 183 if (pe) { ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0 184 # endif 185 #else 186 # undef ELPP_INTERNAL_INFO 187 # define ELPP_INTERNAL_ERROR(msg, pe) 188 #endif // defined(ELPP_DEBUG_ERRORS) 189 #if (defined(ELPP_DEBUG_INFO)) 190 # if !(defined(ELPP_INTERNAL_INFO_LEVEL)) 191 # define ELPP_INTERNAL_INFO_LEVEL 9 192 # endif // !(defined(ELPP_INTERNAL_INFO_LEVEL)) 193 # if !defined(ELPP_INTERNAL_INFO) 194 # define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= ELPP_INTERNAL_INFO_LEVEL) { \ 195 std::stringstream internalInfoStream; internalInfoStream << "<INFO> " << msg; \ 196 ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \ 197 << ELPP_INTERNAL_DEBUGGING_ENDL; }} 198 # endif 199 #else 200 # undef ELPP_INTERNAL_INFO 201 # define ELPP_INTERNAL_INFO(lvl, msg) 202 #endif // (defined(ELPP_DEBUG_INFO)) 203 #if (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) 204 # if (ELPP_COMPILER_GCC && !ELPP_MINGW && !ELPP_OS_ANDROID) 205 # define ELPP_STACKTRACE 1 206 # else 207 # if ELPP_COMPILER_MSVC 208 # pragma message("Stack trace not available for this compiler") 209 # else 210 # warning "Stack trace not available for this compiler"; 211 # endif // ELPP_COMPILER_MSVC 212 # define ELPP_STACKTRACE 0 213 # endif // ELPP_COMPILER_GCC 214 #else 215 # define ELPP_STACKTRACE 0 216 #endif // (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) 217 // Miscellaneous macros 218 #define ELPP_UNUSED(x) (void)x 219 #if ELPP_OS_UNIX 220 // Log file permissions for unix-based systems 221 # define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH 222 #endif // ELPP_OS_UNIX 223 #if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC 224 # if defined(ELPP_EXPORT_SYMBOLS) 225 # define ELPP_EXPORT __declspec(dllexport) 226 # else 227 # define ELPP_EXPORT __declspec(dllimport) 228 # endif // defined(ELPP_EXPORT_SYMBOLS) 229 #else 230 # define ELPP_EXPORT 231 #endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC 232 // Some special functions that are VC++ specific 233 #undef STRTOK 234 #undef STRERROR 235 #undef STRCAT 236 #undef STRCPY 237 #if ELPP_CRT_DBG_WARNINGS 238 # define STRTOK(a, b, c) strtok_s(a, b, c) 239 # define STRERROR(a, b, c) strerror_s(a, b, c) 240 # define STRCAT(a, b, len) strcat_s(a, len, b) 241 # define STRCPY(a, b, len) strcpy_s(a, len, b) 242 #else 243 # define STRTOK(a, b, c) strtok(a, b) 244 # define STRERROR(a, b, c) strerror(c) 245 # define STRCAT(a, b, len) strcat(a, b) 246 # define STRCPY(a, b, len) strcpy(a, b) 247 #endif 248 // Compiler specific support evaluations 249 #if (ELPP_MINGW && !defined(ELPP_FORCE_USE_STD_THREAD)) 250 # define ELPP_USE_STD_THREADING 0 251 #else 252 # if ((ELPP_COMPILER_CLANG && defined(ELPP_CLANG_SUPPORTS_THREAD)) || \ 253 (!ELPP_COMPILER_CLANG && defined(ELPP_CXX11)) || \ 254 defined(ELPP_FORCE_USE_STD_THREAD)) 255 # define ELPP_USE_STD_THREADING 1 256 # else 257 # define ELPP_USE_STD_THREADING 0 258 # endif 259 #endif 260 #undef ELPP_FINAL 261 #if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) 262 # define ELPP_FINAL 263 #else 264 # define ELPP_FINAL final 265 #endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) 266 #if defined(ELPP_EXPERIMENTAL_ASYNC) 267 # define ELPP_ASYNC_LOGGING 1 268 #else 269 # define ELPP_ASYNC_LOGGING 0 270 #endif // defined(ELPP_EXPERIMENTAL_ASYNC) 271 #if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING 272 # define ELPP_THREADING_ENABLED 1 273 #else 274 # define ELPP_THREADING_ENABLED 0 275 #endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING 276 // Function macro ELPP_FUNC 277 #undef ELPP_FUNC 278 #if ELPP_COMPILER_MSVC // Visual C++ 279 # define ELPP_FUNC __FUNCSIG__ 280 #elif ELPP_COMPILER_GCC // GCC 281 # define ELPP_FUNC __PRETTY_FUNCTION__ 282 #elif ELPP_COMPILER_INTEL // Intel C++ 283 # define ELPP_FUNC __PRETTY_FUNCTION__ 284 #elif ELPP_COMPILER_CLANG // Clang++ 285 # define ELPP_FUNC __PRETTY_FUNCTION__ 286 #else 287 # if defined(__func__) 288 # define ELPP_FUNC __func__ 289 # else 290 # define ELPP_FUNC "" 291 # endif // defined(__func__) 292 #endif // defined(_MSC_VER) 293 #undef ELPP_VARIADIC_TEMPLATES_SUPPORTED 294 // Keep following line commented until features are fixed 295 #define ELPP_VARIADIC_TEMPLATES_SUPPORTED \ 296 (ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800)) 297 // Logging Enable/Disable macros 298 #if defined(ELPP_DISABLE_LOGS) 299 #define ELPP_LOGGING_ENABLED 0 300 #else 301 #define ELPP_LOGGING_ENABLED 1 302 #endif 303 #if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) 304 # define ELPP_DEBUG_LOG 1 305 #else 306 # define ELPP_DEBUG_LOG 0 307 #endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) 308 #if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) 309 # define ELPP_INFO_LOG 1 310 #else 311 # define ELPP_INFO_LOG 0 312 #endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) 313 #if (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) 314 # define ELPP_WARNING_LOG 1 315 #else 316 # define ELPP_WARNING_LOG 0 317 #endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) 318 #if (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) 319 # define ELPP_ERROR_LOG 1 320 #else 321 # define ELPP_ERROR_LOG 0 322 #endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) 323 #if (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) 324 # define ELPP_FATAL_LOG 1 325 #else 326 # define ELPP_FATAL_LOG 0 327 #endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) 328 #if (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) 329 # define ELPP_TRACE_LOG 1 330 #else 331 # define ELPP_TRACE_LOG 0 332 #endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) 333 #if (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) 334 # define ELPP_VERBOSE_LOG 1 335 #else 336 # define ELPP_VERBOSE_LOG 0 337 #endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) 338 #if (!(ELPP_CXX0X || ELPP_CXX11)) 339 # error "C++0x (or higher) support not detected! (Is `-std=c++11' missing?)" 340 #endif // (!(ELPP_CXX0X || ELPP_CXX11)) 341 // Headers 342 #if defined(ELPP_SYSLOG) 343 # include <syslog.h> 344 #endif // defined(ELPP_SYSLOG) 345 #include <ctime> 346 #include <cstring> 347 #include <cstdlib> 348 #include <cctype> 349 #include <cwchar> 350 #include <csignal> 351 #include <cerrno> 352 #include <cstdarg> 353 #if defined(ELPP_UNICODE) 354 # include <locale> 355 # if ELPP_OS_WINDOWS 356 # include <codecvt> 357 # endif // ELPP_OS_WINDOWS 358 #endif // defined(ELPP_UNICODE) 359 #if ELPP_STACKTRACE 360 # include <cxxabi.h> 361 # include <execinfo.h> 362 #endif // ELPP_STACKTRACE 363 #if ELPP_OS_ANDROID 364 # include <sys/system_properties.h> 365 #endif // ELPP_OS_ANDROID 366 #if ELPP_OS_UNIX 367 # include <sys/stat.h> 368 # include <sys/time.h> 369 #elif ELPP_OS_WINDOWS 370 # include <direct.h> 371 # include <windows.h> 372 # if defined(WIN32_LEAN_AND_MEAN) 373 # if defined(ELPP_WINSOCK2) 374 # include <winsock2.h> 375 # else 376 # include <winsock.h> 377 # endif // defined(ELPP_WINSOCK2) 378 # endif // defined(WIN32_LEAN_AND_MEAN) 379 #endif // ELPP_OS_UNIX 380 #include <string> 381 #include <vector> 382 #include <map> 383 #include <unordered_map> 384 #include <utility> 385 #include <functional> 386 #include <algorithm> 387 #include <fstream> 388 #include <iostream> 389 #include <sstream> 390 #include <memory> 391 #include <type_traits> 392 #if ELPP_THREADING_ENABLED 393 # if ELPP_USE_STD_THREADING 394 # include <mutex> 395 # include <thread> 396 # else 397 # if ELPP_OS_UNIX 398 # include <pthread.h> 399 # endif // ELPP_OS_UNIX 400 # endif // ELPP_USE_STD_THREADING 401 #endif // ELPP_THREADING_ENABLED 402 #if ELPP_ASYNC_LOGGING 403 # if defined(ELPP_NO_SLEEP_FOR) 404 # include <unistd.h> 405 # endif // defined(ELPP_NO_SLEEP_FOR) 406 # include <thread> 407 # include <queue> 408 # include <condition_variable> 409 #endif // ELPP_ASYNC_LOGGING 410 #if defined(ELPP_STL_LOGGING) 411 // For logging STL based templates 412 # include <list> 413 # include <queue> 414 # include <deque> 415 # include <set> 416 # include <bitset> 417 # include <stack> 418 # if defined(ELPP_LOG_STD_ARRAY) 419 # include <array> 420 # endif // defined(ELPP_LOG_STD_ARRAY) 421 # if defined(ELPP_LOG_UNORDERED_SET) 422 # include <unordered_set> 423 # endif // defined(ELPP_UNORDERED_SET) 424 #endif // defined(ELPP_STL_LOGGING) 425 #if defined(ELPP_QT_LOGGING) 426 // For logging Qt based classes & templates 427 # include <QString> 428 # include <QByteArray> 429 # include <QVector> 430 # include <QList> 431 # include <QPair> 432 # include <QMap> 433 # include <QQueue> 434 # include <QSet> 435 # include <QLinkedList> 436 # include <QHash> 437 # include <QMultiHash> 438 # include <QStack> 439 #endif // defined(ELPP_QT_LOGGING) 440 #if defined(ELPP_BOOST_LOGGING) 441 // For logging boost based classes & templates 442 # include <boost/container/vector.hpp> 443 # include <boost/container/stable_vector.hpp> 444 # include <boost/container/list.hpp> 445 # include <boost/container/deque.hpp> 446 # include <boost/container/map.hpp> 447 # include <boost/container/flat_map.hpp> 448 # include <boost/container/set.hpp> 449 # include <boost/container/flat_set.hpp> 450 #endif // defined(ELPP_BOOST_LOGGING) 451 #if defined(ELPP_WXWIDGETS_LOGGING) 452 // For logging wxWidgets based classes & templates 453 # include <wx/vector.h> 454 #endif // defined(ELPP_WXWIDGETS_LOGGING) 455 #if defined(ELPP_UTC_DATETIME) 456 # define elpptime_r gmtime_r 457 # define elpptime_s gmtime_s 458 # define elpptime gmtime 459 #else 460 # define elpptime_r localtime_r 461 # define elpptime_s localtime_s 462 # define elpptime localtime 463 #endif // defined(ELPP_UTC_DATETIME) 464 // Forward declarations 465 namespace el { 466 class Logger; 467 class LogMessage; 468 class PerformanceTrackingData; 469 class Loggers; 470 class Helpers; 471 template <typename T> class Callback; 472 class LogDispatchCallback; 473 class PerformanceTrackingCallback; 474 class LoggerRegistrationCallback; 475 class LogDispatchData; 476 namespace base { 477 class Storage; 478 class RegisteredLoggers; 479 class PerformanceTracker; 480 class MessageBuilder; 481 class Writer; 482 class PErrorWriter; 483 class LogDispatcher; 484 class DefaultLogBuilder; 485 class DefaultLogDispatchCallback; 486 #if ELPP_ASYNC_LOGGING 487 class AsyncLogDispatchCallback; 488 class AsyncDispatchWorker; 489 #endif // ELPP_ASYNC_LOGGING 490 class DefaultPerformanceTrackingCallback; 491 } // namespace base 492 } // namespace el 493 /// @brief Easylogging++ entry namespace 494 namespace el { 495 /// @brief Namespace containing base/internal functionality used by Easylogging++ 496 namespace base { 497 /// @brief Data types used by Easylogging++ 498 namespace type { 499 #undef ELPP_LITERAL 500 #undef ELPP_STRLEN 501 #undef ELPP_COUT 502 #if defined(ELPP_UNICODE) 503 # define ELPP_LITERAL(txt) L##txt 504 # define ELPP_STRLEN wcslen 505 # if defined ELPP_CUSTOM_COUT 506 # define ELPP_COUT ELPP_CUSTOM_COUT 507 # else 508 # define ELPP_COUT std::wcout 509 # endif // defined ELPP_CUSTOM_COUT 510 typedef wchar_t char_t; 511 typedef std::wstring string_t; 512 typedef std::wstringstream stringstream_t; 513 typedef std::wfstream fstream_t; 514 typedef std::wostream ostream_t; 515 #else 516 # define ELPP_LITERAL(txt) txt 517 # define ELPP_STRLEN strlen 518 # if defined ELPP_CUSTOM_COUT 519 # define ELPP_COUT ELPP_CUSTOM_COUT 520 # else 521 # define ELPP_COUT std::cout 522 # endif // defined ELPP_CUSTOM_COUT 523 typedef char char_t; 524 typedef std::string string_t; 525 typedef std::stringstream stringstream_t; 526 typedef std::fstream fstream_t; 527 typedef std::ostream ostream_t; 528 #endif // defined(ELPP_UNICODE) 529 #if defined(ELPP_CUSTOM_COUT_LINE) 530 # define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine) 531 #else 532 # define ELPP_COUT_LINE(logLine) logLine << std::flush 533 #endif // defined(ELPP_CUSTOM_COUT_LINE) 534 typedef unsigned int EnumType; 535 typedef unsigned short VerboseLevel; 536 typedef unsigned long int LineNumber; 537 typedef std::shared_ptr<base::Storage> StoragePointer; 538 typedef std::shared_ptr<LogDispatchCallback> LogDispatchCallbackPtr; 539 typedef std::shared_ptr<PerformanceTrackingCallback> PerformanceTrackingCallbackPtr; 540 typedef std::shared_ptr<LoggerRegistrationCallback> LoggerRegistrationCallbackPtr; 541 typedef std::unique_ptr<el::base::PerformanceTracker> PerformanceTrackerPtr; 542 } // namespace type 543 /// @brief Internal helper class that prevent copy constructor for class 544 /// 545 /// @detail When using this class simply inherit it privately 546 class NoCopy { 547 protected: NoCopy(void)548 NoCopy(void) {} 549 private: 550 NoCopy(const NoCopy&); 551 NoCopy& operator=(const NoCopy&); 552 }; 553 /// @brief Internal helper class that makes all default constructors private. 554 /// 555 /// @detail This prevents initializing class making it static unless an explicit constructor is declared. 556 /// When using this class simply inherit it privately 557 class StaticClass { 558 private: 559 StaticClass(void); 560 StaticClass(const StaticClass&); 561 StaticClass& operator=(const StaticClass&); 562 }; 563 } // namespace base 564 /// @brief Represents enumeration for severity level used to determine level of logging 565 /// 566 /// @detail With Easylogging++, developers may disable or enable any level regardless of 567 /// what the severity is. Or they can choose to log using hierarchical logging flag 568 enum class Level : base::type::EnumType { 569 /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels 570 Global = 1, 571 /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs. 572 Trace = 2, 573 /// @brief Informational events most useful for developers to debug application 574 Debug = 4, 575 /// @brief Severe error information that will presumably abort application 576 Fatal = 8, 577 /// @brief Information representing errors in application but application will keep running 578 Error = 16, 579 /// @brief Useful when application has potentially harmful situtaions 580 Warning = 32, 581 /// @brief Information that can be highly useful and vary with verbose logging level. 582 Verbose = 64, 583 /// @brief Mainly useful to represent current progress of application 584 Info = 128, 585 /// @brief Represents unknown level 586 Unknown = 1010 587 }; 588 } // namespace el 589 namespace std { 590 template<> struct hash<el::Level> { 591 public: 592 std::size_t operator()(const el::Level& l) const { 593 return hash<el::base::type::EnumType> {}(static_cast<el::base::type::EnumType>(l)); 594 } 595 }; 596 } 597 namespace el { 598 /// @brief Static class that contains helper functions for el::Level 599 class LevelHelper : base::StaticClass { 600 public: 601 /// @brief Represents minimum valid level. Useful when iterating through enum. 602 static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(Level::Trace); 603 /// @brief Represents maximum valid level. This is used internally and you should not need it. 604 static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(Level::Info); 605 /// @brief Casts level to int, useful for iterating through enum. 606 static base::type::EnumType castToInt(Level level) { 607 return static_cast<base::type::EnumType>(level); 608 } 609 /// @brief Casts int(ushort) to level, useful for iterating through enum. 610 static Level castFromInt(base::type::EnumType l) { 611 return static_cast<Level>(l); 612 } 613 /// @brief Converts level to associated const char* 614 /// @return Upper case string based level. 615 static const char* convertToString(Level level); 616 /// @brief Converts from levelStr to Level 617 /// @param levelStr Upper case string based level. 618 /// Lower case is also valid but providing upper case is recommended. 619 static Level convertFromString(const char* levelStr); 620 /// @brief Applies specified function to each level starting from startIndex 621 /// @param startIndex initial value to start the iteration from. This is passed as pointer and 622 /// is left-shifted so this can be used inside function (fn) to represent current level. 623 /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels. 624 static void forEachLevel(base::type::EnumType* startIndex, const std::function<bool(void)>& fn); 625 }; 626 /// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect 627 /// of logging 628 enum class ConfigurationType : base::type::EnumType { 629 /// @brief Determines whether or not corresponding level and logger of logging is enabled 630 /// You may disable all logs by using el::Level::Global 631 Enabled = 1, 632 /// @brief Whether or not to write corresponding log to log file 633 ToFile = 2, 634 /// @brief Whether or not to write corresponding level and logger log to standard output. 635 /// By standard output meaning termnal, command prompt etc 636 ToStandardOutput = 4, 637 /// @brief Determines format of logging corresponding level and logger. 638 Format = 8, 639 /// @brief Determines log file (full path) to write logs to for correponding level and logger 640 Filename = 16, 641 /// @brief Specifies precision of the subsecond part. It should be within range (1-6). 642 SubsecondPrecision = 32, 643 /// @brief Alias of SubsecondPrecision (for backward compatibility) 644 MillisecondsWidth = SubsecondPrecision, 645 /// @brief Determines whether or not performance tracking is enabled. 646 /// 647 /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger 648 PerformanceTracking = 64, 649 /// @brief Specifies log file max size. 650 /// 651 /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will 652 /// be truncated and re-initiated. 653 MaxLogFileSize = 128, 654 /// @brief Specifies number of log entries to hold until we flush pending log data 655 LogFlushThreshold = 256, 656 /// @brief Represents unknown configuration 657 Unknown = 1010 658 }; 659 /// @brief Static class that contains helper functions for el::ConfigurationType 660 class ConfigurationTypeHelper : base::StaticClass { 661 public: 662 /// @brief Represents minimum valid configuration type. Useful when iterating through enum. 663 static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(ConfigurationType::Enabled); 664 /// @brief Represents maximum valid configuration type. This is used internally and you should not need it. 665 static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(ConfigurationType::MaxLogFileSize); 666 /// @brief Casts configuration type to int, useful for iterating through enum. 667 static base::type::EnumType castToInt(ConfigurationType configurationType) { 668 return static_cast<base::type::EnumType>(configurationType); 669 } 670 /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum. 671 static ConfigurationType castFromInt(base::type::EnumType c) { 672 return static_cast<ConfigurationType>(c); 673 } 674 /// @brief Converts configuration type to associated const char* 675 /// @returns Upper case string based configuration type. 676 static const char* convertToString(ConfigurationType configurationType); 677 /// @brief Converts from configStr to ConfigurationType 678 /// @param configStr Upper case string based configuration type. 679 /// Lower case is also valid but providing upper case is recommended. 680 static ConfigurationType convertFromString(const char* configStr); 681 /// @brief Applies specified function to each configuration type starting from startIndex 682 /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted 683 /// so this can be used inside function (fn) to represent current configuration type. 684 /// @param fn function to apply with each configuration type. 685 /// This bool represent whether or not to stop iterating through configurations. 686 static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function<bool(void)>& fn); 687 }; 688 /// @brief Flags used while writing logs. This flags are set by user 689 enum class LoggingFlag : base::type::EnumType { 690 /// @brief Makes sure we have new line for each container log entry 691 NewLineForContainer = 1, 692 /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose 693 /// logging is allowed via that module. 694 AllowVerboseIfModuleNotSpecified = 2, 695 /// @brief When handling crashes by default, detailed crash reason will be logged as well 696 LogDetailedCrashReason = 4, 697 /// @brief Allows to disable application abortion when logged using FATAL level 698 DisableApplicationAbortOnFatalLog = 8, 699 /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default 700 ImmediateFlush = 16, 701 /// @brief Enables strict file rolling 702 StrictLogFileSizeCheck = 32, 703 /// @brief Make terminal output colorful for supported terminals 704 ColoredTerminalOutput = 64, 705 /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network") 706 MultiLoggerSupport = 128, 707 /// @brief Disables comparing performance tracker's checkpoints 708 DisablePerformanceTrackingCheckpointComparison = 256, 709 /// @brief Disable VModules 710 DisableVModules = 512, 711 /// @brief Disable VModules extensions 712 DisableVModulesExtensions = 1024, 713 /// @brief Enables hierarchical logging 714 HierarchicalLogging = 2048, 715 /// @brief Creates logger automatically when not available 716 CreateLoggerAutomatically = 4096, 717 /// @brief Adds spaces b/w logs that separated by left-shift operator 718 AutoSpacing = 8192, 719 /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) 720 FixedTimeFormat = 16384 721 }; 722 namespace base { 723 /// @brief Namespace containing constants used internally. 724 namespace consts { 725 static const char kFormatSpecifierCharValue = 'v'; 726 static const char kFormatSpecifierChar = '%'; 727 static const unsigned int kMaxLogPerCounter = 100000; 728 static const unsigned int kMaxLogPerContainer = 100; 729 static const unsigned int kDefaultSubsecondPrecision = 3; 730 731 #ifdef ELPP_DEFAULT_LOGGER 732 static const char* kDefaultLoggerId = ELPP_DEFAULT_LOGGER; 733 #else 734 static const char* kDefaultLoggerId = "default"; 735 #endif 736 737 #ifdef ELPP_DEFAULT_PERFORMANCE_LOGGER 738 static const char* kPerformanceLoggerId = ELPP_DEFAULT_PERFORMANCE_LOGGER; 739 #endif 740 741 #if defined(ELPP_SYSLOG) 742 static const char* kSysLogLoggerId = "syslog"; 743 #endif // defined(ELPP_SYSLOG) 744 745 #if ELPP_OS_WINDOWS 746 static const char* kFilePathSeperator = "\\"; 747 #else 748 static const char* kFilePathSeperator = "/"; 749 #endif // ELPP_OS_WINDOWS 750 751 static const std::size_t kSourceFilenameMaxLength = 100; 752 static const std::size_t kSourceLineMaxLength = 10; 753 static const Level kPerformanceTrackerDefaultLevel = Level::Info; 754 const struct { 755 double value; 756 const base::type::char_t* unit; 757 } kTimeFormats[] = { 758 { 1000.0f, ELPP_LITERAL("us") }, 759 { 1000.0f, ELPP_LITERAL("ms") }, 760 { 60.0f, ELPP_LITERAL("seconds") }, 761 { 60.0f, ELPP_LITERAL("minutes") }, 762 { 24.0f, ELPP_LITERAL("hours") }, 763 { 7.0f, ELPP_LITERAL("days") } 764 }; 765 static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]); 766 const struct { 767 int numb; 768 const char* name; 769 const char* brief; 770 const char* detail; 771 } kCrashSignals[] = { 772 // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..) 773 { 774 SIGABRT, "SIGABRT", "Abnormal termination", 775 "Program was abnormally terminated." 776 }, 777 { 778 SIGFPE, "SIGFPE", "Erroneous arithmetic operation", 779 "Arithemetic operation issue such as division by zero or operation resulting in overflow." 780 }, 781 { 782 SIGILL, "SIGILL", "Illegal instruction", 783 "Generally due to a corruption in the code or to an attempt to execute data." 784 }, 785 { 786 SIGSEGV, "SIGSEGV", "Invalid access to memory", 787 "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory." 788 }, 789 { 790 SIGINT, "SIGINT", "Interactive attention signal", 791 "Interruption generated (generally) by user or operating system." 792 }, 793 }; 794 static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); 795 } // namespace consts 796 } // namespace base 797 typedef std::function<void(const char*, std::size_t)> PreRollOutCallback; 798 namespace base { 799 static inline void defaultPreRollOutCallback(const char*, std::size_t) {} 800 /// @brief Enum to represent timestamp unit 801 enum class TimestampUnit : base::type::EnumType { 802 Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5 803 }; 804 /// @brief Format flags used to determine specifiers that are active for performance improvements. 805 enum class FormatFlags : base::type::EnumType { 806 DateTime = 1 << 1, 807 LoggerId = 1 << 2, 808 File = 1 << 3, 809 Line = 1 << 4, 810 Location = 1 << 5, 811 Function = 1 << 6, 812 User = 1 << 7, 813 Host = 1 << 8, 814 LogMessage = 1 << 9, 815 VerboseLevel = 1 << 10, 816 AppName = 1 << 11, 817 ThreadId = 1 << 12, 818 Level = 1 << 13, 819 FileBase = 1 << 14, 820 LevelShort = 1 << 15 821 }; 822 /// @brief A subsecond precision class containing actual width and offset of the subsecond part 823 class SubsecondPrecision { 824 public: 825 SubsecondPrecision(void) { 826 init(base::consts::kDefaultSubsecondPrecision); 827 } 828 explicit SubsecondPrecision(int width) { 829 init(width); 830 } 831 bool operator==(const SubsecondPrecision& ssPrec) { 832 return m_width == ssPrec.m_width && m_offset == ssPrec.m_offset; 833 } 834 int m_width; 835 unsigned int m_offset; 836 private: 837 void init(int width); 838 }; 839 /// @brief Type alias of SubsecondPrecision 840 typedef SubsecondPrecision MillisecondsWidth; 841 /// @brief Namespace containing utility functions/static classes used internally 842 namespace utils { 843 /// @brief Deletes memory safely and points to null 844 template <typename T> 845 static 846 typename std::enable_if<std::is_pointer<T*>::value, void>::type 847 safeDelete(T*& pointer) { 848 if (pointer == nullptr) 849 return; 850 delete pointer; 851 pointer = nullptr; 852 } 853 /// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation 854 /// Use these function as <pre>flag = bitwise::Or<MyEnum>(MyEnum::val1, flag);</pre> 855 namespace bitwise { 856 template <typename Enum> 857 static inline base::type::EnumType And(Enum e, base::type::EnumType flag) { 858 return static_cast<base::type::EnumType>(flag) & static_cast<base::type::EnumType>(e); 859 } 860 template <typename Enum> 861 static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) { 862 return static_cast<base::type::EnumType>(flag) & ~(static_cast<base::type::EnumType>(e)); 863 } 864 template <typename Enum> 865 static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) { 866 return static_cast<base::type::EnumType>(flag) | static_cast<base::type::EnumType>(e); 867 } 868 } // namespace bitwise 869 template <typename Enum> 870 static inline void addFlag(Enum e, base::type::EnumType* flag) { 871 *flag = base::utils::bitwise::Or<Enum>(e, *flag); 872 } 873 template <typename Enum> 874 static inline void removeFlag(Enum e, base::type::EnumType* flag) { 875 *flag = base::utils::bitwise::Not<Enum>(e, *flag); 876 } 877 template <typename Enum> 878 static inline bool hasFlag(Enum e, base::type::EnumType flag) { 879 return base::utils::bitwise::And<Enum>(e, flag) > 0x0; 880 } 881 } // namespace utils 882 namespace threading { 883 #if ELPP_THREADING_ENABLED 884 # if !ELPP_USE_STD_THREADING 885 namespace internal { 886 /// @brief A mutex wrapper for compiler that dont yet support std::recursive_mutex 887 class Mutex : base::NoCopy { 888 public: 889 Mutex(void) { 890 # if ELPP_OS_UNIX 891 pthread_mutexattr_t attr; 892 pthread_mutexattr_init(&attr); 893 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 894 pthread_mutex_init(&m_underlyingMutex, &attr); 895 pthread_mutexattr_destroy(&attr); 896 # elif ELPP_OS_WINDOWS 897 InitializeCriticalSection(&m_underlyingMutex); 898 # endif // ELPP_OS_UNIX 899 } 900 901 virtual ~Mutex(void) { 902 # if ELPP_OS_UNIX 903 pthread_mutex_destroy(&m_underlyingMutex); 904 # elif ELPP_OS_WINDOWS 905 DeleteCriticalSection(&m_underlyingMutex); 906 # endif // ELPP_OS_UNIX 907 } 908 909 inline void lock(void) { 910 # if ELPP_OS_UNIX 911 pthread_mutex_lock(&m_underlyingMutex); 912 # elif ELPP_OS_WINDOWS 913 EnterCriticalSection(&m_underlyingMutex); 914 # endif // ELPP_OS_UNIX 915 } 916 917 inline bool try_lock(void) { 918 # if ELPP_OS_UNIX 919 return (pthread_mutex_trylock(&m_underlyingMutex) == 0); 920 # elif ELPP_OS_WINDOWS 921 return TryEnterCriticalSection(&m_underlyingMutex); 922 # endif // ELPP_OS_UNIX 923 } 924 925 inline void unlock(void) { 926 # if ELPP_OS_UNIX 927 pthread_mutex_unlock(&m_underlyingMutex); 928 # elif ELPP_OS_WINDOWS 929 LeaveCriticalSection(&m_underlyingMutex); 930 # endif // ELPP_OS_UNIX 931 } 932 933 private: 934 # if ELPP_OS_UNIX 935 pthread_mutex_t m_underlyingMutex; 936 # elif ELPP_OS_WINDOWS 937 CRITICAL_SECTION m_underlyingMutex; 938 # endif // ELPP_OS_UNIX 939 }; 940 /// @brief Scoped lock for compiler that dont yet support std::lock_guard 941 template <typename M> 942 class ScopedLock : base::NoCopy { 943 public: 944 explicit ScopedLock(M& mutex) { 945 m_mutex = &mutex; 946 m_mutex->lock(); 947 } 948 949 virtual ~ScopedLock(void) { 950 m_mutex->unlock(); 951 } 952 private: 953 M* m_mutex; 954 ScopedLock(void); 955 }; 956 } // namespace internal 957 typedef base::threading::internal::Mutex Mutex; 958 typedef base::threading::internal::ScopedLock<base::threading::Mutex> ScopedLock; 959 # else 960 typedef std::recursive_mutex Mutex; 961 typedef std::lock_guard<base::threading::Mutex> ScopedLock; 962 # endif // !ELPP_USE_STD_THREADING 963 #else 964 namespace internal { 965 /// @brief Mutex wrapper used when multi-threading is disabled. 966 class NoMutex : base::NoCopy { 967 public: 968 NoMutex(void) {} 969 inline void lock(void) {} 970 inline bool try_lock(void) { 971 return true; 972 } 973 inline void unlock(void) {} 974 }; 975 /// @brief Lock guard wrapper used when multi-threading is disabled. 976 template <typename Mutex> 977 class NoScopedLock : base::NoCopy { 978 public: 979 explicit NoScopedLock(Mutex&) { 980 } 981 virtual ~NoScopedLock(void) { 982 } 983 private: 984 NoScopedLock(void); 985 }; 986 } // namespace internal 987 typedef base::threading::internal::NoMutex Mutex; 988 typedef base::threading::internal::NoScopedLock<base::threading::Mutex> ScopedLock; 989 #endif // ELPP_THREADING_ENABLED 990 /// @brief Base of thread safe class, this class is inheritable-only 991 class ThreadSafe { 992 public: 993 virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); } 994 virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); } 995 virtual inline base::threading::Mutex& lock(void) ELPP_FINAL { return m_mutex; } 996 protected: 997 ThreadSafe(void) {} 998 virtual ~ThreadSafe(void) {} 999 private: 1000 base::threading::Mutex m_mutex; 1001 }; 1002 1003 #if ELPP_THREADING_ENABLED 1004 # if !ELPP_USE_STD_THREADING 1005 /// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned. 1006 static std::string getCurrentThreadId(void) { 1007 std::stringstream ss; 1008 # if (ELPP_OS_WINDOWS) 1009 ss << GetCurrentThreadId(); 1010 # endif // (ELPP_OS_WINDOWS) 1011 return ss.str(); 1012 } 1013 # else 1014 /// @brief Gets ID of currently running threading using std::this_thread::get_id() 1015 static std::string getCurrentThreadId(void) { 1016 std::stringstream ss; 1017 ss << std::this_thread::get_id(); 1018 return ss.str(); 1019 } 1020 # endif // !ELPP_USE_STD_THREADING 1021 #else 1022 static inline std::string getCurrentThreadId(void) { 1023 return std::string(); 1024 } 1025 #endif // ELPP_THREADING_ENABLED 1026 } // namespace threading 1027 namespace utils { 1028 class File : base::StaticClass { 1029 public: 1030 /// @brief Creates new out file stream for specified filename. 1031 /// @return Pointer to newly created fstream or nullptr 1032 static base::type::fstream_t* newFileStream(const std::string& filename); 1033 1034 /// @brief Gets size of file provided in stream 1035 static std::size_t getSizeOfFile(base::type::fstream_t* fs); 1036 1037 /// @brief Determines whether or not provided path exist in current file system 1038 static bool pathExists(const char* path, bool considerFile = false); 1039 1040 /// @brief Creates specified path on file system 1041 /// @param path Path to create. 1042 static bool createPath(const std::string& path); 1043 /// @brief Extracts path of filename with leading slash 1044 static std::string extractPathFromFilename(const std::string& fullPath, 1045 const char* seperator = base::consts::kFilePathSeperator); 1046 /// @brief builds stripped filename and puts it in buff 1047 static void buildStrippedFilename(const char* filename, char buff[], 1048 std::size_t limit = base::consts::kSourceFilenameMaxLength); 1049 /// @brief builds base filename and puts it in buff 1050 static void buildBaseFilename(const std::string& fullPath, char buff[], 1051 std::size_t limit = base::consts::kSourceFilenameMaxLength, 1052 const char* seperator = base::consts::kFilePathSeperator); 1053 }; 1054 /// @brief String utilities helper class used internally. You should not use it. 1055 class Str : base::StaticClass { 1056 public: 1057 /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues. 1058 static inline bool isDigit(char c) { 1059 return c >= '0' && c <= '9'; 1060 } 1061 1062 /// @brief Matches wildcards, '*' and '?' only supported. 1063 static bool wildCardMatch(const char* str, const char* pattern); 1064 1065 static std::string& ltrim(std::string& str); 1066 static std::string& rtrim(std::string& str); 1067 static std::string& trim(std::string& str); 1068 1069 /// @brief Determines whether or not str starts with specified string 1070 /// @param str String to check 1071 /// @param start String to check against 1072 /// @return Returns true if starts with specified string, false otherwise 1073 static bool startsWith(const std::string& str, const std::string& start); 1074 1075 /// @brief Determines whether or not str ends with specified string 1076 /// @param str String to check 1077 /// @param end String to check against 1078 /// @return Returns true if ends with specified string, false otherwise 1079 static bool endsWith(const std::string& str, const std::string& end); 1080 1081 /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance. 1082 /// @param [in,out] str String to replace from 1083 /// @param replaceWhat Character to replace 1084 /// @param replaceWith Character to replace with 1085 /// @return Modified version of str 1086 static std::string& replaceAll(std::string& str, char replaceWhat, char replaceWith); 1087 1088 /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place 1089 /// @param str String to replace from 1090 /// @param replaceWhat Character to replace 1091 /// @param replaceWith Character to replace with 1092 /// @return Modified (original) str 1093 static std::string& replaceAll(std::string& str, const std::string& replaceWhat, 1094 const std::string& replaceWith); 1095 1096 static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, 1097 const base::type::string_t& replaceWith); 1098 #if defined(ELPP_UNICODE) 1099 static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, 1100 const std::string& replaceWith); 1101 #endif // defined(ELPP_UNICODE) 1102 /// @brief Converts string to uppercase 1103 /// @param str String to convert 1104 /// @return Uppercase string 1105 static std::string& toUpper(std::string& str); 1106 1107 /// @brief Compares cstring equality - uses strcmp 1108 static bool cStringEq(const char* s1, const char* s2); 1109 1110 /// @brief Compares cstring equality (case-insensitive) - uses toupper(char) 1111 /// Dont use strcasecmp because of CRT (VC++) 1112 static bool cStringCaseEq(const char* s1, const char* s2); 1113 1114 /// @brief Returns true if c exist in str 1115 static bool contains(const char* str, char c); 1116 1117 static char* convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded = true); 1118 static char* addToBuff(const char* str, char* buf, const char* bufLim); 1119 static char* clearBuff(char buff[], std::size_t lim); 1120 1121 /// @brief Converst wchar* to char* 1122 /// NOTE: Need to free return value after use! 1123 static char* wcharPtrToCharPtr(const wchar_t* line); 1124 }; 1125 /// @brief Operating System helper static class used internally. You should not use it. 1126 class OS : base::StaticClass { 1127 public: 1128 #if ELPP_OS_WINDOWS 1129 /// @brief Gets environment variables for Windows based OS. 1130 /// We are not using <code>getenv(const char*)</code> because of CRT deprecation 1131 /// @param varname Variable name to get environment variable value for 1132 /// @return If variable exist the value of it otherwise nullptr 1133 static const char* getWindowsEnvironmentVariable(const char* varname); 1134 #endif // ELPP_OS_WINDOWS 1135 #if ELPP_OS_ANDROID 1136 /// @brief Reads android property value 1137 static std::string getProperty(const char* prop); 1138 1139 /// @brief Reads android device name 1140 static std::string getDeviceName(void); 1141 #endif // ELPP_OS_ANDROID 1142 1143 /// @brief Runs command on terminal and returns the output. 1144 /// 1145 /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned. 1146 /// @param command Bash command 1147 /// @return Result of bash output or empty string if no result found. 1148 static const std::string getBashOutput(const char* command); 1149 1150 /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++) 1151 /// @param variableName Environment variable name 1152 /// @param defaultVal If no environment variable or value found the value to return by default 1153 /// @param alternativeBashCommand If environment variable not found what would be alternative bash command 1154 /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami' 1155 static std::string getEnvironmentVariable(const char* variableName, const char* defaultVal, 1156 const char* alternativeBashCommand = nullptr); 1157 /// @brief Gets current username. 1158 static std::string currentUser(void); 1159 1160 /// @brief Gets current host name or computer name. 1161 /// 1162 /// @detail For android systems this is device name with its manufacturer and model seperated by hyphen 1163 static std::string currentHost(void); 1164 /// @brief Whether or not terminal supports colors 1165 static bool termSupportsColor(void); 1166 }; 1167 /// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str 1168 class DateTime : base::StaticClass { 1169 public: 1170 /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current microsecond. 1171 /// 1172 /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a seperate implementation is provided 1173 /// @param [in,out] tv Pointer that gets updated 1174 static void gettimeofday(struct timeval* tv); 1175 1176 /// @brief Gets current date and time with a subsecond part. 1177 /// @param format User provided date/time format 1178 /// @param ssPrec A pointer to base::SubsecondPrecision from configuration (non-null) 1179 /// @returns string based date time in specified format. 1180 static std::string getDateTime(const char* format, const base::SubsecondPrecision* ssPrec); 1181 1182 /// @brief Converts timeval (struct from ctime) to string using specified format and subsecond precision 1183 static std::string timevalToString(struct timeval tval, const char* format, 1184 const el::base::SubsecondPrecision* ssPrec); 1185 1186 /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc 1187 static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit); 1188 1189 /// @brief Gets time difference in milli/micro second depending on timestampUnit 1190 static unsigned long long getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, 1191 base::TimestampUnit timestampUnit); 1192 1193 1194 static struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo); 1195 private: 1196 static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, 1197 std::size_t msec, const base::SubsecondPrecision* ssPrec); 1198 }; 1199 /// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..) 1200 class CommandLineArgs { 1201 public: 1202 CommandLineArgs(void) { 1203 setArgs(0, static_cast<char**>(nullptr)); 1204 } 1205 CommandLineArgs(int argc, const char** argv) { 1206 setArgs(argc, argv); 1207 } 1208 CommandLineArgs(int argc, char** argv) { 1209 setArgs(argc, argv); 1210 } 1211 virtual ~CommandLineArgs(void) {} 1212 /// @brief Sets arguments and parses them 1213 inline void setArgs(int argc, const char** argv) { 1214 setArgs(argc, const_cast<char**>(argv)); 1215 } 1216 /// @brief Sets arguments and parses them 1217 void setArgs(int argc, char** argv); 1218 /// @brief Returns true if arguments contain paramKey with a value (seperated by '=') 1219 bool hasParamWithValue(const char* paramKey) const; 1220 /// @brief Returns value of arguments 1221 /// @see hasParamWithValue(const char*) 1222 const char* getParamValue(const char* paramKey) const; 1223 /// @brief Return true if arguments has a param (not having a value) i,e without '=' 1224 bool hasParam(const char* paramKey) const; 1225 /// @brief Returns true if no params available. This exclude argv[0] 1226 bool empty(void) const; 1227 /// @brief Returns total number of arguments. This exclude argv[0] 1228 std::size_t size(void) const; 1229 friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c); 1230 1231 private: 1232 int m_argc; 1233 char** m_argv; 1234 std::unordered_map<std::string, std::string> m_paramsWithValue; 1235 std::vector<std::string> m_params; 1236 }; 1237 /// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. 1238 /// 1239 /// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement 1240 /// unregisterAll() and deepCopy(const AbstractRegistry<T_Ptr, Container>&) and write registerNew() method according to container 1241 /// and few more methods; get() to find element, unregister() to unregister single entry. 1242 /// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation. 1243 template <typename T_Ptr, typename Container> 1244 class AbstractRegistry : public base::threading::ThreadSafe { 1245 public: 1246 typedef typename Container::iterator iterator; 1247 typedef typename Container::const_iterator const_iterator; 1248 1249 /// @brief Default constructor 1250 AbstractRegistry(void) {} 1251 1252 /// @brief Move constructor that is useful for base classes 1253 AbstractRegistry(AbstractRegistry&& sr) { 1254 if (this == &sr) { 1255 return; 1256 } 1257 unregisterAll(); 1258 m_list = std::move(sr.m_list); 1259 } 1260 1261 bool operator==(const AbstractRegistry<T_Ptr, Container>& other) { 1262 if (size() != other.size()) { 1263 return false; 1264 } 1265 for (std::size_t i = 0; i < m_list.size(); ++i) { 1266 if (m_list.at(i) != other.m_list.at(i)) { 1267 return false; 1268 } 1269 } 1270 return true; 1271 } 1272 1273 bool operator!=(const AbstractRegistry<T_Ptr, Container>& other) { 1274 if (size() != other.size()) { 1275 return true; 1276 } 1277 for (std::size_t i = 0; i < m_list.size(); ++i) { 1278 if (m_list.at(i) != other.m_list.at(i)) { 1279 return true; 1280 } 1281 } 1282 return false; 1283 } 1284 1285 /// @brief Assignment move operator 1286 AbstractRegistry& operator=(AbstractRegistry&& sr) { 1287 if (this == &sr) { 1288 return *this; 1289 } 1290 unregisterAll(); 1291 m_list = std::move(sr.m_list); 1292 return *this; 1293 } 1294 1295 virtual ~AbstractRegistry(void) { 1296 } 1297 1298 /// @return Iterator pointer from start of repository 1299 virtual inline iterator begin(void) ELPP_FINAL { 1300 return m_list.begin(); 1301 } 1302 1303 /// @return Iterator pointer from end of repository 1304 virtual inline iterator end(void) ELPP_FINAL { 1305 return m_list.end(); 1306 } 1307 1308 1309 /// @return Constant iterator pointer from start of repository 1310 virtual inline const_iterator cbegin(void) const ELPP_FINAL { 1311 return m_list.cbegin(); 1312 } 1313 1314 /// @return End of repository 1315 virtual inline const_iterator cend(void) const ELPP_FINAL { 1316 return m_list.cend(); 1317 } 1318 1319 /// @return Whether or not repository is empty 1320 virtual inline bool empty(void) const ELPP_FINAL { 1321 return m_list.empty(); 1322 } 1323 1324 /// @return Size of repository 1325 virtual inline std::size_t size(void) const ELPP_FINAL { 1326 return m_list.size(); 1327 } 1328 1329 /// @brief Returns underlying container by reference 1330 virtual inline Container& list(void) ELPP_FINAL { 1331 return m_list; 1332 } 1333 1334 /// @brief Returns underlying container by constant reference. 1335 virtual inline const Container& list(void) const ELPP_FINAL { 1336 return m_list; 1337 } 1338 1339 /// @brief Unregisters all the pointers from current repository. 1340 virtual void unregisterAll(void) = 0; 1341 1342 protected: 1343 virtual void deepCopy(const AbstractRegistry<T_Ptr, Container>&) = 0; 1344 void reinitDeepCopy(const AbstractRegistry<T_Ptr, Container>& sr) { 1345 unregisterAll(); 1346 deepCopy(sr); 1347 } 1348 1349 private: 1350 Container m_list; 1351 }; 1352 1353 /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version) 1354 /// 1355 /// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions) 1356 /// of AbstractRegistry<T_Ptr, Container>. Any implementation of this class should be 1357 /// explicitly (by using lock functions) 1358 template <typename T_Ptr, typename T_Key = const char*> 1359 class Registry : public AbstractRegistry<T_Ptr, std::unordered_map<T_Key, T_Ptr*>> { 1360 public: 1361 typedef typename Registry<T_Ptr, T_Key>::iterator iterator; 1362 typedef typename Registry<T_Ptr, T_Key>::const_iterator const_iterator; 1363 1364 Registry(void) {} 1365 1366 /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. 1367 Registry(const Registry& sr) : AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>() { 1368 if (this == &sr) { 1369 return; 1370 } 1371 this->reinitDeepCopy(sr); 1372 } 1373 1374 /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element 1375 /// @see unregisterAll() 1376 /// @see deepCopy(const AbstractRegistry&) 1377 Registry& operator=(const Registry& sr) { 1378 if (this == &sr) { 1379 return *this; 1380 } 1381 this->reinitDeepCopy(sr); 1382 return *this; 1383 } 1384 1385 virtual ~Registry(void) { 1386 unregisterAll(); 1387 } 1388 1389 protected: 1390 virtual void unregisterAll(void) ELPP_FINAL { 1391 if (!this->empty()) { 1392 for (auto&& curr : this->list()) { 1393 base::utils::safeDelete(curr.second); 1394 } 1395 this->list().clear(); 1396 } 1397 } 1398 1399 /// @brief Registers new registry to repository. 1400 virtual void registerNew(const T_Key& uniqKey, T_Ptr* ptr) ELPP_FINAL { 1401 unregister(uniqKey); 1402 this->list().insert(std::make_pair(uniqKey, ptr)); 1403 } 1404 1405 /// @brief Unregisters single entry mapped to specified unique key 1406 void unregister(const T_Key& uniqKey) { 1407 T_Ptr* existing = get(uniqKey); 1408 if (existing != nullptr) { 1409 this->list().erase(uniqKey); 1410 base::utils::safeDelete(existing); 1411 } 1412 } 1413 1414 /// @brief Gets pointer from repository. If none found, nullptr is returned. 1415 T_Ptr* get(const T_Key& uniqKey) { 1416 iterator it = this->list().find(uniqKey); 1417 return it == this->list().end() 1418 ? nullptr 1419 : it->second; 1420 } 1421 1422 private: 1423 virtual void deepCopy(const AbstractRegistry<T_Ptr, std::unordered_map<T_Key, T_Ptr*>>& sr) ELPP_FINAL { 1424 for (const_iterator it = sr.cbegin(); it != sr.cend(); ++it) { 1425 registerNew(it->first, new T_Ptr(*it->second)); 1426 } 1427 } 1428 }; 1429 1430 /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version) 1431 /// 1432 /// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry<T_Ptr, Container>. Any implementation of this class 1433 /// should be made thread-safe explicitly 1434 template <typename T_Ptr, typename Pred> 1435 class RegistryWithPred : public AbstractRegistry<T_Ptr, std::vector<T_Ptr*>> { 1436 public: 1437 typedef typename RegistryWithPred<T_Ptr, Pred>::iterator iterator; 1438 typedef typename RegistryWithPred<T_Ptr, Pred>::const_iterator const_iterator; 1439 1440 RegistryWithPred(void) { 1441 } 1442 1443 virtual ~RegistryWithPred(void) { 1444 unregisterAll(); 1445 } 1446 1447 /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. 1448 RegistryWithPred(const RegistryWithPred& sr) : AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>() { 1449 if (this == &sr) { 1450 return; 1451 } 1452 this->reinitDeepCopy(sr); 1453 } 1454 1455 /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element 1456 /// @see unregisterAll() 1457 /// @see deepCopy(const AbstractRegistry&) 1458 RegistryWithPred& operator=(const RegistryWithPred& sr) { 1459 if (this == &sr) { 1460 return *this; 1461 } 1462 this->reinitDeepCopy(sr); 1463 return *this; 1464 } 1465 1466 friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const RegistryWithPred& sr) { 1467 for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { 1468 os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n"); 1469 } 1470 return os; 1471 } 1472 1473 protected: 1474 virtual void unregisterAll(void) ELPP_FINAL { 1475 if (!this->empty()) { 1476 for (auto&& curr : this->list()) { 1477 base::utils::safeDelete(curr); 1478 } 1479 this->list().clear(); 1480 } 1481 } 1482 1483 virtual void unregister(T_Ptr*& ptr) ELPP_FINAL { 1484 if (ptr) { 1485 iterator iter = this->begin(); 1486 for (; iter != this->end(); ++iter) { 1487 if (ptr == *iter) { 1488 break; 1489 } 1490 } 1491 if (iter != this->end() && *iter != nullptr) { 1492 this->list().erase(iter); 1493 base::utils::safeDelete(*iter); 1494 } 1495 } 1496 } 1497 1498 virtual inline void registerNew(T_Ptr* ptr) ELPP_FINAL { 1499 this->list().push_back(ptr); 1500 } 1501 1502 /// @brief Gets pointer from repository with speicifed arguments. Arguments are passed to predicate 1503 /// in order to validate pointer. 1504 template <typename T, typename T2> 1505 T_Ptr* get(const T& arg1, const T2 arg2) { 1506 iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2)); 1507 if (iter != this->list().end() && *iter != nullptr) { 1508 return *iter; 1509 } 1510 return nullptr; 1511 } 1512 1513 private: 1514 virtual void deepCopy(const AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>& sr) { 1515 for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { 1516 registerNew(new T_Ptr(**it)); 1517 } 1518 } 1519 }; 1520 class Utils { 1521 public: 1522 template <typename T, typename TPtr> 1523 static bool installCallback(const std::string& id, std::unordered_map<std::string, TPtr>* mapT) { 1524 if (mapT->find(id) == mapT->end()) { 1525 mapT->insert(std::make_pair(id, TPtr(new T()))); 1526 return true; 1527 } 1528 return false; 1529 } 1530 1531 template <typename T, typename TPtr> 1532 static void uninstallCallback(const std::string& id, std::unordered_map<std::string, TPtr>* mapT) { 1533 if (mapT->find(id) != mapT->end()) { 1534 mapT->erase(id); 1535 } 1536 } 1537 1538 template <typename T, typename TPtr> 1539 static T* callback(const std::string& id, std::unordered_map<std::string, TPtr>* mapT) { 1540 typename std::unordered_map<std::string, TPtr>::iterator iter = mapT->find(id); 1541 if (iter != mapT->end()) { 1542 return static_cast<T*>(iter->second.get()); 1543 } 1544 return nullptr; 1545 } 1546 }; 1547 } // namespace utils 1548 } // namespace base 1549 /// @brief Base of Easylogging++ friendly class 1550 /// 1551 /// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const` 1552 class Loggable { 1553 public: 1554 virtual ~Loggable(void) {} 1555 virtual void log(el::base::type::ostream_t&) const = 0; 1556 private: 1557 friend inline el::base::type::ostream_t& operator<<(el::base::type::ostream_t& os, const Loggable& loggable) { 1558 loggable.log(os); 1559 return os; 1560 } 1561 }; 1562 namespace base { 1563 /// @brief Represents log format containing flags and date format. This is used internally to start initial log 1564 class LogFormat : public Loggable { 1565 public: 1566 LogFormat(void); 1567 LogFormat(Level level, const base::type::string_t& format); 1568 LogFormat(const LogFormat& logFormat); 1569 LogFormat(LogFormat&& logFormat); 1570 LogFormat& operator=(const LogFormat& logFormat); 1571 virtual ~LogFormat(void) {} 1572 bool operator==(const LogFormat& other); 1573 1574 /// @brief Updates format to be used while logging. 1575 /// @param userFormat User provided format 1576 void parseFromFormat(const base::type::string_t& userFormat); 1577 1578 inline Level level(void) const { 1579 return m_level; 1580 } 1581 1582 inline const base::type::string_t& userFormat(void) const { 1583 return m_userFormat; 1584 } 1585 1586 inline const base::type::string_t& format(void) const { 1587 return m_format; 1588 } 1589 1590 inline const std::string& dateTimeFormat(void) const { 1591 return m_dateTimeFormat; 1592 } 1593 1594 inline base::type::EnumType flags(void) const { 1595 return m_flags; 1596 } 1597 1598 inline bool hasFlag(base::FormatFlags flag) const { 1599 return base::utils::hasFlag(flag, m_flags); 1600 } 1601 1602 virtual void log(el::base::type::ostream_t& os) const { 1603 os << m_format; 1604 } 1605 1606 protected: 1607 /// @brief Updates date time format if available in currFormat. 1608 /// @param index Index where %datetime, %date or %time was found 1609 /// @param [in,out] currFormat current format that is being used to format 1610 virtual void updateDateFormat(std::size_t index, base::type::string_t& currFormat) ELPP_FINAL; 1611 1612 /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level 1613 virtual void updateFormatSpec(void) ELPP_FINAL; 1614 1615 inline void addFlag(base::FormatFlags flag) { 1616 base::utils::addFlag(flag, &m_flags); 1617 } 1618 1619 private: 1620 Level m_level; 1621 base::type::string_t m_userFormat; 1622 base::type::string_t m_format; 1623 std::string m_dateTimeFormat; 1624 base::type::EnumType m_flags; 1625 std::string m_currentUser; 1626 std::string m_currentHost; 1627 friend class el::Logger; // To resolve loggerId format specifier easily 1628 }; 1629 } // namespace base 1630 /// @brief Resolving function for format specifier 1631 typedef std::function<std::string(const LogMessage*)> FormatSpecifierValueResolver; 1632 /// @brief User-provided custom format specifier 1633 /// @see el::Helpers::installCustomFormatSpecifier 1634 /// @see FormatSpecifierValueResolver 1635 class CustomFormatSpecifier { 1636 public: 1637 CustomFormatSpecifier(const char* formatSpecifier, const FormatSpecifierValueResolver& resolver) : 1638 m_formatSpecifier(formatSpecifier), m_resolver(resolver) {} 1639 inline const char* formatSpecifier(void) const { 1640 return m_formatSpecifier; 1641 } 1642 inline const FormatSpecifierValueResolver& resolver(void) const { 1643 return m_resolver; 1644 } 1645 inline bool operator==(const char* formatSpecifier) { 1646 return strcmp(m_formatSpecifier, formatSpecifier) == 0; 1647 } 1648 1649 private: 1650 const char* m_formatSpecifier; 1651 FormatSpecifierValueResolver m_resolver; 1652 }; 1653 /// @brief Represents single configuration that has representing level, configuration type and a string based value. 1654 /// 1655 /// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes 1656 /// and will be parsed later. 1657 /// 1658 /// Consider some examples below: 1659 /// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true"); 1660 /// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048"); 1661 /// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log"); 1662 class Configuration : public Loggable { 1663 public: 1664 Configuration(const Configuration& c); 1665 Configuration& operator=(const Configuration& c); 1666 1667 virtual ~Configuration(void) { 1668 } 1669 1670 /// @brief Full constructor used to sets value of configuration 1671 Configuration(Level level, ConfigurationType configurationType, const std::string& value); 1672 1673 /// @brief Gets level of current configuration 1674 inline Level level(void) const { 1675 return m_level; 1676 } 1677 1678 /// @brief Gets configuration type of current configuration 1679 inline ConfigurationType configurationType(void) const { 1680 return m_configurationType; 1681 } 1682 1683 /// @brief Gets string based configuration value 1684 inline const std::string& value(void) const { 1685 return m_value; 1686 } 1687 1688 /// @brief Set string based configuration value 1689 /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values 1690 /// use them in quotes. They will be parsed when configuring 1691 inline void setValue(const std::string& value) { 1692 m_value = value; 1693 } 1694 1695 virtual void log(el::base::type::ostream_t& os) const; 1696 1697 /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. 1698 class Predicate { 1699 public: 1700 Predicate(Level level, ConfigurationType configurationType); 1701 1702 bool operator()(const Configuration* conf) const; 1703 1704 private: 1705 Level m_level; 1706 ConfigurationType m_configurationType; 1707 }; 1708 1709 private: 1710 Level m_level; 1711 ConfigurationType m_configurationType; 1712 std::string m_value; 1713 }; 1714 1715 /// @brief Thread-safe Configuration repository 1716 /// 1717 /// @detail This repository represents configurations for all the levels and configuration type mapped to a value. 1718 class Configurations : public base::utils::RegistryWithPred<Configuration, Configuration::Predicate> { 1719 public: 1720 /// @brief Default constructor with empty repository 1721 Configurations(void); 1722 1723 /// @brief Constructor used to set configurations using configuration file. 1724 /// @param configurationFile Full path to configuration file 1725 /// @param useDefaultsForRemaining Lets you set the remaining configurations to default. 1726 /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. 1727 /// @see parseFromFile(const std::string&, Configurations* base) 1728 /// @see setRemainingToDefault() 1729 Configurations(const std::string& configurationFile, bool useDefaultsForRemaining = true, 1730 Configurations* base = nullptr); 1731 1732 virtual ~Configurations(void) { 1733 } 1734 1735 /// @brief Parses configuration from file. 1736 /// @param configurationFile Full path to configuration file 1737 /// @param base Configurations to base new configuration repository off. This value is used when you want to use 1738 /// existing Configurations to base all the values and then set rest of configuration via configuration file. 1739 /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you 1740 /// do not proceed without successful parse. 1741 bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr); 1742 1743 /// @brief Parse configurations from configuration string. 1744 /// 1745 /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary 1746 /// new line characters are provided. 1747 /// @param base Configurations to base new configuration repository off. This value is used when you want to use 1748 /// existing Configurations to base all the values and then set rest of configuration via configuration text. 1749 /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you 1750 /// do not proceed without successful parse. 1751 bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr); 1752 1753 /// @brief Sets configuration based-off an existing configurations. 1754 /// @param base Pointer to existing configurations. 1755 void setFromBase(Configurations* base); 1756 1757 /// @brief Determines whether or not specified configuration type exists in the repository. 1758 /// 1759 /// @detail Returns as soon as first level is found. 1760 /// @param configurationType Type of configuration to check existence for. 1761 bool hasConfiguration(ConfigurationType configurationType); 1762 1763 /// @brief Determines whether or not specified configuration type exists for specified level 1764 /// @param level Level to check 1765 /// @param configurationType Type of configuration to check existence for. 1766 bool hasConfiguration(Level level, ConfigurationType configurationType); 1767 1768 /// @brief Sets value of configuration for specified level. 1769 /// 1770 /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types 1771 /// ConfigurationType::SubsecondPrecision and ConfigurationType::PerformanceTracking will be ignored if not set for 1772 /// Level::Global because these configurations are not dependant on level. 1773 /// @param level Level to set configuration for (el::Level). 1774 /// @param configurationType Type of configuration (el::ConfigurationType) 1775 /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string 1776 /// from users' point of view. This is then parsed later to be used internally. 1777 /// @see Configuration::setValue(const std::string& value) 1778 /// @see el::Level 1779 /// @see el::ConfigurationType 1780 void set(Level level, ConfigurationType configurationType, const std::string& value); 1781 1782 /// @brief Sets single configuration based on other single configuration. 1783 /// @see set(Level level, ConfigurationType configurationType, const std::string& value) 1784 void set(Configuration* conf); 1785 1786 inline Configuration* get(Level level, ConfigurationType configurationType) { 1787 base::threading::ScopedLock scopedLock(lock()); 1788 return RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType); 1789 } 1790 1791 /// @brief Sets configuration for all levels. 1792 /// @param configurationType Type of configuration 1793 /// @param value String based value 1794 /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) 1795 inline void setGlobally(ConfigurationType configurationType, const std::string& value) { 1796 setGlobally(configurationType, value, false); 1797 } 1798 1799 /// @brief Clears repository so that all the configurations are unset 1800 inline void clear(void) { 1801 base::threading::ScopedLock scopedLock(lock()); 1802 unregisterAll(); 1803 } 1804 1805 /// @brief Gets configuration file used in parsing this configurations. 1806 /// 1807 /// @detail If this repository was set manually or by text this returns empty string. 1808 inline const std::string& configurationFile(void) const { 1809 return m_configurationFile; 1810 } 1811 1812 /// @brief Sets configurations to "factory based" configurations. 1813 void setToDefault(void); 1814 1815 /// @brief Lets you set the remaining configurations to default. 1816 /// 1817 /// @detail By remaining, it means that the level/type a configuration does not exist for. 1818 /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets 1819 /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, 1820 /// true. If you dont do this explicitly (either by calling this function or by using second param in Constructor 1821 /// and try to access a value, an error is thrown 1822 void setRemainingToDefault(void); 1823 1824 /// @brief Parser used internally to parse configurations from file or text. 1825 /// 1826 /// @detail This class makes use of base::utils::Str. 1827 /// You should not need this unless you are working on some tool for Easylogging++ 1828 class Parser : base::StaticClass { 1829 public: 1830 /// @brief Parses configuration from file. 1831 /// @param configurationFile Full path to configuration file 1832 /// @param sender Sender configurations pointer. Usually 'this' is used from calling class 1833 /// @param base Configurations to base new configuration repository off. This value is used when you want to use 1834 /// existing Configurations to base all the values and then set rest of configuration via configuration file. 1835 /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you 1836 /// do not proceed without successful parse. 1837 static bool parseFromFile(const std::string& configurationFile, Configurations* sender, 1838 Configurations* base = nullptr); 1839 1840 /// @brief Parse configurations from configuration string. 1841 /// 1842 /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary 1843 /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you 1844 /// do not proceed without successful parse (This is recommended) 1845 /// @param configurationsString the configuration in plain text format 1846 /// @param sender Sender configurations pointer. Usually 'this' is used from calling class 1847 /// @param base Configurations to base new configuration repository off. This value is used when you want to use 1848 /// existing Configurations to base all the values and then set rest of configuration via configuration text. 1849 /// @return True if successfully parsed, false otherwise. 1850 static bool parseFromText(const std::string& configurationsString, Configurations* sender, 1851 Configurations* base = nullptr); 1852 1853 private: 1854 friend class el::Loggers; 1855 static void ignoreComments(std::string* line); 1856 static bool isLevel(const std::string& line); 1857 static bool isComment(const std::string& line); 1858 static inline bool isConfig(const std::string& line); 1859 static bool parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, Level* currLevel, 1860 Configurations* conf); 1861 }; 1862 1863 private: 1864 std::string m_configurationFile; 1865 bool m_isFromFile; 1866 friend class el::Loggers; 1867 1868 /// @brief Unsafely sets configuration if does not already exist 1869 void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value); 1870 1871 /// @brief Thread unsafe set 1872 void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value); 1873 1874 /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true 1875 /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) 1876 void setGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel); 1877 1878 /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true 1879 /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) 1880 void unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel); 1881 }; 1882 1883 namespace base { 1884 typedef std::shared_ptr<base::type::fstream_t> FileStreamPtr; 1885 typedef std::unordered_map<std::string, FileStreamPtr> LogStreamsReferenceMap; 1886 /// @brief Configurations with data types. 1887 /// 1888 /// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. 1889 /// This is to perform faster while writing logs using correct configurations. 1890 /// 1891 /// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class) 1892 class TypedConfigurations : public base::threading::ThreadSafe { 1893 public: 1894 /// @brief Constructor to initialize (construct) the object off el::Configurations 1895 /// @param configurations Configurations pointer/reference to base this typed configurations off. 1896 /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference() 1897 TypedConfigurations(Configurations* configurations, base::LogStreamsReferenceMap* logStreamsReference); 1898 1899 TypedConfigurations(const TypedConfigurations& other); 1900 1901 virtual ~TypedConfigurations(void) { 1902 } 1903 1904 const Configurations* configurations(void) const { 1905 return m_configurations; 1906 } 1907 1908 bool enabled(Level level); 1909 bool toFile(Level level); 1910 const std::string& filename(Level level); 1911 bool toStandardOutput(Level level); 1912 const base::LogFormat& logFormat(Level level); 1913 const base::SubsecondPrecision& subsecondPrecision(Level level = Level::Global); 1914 const base::MillisecondsWidth& millisecondsWidth(Level level = Level::Global); 1915 bool performanceTracking(Level level = Level::Global); 1916 base::type::fstream_t* fileStream(Level level); 1917 std::size_t maxLogFileSize(Level level); 1918 std::size_t logFlushThreshold(Level level); 1919 1920 private: 1921 Configurations* m_configurations; 1922 std::unordered_map<Level, bool> m_enabledMap; 1923 std::unordered_map<Level, bool> m_toFileMap; 1924 std::unordered_map<Level, std::string> m_filenameMap; 1925 std::unordered_map<Level, bool> m_toStandardOutputMap; 1926 std::unordered_map<Level, base::LogFormat> m_logFormatMap; 1927 std::unordered_map<Level, base::SubsecondPrecision> m_subsecondPrecisionMap; 1928 std::unordered_map<Level, bool> m_performanceTrackingMap; 1929 std::unordered_map<Level, base::FileStreamPtr> m_fileStreamMap; 1930 std::unordered_map<Level, std::size_t> m_maxLogFileSizeMap; 1931 std::unordered_map<Level, std::size_t> m_logFlushThresholdMap; 1932 base::LogStreamsReferenceMap* m_logStreamsReference; 1933 1934 friend class el::Helpers; 1935 friend class el::base::MessageBuilder; 1936 friend class el::base::Writer; 1937 friend class el::base::DefaultLogDispatchCallback; 1938 friend class el::base::LogDispatcher; 1939 1940 template <typename Conf_T> 1941 inline Conf_T getConfigByVal(Level level, const std::unordered_map<Level, Conf_T>* confMap, const char* confName) { 1942 base::threading::ScopedLock scopedLock(lock()); 1943 return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope 1944 } 1945 1946 template <typename Conf_T> 1947 inline Conf_T& getConfigByRef(Level level, std::unordered_map<Level, Conf_T>* confMap, const char* confName) { 1948 base::threading::ScopedLock scopedLock(lock()); 1949 return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope 1950 } 1951 1952 template <typename Conf_T> 1953 Conf_T unsafeGetConfigByVal(Level level, const std::unordered_map<Level, Conf_T>* confMap, const char* confName) { 1954 ELPP_UNUSED(confName); 1955 typename std::unordered_map<Level, Conf_T>::const_iterator it = confMap->find(level); 1956 if (it == confMap->end()) { 1957 try { 1958 return confMap->at(Level::Global); 1959 } catch (...) { 1960 ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" 1961 << LevelHelper::convertToString(level) << "]" 1962 << std::endl << "Please ensure you have properly configured logger.", false); 1963 return Conf_T(); 1964 } 1965 } 1966 return it->second; 1967 } 1968 1969 template <typename Conf_T> 1970 Conf_T& unsafeGetConfigByRef(Level level, std::unordered_map<Level, Conf_T>* confMap, const char* confName) { 1971 ELPP_UNUSED(confName); 1972 typename std::unordered_map<Level, Conf_T>::iterator it = confMap->find(level); 1973 if (it == confMap->end()) { 1974 try { 1975 return confMap->at(Level::Global); 1976 } catch (...) { 1977 ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" 1978 << LevelHelper::convertToString(level) << "]" 1979 << std::endl << "Please ensure you have properly configured logger.", false); 1980 } 1981 } 1982 return it->second; 1983 } 1984 1985 template <typename Conf_T> 1986 void setValue(Level level, const Conf_T& value, std::unordered_map<Level, Conf_T>* confMap, 1987 bool includeGlobalLevel = true) { 1988 // If map is empty and we are allowed to add into generic level (Level::Global), do it! 1989 if (confMap->empty() && includeGlobalLevel) { 1990 confMap->insert(std::make_pair(Level::Global, value)); 1991 return; 1992 } 1993 // If same value exist in generic level already, dont add it to explicit level 1994 typename std::unordered_map<Level, Conf_T>::iterator it = confMap->find(Level::Global); 1995 if (it != confMap->end() && it->second == value) { 1996 return; 1997 } 1998 // Now make sure we dont double up values if we really need to add it to explicit level 1999 it = confMap->find(level); 2000 if (it == confMap->end()) { 2001 // Value not found for level, add new 2002 confMap->insert(std::make_pair(level, value)); 2003 } else { 2004 // Value found, just update value 2005 confMap->at(level) = value; 2006 } 2007 } 2008 2009 void build(Configurations* configurations); 2010 unsigned long getULong(std::string confVal); 2011 std::string resolveFilename(const std::string& filename); 2012 void insertFile(Level level, const std::string& fullFilename); 2013 bool unsafeValidateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback); 2014 2015 inline bool validateFileRolling(Level level, const PreRollOutCallback& preRollOutCallback) { 2016 base::threading::ScopedLock scopedLock(lock()); 2017 return unsafeValidateFileRolling(level, preRollOutCallback); 2018 } 2019 }; 2020 /// @brief Class that keeps record of current line hit for occasional logging 2021 class HitCounter { 2022 public: 2023 HitCounter(void) : 2024 m_filename(""), 2025 m_lineNumber(0), 2026 m_hitCounts(0) { 2027 } 2028 2029 HitCounter(const char* filename, base::type::LineNumber lineNumber) : 2030 m_filename(filename), 2031 m_lineNumber(lineNumber), 2032 m_hitCounts(0) { 2033 } 2034 2035 HitCounter(const HitCounter& hitCounter) : 2036 m_filename(hitCounter.m_filename), 2037 m_lineNumber(hitCounter.m_lineNumber), 2038 m_hitCounts(hitCounter.m_hitCounts) { 2039 } 2040 2041 HitCounter& operator=(const HitCounter& hitCounter) { 2042 if (&hitCounter != this) { 2043 m_filename = hitCounter.m_filename; 2044 m_lineNumber = hitCounter.m_lineNumber; 2045 m_hitCounts = hitCounter.m_hitCounts; 2046 } 2047 return *this; 2048 } 2049 2050 virtual ~HitCounter(void) { 2051 } 2052 2053 /// @brief Resets location of current hit counter 2054 inline void resetLocation(const char* filename, base::type::LineNumber lineNumber) { 2055 m_filename = filename; 2056 m_lineNumber = lineNumber; 2057 } 2058 2059 /// @brief Validates hit counts and resets it if necessary 2060 inline void validateHitCounts(std::size_t n) { 2061 if (m_hitCounts >= base::consts::kMaxLogPerCounter) { 2062 m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); 2063 } 2064 ++m_hitCounts; 2065 } 2066 2067 inline const char* filename(void) const { 2068 return m_filename; 2069 } 2070 2071 inline base::type::LineNumber lineNumber(void) const { 2072 return m_lineNumber; 2073 } 2074 2075 inline std::size_t hitCounts(void) const { 2076 return m_hitCounts; 2077 } 2078 2079 inline void increment(void) { 2080 ++m_hitCounts; 2081 } 2082 2083 class Predicate { 2084 public: 2085 Predicate(const char* filename, base::type::LineNumber lineNumber) 2086 : m_filename(filename), 2087 m_lineNumber(lineNumber) { 2088 } 2089 inline bool operator()(const HitCounter* counter) { 2090 return ((counter != nullptr) && 2091 (strcmp(counter->m_filename, m_filename) == 0) && 2092 (counter->m_lineNumber == m_lineNumber)); 2093 } 2094 2095 private: 2096 const char* m_filename; 2097 base::type::LineNumber m_lineNumber; 2098 }; 2099 2100 private: 2101 const char* m_filename; 2102 base::type::LineNumber m_lineNumber; 2103 std::size_t m_hitCounts; 2104 }; 2105 /// @brief Repository for hit counters used across the application 2106 class RegisteredHitCounters : public base::utils::RegistryWithPred<base::HitCounter, base::HitCounter::Predicate> { 2107 public: 2108 /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one 2109 /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned 2110 bool validateEveryN(const char* filename, base::type::LineNumber lineNumber, std::size_t n); 2111 2112 /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one 2113 /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned 2114 bool validateAfterN(const char* filename, base::type::LineNumber lineNumber, std::size_t n); 2115 2116 /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one 2117 /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned 2118 bool validateNTimes(const char* filename, base::type::LineNumber lineNumber, std::size_t n); 2119 2120 /// @brief Gets hit counter registered at specified position 2121 inline const base::HitCounter* getCounter(const char* filename, base::type::LineNumber lineNumber) { 2122 base::threading::ScopedLock scopedLock(lock()); 2123 return get(filename, lineNumber); 2124 } 2125 }; 2126 /// @brief Action to be taken for dispatching 2127 enum class DispatchAction : base::type::EnumType { 2128 None = 1, NormalLog = 2, SysLog = 4 2129 }; 2130 } // namespace base 2131 template <typename T> 2132 class Callback : protected base::threading::ThreadSafe { 2133 public: 2134 Callback(void) : m_enabled(true) {} 2135 inline bool enabled(void) const { 2136 return m_enabled; 2137 } 2138 inline void setEnabled(bool enabled) { 2139 base::threading::ScopedLock scopedLock(lock()); 2140 m_enabled = enabled; 2141 } 2142 protected: 2143 virtual void handle(const T* handlePtr) = 0; 2144 private: 2145 bool m_enabled; 2146 }; 2147 class LogDispatchData { 2148 public: 2149 LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None) {} 2150 inline const LogMessage* logMessage(void) const { 2151 return m_logMessage; 2152 } 2153 inline base::DispatchAction dispatchAction(void) const { 2154 return m_dispatchAction; 2155 } 2156 inline void setLogMessage(LogMessage* logMessage) { 2157 m_logMessage = logMessage; 2158 } 2159 inline void setDispatchAction(base::DispatchAction dispatchAction) { 2160 m_dispatchAction = dispatchAction; 2161 } 2162 private: 2163 LogMessage* m_logMessage; 2164 base::DispatchAction m_dispatchAction; 2165 friend class base::LogDispatcher; 2166 2167 }; 2168 class LogDispatchCallback : public Callback<LogDispatchData> { 2169 protected: 2170 virtual void handle(const LogDispatchData* data); 2171 base::threading::Mutex& fileHandle(const LogDispatchData* data); 2172 private: 2173 friend class base::LogDispatcher; 2174 std::unordered_map<std::string, std::unique_ptr<base::threading::Mutex>> m_fileLocks; 2175 base::threading::Mutex m_fileLocksMapLock; 2176 }; 2177 class PerformanceTrackingCallback : public Callback<PerformanceTrackingData> { 2178 private: 2179 friend class base::PerformanceTracker; 2180 }; 2181 class LoggerRegistrationCallback : public Callback<Logger> { 2182 private: 2183 friend class base::RegisteredLoggers; 2184 }; 2185 class LogBuilder : base::NoCopy { 2186 public: 2187 LogBuilder() : m_termSupportsColor(base::utils::OS::termSupportsColor()) {} 2188 virtual ~LogBuilder(void) { 2189 ELPP_INTERNAL_INFO(3, "Destroying log builder...") 2190 } 2191 virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0; 2192 void convertToColoredOutput(base::type::string_t* logLine, Level level); 2193 private: 2194 bool m_termSupportsColor; 2195 friend class el::base::DefaultLogDispatchCallback; 2196 }; 2197 typedef std::shared_ptr<LogBuilder> LogBuilderPtr; 2198 /// @brief Represents a logger holding ID and configurations we need to write logs 2199 /// 2200 /// @detail This class does not write logs itself instead its used by writer to read configuations from. 2201 class Logger : public base::threading::ThreadSafe, public Loggable { 2202 public: 2203 Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference); 2204 Logger(const std::string& id, const Configurations& configurations, base::LogStreamsReferenceMap* logStreamsReference); 2205 Logger(const Logger& logger); 2206 Logger& operator=(const Logger& logger); 2207 2208 virtual ~Logger(void) { 2209 base::utils::safeDelete(m_typedConfigurations); 2210 } 2211 2212 virtual inline void log(el::base::type::ostream_t& os) const { 2213 os << m_id.c_str(); 2214 } 2215 2216 /// @brief Configures the logger using specified configurations. 2217 void configure(const Configurations& configurations); 2218 2219 /// @brief Reconfigures logger using existing configurations 2220 void reconfigure(void); 2221 2222 inline const std::string& id(void) const { 2223 return m_id; 2224 } 2225 2226 inline const std::string& parentApplicationName(void) const { 2227 return m_parentApplicationName; 2228 } 2229 2230 inline void setParentApplicationName(const std::string& parentApplicationName) { 2231 m_parentApplicationName = parentApplicationName; 2232 } 2233 2234 inline Configurations* configurations(void) { 2235 return &m_configurations; 2236 } 2237 2238 inline base::TypedConfigurations* typedConfigurations(void) { 2239 return m_typedConfigurations; 2240 } 2241 2242 static bool isValidId(const std::string& id); 2243 2244 /// @brief Flushes logger to sync all log files for all levels 2245 void flush(void); 2246 2247 void flush(Level level, base::type::fstream_t* fs); 2248 2249 inline bool isFlushNeeded(Level level) { 2250 return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level); 2251 } 2252 2253 inline LogBuilder* logBuilder(void) const { 2254 return m_logBuilder.get(); 2255 } 2256 2257 inline void setLogBuilder(const LogBuilderPtr& logBuilder) { 2258 m_logBuilder = logBuilder; 2259 } 2260 2261 inline bool enabled(Level level) const { 2262 return m_typedConfigurations->enabled(level); 2263 } 2264 2265 #if ELPP_VARIADIC_TEMPLATES_SUPPORTED 2266 # define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME)\ 2267 template <typename T, typename... Args>\ 2268 inline void FUNCTION_NAME(const char*, const T&, const Args&...);\ 2269 template <typename T>\ 2270 inline void FUNCTION_NAME(const T&); 2271 2272 template <typename T, typename... Args> 2273 inline void verbose(int, const char*, const T&, const Args&...); 2274 2275 template <typename T> 2276 inline void verbose(int, const T&); 2277 2278 LOGGER_LEVEL_WRITERS_SIGNATURES(info) 2279 LOGGER_LEVEL_WRITERS_SIGNATURES(debug) 2280 LOGGER_LEVEL_WRITERS_SIGNATURES(warn) 2281 LOGGER_LEVEL_WRITERS_SIGNATURES(error) 2282 LOGGER_LEVEL_WRITERS_SIGNATURES(fatal) 2283 LOGGER_LEVEL_WRITERS_SIGNATURES(trace) 2284 # undef LOGGER_LEVEL_WRITERS_SIGNATURES 2285 #endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED 2286 private: 2287 std::string m_id; 2288 base::TypedConfigurations* m_typedConfigurations; 2289 base::type::stringstream_t m_stream; 2290 std::string m_parentApplicationName; 2291 bool m_isConfigured; 2292 Configurations m_configurations; 2293 std::unordered_map<Level, unsigned int> m_unflushedCount; 2294 base::LogStreamsReferenceMap* m_logStreamsReference; 2295 LogBuilderPtr m_logBuilder; 2296 2297 friend class el::LogMessage; 2298 friend class el::Loggers; 2299 friend class el::Helpers; 2300 friend class el::base::RegisteredLoggers; 2301 friend class el::base::DefaultLogDispatchCallback; 2302 friend class el::base::MessageBuilder; 2303 friend class el::base::Writer; 2304 friend class el::base::PErrorWriter; 2305 friend class el::base::Storage; 2306 friend class el::base::PerformanceTracker; 2307 friend class el::base::LogDispatcher; 2308 2309 Logger(void); 2310 2311 #if ELPP_VARIADIC_TEMPLATES_SUPPORTED 2312 template <typename T, typename... Args> 2313 void log_(Level, int, const char*, const T&, const Args&...); 2314 2315 template <typename T> 2316 inline void log_(Level, int, const T&); 2317 2318 template <typename T, typename... Args> 2319 void log(Level, const char*, const T&, const Args&...); 2320 2321 template <typename T> 2322 inline void log(Level, const T&); 2323 #endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED 2324 2325 void initUnflushedCount(void); 2326 2327 inline base::type::stringstream_t& stream(void) { 2328 return m_stream; 2329 } 2330 2331 void resolveLoggerFormatSpec(void) const; 2332 }; 2333 namespace base { 2334 /// @brief Loggers repository 2335 class RegisteredLoggers : public base::utils::Registry<Logger, std::string> { 2336 public: 2337 explicit RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder); 2338 2339 virtual ~RegisteredLoggers(void) { 2340 unsafeFlushAll(); 2341 } 2342 2343 inline void setDefaultConfigurations(const Configurations& configurations) { 2344 base::threading::ScopedLock scopedLock(lock()); 2345 m_defaultConfigurations.setFromBase(const_cast<Configurations*>(&configurations)); 2346 } 2347 2348 inline Configurations* defaultConfigurations(void) { 2349 return &m_defaultConfigurations; 2350 } 2351 2352 Logger* get(const std::string& id, bool forceCreation = true); 2353 2354 template <typename T> 2355 inline bool installLoggerRegistrationCallback(const std::string& id) { 2356 return base::utils::Utils::installCallback<T, base::type::LoggerRegistrationCallbackPtr>(id, 2357 &m_loggerRegistrationCallbacks); 2358 } 2359 2360 template <typename T> 2361 inline void uninstallLoggerRegistrationCallback(const std::string& id) { 2362 base::utils::Utils::uninstallCallback<T, base::type::LoggerRegistrationCallbackPtr>(id, &m_loggerRegistrationCallbacks); 2363 } 2364 2365 template <typename T> 2366 inline T* loggerRegistrationCallback(const std::string& id) { 2367 return base::utils::Utils::callback<T, base::type::LoggerRegistrationCallbackPtr>(id, &m_loggerRegistrationCallbacks); 2368 } 2369 2370 bool remove(const std::string& id); 2371 2372 inline bool has(const std::string& id) { 2373 return get(id, false) != nullptr; 2374 } 2375 2376 inline void unregister(Logger*& logger) { 2377 base::threading::ScopedLock scopedLock(lock()); 2378 base::utils::Registry<Logger, std::string>::unregister(logger->id()); 2379 } 2380 2381 inline base::LogStreamsReferenceMap* logStreamsReference(void) { 2382 return &m_logStreamsReference; 2383 } 2384 2385 inline void flushAll(void) { 2386 base::threading::ScopedLock scopedLock(lock()); 2387 unsafeFlushAll(); 2388 } 2389 2390 inline void setDefaultLogBuilder(LogBuilderPtr& logBuilderPtr) { 2391 base::threading::ScopedLock scopedLock(lock()); 2392 m_defaultLogBuilder = logBuilderPtr; 2393 } 2394 2395 private: 2396 LogBuilderPtr m_defaultLogBuilder; 2397 Configurations m_defaultConfigurations; 2398 base::LogStreamsReferenceMap m_logStreamsReference; 2399 std::unordered_map<std::string, base::type::LoggerRegistrationCallbackPtr> m_loggerRegistrationCallbacks; 2400 friend class el::base::Storage; 2401 2402 void unsafeFlushAll(void); 2403 }; 2404 /// @brief Represents registries for verbose logging 2405 class VRegistry : base::NoCopy, public base::threading::ThreadSafe { 2406 public: 2407 explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags); 2408 2409 /// @brief Sets verbose level. Accepted range is 0-9 2410 void setLevel(base::type::VerboseLevel level); 2411 2412 inline base::type::VerboseLevel level(void) const { 2413 return m_level; 2414 } 2415 2416 inline void clearModules(void) { 2417 base::threading::ScopedLock scopedLock(lock()); 2418 m_modules.clear(); 2419 } 2420 2421 void setModules(const char* modules); 2422 2423 bool allowed(base::type::VerboseLevel vlevel, const char* file); 2424 2425 inline const std::unordered_map<std::string, base::type::VerboseLevel>& modules(void) const { 2426 return m_modules; 2427 } 2428 2429 void setFromArgs(const base::utils::CommandLineArgs* commandLineArgs); 2430 2431 /// @brief Whether or not vModules enabled 2432 inline bool vModulesEnabled(void) { 2433 return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags); 2434 } 2435 2436 private: 2437 base::type::VerboseLevel m_level; 2438 base::type::EnumType* m_pFlags; 2439 std::unordered_map<std::string, base::type::VerboseLevel> m_modules; 2440 }; 2441 } // namespace base 2442 class LogMessage { 2443 public: 2444 LogMessage(Level level, const std::string& file, base::type::LineNumber line, const std::string& func, 2445 base::type::VerboseLevel verboseLevel, Logger* logger) : 2446 m_level(level), m_file(file), m_line(line), m_func(func), 2447 m_verboseLevel(verboseLevel), m_logger(logger), m_message(logger->stream().str()) { 2448 } 2449 inline Level level(void) const { 2450 return m_level; 2451 } 2452 inline const std::string& file(void) const { 2453 return m_file; 2454 } 2455 inline base::type::LineNumber line(void) const { 2456 return m_line; 2457 } 2458 inline const std::string& func(void) const { 2459 return m_func; 2460 } 2461 inline base::type::VerboseLevel verboseLevel(void) const { 2462 return m_verboseLevel; 2463 } 2464 inline Logger* logger(void) const { 2465 return m_logger; 2466 } 2467 inline const base::type::string_t& message(void) const { 2468 return m_message; 2469 } 2470 private: 2471 Level m_level; 2472 std::string m_file; 2473 base::type::LineNumber m_line; 2474 std::string m_func; 2475 base::type::VerboseLevel m_verboseLevel; 2476 Logger* m_logger; 2477 base::type::string_t m_message; 2478 }; 2479 namespace base { 2480 #if ELPP_ASYNC_LOGGING 2481 class AsyncLogItem { 2482 public: 2483 explicit AsyncLogItem(const LogMessage& logMessage, const LogDispatchData& data, const base::type::string_t& logLine) 2484 : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine) {} 2485 virtual ~AsyncLogItem() {} 2486 inline LogMessage* logMessage(void) { 2487 return &m_logMessage; 2488 } 2489 inline LogDispatchData* data(void) { 2490 return &m_dispatchData; 2491 } 2492 inline base::type::string_t logLine(void) { 2493 return m_logLine; 2494 } 2495 private: 2496 LogMessage m_logMessage; 2497 LogDispatchData m_dispatchData; 2498 base::type::string_t m_logLine; 2499 }; 2500 class AsyncLogQueue : public base::threading::ThreadSafe { 2501 public: 2502 virtual ~AsyncLogQueue() { 2503 ELPP_INTERNAL_INFO(6, "~AsyncLogQueue"); 2504 } 2505 2506 inline AsyncLogItem next(void) { 2507 base::threading::ScopedLock scopedLock(lock()); 2508 AsyncLogItem result = m_queue.front(); 2509 m_queue.pop(); 2510 return result; 2511 } 2512 2513 inline void push(const AsyncLogItem& item) { 2514 base::threading::ScopedLock scopedLock(lock()); 2515 m_queue.push(item); 2516 } 2517 inline void pop(void) { 2518 base::threading::ScopedLock scopedLock(lock()); 2519 m_queue.pop(); 2520 } 2521 inline AsyncLogItem front(void) { 2522 base::threading::ScopedLock scopedLock(lock()); 2523 return m_queue.front(); 2524 } 2525 inline bool empty(void) { 2526 base::threading::ScopedLock scopedLock(lock()); 2527 return m_queue.empty(); 2528 } 2529 private: 2530 std::queue<AsyncLogItem> m_queue; 2531 }; 2532 class IWorker { 2533 public: 2534 virtual ~IWorker() {} 2535 virtual void start() = 0; 2536 }; 2537 #endif // ELPP_ASYNC_LOGGING 2538 /// @brief Easylogging++ management storage 2539 class Storage : base::NoCopy, public base::threading::ThreadSafe { 2540 public: 2541 #if ELPP_ASYNC_LOGGING 2542 Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker); 2543 #else 2544 explicit Storage(const LogBuilderPtr& defaultLogBuilder); 2545 #endif // ELPP_ASYNC_LOGGING 2546 2547 virtual ~Storage(void); 2548 2549 inline bool validateEveryNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t occasion) { 2550 return hitCounters()->validateEveryN(filename, lineNumber, occasion); 2551 } 2552 2553 inline bool validateAfterNCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { 2554 return hitCounters()->validateAfterN(filename, lineNumber, n); 2555 } 2556 2557 inline bool validateNTimesCounter(const char* filename, base::type::LineNumber lineNumber, std::size_t n) { 2558 return hitCounters()->validateNTimes(filename, lineNumber, n); 2559 } 2560 2561 inline base::RegisteredHitCounters* hitCounters(void) const { 2562 return m_registeredHitCounters; 2563 } 2564 2565 inline base::RegisteredLoggers* registeredLoggers(void) const { 2566 return m_registeredLoggers; 2567 } 2568 2569 inline base::VRegistry* vRegistry(void) const { 2570 return m_vRegistry; 2571 } 2572 2573 #if ELPP_ASYNC_LOGGING 2574 inline base::AsyncLogQueue* asyncLogQueue(void) const { 2575 return m_asyncLogQueue; 2576 } 2577 #endif // ELPP_ASYNC_LOGGING 2578 2579 inline const base::utils::CommandLineArgs* commandLineArgs(void) const { 2580 return &m_commandLineArgs; 2581 } 2582 2583 inline void addFlag(LoggingFlag flag) { 2584 base::utils::addFlag(flag, &m_flags); 2585 } 2586 2587 inline void removeFlag(LoggingFlag flag) { 2588 base::utils::removeFlag(flag, &m_flags); 2589 } 2590 2591 inline bool hasFlag(LoggingFlag flag) const { 2592 return base::utils::hasFlag(flag, m_flags); 2593 } 2594 2595 inline base::type::EnumType flags(void) const { 2596 return m_flags; 2597 } 2598 2599 inline void setFlags(base::type::EnumType flags) { 2600 m_flags = flags; 2601 } 2602 2603 inline void setPreRollOutCallback(const PreRollOutCallback& callback) { 2604 m_preRollOutCallback = callback; 2605 } 2606 2607 inline void unsetPreRollOutCallback(void) { 2608 m_preRollOutCallback = base::defaultPreRollOutCallback; 2609 } 2610 2611 inline PreRollOutCallback& preRollOutCallback(void) { 2612 return m_preRollOutCallback; 2613 } 2614 2615 bool hasCustomFormatSpecifier(const char* formatSpecifier); 2616 void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier); 2617 bool uninstallCustomFormatSpecifier(const char* formatSpecifier); 2618 2619 const std::vector<CustomFormatSpecifier>* customFormatSpecifiers(void) const { 2620 return &m_customFormatSpecifiers; 2621 } 2622 2623 base::threading::Mutex& customFormatSpecifiersLock() { 2624 return m_customFormatSpecifiersLock; 2625 } 2626 2627 inline void setLoggingLevel(Level level) { 2628 m_loggingLevel = level; 2629 } 2630 2631 template <typename T> 2632 inline bool installLogDispatchCallback(const std::string& id) { 2633 return base::utils::Utils::installCallback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks); 2634 } 2635 2636 template <typename T> 2637 inline void uninstallLogDispatchCallback(const std::string& id) { 2638 base::utils::Utils::uninstallCallback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks); 2639 } 2640 template <typename T> 2641 inline T* logDispatchCallback(const std::string& id) { 2642 return base::utils::Utils::callback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks); 2643 } 2644 2645 #if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) 2646 template <typename T> 2647 inline bool installPerformanceTrackingCallback(const std::string& id) { 2648 return base::utils::Utils::installCallback<T, base::type::PerformanceTrackingCallbackPtr>(id, 2649 &m_performanceTrackingCallbacks); 2650 } 2651 2652 template <typename T> 2653 inline void uninstallPerformanceTrackingCallback(const std::string& id) { 2654 base::utils::Utils::uninstallCallback<T, base::type::PerformanceTrackingCallbackPtr>(id, 2655 &m_performanceTrackingCallbacks); 2656 } 2657 2658 template <typename T> 2659 inline T* performanceTrackingCallback(const std::string& id) { 2660 return base::utils::Utils::callback<T, base::type::PerformanceTrackingCallbackPtr>(id, &m_performanceTrackingCallbacks); 2661 } 2662 #endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) 2663 2664 /// @brief Sets thread name for current thread. Requires std::thread 2665 inline void setThreadName(const std::string& name) { 2666 if (name.empty()) return; 2667 base::threading::ScopedLock scopedLock(m_threadNamesLock); 2668 m_threadNames[base::threading::getCurrentThreadId()] = name; 2669 } 2670 2671 inline std::string getThreadName(const std::string& threadId) { 2672 base::threading::ScopedLock scopedLock(m_threadNamesLock); 2673 std::unordered_map<std::string, std::string>::const_iterator it = m_threadNames.find(threadId); 2674 if (it == m_threadNames.end()) { 2675 return threadId; 2676 } 2677 return it->second; 2678 } 2679 private: 2680 base::RegisteredHitCounters* m_registeredHitCounters; 2681 base::RegisteredLoggers* m_registeredLoggers; 2682 base::type::EnumType m_flags; 2683 base::VRegistry* m_vRegistry; 2684 #if ELPP_ASYNC_LOGGING 2685 base::AsyncLogQueue* m_asyncLogQueue; 2686 base::IWorker* m_asyncDispatchWorker; 2687 #endif // ELPP_ASYNC_LOGGING 2688 base::utils::CommandLineArgs m_commandLineArgs; 2689 PreRollOutCallback m_preRollOutCallback; 2690 std::unordered_map<std::string, base::type::LogDispatchCallbackPtr> m_logDispatchCallbacks; 2691 std::unordered_map<std::string, base::type::PerformanceTrackingCallbackPtr> m_performanceTrackingCallbacks; 2692 std::unordered_map<std::string, std::string> m_threadNames; 2693 std::vector<CustomFormatSpecifier> m_customFormatSpecifiers; 2694 base::threading::Mutex m_customFormatSpecifiersLock; 2695 base::threading::Mutex m_threadNamesLock; 2696 Level m_loggingLevel; 2697 2698 friend class el::Helpers; 2699 friend class el::base::DefaultLogDispatchCallback; 2700 friend class el::LogBuilder; 2701 friend class el::base::MessageBuilder; 2702 friend class el::base::Writer; 2703 friend class el::base::PerformanceTracker; 2704 friend class el::base::LogDispatcher; 2705 2706 void setApplicationArguments(int argc, char** argv); 2707 2708 inline void setApplicationArguments(int argc, const char** argv) { 2709 setApplicationArguments(argc, const_cast<char**>(argv)); 2710 } 2711 }; 2712 extern ELPP_EXPORT base::type::StoragePointer elStorage; 2713 #define ELPP el::base::elStorage 2714 class DefaultLogDispatchCallback : public LogDispatchCallback { 2715 protected: 2716 void handle(const LogDispatchData* data); 2717 private: 2718 const LogDispatchData* m_data; 2719 void dispatch(base::type::string_t&& logLine); 2720 }; 2721 #if ELPP_ASYNC_LOGGING 2722 class AsyncLogDispatchCallback : public LogDispatchCallback { 2723 protected: 2724 void handle(const LogDispatchData* data); 2725 }; 2726 class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe { 2727 public: 2728 AsyncDispatchWorker(); 2729 virtual ~AsyncDispatchWorker(); 2730 2731 bool clean(void); 2732 void emptyQueue(void); 2733 virtual void start(void); 2734 void handle(AsyncLogItem* logItem); 2735 void run(void); 2736 2737 void setContinueRunning(bool value) { 2738 base::threading::ScopedLock scopedLock(m_continueRunningLock); 2739 m_continueRunning = value; 2740 } 2741 2742 bool continueRunning(void) const { 2743 return m_continueRunning; 2744 } 2745 private: 2746 std::condition_variable cv; 2747 bool m_continueRunning; 2748 base::threading::Mutex m_continueRunningLock; 2749 }; 2750 #endif // ELPP_ASYNC_LOGGING 2751 } // namespace base 2752 namespace base { 2753 class DefaultLogBuilder : public LogBuilder { 2754 public: 2755 base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const; 2756 }; 2757 /// @brief Dispatches log messages 2758 class LogDispatcher : base::NoCopy { 2759 public: 2760 LogDispatcher(bool proceed, LogMessage* logMessage, base::DispatchAction dispatchAction) : 2761 m_proceed(proceed), 2762 m_logMessage(logMessage), 2763 m_dispatchAction(std::move(dispatchAction)) { 2764 } 2765 2766 void dispatch(void); 2767 2768 private: 2769 bool m_proceed; 2770 LogMessage* m_logMessage; 2771 base::DispatchAction m_dispatchAction; 2772 }; 2773 #if defined(ELPP_STL_LOGGING) 2774 /// @brief Workarounds to write some STL logs 2775 /// 2776 /// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers 2777 /// of same type and provide iterator interface and pass it on to writeIterator(). 2778 /// Remember, this is passed by value in constructor so that we dont change original containers. 2779 /// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer)) 2780 namespace workarounds { 2781 /// @brief Abstract IterableContainer template that provides interface for iterable classes of type T 2782 template <typename T, typename Container> 2783 class IterableContainer { 2784 public: 2785 typedef typename Container::iterator iterator; 2786 typedef typename Container::const_iterator const_iterator; 2787 IterableContainer(void) {} 2788 virtual ~IterableContainer(void) {} 2789 iterator begin(void) { 2790 return getContainer().begin(); 2791 } 2792 iterator end(void) { 2793 return getContainer().end(); 2794 } 2795 private: 2796 virtual Container& getContainer(void) = 0; 2797 }; 2798 /// @brief Implements IterableContainer and provides iterable std::priority_queue class 2799 template<typename T, typename Container = std::vector<T>, typename Comparator = std::less<typename Container::value_type>> 2800 class IterablePriorityQueue : public IterableContainer<T, Container>, 2801 public std::priority_queue<T, Container, Comparator> { 2802 public: 2803 IterablePriorityQueue(std::priority_queue<T, Container, Comparator> queue_) { 2804 std::size_t count_ = 0; 2805 while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { 2806 this->push(queue_.top()); 2807 queue_.pop(); 2808 } 2809 } 2810 private: 2811 inline Container& getContainer(void) { 2812 return this->c; 2813 } 2814 }; 2815 /// @brief Implements IterableContainer and provides iterable std::queue class 2816 template<typename T, typename Container = std::deque<T>> 2817 class IterableQueue : public IterableContainer<T, Container>, public std::queue<T, Container> { 2818 public: 2819 IterableQueue(std::queue<T, Container> queue_) { 2820 std::size_t count_ = 0; 2821 while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { 2822 this->push(queue_.front()); 2823 queue_.pop(); 2824 } 2825 } 2826 private: 2827 inline Container& getContainer(void) { 2828 return this->c; 2829 } 2830 }; 2831 /// @brief Implements IterableContainer and provides iterable std::stack class 2832 template<typename T, typename Container = std::deque<T>> 2833 class IterableStack : public IterableContainer<T, Container>, public std::stack<T, Container> { 2834 public: 2835 IterableStack(std::stack<T, Container> stack_) { 2836 std::size_t count_ = 0; 2837 while (++count_ < base::consts::kMaxLogPerContainer && !stack_.empty()) { 2838 this->push(stack_.top()); 2839 stack_.pop(); 2840 } 2841 } 2842 private: 2843 inline Container& getContainer(void) { 2844 return this->c; 2845 } 2846 }; 2847 } // namespace workarounds 2848 #endif // defined(ELPP_STL_LOGGING) 2849 // Log message builder 2850 class MessageBuilder { 2851 public: 2852 MessageBuilder(void) : m_logger(nullptr), m_containerLogSeperator(ELPP_LITERAL("")) {} 2853 void initialize(Logger* logger); 2854 2855 # define ELPP_SIMPLE_LOG(LOG_TYPE)\ 2856 MessageBuilder& operator<<(LOG_TYPE msg) {\ 2857 m_logger->stream() << msg;\ 2858 if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {\ 2859 m_logger->stream() << " ";\ 2860 }\ 2861 return *this;\ 2862 } 2863 2864 inline MessageBuilder& operator<<(const std::string& msg) { 2865 return operator<<(msg.c_str()); 2866 } 2867 ELPP_SIMPLE_LOG(char) 2868 ELPP_SIMPLE_LOG(bool) 2869 ELPP_SIMPLE_LOG(signed short) 2870 ELPP_SIMPLE_LOG(unsigned short) 2871 ELPP_SIMPLE_LOG(signed int) 2872 ELPP_SIMPLE_LOG(unsigned int) 2873 ELPP_SIMPLE_LOG(signed long) 2874 ELPP_SIMPLE_LOG(unsigned long) 2875 ELPP_SIMPLE_LOG(float) 2876 ELPP_SIMPLE_LOG(double) 2877 ELPP_SIMPLE_LOG(char*) 2878 ELPP_SIMPLE_LOG(const char*) 2879 ELPP_SIMPLE_LOG(const void*) 2880 ELPP_SIMPLE_LOG(long double) 2881 inline MessageBuilder& operator<<(const std::wstring& msg) { 2882 return operator<<(msg.c_str()); 2883 } 2884 MessageBuilder& operator<<(const wchar_t* msg); 2885 // ostream manipulators 2886 inline MessageBuilder& operator<<(std::ostream& (*OStreamMani)(std::ostream&)) { 2887 m_logger->stream() << OStreamMani; 2888 return *this; 2889 } 2890 #define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \ 2891 template <typename T> \ 2892 inline MessageBuilder& operator<<(const temp<T>& template_inst) { \ 2893 return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ 2894 } 2895 #define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \ 2896 template <typename T1, typename T2> \ 2897 inline MessageBuilder& operator<<(const temp<T1, T2>& template_inst) { \ 2898 return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ 2899 } 2900 #define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \ 2901 template <typename T1, typename T2, typename T3> \ 2902 inline MessageBuilder& operator<<(const temp<T1, T2, T3>& template_inst) { \ 2903 return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ 2904 } 2905 #define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \ 2906 template <typename T1, typename T2, typename T3, typename T4> \ 2907 inline MessageBuilder& operator<<(const temp<T1, T2, T3, T4>& template_inst) { \ 2908 return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ 2909 } 2910 #define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \ 2911 template <typename T1, typename T2, typename T3, typename T4, typename T5> \ 2912 inline MessageBuilder& operator<<(const temp<T1, T2, T3, T4, T5>& template_inst) { \ 2913 return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ 2914 } 2915 2916 #if defined(ELPP_STL_LOGGING) 2917 ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector) 2918 ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list) 2919 ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque) 2920 ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set) 2921 ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset) 2922 ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map) 2923 ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap) 2924 template <class T, class Container> 2925 inline MessageBuilder& operator<<(const std::queue<T, Container>& queue_) { 2926 base::workarounds::IterableQueue<T, Container> iterableQueue_ = 2927 static_cast<base::workarounds::IterableQueue<T, Container> >(queue_); 2928 return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size()); 2929 } 2930 template <class T, class Container> 2931 inline MessageBuilder& operator<<(const std::stack<T, Container>& stack_) { 2932 base::workarounds::IterableStack<T, Container> iterableStack_ = 2933 static_cast<base::workarounds::IterableStack<T, Container> >(stack_); 2934 return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size()); 2935 } 2936 template <class T, class Container, class Comparator> 2937 inline MessageBuilder& operator<<(const std::priority_queue<T, Container, Comparator>& priorityQueue_) { 2938 base::workarounds::IterablePriorityQueue<T, Container, Comparator> iterablePriorityQueue_ = 2939 static_cast<base::workarounds::IterablePriorityQueue<T, Container, Comparator> >(priorityQueue_); 2940 return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size()); 2941 } 2942 template <class First, class Second> 2943 MessageBuilder& operator<<(const std::pair<First, Second>& pair_) { 2944 m_logger->stream() << ELPP_LITERAL("("); 2945 operator << (static_cast<First>(pair_.first)); 2946 m_logger->stream() << ELPP_LITERAL(", "); 2947 operator << (static_cast<Second>(pair_.second)); 2948 m_logger->stream() << ELPP_LITERAL(")"); 2949 return *this; 2950 } 2951 template <std::size_t Size> 2952 MessageBuilder& operator<<(const std::bitset<Size>& bitset_) { 2953 m_logger->stream() << ELPP_LITERAL("["); 2954 operator << (bitset_.to_string()); 2955 m_logger->stream() << ELPP_LITERAL("]"); 2956 return *this; 2957 } 2958 # if defined(ELPP_LOG_STD_ARRAY) 2959 template <class T, std::size_t Size> 2960 inline MessageBuilder& operator<<(const std::array<T, Size>& array) { 2961 return writeIterator(array.begin(), array.end(), array.size()); 2962 } 2963 # endif // defined(ELPP_LOG_STD_ARRAY) 2964 # if defined(ELPP_LOG_UNORDERED_MAP) 2965 ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map) 2966 ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap) 2967 # endif // defined(ELPP_LOG_UNORDERED_MAP) 2968 # if defined(ELPP_LOG_UNORDERED_SET) 2969 ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set) 2970 ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset) 2971 # endif // defined(ELPP_LOG_UNORDERED_SET) 2972 #endif // defined(ELPP_STL_LOGGING) 2973 #if defined(ELPP_QT_LOGGING) 2974 inline MessageBuilder& operator<<(const QString& msg) { 2975 # if defined(ELPP_UNICODE) 2976 m_logger->stream() << msg.toStdWString(); 2977 # else 2978 m_logger->stream() << msg.toStdString(); 2979 # endif // defined(ELPP_UNICODE) 2980 return *this; 2981 } 2982 inline MessageBuilder& operator<<(const QByteArray& msg) { 2983 return operator << (QString(msg)); 2984 } 2985 inline MessageBuilder& operator<<(const QStringRef& msg) { 2986 return operator<<(msg.toString()); 2987 } 2988 inline MessageBuilder& operator<<(qint64 msg) { 2989 # if defined(ELPP_UNICODE) 2990 m_logger->stream() << QString::number(msg).toStdWString(); 2991 # else 2992 m_logger->stream() << QString::number(msg).toStdString(); 2993 # endif // defined(ELPP_UNICODE) 2994 return *this; 2995 } 2996 inline MessageBuilder& operator<<(quint64 msg) { 2997 # if defined(ELPP_UNICODE) 2998 m_logger->stream() << QString::number(msg).toStdWString(); 2999 # else 3000 m_logger->stream() << QString::number(msg).toStdString(); 3001 # endif // defined(ELPP_UNICODE) 3002 return *this; 3003 } 3004 inline MessageBuilder& operator<<(QChar msg) { 3005 m_logger->stream() << msg.toLatin1(); 3006 return *this; 3007 } 3008 inline MessageBuilder& operator<<(const QLatin1String& msg) { 3009 m_logger->stream() << msg.latin1(); 3010 return *this; 3011 } 3012 ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList) 3013 ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector) 3014 ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue) 3015 ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet) 3016 ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList) 3017 ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack) 3018 template <typename First, typename Second> 3019 MessageBuilder& operator<<(const QPair<First, Second>& pair_) { 3020 m_logger->stream() << ELPP_LITERAL("("); 3021 operator << (static_cast<First>(pair_.first)); 3022 m_logger->stream() << ELPP_LITERAL(", "); 3023 operator << (static_cast<Second>(pair_.second)); 3024 m_logger->stream() << ELPP_LITERAL(")"); 3025 return *this; 3026 } 3027 template <typename K, typename V> 3028 MessageBuilder& operator<<(const QMap<K, V>& map_) { 3029 m_logger->stream() << ELPP_LITERAL("["); 3030 QList<K> keys = map_.keys(); 3031 typename QList<K>::const_iterator begin = keys.begin(); 3032 typename QList<K>::const_iterator end = keys.end(); 3033 int max_ = static_cast<int>(base::consts::kMaxLogPerContainer); // to prevent warning 3034 for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { 3035 m_logger->stream() << ELPP_LITERAL("("); 3036 operator << (static_cast<K>(*begin)); 3037 m_logger->stream() << ELPP_LITERAL(", "); 3038 operator << (static_cast<V>(map_.value(*begin))); 3039 m_logger->stream() << ELPP_LITERAL(")"); 3040 m_logger->stream() << ((index_ < keys.size() -1) ? m_containerLogSeperator : ELPP_LITERAL("")); 3041 } 3042 if (begin != end) { 3043 m_logger->stream() << ELPP_LITERAL("..."); 3044 } 3045 m_logger->stream() << ELPP_LITERAL("]"); 3046 return *this; 3047 } 3048 template <typename K, typename V> 3049 inline MessageBuilder& operator<<(const QMultiMap<K, V>& map_) { 3050 operator << (static_cast<QMap<K, V>>(map_)); 3051 return *this; 3052 } 3053 template <typename K, typename V> 3054 MessageBuilder& operator<<(const QHash<K, V>& hash_) { 3055 m_logger->stream() << ELPP_LITERAL("["); 3056 QList<K> keys = hash_.keys(); 3057 typename QList<K>::const_iterator begin = keys.begin(); 3058 typename QList<K>::const_iterator end = keys.end(); 3059 int max_ = static_cast<int>(base::consts::kMaxLogPerContainer); // prevent type warning 3060 for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { 3061 m_logger->stream() << ELPP_LITERAL("("); 3062 operator << (static_cast<K>(*begin)); 3063 m_logger->stream() << ELPP_LITERAL(", "); 3064 operator << (static_cast<V>(hash_.value(*begin))); 3065 m_logger->stream() << ELPP_LITERAL(")"); 3066 m_logger->stream() << ((index_ < keys.size() -1) ? m_containerLogSeperator : ELPP_LITERAL("")); 3067 } 3068 if (begin != end) { 3069 m_logger->stream() << ELPP_LITERAL("..."); 3070 } 3071 m_logger->stream() << ELPP_LITERAL("]"); 3072 return *this; 3073 } 3074 template <typename K, typename V> 3075 inline MessageBuilder& operator<<(const QMultiHash<K, V>& multiHash_) { 3076 operator << (static_cast<QHash<K, V>>(multiHash_)); 3077 return *this; 3078 } 3079 #endif // defined(ELPP_QT_LOGGING) 3080 #if defined(ELPP_BOOST_LOGGING) 3081 ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector) 3082 ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector) 3083 ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list) 3084 ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque) 3085 ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map) 3086 ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map) 3087 ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set) 3088 ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set) 3089 #endif // defined(ELPP_BOOST_LOGGING) 3090 3091 /// @brief Macro used internally that can be used externally to make containers easylogging++ friendly 3092 /// 3093 /// @detail This macro expands to write an ostream& operator<< for container. This container is expected to 3094 /// have begin() and end() methods that return respective iterators 3095 /// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets 3096 /// @param SizeMethod Method used to get size of container. 3097 /// @param ElementInstance Instance of element to be fed out. Insance name is "elem". See WXELPP_ENABLED macro 3098 /// for an example usage 3099 #define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \ 3100 el::base::type::ostream_t& operator<<(el::base::type::ostream_t& ss, const ContainerType& container) {\ 3101 const el::base::type::char_t* sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? \ 3102 ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");\ 3103 ContainerType::const_iterator elem = container.begin();\ 3104 ContainerType::const_iterator endElem = container.end();\ 3105 std::size_t size_ = container.SizeMethod; \ 3106 ss << ELPP_LITERAL("[");\ 3107 for (std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) { \ 3108 ss << ElementInstance;\ 3109 ss << ((i < size_ - 1) ? sep : ELPP_LITERAL(""));\ 3110 }\ 3111 if (elem != endElem) {\ 3112 ss << ELPP_LITERAL("...");\ 3113 }\ 3114 ss << ELPP_LITERAL("]");\ 3115 return ss;\ 3116 } 3117 #if defined(ELPP_WXWIDGETS_LOGGING) 3118 ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector) 3119 # define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem)) 3120 # define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem)) 3121 # define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \ 3122 ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")") 3123 #else 3124 # define ELPP_WX_PTR_ENABLED(ContainerType) 3125 # define ELPP_WX_ENABLED(ContainerType) 3126 # define ELPP_WX_HASH_MAP_ENABLED(ContainerType) 3127 #endif // defined(ELPP_WXWIDGETS_LOGGING) 3128 // Other classes 3129 template <class Class> 3130 ELPP_SIMPLE_LOG(const Class&) 3131 #undef ELPP_SIMPLE_LOG 3132 #undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG 3133 #undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG 3134 #undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG 3135 #undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG 3136 #undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG 3137 private: 3138 Logger* m_logger; 3139 const base::type::char_t* m_containerLogSeperator; 3140 3141 template<class Iterator> 3142 MessageBuilder& writeIterator(Iterator begin_, Iterator end_, std::size_t size_) { 3143 m_logger->stream() << ELPP_LITERAL("["); 3144 for (std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_) { 3145 operator << (*begin_); 3146 m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); 3147 } 3148 if (begin_ != end_) { 3149 m_logger->stream() << ELPP_LITERAL("..."); 3150 } 3151 m_logger->stream() << ELPP_LITERAL("]"); 3152 if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { 3153 m_logger->stream() << " "; 3154 } 3155 return *this; 3156 } 3157 }; 3158 /// @brief Writes nothing - Used when certain log is disabled 3159 class NullWriter : base::NoCopy { 3160 public: 3161 NullWriter(void) {} 3162 3163 // Null manipulator 3164 inline NullWriter& operator<<(std::ostream& (*)(std::ostream&)) { 3165 return *this; 3166 } 3167 3168 template <typename T> 3169 inline NullWriter& operator<<(const T&) { 3170 return *this; 3171 } 3172 3173 inline operator bool() { 3174 return true; 3175 } 3176 }; 3177 /// @brief Main entry point of each logging 3178 class Writer : base::NoCopy { 3179 public: 3180 Writer(Level level, const char* file, base::type::LineNumber line, 3181 const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, 3182 base::type::VerboseLevel verboseLevel = 0) : 3183 m_msg(nullptr), m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), 3184 m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { 3185 } 3186 3187 Writer(LogMessage* msg, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog) : 3188 m_msg(msg), m_line(0), m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { 3189 } 3190 3191 virtual ~Writer(void) { 3192 processDispatch(); 3193 } 3194 3195 template <typename T> 3196 inline Writer& operator<<(const T& log) { 3197 #if ELPP_LOGGING_ENABLED 3198 if (m_proceed) { 3199 m_messageBuilder << log; 3200 } 3201 #endif // ELPP_LOGGING_ENABLED 3202 return *this; 3203 } 3204 3205 inline Writer& operator<<(std::ostream& (*log)(std::ostream&)) { 3206 #if ELPP_LOGGING_ENABLED 3207 if (m_proceed) { 3208 m_messageBuilder << log; 3209 } 3210 #endif // ELPP_LOGGING_ENABLED 3211 return *this; 3212 } 3213 3214 inline operator bool() { 3215 return true; 3216 } 3217 3218 Writer& construct(Logger* logger, bool needLock = true); 3219 Writer& construct(int count, const char* loggerIds, ...); 3220 protected: 3221 LogMessage* m_msg; 3222 Level m_level; 3223 const char* m_file; 3224 const base::type::LineNumber m_line; 3225 const char* m_func; 3226 base::type::VerboseLevel m_verboseLevel; 3227 Logger* m_logger; 3228 bool m_proceed; 3229 base::MessageBuilder m_messageBuilder; 3230 base::DispatchAction m_dispatchAction; 3231 std::vector<std::string> m_loggerIds; 3232 friend class el::Helpers; 3233 3234 void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true); 3235 void processDispatch(); 3236 void triggerDispatch(void); 3237 }; 3238 class PErrorWriter : public base::Writer { 3239 public: 3240 PErrorWriter(Level level, const char* file, base::type::LineNumber line, 3241 const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, 3242 base::type::VerboseLevel verboseLevel = 0) : 3243 base::Writer(level, file, line, func, dispatchAction, verboseLevel) { 3244 } 3245 3246 virtual ~PErrorWriter(void); 3247 }; 3248 } // namespace base 3249 // Logging from Logger class. Why this is here? Because we have Storage and Writer class available 3250 #if ELPP_VARIADIC_TEMPLATES_SUPPORTED 3251 template <typename T, typename... Args> 3252 void Logger::log_(Level level, int vlevel, const char* s, const T& value, const Args&... args) { 3253 base::MessageBuilder b; 3254 b.initialize(this); 3255 while (*s) { 3256 if (*s == base::consts::kFormatSpecifierChar) { 3257 if (*(s + 1) == base::consts::kFormatSpecifierChar) { 3258 ++s; 3259 } else { 3260 if (*(s + 1) == base::consts::kFormatSpecifierCharValue) { 3261 ++s; 3262 b << value; 3263 log_(level, vlevel, ++s, args...); 3264 return; 3265 } 3266 } 3267 } 3268 b << *s++; 3269 } 3270 ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false); 3271 } 3272 template <typename T> 3273 void Logger::log_(Level level, int vlevel, const T& log) { 3274 if (level == Level::Verbose) { 3275 if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) { 3276 base::Writer(Level::Verbose, "FILE", 0, "FUNCTION", 3277 base::DispatchAction::NormalLog, vlevel).construct(this, false) << log; 3278 } else { 3279 stream().str(ELPP_LITERAL("")); 3280 releaseLock(); 3281 } 3282 } else { 3283 base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; 3284 } 3285 } 3286 template <typename T, typename... Args> 3287 inline void Logger::log(Level level, const char* s, const T& value, const Args&... args) { 3288 acquireLock(); // released in Writer! 3289 log_(level, 0, s, value, args...); 3290 } 3291 template <typename T> 3292 inline void Logger::log(Level level, const T& log) { 3293 acquireLock(); // released in Writer! 3294 log_(level, 0, log); 3295 } 3296 # if ELPP_VERBOSE_LOG 3297 template <typename T, typename... Args> 3298 inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args) { 3299 acquireLock(); // released in Writer! 3300 log_(el::Level::Verbose, vlevel, s, value, args...); 3301 } 3302 template <typename T> 3303 inline void Logger::verbose(int vlevel, const T& log) { 3304 acquireLock(); // released in Writer! 3305 log_(el::Level::Verbose, vlevel, log); 3306 } 3307 # else 3308 template <typename T, typename... Args> 3309 inline void Logger::verbose(int, const char*, const T&, const Args&...) { 3310 return; 3311 } 3312 template <typename T> 3313 inline void Logger::verbose(int, const T&) { 3314 return; 3315 } 3316 # endif // ELPP_VERBOSE_LOG 3317 # define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL)\ 3318 template <typename T, typename... Args>\ 3319 inline void Logger::FUNCTION_NAME(const char* s, const T& value, const Args&... args) {\ 3320 log(LOG_LEVEL, s, value, args...);\ 3321 }\ 3322 template <typename T>\ 3323 inline void Logger::FUNCTION_NAME(const T& value) {\ 3324 log(LOG_LEVEL, value);\ 3325 } 3326 # define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL)\ 3327 template <typename T, typename... Args>\ 3328 inline void Logger::FUNCTION_NAME(const char*, const T&, const Args&...) {\ 3329 return;\ 3330 }\ 3331 template <typename T>\ 3332 inline void Logger::FUNCTION_NAME(const T&) {\ 3333 return;\ 3334 } 3335 3336 # if ELPP_INFO_LOG 3337 LOGGER_LEVEL_WRITERS(info, Level::Info) 3338 # else 3339 LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info) 3340 # endif // ELPP_INFO_LOG 3341 # if ELPP_DEBUG_LOG 3342 LOGGER_LEVEL_WRITERS(debug, Level::Debug) 3343 # else 3344 LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug) 3345 # endif // ELPP_DEBUG_LOG 3346 # if ELPP_WARNING_LOG 3347 LOGGER_LEVEL_WRITERS(warn, Level::Warning) 3348 # else 3349 LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning) 3350 # endif // ELPP_WARNING_LOG 3351 # if ELPP_ERROR_LOG 3352 LOGGER_LEVEL_WRITERS(error, Level::Error) 3353 # else 3354 LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error) 3355 # endif // ELPP_ERROR_LOG 3356 # if ELPP_FATAL_LOG 3357 LOGGER_LEVEL_WRITERS(fatal, Level::Fatal) 3358 # else 3359 LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal) 3360 # endif // ELPP_FATAL_LOG 3361 # if ELPP_TRACE_LOG 3362 LOGGER_LEVEL_WRITERS(trace, Level::Trace) 3363 # else 3364 LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace) 3365 # endif // ELPP_TRACE_LOG 3366 # undef LOGGER_LEVEL_WRITERS 3367 # undef LOGGER_LEVEL_WRITERS_DISABLED 3368 #endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED 3369 #if ELPP_COMPILER_MSVC 3370 # define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs 3371 # define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__)) 3372 # define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ## __VA_ARGS__,\ 3373 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 3374 #else 3375 # if ELPP_COMPILER_CLANG 3376 # define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 3377 # else 3378 # define el_getVALength(...) el_resolveVALength(0, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 3379 # endif // ELPP_COMPILER_CLANG 3380 #endif // ELPP_COMPILER_MSVC 3381 #define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N 3382 #define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \ 3383 writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) 3384 #define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \ 3385 writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) 3386 #define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ 3387 ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion) && \ 3388 writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) 3389 #define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ 3390 ELPP->validateAfterNCounter(__FILE__, __LINE__, n) && \ 3391 writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) 3392 #define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ 3393 ELPP->validateNTimesCounter(__FILE__, __LINE__, n) && \ 3394 writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) 3395 #if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) 3396 class PerformanceTrackingData { 3397 public: 3398 enum class DataType : base::type::EnumType { 3399 Checkpoint = 1, Complete = 2 3400 }; 3401 // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*) 3402 explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr), 3403 m_dataType(dataType), m_firstCheckpoint(false), m_file(""), m_line(0), m_func("") {} 3404 inline const std::string* blockName(void) const; 3405 inline const struct timeval* startTime(void) const; 3406 inline const struct timeval* endTime(void) const; 3407 inline const struct timeval* lastCheckpointTime(void) const; 3408 inline const base::PerformanceTracker* performanceTracker(void) const { 3409 return m_performanceTracker; 3410 } 3411 inline PerformanceTrackingData::DataType dataType(void) const { 3412 return m_dataType; 3413 } 3414 inline bool firstCheckpoint(void) const { 3415 return m_firstCheckpoint; 3416 } 3417 inline std::string checkpointId(void) const { 3418 return m_checkpointId; 3419 } 3420 inline const char* file(void) const { 3421 return m_file; 3422 } 3423 inline base::type::LineNumber line(void) const { 3424 return m_line; 3425 } 3426 inline const char* func(void) const { 3427 return m_func; 3428 } 3429 inline const base::type::string_t* formattedTimeTaken() const { 3430 return &m_formattedTimeTaken; 3431 } 3432 inline const std::string& loggerId(void) const; 3433 private: 3434 base::PerformanceTracker* m_performanceTracker; 3435 base::type::string_t m_formattedTimeTaken; 3436 PerformanceTrackingData::DataType m_dataType; 3437 bool m_firstCheckpoint; 3438 std::string m_checkpointId; 3439 const char* m_file; 3440 base::type::LineNumber m_line; 3441 const char* m_func; 3442 inline void init(base::PerformanceTracker* performanceTracker, bool firstCheckpoint = false) { 3443 m_performanceTracker = performanceTracker; 3444 m_firstCheckpoint = firstCheckpoint; 3445 } 3446 3447 friend class el::base::PerformanceTracker; 3448 }; 3449 namespace base { 3450 /// @brief Represents performanceTracker block of code that conditionally adds performance status to log 3451 /// either when goes outside the scope of when checkpoint() is called 3452 class PerformanceTracker : public base::threading::ThreadSafe, public Loggable { 3453 public: 3454 PerformanceTracker(const std::string& blockName, 3455 base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond, 3456 const std::string& loggerId = std::string(el::base::consts::kPerformanceLoggerId), 3457 bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel); 3458 /// @brief Copy constructor 3459 PerformanceTracker(const PerformanceTracker& t) : 3460 m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog), 3461 m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled), 3462 m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime) { 3463 } 3464 virtual ~PerformanceTracker(void); 3465 /// @brief A checkpoint for current performanceTracker block. 3466 void checkpoint(const std::string& id = std::string(), const char* file = __FILE__, 3467 base::type::LineNumber line = __LINE__, 3468 const char* func = ""); 3469 inline Level level(void) const { 3470 return m_level; 3471 } 3472 private: 3473 std::string m_blockName; 3474 base::TimestampUnit m_timestampUnit; 3475 std::string m_loggerId; 3476 bool m_scopedLog; 3477 Level m_level; 3478 bool m_hasChecked; 3479 std::string m_lastCheckpointId; 3480 bool m_enabled; 3481 struct timeval m_startTime, m_endTime, m_lastCheckpointTime; 3482 3483 PerformanceTracker(void); 3484 3485 friend class el::PerformanceTrackingData; 3486 friend class base::DefaultPerformanceTrackingCallback; 3487 3488 const inline base::type::string_t getFormattedTimeTaken() const { 3489 return getFormattedTimeTaken(m_startTime); 3490 } 3491 3492 const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const; 3493 3494 virtual inline void log(el::base::type::ostream_t& os) const { 3495 os << getFormattedTimeTaken(); 3496 } 3497 }; 3498 class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback { 3499 protected: 3500 void handle(const PerformanceTrackingData* data) { 3501 m_data = data; 3502 base::type::stringstream_t ss; 3503 if (m_data->dataType() == PerformanceTrackingData::DataType::Complete) { 3504 ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << 3505 *m_data->formattedTimeTaken() << ELPP_LITERAL("]"); 3506 } else { 3507 ss << ELPP_LITERAL("Performance checkpoint"); 3508 if (!m_data->checkpointId().empty()) { 3509 ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]"); 3510 } 3511 ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << 3512 *m_data->performanceTracker(); 3513 if (!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) 3514 && m_data->performanceTracker()->m_hasChecked) { 3515 ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from "); 3516 if (m_data->performanceTracker()->m_lastCheckpointId.empty()) { 3517 ss << ELPP_LITERAL("last checkpoint"); 3518 } else { 3519 ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'"); 3520 } 3521 ss << ELPP_LITERAL(")]"); 3522 } else { 3523 ss << ELPP_LITERAL("]"); 3524 } 3525 } 3526 el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, 3527 m_data->loggerId().c_str()) << ss.str(); 3528 } 3529 private: 3530 const PerformanceTrackingData* m_data; 3531 }; 3532 } // namespace base 3533 inline const std::string* PerformanceTrackingData::blockName() const { 3534 return const_cast<const std::string*>(&m_performanceTracker->m_blockName); 3535 } 3536 inline const struct timeval* PerformanceTrackingData::startTime() const { 3537 return const_cast<const struct timeval*>(&m_performanceTracker->m_startTime); 3538 } 3539 inline const struct timeval* PerformanceTrackingData::endTime() const { 3540 return const_cast<const struct timeval*>(&m_performanceTracker->m_endTime); 3541 } 3542 inline const struct timeval* PerformanceTrackingData::lastCheckpointTime() const { 3543 return const_cast<const struct timeval*>(&m_performanceTracker->m_lastCheckpointTime); 3544 } 3545 inline const std::string& PerformanceTrackingData::loggerId(void) const { 3546 return m_performanceTracker->m_loggerId; 3547 } 3548 #endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) 3549 namespace base { 3550 /// @brief Contains some internal debugging tools like crash handler and stack tracer 3551 namespace debug { 3552 #if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) 3553 class StackTrace : base::NoCopy { 3554 public: 3555 static const unsigned int kMaxStack = 64; 3556 static const unsigned int kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() 3557 class StackTraceEntry { 3558 public: 3559 StackTraceEntry(std::size_t index, const std::string& loc, const std::string& demang, const std::string& hex, 3560 const std::string& addr); 3561 StackTraceEntry(std::size_t index, const std::string& loc) : 3562 m_index(index), 3563 m_location(loc) { 3564 } 3565 std::size_t m_index; 3566 std::string m_location; 3567 std::string m_demangled; 3568 std::string m_hex; 3569 std::string m_addr; 3570 friend std::ostream& operator<<(std::ostream& ss, const StackTraceEntry& si); 3571 3572 private: 3573 StackTraceEntry(void); 3574 }; 3575 3576 StackTrace(void) { 3577 generateNew(); 3578 } 3579 3580 virtual ~StackTrace(void) { 3581 } 3582 3583 inline std::vector<StackTraceEntry>& getLatestStack(void) { 3584 return m_stack; 3585 } 3586 3587 friend std::ostream& operator<<(std::ostream& os, const StackTrace& st); 3588 3589 private: 3590 std::vector<StackTraceEntry> m_stack; 3591 3592 void generateNew(void); 3593 }; 3594 /// @brief Handles unexpected crashes 3595 class CrashHandler : base::NoCopy { 3596 public: 3597 typedef void (*Handler)(int); 3598 3599 explicit CrashHandler(bool useDefault); 3600 explicit CrashHandler(const Handler& cHandler) { 3601 setHandler(cHandler); 3602 } 3603 void setHandler(const Handler& cHandler); 3604 3605 private: 3606 Handler m_handler; 3607 }; 3608 #else 3609 class CrashHandler { 3610 public: 3611 explicit CrashHandler(bool) {} 3612 }; 3613 #endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) 3614 } // namespace debug 3615 } // namespace base 3616 extern base::debug::CrashHandler elCrashHandler; 3617 #define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \ 3618 el::base::type::ostream_t& operator<<(el::base::type::ostream_t& OutputStreamInstance, const ClassType& ClassInstance) 3619 /// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor 3620 class SysLogInitializer { 3621 public: 3622 SysLogInitializer(const char* processIdent, int options = 0, int facility = 0) { 3623 #if defined(ELPP_SYSLOG) 3624 openlog(processIdent, options, facility); 3625 #else 3626 ELPP_UNUSED(processIdent); 3627 ELPP_UNUSED(options); 3628 ELPP_UNUSED(facility); 3629 #endif // defined(ELPP_SYSLOG) 3630 } 3631 virtual ~SysLogInitializer(void) { 3632 #if defined(ELPP_SYSLOG) 3633 closelog(); 3634 #endif // defined(ELPP_SYSLOG) 3635 } 3636 }; 3637 #define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac) 3638 /// @brief Static helpers for developers 3639 class Helpers : base::StaticClass { 3640 public: 3641 /// @brief Shares logging repository (base::Storage) 3642 static inline void setStorage(base::type::StoragePointer storage) { 3643 ELPP = storage; 3644 } 3645 /// @return Main storage repository 3646 static inline base::type::StoragePointer storage() { 3647 return ELPP; 3648 } 3649 /// @brief Sets application arguments and figures out whats active for logging and whats not. 3650 static inline void setArgs(int argc, char** argv) { 3651 ELPP->setApplicationArguments(argc, argv); 3652 } 3653 /// @copydoc setArgs(int argc, char** argv) 3654 static inline void setArgs(int argc, const char** argv) { 3655 ELPP->setApplicationArguments(argc, const_cast<char**>(argv)); 3656 } 3657 /// @brief Sets thread name for current thread. Requires std::thread 3658 static inline void setThreadName(const std::string& name) { 3659 ELPP->setThreadName(name); 3660 } 3661 static inline std::string getThreadName() { 3662 return ELPP->getThreadName(base::threading::getCurrentThreadId()); 3663 } 3664 #if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) 3665 /// @brief Overrides default crash handler and installs custom handler. 3666 /// @param crashHandler A functor with no return type that takes single int argument. 3667 /// Handler is a typedef with specification: void (*Handler)(int) 3668 static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler& crashHandler) { 3669 el::elCrashHandler.setHandler(crashHandler); 3670 } 3671 /// @brief Abort due to crash with signal in parameter 3672 /// @param sig Crash signal 3673 static void crashAbort(int sig, const char* sourceFile = "", unsigned int long line = 0); 3674 /// @brief Logs reason of crash as per sig 3675 /// @param sig Crash signal 3676 /// @param stackTraceIfAvailable Includes stack trace if available 3677 /// @param level Logging level 3678 /// @param logger Logger to use for logging 3679 static void logCrashReason(int sig, bool stackTraceIfAvailable = false, 3680 Level level = Level::Fatal, const char* logger = base::consts::kDefaultLoggerId); 3681 #endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) 3682 /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out 3683 /// (can be useful for backing up) 3684 static inline void installPreRollOutCallback(const PreRollOutCallback& callback) { 3685 ELPP->setPreRollOutCallback(callback); 3686 } 3687 /// @brief Uninstalls pre rollout callback 3688 static inline void uninstallPreRollOutCallback(void) { 3689 ELPP->unsetPreRollOutCallback(); 3690 } 3691 /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched 3692 template <typename T> 3693 static inline bool installLogDispatchCallback(const std::string& id) { 3694 return ELPP->installLogDispatchCallback<T>(id); 3695 } 3696 /// @brief Uninstalls log dispatch callback 3697 template <typename T> 3698 static inline void uninstallLogDispatchCallback(const std::string& id) { 3699 ELPP->uninstallLogDispatchCallback<T>(id); 3700 } 3701 template <typename T> 3702 static inline T* logDispatchCallback(const std::string& id) { 3703 return ELPP->logDispatchCallback<T>(id); 3704 } 3705 #if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) 3706 /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished 3707 template <typename T> 3708 static inline bool installPerformanceTrackingCallback(const std::string& id) { 3709 return ELPP->installPerformanceTrackingCallback<T>(id); 3710 } 3711 /// @brief Uninstalls post performance tracking handler 3712 template <typename T> 3713 static inline void uninstallPerformanceTrackingCallback(const std::string& id) { 3714 ELPP->uninstallPerformanceTrackingCallback<T>(id); 3715 } 3716 template <typename T> 3717 static inline T* performanceTrackingCallback(const std::string& id) { 3718 return ELPP->performanceTrackingCallback<T>(id); 3719 } 3720 #endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) 3721 /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const 3722 template <typename T> 3723 static std::string convertTemplateToStdString(const T& templ) { 3724 el::Logger* logger = 3725 ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId); 3726 if (logger == nullptr) { 3727 return std::string(); 3728 } 3729 base::MessageBuilder b; 3730 b.initialize(logger); 3731 logger->acquireLock(); 3732 b << templ; 3733 #if defined(ELPP_UNICODE) 3734 std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end()); 3735 #else 3736 std::string s = logger->stream().str(); 3737 #endif // defined(ELPP_UNICODE) 3738 logger->stream().str(ELPP_LITERAL("")); 3739 logger->releaseLock(); 3740 return s; 3741 } 3742 /// @brief Returns command line arguments (pointer) provided to easylogging++ 3743 static inline const el::base::utils::CommandLineArgs* commandLineArgs(void) { 3744 return ELPP->commandLineArgs(); 3745 } 3746 /// @brief Reserve space for custom format specifiers for performance 3747 /// @see std::vector::reserve 3748 static inline void reserveCustomFormatSpecifiers(std::size_t size) { 3749 ELPP->m_customFormatSpecifiers.reserve(size); 3750 } 3751 /// @brief Installs user defined format specifier and handler 3752 static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { 3753 ELPP->installCustomFormatSpecifier(customFormatSpecifier); 3754 } 3755 /// @brief Uninstalls user defined format specifier and handler 3756 static inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { 3757 return ELPP->uninstallCustomFormatSpecifier(formatSpecifier); 3758 } 3759 /// @brief Returns true if custom format specifier is installed 3760 static inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { 3761 return ELPP->hasCustomFormatSpecifier(formatSpecifier); 3762 } 3763 static inline void validateFileRolling(Logger* logger, Level level) { 3764 if (logger == nullptr) return; 3765 logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback()); 3766 } 3767 }; 3768 /// @brief Static helpers to deal with loggers and their configurations 3769 class Loggers : base::StaticClass { 3770 public: 3771 /// @brief Gets existing or registers new logger 3772 static Logger* getLogger(const std::string& identity, bool registerIfNotAvailable = true); 3773 /// @brief Changes default log builder for future loggers 3774 static void setDefaultLogBuilder(el::LogBuilderPtr& logBuilderPtr); 3775 /// @brief Installs logger registration callback, this callback is triggered when new logger is registered 3776 template <typename T> 3777 static inline bool installLoggerRegistrationCallback(const std::string& id) { 3778 return ELPP->registeredLoggers()->installLoggerRegistrationCallback<T>(id); 3779 } 3780 /// @brief Uninstalls log dispatch callback 3781 template <typename T> 3782 static inline void uninstallLoggerRegistrationCallback(const std::string& id) { 3783 ELPP->registeredLoggers()->uninstallLoggerRegistrationCallback<T>(id); 3784 } 3785 template <typename T> 3786 static inline T* loggerRegistrationCallback(const std::string& id) { 3787 return ELPP->registeredLoggers()->loggerRegistrationCallback<T>(id); 3788 } 3789 /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister 3790 /// loggers initialized / used by third-party libs. 3791 static bool unregisterLogger(const std::string& identity); 3792 /// @brief Whether or not logger with id is registered 3793 static bool hasLogger(const std::string& identity); 3794 /// @brief Reconfigures specified logger with new configurations 3795 static Logger* reconfigureLogger(Logger* logger, const Configurations& configurations); 3796 /// @brief Reconfigures logger with new configurations after looking it up using identity 3797 static Logger* reconfigureLogger(const std::string& identity, const Configurations& configurations); 3798 /// @brief Reconfigures logger's single configuration 3799 static Logger* reconfigureLogger(const std::string& identity, ConfigurationType configurationType, 3800 const std::string& value); 3801 /// @brief Reconfigures all the existing loggers with new configurations 3802 static void reconfigureAllLoggers(const Configurations& configurations); 3803 /// @brief Reconfigures single configuration for all the loggers 3804 static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string& value) { 3805 reconfigureAllLoggers(Level::Global, configurationType, value); 3806 } 3807 /// @brief Reconfigures single configuration for all the loggers for specified level 3808 static void reconfigureAllLoggers(Level level, ConfigurationType configurationType, 3809 const std::string& value); 3810 /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers 3811 static void setDefaultConfigurations(const Configurations& configurations, 3812 bool reconfigureExistingLoggers = false); 3813 /// @brief Returns current default 3814 static const Configurations* defaultConfigurations(void); 3815 /// @brief Returns log stream reference pointer if needed by user 3816 static const base::LogStreamsReferenceMap* logStreamsReference(void); 3817 /// @brief Default typed configuration based on existing defaultConf 3818 static base::TypedConfigurations defaultTypedConfigurations(void); 3819 /// @brief Populates all logger IDs in current repository. 3820 /// @param [out] targetList List of fill up. 3821 static std::vector<std::string>* populateAllLoggerIds(std::vector<std::string>* targetList); 3822 /// @brief Sets configurations from global configuration file. 3823 static void configureFromGlobal(const char* globalConfigurationFilePath); 3824 /// @brief Configures loggers using command line arg. Ensure you have already set command line args, 3825 /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. 3826 /// If true is returned that does not mean it has been configured successfully, it only means that it 3827 /// has attempeted to configure logger using configuration file provided in argument 3828 static bool configureFromArg(const char* argKey); 3829 /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered 3830 static void flushAll(void); 3831 /// @brief Adds logging flag used internally. 3832 static inline void addFlag(LoggingFlag flag) { 3833 ELPP->addFlag(flag); 3834 } 3835 /// @brief Removes logging flag used internally. 3836 static inline void removeFlag(LoggingFlag flag) { 3837 ELPP->removeFlag(flag); 3838 } 3839 /// @brief Determines whether or not certain flag is active 3840 static inline bool hasFlag(LoggingFlag flag) { 3841 return ELPP->hasFlag(flag); 3842 } 3843 /// @brief Adds flag and removes it when scope goes out 3844 class ScopedAddFlag { 3845 public: 3846 ScopedAddFlag(LoggingFlag flag) : m_flag(flag) { 3847 Loggers::addFlag(m_flag); 3848 } 3849 ~ScopedAddFlag(void) { 3850 Loggers::removeFlag(m_flag); 3851 } 3852 private: 3853 LoggingFlag m_flag; 3854 }; 3855 /// @brief Removes flag and add it when scope goes out 3856 class ScopedRemoveFlag { 3857 public: 3858 ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) { 3859 Loggers::removeFlag(m_flag); 3860 } 3861 ~ScopedRemoveFlag(void) { 3862 Loggers::addFlag(m_flag); 3863 } 3864 private: 3865 LoggingFlag m_flag; 3866 }; 3867 /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging) 3868 static void setLoggingLevel(Level level) { 3869 ELPP->setLoggingLevel(level); 3870 } 3871 /// @brief Sets verbose level on the fly 3872 static void setVerboseLevel(base::type::VerboseLevel level); 3873 /// @brief Gets current verbose level 3874 static base::type::VerboseLevel verboseLevel(void); 3875 /// @brief Sets vmodules as specified (on the fly) 3876 static void setVModules(const char* modules); 3877 /// @brief Clears vmodules 3878 static void clearVModules(void); 3879 }; 3880 class VersionInfo : base::StaticClass { 3881 public: 3882 /// @brief Current version number 3883 static const std::string version(void); 3884 3885 /// @brief Release date of current version 3886 static const std::string releaseDate(void); 3887 }; 3888 } // namespace el 3889 #undef VLOG_IS_ON 3890 /// @brief Determines whether verbose logging is on for specified level current file. 3891 #define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__)) 3892 #undef TIMED_BLOCK 3893 #undef TIMED_SCOPE 3894 #undef TIMED_SCOPE_IF 3895 #undef TIMED_FUNC 3896 #undef TIMED_FUNC_IF 3897 #undef ELPP_MIN_UNIT 3898 #if defined(ELPP_PERFORMANCE_MICROSECONDS) 3899 # define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond 3900 #else 3901 # define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond 3902 #endif // (defined(ELPP_PERFORMANCE_MICROSECONDS)) 3903 /// @brief Performance tracked scope. Performance gets written when goes out of scope using 3904 /// 'performance' logger. 3905 /// 3906 /// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); 3907 /// @see el::base::PerformanceTracker 3908 /// @see el::base::PerformanceTracker::checkpoint 3909 // Note: Do not surround this definition with null macro because of obj instance 3910 #define TIMED_SCOPE_IF(obj, blockname, condition) el::base::type::PerformanceTrackerPtr obj( condition ? \ 3911 new el::base::PerformanceTracker(blockname, ELPP_MIN_UNIT) : nullptr ) 3912 #define TIMED_SCOPE(obj, blockname) TIMED_SCOPE_IF(obj, blockname, true) 3913 #define TIMED_BLOCK(obj, blockName) for (struct { int i; el::base::type::PerformanceTrackerPtr timer; } obj = { 0, \ 3914 el::base::type::PerformanceTrackerPtr(new el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT)) }; obj.i < 1; ++obj.i) 3915 /// @brief Performance tracked function. Performance gets written when goes out of scope using 3916 /// 'performance' logger. 3917 /// 3918 /// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); 3919 /// @see el::base::PerformanceTracker 3920 /// @see el::base::PerformanceTracker::checkpoint 3921 #define TIMED_FUNC_IF(obj,condition) TIMED_SCOPE_IF(obj, ELPP_FUNC, condition) 3922 #define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC) 3923 #undef PERFORMANCE_CHECKPOINT 3924 #undef PERFORMANCE_CHECKPOINT_WITH_ID 3925 #define PERFORMANCE_CHECKPOINT(obj) obj->checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC) 3926 #define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj->checkpoint(id, __FILE__, __LINE__, ELPP_FUNC) 3927 #undef ELPP_COUNTER 3928 #undef ELPP_COUNTER_POS 3929 /// @brief Gets hit counter for file/line 3930 #define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__)) 3931 /// @brief Gets hit counter position for file/line, -1 if not registered yet 3932 #define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts()) 3933 // Undef levels to support LOG(LEVEL) 3934 #undef INFO 3935 #undef WARNING 3936 #undef DEBUG 3937 #undef ERROR 3938 #undef FATAL 3939 #undef TRACE 3940 #undef VERBOSE 3941 // Undef existing 3942 #undef CINFO 3943 #undef CWARNING 3944 #undef CDEBUG 3945 #undef CFATAL 3946 #undef CERROR 3947 #undef CTRACE 3948 #undef CVERBOSE 3949 #undef CINFO_IF 3950 #undef CWARNING_IF 3951 #undef CDEBUG_IF 3952 #undef CERROR_IF 3953 #undef CFATAL_IF 3954 #undef CTRACE_IF 3955 #undef CVERBOSE_IF 3956 #undef CINFO_EVERY_N 3957 #undef CWARNING_EVERY_N 3958 #undef CDEBUG_EVERY_N 3959 #undef CERROR_EVERY_N 3960 #undef CFATAL_EVERY_N 3961 #undef CTRACE_EVERY_N 3962 #undef CVERBOSE_EVERY_N 3963 #undef CINFO_AFTER_N 3964 #undef CWARNING_AFTER_N 3965 #undef CDEBUG_AFTER_N 3966 #undef CERROR_AFTER_N 3967 #undef CFATAL_AFTER_N 3968 #undef CTRACE_AFTER_N 3969 #undef CVERBOSE_AFTER_N 3970 #undef CINFO_N_TIMES 3971 #undef CWARNING_N_TIMES 3972 #undef CDEBUG_N_TIMES 3973 #undef CERROR_N_TIMES 3974 #undef CFATAL_N_TIMES 3975 #undef CTRACE_N_TIMES 3976 #undef CVERBOSE_N_TIMES 3977 // Normal logs 3978 #if ELPP_INFO_LOG 3979 # define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__) 3980 #else 3981 # define CINFO(writer, dispatchAction, ...) el::base::NullWriter() 3982 #endif // ELPP_INFO_LOG 3983 #if ELPP_WARNING_LOG 3984 # define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__) 3985 #else 3986 # define CWARNING(writer, dispatchAction, ...) el::base::NullWriter() 3987 #endif // ELPP_WARNING_LOG 3988 #if ELPP_DEBUG_LOG 3989 # define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) 3990 #else 3991 # define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter() 3992 #endif // ELPP_DEBUG_LOG 3993 #if ELPP_ERROR_LOG 3994 # define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__) 3995 #else 3996 # define CERROR(writer, dispatchAction, ...) el::base::NullWriter() 3997 #endif // ELPP_ERROR_LOG 3998 #if ELPP_FATAL_LOG 3999 # define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__) 4000 #else 4001 # define CFATAL(writer, dispatchAction, ...) el::base::NullWriter() 4002 #endif // ELPP_FATAL_LOG 4003 #if ELPP_TRACE_LOG 4004 # define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__) 4005 #else 4006 # define CTRACE(writer, dispatchAction, ...) el::base::NullWriter() 4007 #endif // ELPP_TRACE_LOG 4008 #if ELPP_VERBOSE_LOG 4009 # define CVERBOSE(writer, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel)) writer(\ 4010 el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) 4011 #else 4012 # define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter() 4013 #endif // ELPP_VERBOSE_LOG 4014 // Conditional logs 4015 #if ELPP_INFO_LOG 4016 # define CINFO_IF(writer, condition_, dispatchAction, ...) \ 4017 ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__) 4018 #else 4019 # define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() 4020 #endif // ELPP_INFO_LOG 4021 #if ELPP_WARNING_LOG 4022 # define CWARNING_IF(writer, condition_, dispatchAction, ...)\ 4023 ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__) 4024 #else 4025 # define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() 4026 #endif // ELPP_WARNING_LOG 4027 #if ELPP_DEBUG_LOG 4028 # define CDEBUG_IF(writer, condition_, dispatchAction, ...)\ 4029 ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__) 4030 #else 4031 # define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() 4032 #endif // ELPP_DEBUG_LOG 4033 #if ELPP_ERROR_LOG 4034 # define CERROR_IF(writer, condition_, dispatchAction, ...)\ 4035 ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__) 4036 #else 4037 # define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() 4038 #endif // ELPP_ERROR_LOG 4039 #if ELPP_FATAL_LOG 4040 # define CFATAL_IF(writer, condition_, dispatchAction, ...)\ 4041 ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__) 4042 #else 4043 # define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() 4044 #endif // ELPP_FATAL_LOG 4045 #if ELPP_TRACE_LOG 4046 # define CTRACE_IF(writer, condition_, dispatchAction, ...)\ 4047 ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__) 4048 #else 4049 # define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() 4050 #endif // ELPP_TRACE_LOG 4051 #if ELPP_VERBOSE_LOG 4052 # define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel) && (condition_)) writer( \ 4053 el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) 4054 #else 4055 # define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter() 4056 #endif // ELPP_VERBOSE_LOG 4057 // Occasional logs 4058 #if ELPP_INFO_LOG 4059 # define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\ 4060 ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) 4061 #else 4062 # define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() 4063 #endif // ELPP_INFO_LOG 4064 #if ELPP_WARNING_LOG 4065 # define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\ 4066 ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) 4067 #else 4068 # define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() 4069 #endif // ELPP_WARNING_LOG 4070 #if ELPP_DEBUG_LOG 4071 # define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\ 4072 ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) 4073 #else 4074 # define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() 4075 #endif // ELPP_DEBUG_LOG 4076 #if ELPP_ERROR_LOG 4077 # define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\ 4078 ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) 4079 #else 4080 # define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() 4081 #endif // ELPP_ERROR_LOG 4082 #if ELPP_FATAL_LOG 4083 # define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\ 4084 ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) 4085 #else 4086 # define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() 4087 #endif // ELPP_FATAL_LOG 4088 #if ELPP_TRACE_LOG 4089 # define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\ 4090 ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) 4091 #else 4092 # define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() 4093 #endif // ELPP_TRACE_LOG 4094 #if ELPP_VERBOSE_LOG 4095 # define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...)\ 4096 CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__) 4097 #else 4098 # define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter() 4099 #endif // ELPP_VERBOSE_LOG 4100 // After N logs 4101 #if ELPP_INFO_LOG 4102 # define CINFO_AFTER_N(writer, n, dispatchAction, ...)\ 4103 ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) 4104 #else 4105 # define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() 4106 #endif // ELPP_INFO_LOG 4107 #if ELPP_WARNING_LOG 4108 # define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\ 4109 ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) 4110 #else 4111 # define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() 4112 #endif // ELPP_WARNING_LOG 4113 #if ELPP_DEBUG_LOG 4114 # define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\ 4115 ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) 4116 #else 4117 # define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() 4118 #endif // ELPP_DEBUG_LOG 4119 #if ELPP_ERROR_LOG 4120 # define CERROR_AFTER_N(writer, n, dispatchAction, ...)\ 4121 ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) 4122 #else 4123 # define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() 4124 #endif // ELPP_ERROR_LOG 4125 #if ELPP_FATAL_LOG 4126 # define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\ 4127 ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) 4128 #else 4129 # define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() 4130 #endif // ELPP_FATAL_LOG 4131 #if ELPP_TRACE_LOG 4132 # define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\ 4133 ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) 4134 #else 4135 # define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() 4136 #endif // ELPP_TRACE_LOG 4137 #if ELPP_VERBOSE_LOG 4138 # define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...)\ 4139 CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) 4140 #else 4141 # define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() 4142 #endif // ELPP_VERBOSE_LOG 4143 // N Times logs 4144 #if ELPP_INFO_LOG 4145 # define CINFO_N_TIMES(writer, n, dispatchAction, ...)\ 4146 ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) 4147 #else 4148 # define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() 4149 #endif // ELPP_INFO_LOG 4150 #if ELPP_WARNING_LOG 4151 # define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\ 4152 ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) 4153 #else 4154 # define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() 4155 #endif // ELPP_WARNING_LOG 4156 #if ELPP_DEBUG_LOG 4157 # define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\ 4158 ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) 4159 #else 4160 # define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() 4161 #endif // ELPP_DEBUG_LOG 4162 #if ELPP_ERROR_LOG 4163 # define CERROR_N_TIMES(writer, n, dispatchAction, ...)\ 4164 ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) 4165 #else 4166 # define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() 4167 #endif // ELPP_ERROR_LOG 4168 #if ELPP_FATAL_LOG 4169 # define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\ 4170 ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) 4171 #else 4172 # define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() 4173 #endif // ELPP_FATAL_LOG 4174 #if ELPP_TRACE_LOG 4175 # define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\ 4176 ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) 4177 #else 4178 # define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() 4179 #endif // ELPP_TRACE_LOG 4180 #if ELPP_VERBOSE_LOG 4181 # define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...)\ 4182 CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) 4183 #else 4184 # define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() 4185 #endif // ELPP_VERBOSE_LOG 4186 // 4187 // Custom Loggers - Requires (level, dispatchAction, loggerId/s) 4188 // 4189 // undef existing 4190 #undef CLOG 4191 #undef CLOG_VERBOSE 4192 #undef CVLOG 4193 #undef CLOG_IF 4194 #undef CLOG_VERBOSE_IF 4195 #undef CVLOG_IF 4196 #undef CLOG_EVERY_N 4197 #undef CVLOG_EVERY_N 4198 #undef CLOG_AFTER_N 4199 #undef CVLOG_AFTER_N 4200 #undef CLOG_N_TIMES 4201 #undef CVLOG_N_TIMES 4202 // Normal logs 4203 #define CLOG(LEVEL, ...)\ 4204 C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4205 #define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4206 // Conditional logs 4207 #define CLOG_IF(condition, LEVEL, ...)\ 4208 C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4209 #define CVLOG_IF(condition, vlevel, ...)\ 4210 CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4211 // Hit counts based logs 4212 #define CLOG_EVERY_N(n, LEVEL, ...)\ 4213 C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4214 #define CVLOG_EVERY_N(n, vlevel, ...)\ 4215 CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4216 #define CLOG_AFTER_N(n, LEVEL, ...)\ 4217 C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4218 #define CVLOG_AFTER_N(n, vlevel, ...)\ 4219 CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4220 #define CLOG_N_TIMES(n, LEVEL, ...)\ 4221 C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4222 #define CVLOG_N_TIMES(n, vlevel, ...)\ 4223 CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4224 // 4225 // Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros 4226 // 4227 // undef existing 4228 #undef LOG 4229 #undef VLOG 4230 #undef LOG_IF 4231 #undef VLOG_IF 4232 #undef LOG_EVERY_N 4233 #undef VLOG_EVERY_N 4234 #undef LOG_AFTER_N 4235 #undef VLOG_AFTER_N 4236 #undef LOG_N_TIMES 4237 #undef VLOG_N_TIMES 4238 #undef ELPP_CURR_FILE_LOGGER_ID 4239 #if defined(ELPP_DEFAULT_LOGGER) 4240 # define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER 4241 #else 4242 # define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId 4243 #endif 4244 #undef ELPP_TRACE 4245 #define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID) 4246 // Normal logs 4247 #define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4248 #define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) 4249 // Conditional logs 4250 #define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4251 #define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4252 // Hit counts based logs 4253 #define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4254 #define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4255 #define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4256 #define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4257 #define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4258 #define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4259 // Generic PLOG() 4260 #undef CPLOG 4261 #undef CPLOG_IF 4262 #undef PLOG 4263 #undef PLOG_IF 4264 #undef DCPLOG 4265 #undef DCPLOG_IF 4266 #undef DPLOG 4267 #undef DPLOG_IF 4268 #define CPLOG(LEVEL, ...)\ 4269 C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4270 #define CPLOG_IF(condition, LEVEL, ...)\ 4271 C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4272 #define DCPLOG(LEVEL, ...)\ 4273 if (ELPP_DEBUG_LOG) C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) 4274 #define DCPLOG_IF(condition, LEVEL, ...)\ 4275 C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__) 4276 #define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4277 #define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4278 #define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4279 #define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4280 // Generic SYSLOG() 4281 #undef CSYSLOG 4282 #undef CSYSLOG_IF 4283 #undef CSYSLOG_EVERY_N 4284 #undef CSYSLOG_AFTER_N 4285 #undef CSYSLOG_N_TIMES 4286 #undef SYSLOG 4287 #undef SYSLOG_IF 4288 #undef SYSLOG_EVERY_N 4289 #undef SYSLOG_AFTER_N 4290 #undef SYSLOG_N_TIMES 4291 #undef DCSYSLOG 4292 #undef DCSYSLOG_IF 4293 #undef DCSYSLOG_EVERY_N 4294 #undef DCSYSLOG_AFTER_N 4295 #undef DCSYSLOG_N_TIMES 4296 #undef DSYSLOG 4297 #undef DSYSLOG_IF 4298 #undef DSYSLOG_EVERY_N 4299 #undef DSYSLOG_AFTER_N 4300 #undef DSYSLOG_N_TIMES 4301 #if defined(ELPP_SYSLOG) 4302 # define CSYSLOG(LEVEL, ...)\ 4303 C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) 4304 # define CSYSLOG_IF(condition, LEVEL, ...)\ 4305 C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__) 4306 # define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) 4307 # define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) 4308 # define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) 4309 # define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) 4310 # define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) 4311 # define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) 4312 # define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) 4313 # define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) 4314 # define DCSYSLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) 4315 # define DCSYSLOG_IF(condition, LEVEL, ...)\ 4316 C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__) 4317 # define DCSYSLOG_EVERY_N(n, LEVEL, ...)\ 4318 if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) 4319 # define DCSYSLOG_AFTER_N(n, LEVEL, ...)\ 4320 if (ELPP_DEBUG_LOG) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) 4321 # define DCSYSLOG_N_TIMES(n, LEVEL, ...)\ 4322 if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) 4323 # define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) 4324 # define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) 4325 # define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) 4326 # define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) 4327 # define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) 4328 #else 4329 # define CSYSLOG(LEVEL, ...) el::base::NullWriter() 4330 # define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() 4331 # define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() 4332 # define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() 4333 # define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() 4334 # define SYSLOG(LEVEL) el::base::NullWriter() 4335 # define SYSLOG_IF(condition, LEVEL) el::base::NullWriter() 4336 # define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() 4337 # define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() 4338 # define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() 4339 # define DCSYSLOG(LEVEL, ...) el::base::NullWriter() 4340 # define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() 4341 # define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() 4342 # define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() 4343 # define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() 4344 # define DSYSLOG(LEVEL) el::base::NullWriter() 4345 # define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter() 4346 # define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() 4347 # define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() 4348 # define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() 4349 #endif // defined(ELPP_SYSLOG) 4350 // 4351 // Custom Debug Only Loggers - Requires (level, loggerId/s) 4352 // 4353 // undef existing 4354 #undef DCLOG 4355 #undef DCVLOG 4356 #undef DCLOG_IF 4357 #undef DCVLOG_IF 4358 #undef DCLOG_EVERY_N 4359 #undef DCVLOG_EVERY_N 4360 #undef DCLOG_AFTER_N 4361 #undef DCVLOG_AFTER_N 4362 #undef DCLOG_N_TIMES 4363 #undef DCVLOG_N_TIMES 4364 // Normal logs 4365 #define DCLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG(LEVEL, __VA_ARGS__) 4366 #define DCLOG_VERBOSE(vlevel, ...) if (ELPP_DEBUG_LOG) CLOG_VERBOSE(vlevel, __VA_ARGS__) 4367 #define DCVLOG(vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG(vlevel, __VA_ARGS__) 4368 // Conditional logs 4369 #define DCLOG_IF(condition, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_IF(condition, LEVEL, __VA_ARGS__) 4370 #define DCVLOG_IF(condition, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_IF(condition, vlevel, __VA_ARGS__) 4371 // Hit counts based logs 4372 #define DCLOG_EVERY_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_EVERY_N(n, LEVEL, __VA_ARGS__) 4373 #define DCVLOG_EVERY_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_EVERY_N(n, vlevel, __VA_ARGS__) 4374 #define DCLOG_AFTER_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_AFTER_N(n, LEVEL, __VA_ARGS__) 4375 #define DCVLOG_AFTER_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_AFTER_N(n, vlevel, __VA_ARGS__) 4376 #define DCLOG_N_TIMES(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_N_TIMES(n, LEVEL, __VA_ARGS__) 4377 #define DCVLOG_N_TIMES(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_N_TIMES(n, vlevel, __VA_ARGS__) 4378 // 4379 // Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros 4380 // 4381 #if !defined(ELPP_NO_DEBUG_MACROS) 4382 // undef existing 4383 #undef DLOG 4384 #undef DVLOG 4385 #undef DLOG_IF 4386 #undef DVLOG_IF 4387 #undef DLOG_EVERY_N 4388 #undef DVLOG_EVERY_N 4389 #undef DLOG_AFTER_N 4390 #undef DVLOG_AFTER_N 4391 #undef DLOG_N_TIMES 4392 #undef DVLOG_N_TIMES 4393 // Normal logs 4394 #define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4395 #define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) 4396 // Conditional logs 4397 #define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4398 #define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4399 // Hit counts based logs 4400 #define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4401 #define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4402 #define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4403 #define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4404 #define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) 4405 #define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) 4406 #endif // defined(ELPP_NO_DEBUG_MACROS) 4407 #if !defined(ELPP_NO_CHECK_MACROS) 4408 // Check macros 4409 #undef CCHECK 4410 #undef CPCHECK 4411 #undef CCHECK_EQ 4412 #undef CCHECK_NE 4413 #undef CCHECK_LT 4414 #undef CCHECK_GT 4415 #undef CCHECK_LE 4416 #undef CCHECK_GE 4417 #undef CCHECK_BOUNDS 4418 #undef CCHECK_NOTNULL 4419 #undef CCHECK_STRCASEEQ 4420 #undef CCHECK_STRCASENE 4421 #undef CHECK 4422 #undef PCHECK 4423 #undef CHECK_EQ 4424 #undef CHECK_NE 4425 #undef CHECK_LT 4426 #undef CHECK_GT 4427 #undef CHECK_LE 4428 #undef CHECK_GE 4429 #undef CHECK_BOUNDS 4430 #undef CHECK_NOTNULL 4431 #undef CHECK_STRCASEEQ 4432 #undef CHECK_STRCASENE 4433 #define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " 4434 #define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " 4435 #define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) 4436 #define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) 4437 #define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__) 4438 #define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__) 4439 #define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__) 4440 #define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__) 4441 #define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__) 4442 #define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__) 4443 #define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__) 4444 #define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) 4445 #define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) 4446 #define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) 4447 #define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) 4448 #define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) 4449 #define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) 4450 #define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) 4451 #define CCHECK_NOTNULL(ptr, ...) CCHECK((ptr) != nullptr, __VA_ARGS__) 4452 #define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ 4453 << "Check failed: [" << #str1 << " == " << #str2 << "] " 4454 #define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ 4455 << "Check failed: [" << #str1 << " != " << #str2 << "] " 4456 #define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ 4457 << "Check failed: [" << #str1 << " == " << #str2 << "] " 4458 #define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ 4459 << "Check failed: [" << #str1 << " != " << #str2 << "] " 4460 #define CHECK_NOTNULL(ptr) CCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) 4461 #define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4462 #define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4463 #define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4464 #define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4465 #undef DCCHECK 4466 #undef DCCHECK_EQ 4467 #undef DCCHECK_NE 4468 #undef DCCHECK_LT 4469 #undef DCCHECK_GT 4470 #undef DCCHECK_LE 4471 #undef DCCHECK_GE 4472 #undef DCCHECK_BOUNDS 4473 #undef DCCHECK_NOTNULL 4474 #undef DCCHECK_STRCASEEQ 4475 #undef DCCHECK_STRCASENE 4476 #undef DCPCHECK 4477 #undef DCHECK 4478 #undef DCHECK_EQ 4479 #undef DCHECK_NE 4480 #undef DCHECK_LT 4481 #undef DCHECK_GT 4482 #undef DCHECK_LE 4483 #undef DCHECK_GE 4484 #undef DCHECK_BOUNDS_ 4485 #undef DCHECK_NOTNULL 4486 #undef DCHECK_STRCASEEQ 4487 #undef DCHECK_STRCASENE 4488 #undef DPCHECK 4489 #define DCCHECK(condition, ...) if (ELPP_DEBUG_LOG) CCHECK(condition, __VA_ARGS__) 4490 #define DCCHECK_EQ(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_EQ(a, b, __VA_ARGS__) 4491 #define DCCHECK_NE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_NE(a, b, __VA_ARGS__) 4492 #define DCCHECK_LT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LT(a, b, __VA_ARGS__) 4493 #define DCCHECK_GT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GT(a, b, __VA_ARGS__) 4494 #define DCCHECK_LE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LE(a, b, __VA_ARGS__) 4495 #define DCCHECK_GE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GE(a, b, __VA_ARGS__) 4496 #define DCCHECK_BOUNDS(val, min, max, ...) if (ELPP_DEBUG_LOG) CCHECK_BOUNDS(val, min, max, __VA_ARGS__) 4497 #define DCCHECK_NOTNULL(ptr, ...) if (ELPP_DEBUG_LOG) CCHECK_NOTNULL((ptr), __VA_ARGS__) 4498 #define DCCHECK_STREQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STREQ(str1, str2, __VA_ARGS__) 4499 #define DCCHECK_STRNE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRNE(str1, str2, __VA_ARGS__) 4500 #define DCCHECK_STRCASEEQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__) 4501 #define DCCHECK_STRCASENE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASENE(str1, str2, __VA_ARGS__) 4502 #define DCPCHECK(condition, ...) if (ELPP_DEBUG_LOG) CPCHECK(condition, __VA_ARGS__) 4503 #define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) 4504 #define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) 4505 #define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) 4506 #define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) 4507 #define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) 4508 #define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) 4509 #define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) 4510 #define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) 4511 #define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) 4512 #define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4513 #define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4514 #define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4515 #define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) 4516 #define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) 4517 #endif // defined(ELPP_NO_CHECK_MACROS) 4518 #if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) 4519 # define ELPP_USE_DEF_CRASH_HANDLER false 4520 #else 4521 # define ELPP_USE_DEF_CRASH_HANDLER true 4522 #endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) 4523 #define ELPP_CRASH_HANDLER_INIT 4524 #define ELPP_INIT_EASYLOGGINGPP(val) \ 4525 namespace el { \ 4526 namespace base { \ 4527 el::base::type::StoragePointer elStorage(val); \ 4528 } \ 4529 el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); \ 4530 } 4531 4532 #if ELPP_ASYNC_LOGGING 4533 # define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\ 4534 new el::base::AsyncDispatchWorker())) 4535 #else 4536 # define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) 4537 #endif // ELPP_ASYNC_LOGGING 4538 #define INITIALIZE_NULL_EASYLOGGINGPP \ 4539 namespace el {\ 4540 namespace base {\ 4541 el::base::type::StoragePointer elStorage;\ 4542 }\ 4543 el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ 4544 } 4545 #define SHARE_EASYLOGGINGPP(initializedStorage)\ 4546 namespace el {\ 4547 namespace base {\ 4548 el::base::type::StoragePointer elStorage(initializedStorage);\ 4549 }\ 4550 el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ 4551 } 4552 4553 #if defined(ELPP_UNICODE) 4554 # define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv); std::locale::global(std::locale("")) 4555 #else 4556 # define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv) 4557 #endif // defined(ELPP_UNICODE) 4558 #endif // EASYLOGGINGPP_H