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