Go to the documentation of this file.
65 #ifndef JOURNALLERBASE_H
66 #define JOURNALLERBASE_H
135 std::string
tag()
const;
176 #if 1 && (defined(MSC_VER) || 1) // add exceptions to compilers here that do not (yet) support constexpr. These will fall back to the full path. If the first 1 is set to 0, no path stripping will be done in any case.
185 #define STRIPPEDFILE jlStrippedPathFile(__FILE__)
187 #define STRIPPEDFILE __FILE__
190 #if !defined(JLNOLINEINFO)
191 #define JLGENERIC_LINEINFO STRIPPEDFILE << "(" << __LINE__ << ") "
193 #define JLGENERIC_LINEINFO ""
196 #define JLGENERIC(journal, level, msg)\
198 if (journal && journal->logLevel(level)) \
200 std::ostringstream os; \
201 os << JLGENERIC_LINEINFO << __FUNCTION__ << " " << msg; \
202 journal->log(level, os.str()); \
204 if (Journaller::hasAdditionalLogger() && Journaller::additionalLogger()->logLevel(level)) \
206 std::ostringstream os; \
208 Journaller::additionalLogger()->log(level, STRIPPEDFILE, __LINE__, __FUNCTION__, os.str()); \
212 #define JLGENERIC_NODEC(journal, level, msg)\
214 if (journal && journal->logLevel(level)) \
216 std::ostringstream os; \
218 journal->writeMessage(os.str()); \
220 if (Journaller::hasAdditionalLogger() && Journaller::additionalLogger()->logLevel(level)) \
222 std::ostringstream os; \
224 Journaller::additionalLogger()->logNoDecoration(level, STRIPPEDFILE, __LINE__, __FUNCTION__, os.str()); \
228 #if !defined(JLDEBUG)
230 #if JLDEF_BUILD > JLL_TRACE
231 #define JLTRACE(...) ((void)0)
232 #define JLTRACE_NODEC(...) ((void)0)
234 #define JLTRACE(journal, msg) JLGENERIC(journal, JLL_Trace, msg)
235 #define JLTRACE_NODEC(journal, msg) JLGENERIC_NODEC(journal, JLL_Trace, msg)
238 #if JLDEF_BUILD > JLL_DEBUG
239 #define JLDEBUG(...) ((void)0)
240 #define JLDEBUG_NODEC(...) ((void)0)
242 #define JLDEBUG(journal, msg) JLGENERIC(journal, JLL_Debug, msg)
243 #define JLDEBUG_NODEC(journal, msg) JLGENERIC_NODEC(journal, JLL_Debug, msg)
246 #if JLDEF_BUILD > JLL_ALERT
247 #define JLALERT(...) ((void)0)
248 #define JLALERT_NODEC(...) ((void)0)
250 #define JLALERT(journal, msg) JLGENERIC(journal, JLL_Alert, msg)
251 #define JLALERT_NODEC(journal, msg) JLGENERIC_NODEC(journal, JLL_Alert, msg)
254 #if JLDEF_BUILD > JLL_ERROR
255 #define JLERROR(...) ((void)0)
256 #define JLERROR_NODEC(...) ((void)0)
258 #define JLERROR(journal, msg) JLGENERIC(journal, JLL_Error, msg)
259 #define JLERROR_NODEC(journal, msg) JLGENERIC_NODEC(journal, JLL_Error, msg)
262 #if JLDEF_BUILD > JLL_FATAL
263 #define JLFATAL(...) ((void)0)
264 #define JLFATAL_NODEC(...) ((void)0)
266 #define JLFATAL(journal, msg) JLGENERIC(journal, JLL_Fatal, msg)
267 #define JLFATAL_NODEC(journal, msg) JLGENERIC_NODEC(journal, JLL_Fatal, msg)
270 #if JLDEF_BUILD > JLL_WRITE
271 #define JLWRITE(...) ((void)0)
272 #define JLWRITE_NODEC(...) ((void)0)
274 #define JLWRITE(journal, msg) JLGENERIC(journal, JLL_Write, msg)
275 #define JLWRITE_NODEC(journal, msg) JLGENERIC_NODEC(journal, JLL_Write, msg)
279 #define JLTRACEG(msg) JLTRACE(gJournal, msg)
280 #define JLDEBUGG(msg) JLDEBUG(gJournal, msg)
281 #define JLALERTG(msg) JLALERT(gJournal, msg)
282 #define JLERRORG(msg) JLERROR(gJournal, msg)
283 #define JLFATALG(msg) JLFATAL(gJournal, msg)
284 #define JLWRITEG(msg) JLWRITE(gJournal, msg)
288 #define JLFINALNAME(a) #a ": "
289 #define JLFINALVALUE(journal, level, a) JournalValueJanitor<decltype(a)> jlFinalValue ## a(journal, a, [](char const* fi, char const* fu, char const* va) { std::stringstream os; os << fi << " " << fu << " exit " << va; return os.str(); }(__FILE__, __FUNCTION__, JLFINALNAME(a)), level, true)
290 #define JLWRITEFINAL(journal, a) JLFINALVALUE(journal, JLL_Write, a)
291 #define JLWRITEFINALG(a) JLWRITEFINAL(gJournal, a)
292 #define JLDEBUGFINAL(journal, a) JLFINALVALUE(journal, JLL_Debug, a)
293 #define JLDEBUGFINALG(a) JLDEBUGFINAL(gJournal, a)
297 #ifndef _lint //pclint defines this
298 #define JLIF(journal, level, todo) do { if (journal && journal->logLevel(level)) { todo; } } while(0)
300 #define JLIF(...) ((void)0)
303 #ifndef JL_NOTEMPLATE
308 template <
typename T>
322 template <
typename T>
325 std::ios_base::fmtflags
f = os.flags();
326 os << std::hex << std::uppercase << hex.
m_value << std::setiosflags(
f);
331 #define JLHEXLOG_BARE(d) JlHexLogger<decltype(d)>(d) // C++0x11 only!
333 #define JLHEXLOG_BARE(d) std::hex << std::uppercase << (int) d << std::nouppercase << std::dec
335 #define JLHEXLOG(d) "0x" << JLHEXLOG_BARE(d)
336 #define JLVARLOG(a) #a ": " << a << " "
338 #define JLPRECISE2(msg, prec)\
340 std::ostringstream os; \
341 os.precision(prec); \
345 #define JLPRECISE(msg) JLPRECISE2(msg, 16)
347 #define JLCASE2(s, a, b) case a: s << b << "(" << static_cast<int>(a) << ")"; break;
348 #define JLCASE(s, a) case a: s << #a << "(" << static_cast<int>(a) << ")"; break;
349 #define JLDEFAULTCASE(s) default: s << "Unknown case: " << static_cast<int>(e); break;
350 #define JLENUMEXPPROTO(E) std::ostream& operator << (std::ostream& dbg, E const& e)
351 #define JLENUMEXPHDR(E, ...) JLENUMEXPPROTO(E) { __VA_ARGS__ switch(e) {
352 #define JLENUMCASE(a) JLCASE(dbg, a)
353 #define JLENUMCASE2(a, b) JLCASE2(dbg, a, b)
354 #define JLENUMEXPFTR(...) JLDEFAULTCASE(dbg) } __VA_ARGS__ return dbg; }
357 #define JLENUMEXPANDER(E, items) JLENUMEXPHDR(E) items JLENUMEXPFTR()
361 #define JLENUMEXPANDERHEX(E, items) JLENUMEXPHDR(E, dbg << std::hex << std::uppercase;) items JLENUMEXPFTR(dbg << std::dec << std::nouppercase;)
365 #define JLENUMEXPANDERBITS(E, items) JLENUMEXPPROTO(E) { bool first = true; dbg << std::hex << std::uppercase << static_cast<int>(e) << "="; items if (first) dbg << "<None>"; dbg << std::dec << std::nouppercase; return dbg; }
366 #define JLENUMCASEBITS(a) if ((static_cast<int>(e) & static_cast<int>(a)) == static_cast<int>(a)) { if (first) first = false; else dbg << " | "; dbg << #a << "(" << static_cast<int>(a) << ")"; }
367 #define JLENUMCASEBITSNONE(a) if (first) { dbg << #a << "(0)"; first = false; }
369 #define JLQTDEBUGHANDLER \
370 QtMessageHandler gOldQtMessageHandler = nullptr; \
371 Journaller* qtJournal = nullptr; \
372 QtMessageHandler qtChecker = nullptr; \
373 void jlQtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {\
374 if (qtChecker) qtChecker(type, context, msg); \
375 if (!qtJournal) return;\
378 JLDEBUG(qtJournal, (const char *)msg.toLatin1());\
381 JLALERT(qtJournal, (const char *)msg.toLatin1());\
384 JLERROR(qtJournal, (const char *)msg.toLatin1());\
387 JLFATAL(qtJournal, (const char *)msg.toLatin1());\
392 if (gOldQtMessageHandler)\
393 gOldQtMessageHandler(type,context,msg);\
396 #define JLINSTALLQTDEBUGHANDLER(journal) \
397 qtJournal = journal;\
399 if (gOldQtMessageHandler == NULL) gOldQtMessageHandler = qInstallMessageHandler(jlQtMessageHandler);\
400 else qInstallMessageHandler(jlQtMessageHandler);\
401 } else if (gOldQtMessageHandler) {\
402 qInstallMessageHandler(gOldQtMessageHandler);\
403 gOldQtMessageHandler = NULL;\
414 template <
typename T =
int>
443 std::stringstream os;
~JournalValueJanitor()
Destructor.
void writeFileHeader(const std::string &appName)
Write a header for the log file including some meta-data about the journaller.
static void setAdditionalLogger(AbstractAdditionalLogger *additionalLogger)
Sets the additional logger.
JournalLogLevel m_debugLevel
JournalLogLevel flushLevel() const
void cleanupThread()
Removes stored information on the current thread after flushing all data.
void moveLogFile(const XsString &pathfile, bool purge=true, bool eraseOld=true)
Move the log file to the supplied path, keeping current contents intact.
void writeTime()
Write the current time to the file.
void moveLogs(Journaller *target, bool eraseOld=true)
Copy the contents of the current log file to target.
bool logLevel(JournalLogLevel level) const
Compares a log/debug level with a set one.
static constexpr char const * jlStrippedPathFile(char const *a)
void setUseDateTime(bool yes)
When setting the Date Time to yes, the timestamps are translated from unix timestamp into a redable d...
~Journaller()
Destructor, detaches from the logfile and closes it if this was the last reference.
JournalLogLevel logLevel() const
void jlTerminate(Journaller **gj)
Cleans up any remaining stuff.
void writeMessage(const std::string &msg)
Write msg to the file without decoration or added newline.
@ JLL_Alert
only log fatal, error and alert messages
bool m_enabled
Boolean value if set to true then the janitor is enabled.
A class containing a journal file and some meta-data.
@ JLL_Debug
log all messages, except function entry/exit (trace)
A journalling class for debugging applications.
Class for journalling a referenced value when the janitor leaves scope.
JournalLogLevel m_flushLevel
std::shared_ptr< JournalFile > m_file
static constexpr char const * jlStrippedPath(char const *a, char const *b)
A support class of journaller that is used for the logging of hex values.
std::shared_ptr< JournalThreader > m_threader
static AbstractAdditionalLogger * m_additionalLogger
The optional additional logger.
const JournalValueJanitor & operator=(const JournalValueJanitor &)
void flushLine()
Flush any data currently queued for logging to the file buffer.
std::ostream & operator<<(std::ostream &os, JlHexLogger< T > const &hex)
Journaller & operator=(Journaller const &)=delete
static bool hasAdditionalLogger()
JournalLogLevel debugLevel() const
void writeThread()
Write the current time to the file.
void setTag(const std::string &tag)
Set a tag to be added before the log level tag in each log file.
Journaller(const XsString &pathfile, bool purge=true, JournalLogLevel initialLogLevel=JLL_Alert)
Constructor.
void setDebugLevel(JournalLogLevel level, bool writeLogLine=true)
Set the log level for logging to debug output.
static AbstractAdditionalLogger * additionalLogger()
void log(JournalLogLevel level, const std::string &msg)
Write a log message to the file if level is at least equal to the current log level.
static std::string tagFromFilename(const std::string &fn)
void writeCallstack(JournalLogLevel level)
Write the current callstack to the file if level is at least equal to the current log level.
void setLogLevel(JournalLogLevel level, bool writeLogLine=true)
Set the log level for logging to file.
void setFlushLevel(JournalLogLevel level, bool writeLogLine=true)
Set level threshold for automatically flushing lines to disk.
void writeTag()
Write the tag to the file.
void flush()
Flush any data to disk.
void writeLevel(JournalLogLevel level)
Write the supplied log level to the file.
A 0-terminated managed string of characters.
void init(XsString const &pathfile, bool purge)
Initialize the Journaller by (re-)creating the internal journal file.
const XsString filename() const
Returns the filename of the used journal file.
Manages threaded writes for the Journaller objects.
JlHexLogger(T i)
Constructor.