gnucash/libgnucash/engine/qoflog.h
Geert Janssens 83d14e1c1c Restructure the src directory
It is split into
- /libgnucash (for the non-gui bits)
- /gnucash (for the gui)
- /common (misc source files used by both)
- /bindings (currently only holds python bindings)

This is the first step in restructuring the code. It will need much
more fine tuning later on.
2017-08-10 18:45:00 +02:00

304 lines
9.3 KiB
C

/* qof-log.h
* Author: Rob Clark <rclark@cs.hmc.edu>
* Copyright (C) 1998-2003 Linas Vepstas <linas@linas.org>
* Copyright 2005 Neil Williams <linux@codehelp.co.uk>
* Copyright 2007 Joshua Sled <jsled@asynchronous.org>
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
/**
* @addtogroup Logging
* @{
* @ingroup QOF
* @brief Logging and tracing facility.
* @sa "Logging overhaul" announcement <http://lists.gnucash.org/pipermail/gnucash-devel/2007-February/019836.html>
*
* qof_log_init(void) installs a handler that interprets the "log_domain"
* as a "."-separated path. Log level thresholds can be set for each level
* in the tree. When a message is logged, the longest level match is
* found, and used as the threshold.
*
* For instance, we can set the levels as such:
* @verbatim
"qof" = WARN
"gnc" = WARN
"gnc.ui" = INFO
"gnc.ui.plugin-page.sx-list" = DEBUG
@endverbatim
*
* When code in the log_module of "gnc.import" attempts to log at DEBUG
* (let's say), the handler will attempt to match the log domain to
* successively-longer paths: first "", then "gnc", then "gnc.import". Given
* the settings above, the path "gnc" will match -- at a level of "WARN" --
* and the DEBUG-level log will be rejected. When code in the log domain of
* "gnc.ui.plugin-page.sx-list" logs at DEBUG, however, it will match at
* DEBUG, and be allowed.
*
* The current log format is as above:
*
* @verbatim
* [timestamp] [level] <[log-domain]> [message]
@endverbatim
*
* The timestamp and level are constant width (level is 5 characters). The
* log domain is re-iterated, which gives some context, but could become
* annoying if they get long.
*
* Trailing newlines (e.g. <tt>PINFO("...\n", ...)</tt>) are removed; the logger
* will newline separate output.
*
* @section best Best Practices
*
* Code should:
*
* @li Define both <tt>static QofLogModule log_module</tt> and <tt>#define
* G_LOG_DOMAIN</tt> to the same value.
* @li Define a logical, specific path as the log domain;
* @c "gnc.gui.plugin-pages.sx-list" or
* @c "gnc.register.gnome.cell.quickfill" are
* good examples.
* @li Use glib-provided @c g_debug(...), @c g_message(...),
* @c g_warning(...), @c g_critical(...) and
* @c g_error(...) functions in preference to the historical qof/gnc @c
* PINFO, @c PERR (&c.) macros
*
* @see qof_log_parse_log_config(const char*)
**/
#ifndef _QOF_LOG_H
#define _QOF_LOG_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdarg.h>
#include <stdio.h>
#include <glib.h>
#include "qofutil.h"
#define QOF_MOD_ENGINE "qof.engine"
#define LOG_LEVEL_LIST(_) \
_(QOF_LOG_FATAL, = G_LOG_LEVEL_ERROR) \
_(QOF_LOG_ERROR, = G_LOG_LEVEL_CRITICAL) \
_(QOF_LOG_WARNING, = G_LOG_LEVEL_WARNING) \
_(QOF_LOG_MESSAGE, = G_LOG_LEVEL_MESSAGE) \
_(QOF_LOG_INFO, = G_LOG_LEVEL_INFO) \
_(QOF_LOG_DEBUG, = G_LOG_LEVEL_DEBUG)
DEFINE_ENUM (QofLogLevel, LOG_LEVEL_LIST)
const char* qof_log_level_to_string(QofLogLevel lvl);
QofLogLevel qof_log_level_from_string(const char *str);
/** Indents one level; see ENTER macro. **/
void qof_log_indent(void);
/**
* De-dent one level, capped at 0; see LEAVE macro.
**/
void qof_log_dedent(void);
/**
* Initialize the error logging subsystem. Defaults to a level-threshold of
* "warning", and logging to stderr.
**/
void qof_log_init (void);
/** Set the logging level of the given log_module. **/
void qof_log_set_level(QofLogModule module, QofLogLevel level);
/** Specify an alternate log output, to pipe or file. **/
void qof_log_set_file (FILE *outfile);
/** Specify a filename for log output. **/
void qof_log_init_filename (const gchar* logfilename);
/**
* If @a log_to_filename is "stderr" or "stdout" (exactly,
* case-insensitive), then those special files are used; otherwise, the
* literal filename as given, as qof_log_init_filename(gchar*)
**/
void qof_log_init_filename_special(const char *log_to_filename);
/**
* Parse a log-configuration file. A GKeyFile-format file of the schema:
* @verbatim
[levels]
# log.ger.path=level
gnc.engine.sx=debug
gnc.gui.sx=debug
gnc.import-export.qif.parse=debug
[output]
# to=["stderr"|"stdout"|filename]
to=stderr
@endverbatim
**/
void qof_log_parse_log_config(const char *filename);
/** Be nice, close the logfile if possible. */
void qof_log_shutdown (void);
/**
* Cleans up subroutine names. AIX/xlC has the habit of printing signatures
* not names; clean this up. On other operating systems, truncate name to
* QOF_LOG_MAX_CHARS chars.
**/
const gchar * qof_log_prettify (const gchar *name);
/** Check to see if the given @a log_module is configured to log at the given
* @a log_level. This implements the "log.path.hierarchy" logic. **/
gboolean qof_log_check(QofLogModule log_module, QofLogLevel log_level);
/** Set the default level for QOF-related log paths. **/
void qof_log_set_default(QofLogLevel log_level);
#define PRETTY_FUNC_NAME qof_log_prettify(G_STRFUNC)
#ifdef _MSC_VER
/* Microsoft Visual Studio: MSVC compiler has a different syntax for
* macros with variadic argument list. */
/** Log a fatal error */
#define FATAL(format, ...) do { \
g_log (log_module, G_LOG_LEVEL_ERROR, \
"[%s()] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \
} while (0)
/** Log a serious error */
#define PERR(format, ...) do { \
g_log (log_module, G_LOG_LEVEL_CRITICAL, \
"[%s()] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \
} while (0)
/** Log a warning */
#define PWARN(format, ...) do { \
g_log (log_module, G_LOG_LEVEL_WARNING, \
"[%s()] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \
} while (0)
/** Print an informational note */
#define PINFO(format, ...) do { \
g_log (log_module, G_LOG_LEVEL_INFO, \
"[%s] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \
} while (0)
/** Print a debugging message */
#define DEBUG(format, ...) do { \
g_log (log_module, G_LOG_LEVEL_DEBUG, \
"[%s] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \
} while (0)
/** Print a function entry debugging message */
#define ENTER(format, ...) do { \
if (qof_log_check(log_module, (QofLogLevel)G_LOG_LEVEL_DEBUG)) { \
g_log (log_module, G_LOG_LEVEL_DEBUG, \
"[enter %s:%s()] " format, __FILE__, \
PRETTY_FUNC_NAME , __VA_ARGS__); \
qof_log_indent(); \
} \
} while (0)
/** Print a function exit debugging message. **/
#define LEAVE(format, ...) do { \
if (qof_log_check(log_module, (QofLogLevel)G_LOG_LEVEL_DEBUG)) { \
qof_log_dedent(); \
g_log (log_module, G_LOG_LEVEL_DEBUG, \
"[leave %s()] " format, \
PRETTY_FUNC_NAME , __VA_ARGS__); \
} \
} while (0)
#else /* _MSC_VER */
/** Log a fatal error */
#define FATAL(format, args...) do { \
g_log (log_module, G_LOG_LEVEL_ERROR, \
"[%s()] " format, PRETTY_FUNC_NAME , ## args); \
} while (0)
/** Log a serious error */
#define PERR(format, args...) do { \
g_log (log_module, G_LOG_LEVEL_CRITICAL, \
"[%s()] " format, PRETTY_FUNC_NAME , ## args); \
} while (0)
/** Log a warning */
#define PWARN(format, args...) do { \
g_log (log_module, G_LOG_LEVEL_WARNING, \
"[%s()] " format, PRETTY_FUNC_NAME , ## args); \
} while (0)
/** Print an informational note */
#define PINFO(format, args...) do { \
g_log (log_module, G_LOG_LEVEL_INFO, \
"[%s] " format, PRETTY_FUNC_NAME , ## args); \
} while (0)
/** Print a debugging message */
#define DEBUG(format, args...) do { \
g_log (log_module, G_LOG_LEVEL_DEBUG, \
"[%s] " format, PRETTY_FUNC_NAME , ## args); \
} while (0)
/** Print a function entry debugging message */
#define ENTER(format, args...) do { \
if (qof_log_check(log_module, (QofLogLevel)G_LOG_LEVEL_DEBUG)) { \
g_log (log_module, G_LOG_LEVEL_DEBUG, \
"[enter %s:%s()] " format, __FILE__, \
PRETTY_FUNC_NAME , ## args); \
qof_log_indent(); \
} \
} while (0)
/** Print a function exit debugging message. **/
#define LEAVE(format, args...) do { \
if (qof_log_check(log_module, (QofLogLevel)G_LOG_LEVEL_DEBUG)) { \
qof_log_dedent(); \
g_log (log_module, G_LOG_LEVEL_DEBUG, \
"[leave %s()] " format, \
PRETTY_FUNC_NAME , ## args); \
} \
} while (0)
#endif /* _MSC_VER */
/** Replacement for @c g_return_val_if_fail, but calls LEAVE if the test fails. **/
#define gnc_leave_return_val_if_fail(test, val) do { \
if (! (test)) { LEAVE(""); } \
g_return_val_if_fail(test, val); \
} while (0);
/** Replacement for @c g_return_if_fail, but calls LEAVE if the test fails. **/
#define gnc_leave_return_if_fail(test) do { \
if (! (test)) { LEAVE(""); } \
g_return_if_fail(test); \
} while (0);
#ifdef __cplusplus
}
#endif
#endif /* _QOF_LOG_H */
/** @} */