1 /*
2   Copyright (c) 2012 Boris Moiseev (cyberbobs at gmail dot com)
3 
4   This program is free software: you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License version 2.1
6   as published by the Free Software Foundation and appearing in the file
7   LICENSE.LGPL included in the packaging of this file.
8 
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU Lesser General Public License for more details.
13 */
14 #ifndef LOGGER_H
15 #define LOGGER_H
16 
17 // Qt
18 #include <QString>
19 #include <QDebug>
20 #include <QDateTime>
21 
22 // Local
23 #include "CuteLogger_global.h"
24 class AbstractAppender;
25 
26 
27 class Logger;
28 CUTELOGGERSHARED_EXPORT Logger* cuteLoggerInstance();
29 #define cuteLogger cuteLoggerInstance()
30 
31 
32 #define LOG_TRACE            CuteMessageLogger(cuteLoggerInstance(), Logger::Trace,   __FILE__, __LINE__, Q_FUNC_INFO).write
33 #define LOG_DEBUG            CuteMessageLogger(cuteLoggerInstance(), Logger::Debug,   __FILE__, __LINE__, Q_FUNC_INFO).write
34 #define LOG_INFO             CuteMessageLogger(cuteLoggerInstance(), Logger::Info,    __FILE__, __LINE__, Q_FUNC_INFO).write
35 #define LOG_WARNING          CuteMessageLogger(cuteLoggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO).write
36 #define LOG_ERROR            CuteMessageLogger(cuteLoggerInstance(), Logger::Error,   __FILE__, __LINE__, Q_FUNC_INFO).write
37 #define LOG_FATAL            CuteMessageLogger(cuteLoggerInstance(), Logger::Fatal,   __FILE__, __LINE__, Q_FUNC_INFO).write
38 
39 #define LOG_CTRACE(category)   CuteMessageLogger(cuteLoggerInstance(), Logger::Trace,   __FILE__, __LINE__, Q_FUNC_INFO, category).write()
40 #define LOG_CDEBUG(category)   CuteMessageLogger(cuteLoggerInstance(), Logger::Debug,   __FILE__, __LINE__, Q_FUNC_INFO, category).write()
41 #define LOG_CINFO(category)    CuteMessageLogger(cuteLoggerInstance(), Logger::Info,    __FILE__, __LINE__, Q_FUNC_INFO, category).write()
42 #define LOG_CWARNING(category) CuteMessageLogger(cuteLoggerInstance(), Logger::Warning, __FILE__, __LINE__, Q_FUNC_INFO, category).write()
43 #define LOG_CERROR(category)   CuteMessageLogger(cuteLoggerInstance(), Logger::Error,   __FILE__, __LINE__, Q_FUNC_INFO, category).write()
44 #define LOG_CFATAL(category)   CuteMessageLogger(cuteLoggerInstance(), Logger::Fatal,   __FILE__, __LINE__, Q_FUNC_INFO, category).write()
45 
46 #define LOG_TRACE_TIME  LoggerTimingHelper loggerTimingHelper(cuteLoggerInstance(), Logger::Trace, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
47 #define LOG_DEBUG_TIME  LoggerTimingHelper loggerTimingHelper(cuteLoggerInstance(), Logger::Debug, __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
48 #define LOG_INFO_TIME   LoggerTimingHelper loggerTimingHelper(cuteLoggerInstance(), Logger::Info,  __FILE__, __LINE__, Q_FUNC_INFO); loggerTimingHelper.start
49 
50 #define LOG_ASSERT(cond)        ((!(cond)) ? cuteLoggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, #cond) : qt_noop())
51 #define LOG_ASSERT_X(cond, msg) ((!(cond)) ? cuteLoggerInstance()->writeAssert(__FILE__, __LINE__, Q_FUNC_INFO, msg) : qt_noop())
52 
53 #define LOG_CATEGORY(category) \
54   private:\
55     Logger* cuteLoggerInstance()\
56     {\
57       static Logger customCuteLoggerInstance(category);\
58       return &customCuteLoggerInstance;\
59     }\
60 
61 #define LOG_GLOBAL_CATEGORY(category) \
62   private:\
63     Logger* cuteLoggerInstance()\
64     {\
65       static Logger customCuteLoggerInstance(category);\
66       customCuteLoggerInstance.logToGlobalInstance(category, true);\
67       return &customCuteLoggerInstance;\
68     }\
69 
70 
71 class LoggerPrivate;
72 class CUTELOGGERSHARED_EXPORT Logger
73 {
74   Q_DISABLE_COPY(Logger)
75 
76   public:
77     Logger();
78     Logger(const QString& defaultCategory);
79     ~Logger();
80 
81     //! Describes the possible severity levels of the log records
82     enum LogLevel
83     {
84       Trace,   //!< Trace level. Can be used for mostly unneeded records used for internal code tracing.
85       Debug,   //!< Debug level. Useful for non-necessary records used for the debugging of the software.
86       Info,    //!< Info level. Can be used for informational records, which may be interesting for not only developers.
87       Warning, //!< Warning. May be used to log some non-fatal warnings detected by your application.
88       Error,   //!< Error. May be used for a big problems making your application work wrong but not crashing.
89       Fatal    //!< Fatal. Used for unrecoverable errors, crashes the application right after the log record is written.
90     };
91 
92     //! Sets the timing display mode for the LOG_TRACE_TIME, LOG_DEBUG_TIME and LOG_INFO_TIME macros
93     enum TimingMode
94     {
95       TimingAuto, //!< Show time in seconds, if it exceeds 10s (default)
96       TimingMs    //!< Always use milliseconds to display
97     };
98 
99     static QString levelToString(LogLevel logLevel);
100     static LogLevel levelFromString(const QString& s);
101 
102     static Logger* globalInstance();
103 
104     void registerAppender(AbstractAppender* appender);
105     void registerCategoryAppender(const QString& category, AbstractAppender* appender);
106 
107     void removeAppender(AbstractAppender* appender);
108 
109     void logToGlobalInstance(const QString& category, bool logToGlobal = false);
110 
111     void setDefaultCategory(const QString& category);
112     QString defaultCategory() const;
113 
114     void write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
115                const QString& message);
116     void write(LogLevel logLevel, const char* file, int line, const char* function, const char* category, const QString& message);
117     QDebug write(LogLevel logLevel, const char* file, int line, const char* function, const char* category);
118 
119     void writeAssert(const char* file, int line, const char* function, const char* condition);
120 
121   private:
122     void write(const QDateTime& timeStamp, LogLevel logLevel, const char* file, int line, const char* function, const char* category,
123                const QString& message, bool fromLocalInstance);
124     Q_DECLARE_PRIVATE(Logger)
125     LoggerPrivate* d_ptr;
126 };
127 
128 
129 class CUTELOGGERSHARED_EXPORT CuteMessageLogger
130 {
131   Q_DISABLE_COPY(CuteMessageLogger)
132 
133   public:
134     Q_DECL_CONSTEXPR CuteMessageLogger(Logger* l, Logger::LogLevel level, const char* file, int line, const char* function)
135         : m_l(l),
136           m_level(level),
137           m_file(file),
138           m_line(line),
139           m_function(function),
140           m_category(0)
141     {}
142 
143     Q_DECL_CONSTEXPR CuteMessageLogger(Logger* l, Logger::LogLevel level, const char* file, int line, const char* function, const char* category)
144         : m_l(l),
145           m_level(level),
146           m_file(file),
147           m_line(line),
148           m_function(function),
149           m_category(category)
150     {}
151 
152     void write(const char* msg, ...) const
153 #if defined(Q_CC_GNU) && !defined(__INSURE__)
154 #  if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
155     __attribute__ ((format (gnu_printf, 2, 3)))
156 #  else
157     __attribute__ ((format (printf, 2, 3)))
158 #  endif
159 #endif
160     ;
161 
162     void write(const QString& msg) const;
163 
164     QDebug write() const;
165 
166   private:
167     Logger* m_l;
168     Logger::LogLevel m_level;
169     const char* m_file;
170     int m_line;
171     const char* m_function;
172     const char* m_category;
173 };
174 
175 
176 class CUTELOGGERSHARED_EXPORT LoggerTimingHelper
177 {
178   Q_DISABLE_COPY(LoggerTimingHelper)
179 
180   public:
181     inline explicit LoggerTimingHelper(Logger* l, Logger::LogLevel logLevel, const char* file, int line,
182                                        const char* function)
183       : m_logger(l),
184         m_logLevel(logLevel),
185         m_timingMode(Logger::TimingAuto),
186         m_file(file),
187         m_line(line),
188         m_function(function)
189     {}
190 
191     void start(const char* msg, ...)
192 #if defined(Q_CC_GNU) && !defined(__INSURE__)
193   #  if defined(Q_CC_MINGW) && !defined(Q_CC_CLANG)
194     __attribute__ ((format (gnu_printf, 2, 3)))
195   #  else
196     __attribute__ ((format (printf, 2, 3)))
197   #  endif
198 #endif
199         ;
200 
201     void start(const QString& msg = QString());
202     void start(Logger::TimingMode mode, const QString& msg);
203 
204     ~LoggerTimingHelper();
205 
206   private:
207     Logger* m_logger;
208     QTime m_time;
209     Logger::LogLevel m_logLevel;
210     Logger::TimingMode m_timingMode;
211     const char* m_file;
212     int m_line;
213     const char* m_function;
214     QString m_block;
215 };
216 
217 
218 #endif // LOGGER_H
219