1 /* qof-log.h 2 * Author: Rob Clark <rclark@cs.hmc.edu> 3 * Copyright (C) 1998-2003 Linas Vepstas <linas@linas.org> 4 * Copyright 2005 Neil Williams <linux@codehelp.co.uk> 5 * Copyright 2007 Joshua Sled <jsled@asynchronous.org> 6 */ 7 8 /* 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22 * 02110-1301, USA 23 */ 24 25 /** 26 * @addtogroup Logging 27 * @{ 28 * @ingroup QOF 29 * @brief Logging and tracing facility. 30 * @sa "Logging overhaul" announcement <https://lists.gnucash.org/pipermail/gnucash-devel/2007-February/019836.html> 31 * 32 * qof_log_init(void) installs a handler that interprets the "log_domain" 33 * as a "."-separated path. Log level thresholds can be set for each level 34 * in the tree. When a message is logged, the longest level match is 35 * found, and used as the threshold. 36 * 37 * For instance, we can set the levels as such: 38 * @verbatim 39 "qof" = WARN 40 "gnc" = WARN 41 "gnc.ui" = INFO 42 "gnc.ui.plugin-page.sx-list" = DEBUG 43 @endverbatim 44 * 45 * When code in the log_module of "gnc.import" attempts to log at DEBUG 46 * (let's say), the handler will attempt to match the log domain to 47 * successively-longer paths: first "", then "gnc", then "gnc.import". Given 48 * the settings above, the path "gnc" will match -- at a level of "WARN" -- 49 * and the DEBUG-level log will be rejected. When code in the log domain of 50 * "gnc.ui.plugin-page.sx-list" logs at DEBUG, however, it will match at 51 * DEBUG, and be allowed. 52 * 53 * The current log format is as above: 54 * 55 * @verbatim 56 * [timestamp] [level] <[log-domain]> [message] 57 @endverbatim 58 * 59 * The timestamp and level are constant width (level is 5 characters). The 60 * log domain is re-iterated, which gives some context, but could become 61 * annoying if they get long. 62 * 63 * Trailing newlines (e.g. <tt>PINFO("...\n", ...)</tt>) are removed; the logger 64 * will newline separate output. 65 * 66 * @section best Best Practices 67 * 68 * Code should: 69 * 70 * @li Define both <tt>static QofLogModule log_module</tt> and <tt>#define 71 * G_LOG_DOMAIN</tt> to the same value. 72 * @li Define a logical, specific path as the log domain; 73 * @c "gnc.gui.plugin-pages.sx-list" or 74 * @c "gnc.register.gnome.cell.quickfill" are 75 * good examples. 76 * @li Prefer the macros defined here (PERR, PWARN, PINFO, etc.) to 77 * the GLib-provided functions that they wrap because it allows us to 78 * more easily replace the GLib logging functinos with another 79 * implementation and besides our macros are able to short-circuit 80 * GLib's rather slow domain and level matching. 81 * 82 * @see qof_log_parse_log_config(const char*) 83 **/ 84 85 #ifndef _QOF_LOG_H 86 #define _QOF_LOG_H 87 88 #ifdef __cplusplus 89 extern "C" 90 { 91 #endif 92 93 #include <stdarg.h> 94 #include <stdio.h> 95 #include <glib.h> 96 #include "qofutil.h" 97 98 typedef const gchar* QofLogModule; 99 100 #define QOF_MOD_ENGINE "qof.engine" 101 102 typedef enum 103 { 104 QOF_LOG_FATAL = G_LOG_LEVEL_ERROR, 105 QOF_LOG_ERROR = G_LOG_LEVEL_CRITICAL, 106 QOF_LOG_WARNING = G_LOG_LEVEL_WARNING, 107 QOF_LOG_MESSAGE = G_LOG_LEVEL_MESSAGE, 108 QOF_LOG_INFO = G_LOG_LEVEL_INFO, 109 QOF_LOG_DEBUG = G_LOG_LEVEL_DEBUG 110 } QofLogLevel; 111 112 const char* qof_log_level_to_string(QofLogLevel lvl); 113 QofLogLevel qof_log_level_from_string(const char *str); 114 115 /** Indents one level; see ENTER macro. **/ 116 void qof_log_indent(void); 117 118 /** 119 * De-dent one level, capped at 0; see LEAVE macro. 120 **/ 121 void qof_log_dedent(void); 122 123 /** 124 * Initialize the error logging subsystem. Defaults to a level-threshold of 125 * "warning", and logging to stderr. 126 **/ 127 void qof_log_init (void); 128 129 /** Set the logging level of the given log_module. **/ 130 void qof_log_set_level(QofLogModule module, QofLogLevel level); 131 132 /** Specify an alternate log output, to pipe or file. **/ 133 void qof_log_set_file (FILE *outfile); 134 135 /** Specify a filename for log output. **/ 136 void qof_log_init_filename (const gchar* logfilename); 137 138 /** 139 * If @a log_to_filename is "stderr" or "stdout" (exactly, 140 * case-insensitive), then those special files are used; otherwise, the 141 * literal filename as given, as qof_log_init_filename(gchar*) 142 **/ 143 void qof_log_init_filename_special(const char *log_to_filename); 144 145 /** 146 * Parse a log-configuration file. A GKeyFile-format file of the schema: 147 * @verbatim 148 [levels] 149 # log.ger.path=level 150 gnc.engine.sx=debug 151 gnc.gui.sx=debug 152 gnc.import-export.qif.parse=debug 153 [output] 154 # to=["stderr"|"stdout"|filename] 155 to=stderr 156 @endverbatim 157 **/ 158 void qof_log_parse_log_config(const char *filename); 159 160 /** Be nice, close the logfile if possible. */ 161 void qof_log_shutdown (void); 162 163 /** 164 * Cleans up subroutine names. AIX/xlC has the habit of printing signatures 165 * not names; clean this up. On other operating systems, truncate name to 166 * QOF_LOG_MAX_CHARS chars. 167 **/ 168 const gchar * qof_log_prettify (const gchar *name); 169 170 /** Check to see if the given @a log_module is configured to log at the given 171 * @a log_level. This implements the "log.path.hierarchy" logic. **/ 172 gboolean qof_log_check(QofLogModule log_module, QofLogLevel log_level); 173 174 #define PRETTY_FUNC_NAME qof_log_prettify(G_STRFUNC) 175 176 #ifdef _MSC_VER 177 /* Microsoft Visual Studio: MSVC compiler has a different syntax for 178 * macros with variadic argument list. */ 179 180 /* TODO: After the C++2a feature __VA_OPT__ gets implemented in both 181 * flavors, it should be inserted before __VA_ARGS__ and the else branch 182 * gets obsolete and should be removed. 183 */ 184 185 /** Log a fatal error */ 186 #define FATAL(format, ...) do { \ 187 g_log (log_module, G_LOG_LEVEL_ERROR, \ 188 "[%s()] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \ 189 } while (0) 190 191 /** Log a serious error */ 192 #define PERR(format, ...) do { \ 193 g_log (log_module, G_LOG_LEVEL_CRITICAL, \ 194 "[%s()] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \ 195 } while (0) 196 197 /** Log a warning */ 198 #define PWARN(format, ...) do { \ 199 g_log (log_module, G_LOG_LEVEL_WARNING, \ 200 "[%s()] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \ 201 } while (0) 202 203 /** Print an informational note */ 204 #define PINFO(format, ...) \ 205 if (qof_log_check(log_module, QOF_LOG_INFO) { \ 206 g_log (log_module, G_LOG_LEVEL_INFO, \ 207 "[%s] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \ 208 } 209 210 /** Print a debugging message */ 211 #define DEBUG(format, ...) \ 212 if (qof_log_check(log_module, QOF_LOG_DEBUG) { \ 213 g_log (log_module, G_LOG_LEVEL_DEBUG, \ 214 "[%s] " format, PRETTY_FUNC_NAME , __VA_ARGS__); \ 215 } 216 217 /** Print a function entry debugging message */ 218 #define ENTER(format, ...) \ 219 if (qof_log_check(log_module, QOFLOG_DEBUG)) { \ 220 g_log (log_module, G_LOG_LEVEL_DEBUG, \ 221 "[enter %s:%s()] " format, __FILE__, \ 222 PRETTY_FUNC_NAME , __VA_ARGS__); \ 223 qof_log_indent(); \ 224 } 225 226 /** Print a function exit debugging message. **/ 227 #define LEAVE(format, ...) \ 228 if (qof_log_check(log_module, QOF_LOG_DEBUG)) { \ 229 qof_log_dedent(); \ 230 g_log (log_module, G_LOG_LEVEL_DEBUG, \ 231 "[leave %s()] " format, \ 232 PRETTY_FUNC_NAME , __VA_ARGS__); \ 233 } 234 235 #else /* _MSC_VER */ 236 237 /** Log a fatal error */ 238 #define FATAL(format, args...) do { \ 239 g_log (log_module, G_LOG_LEVEL_ERROR, \ 240 "[%s()] " format, PRETTY_FUNC_NAME , ## args); \ 241 } while (0) 242 243 /** Log a serious error */ 244 #define PERR(format, args...) do { \ 245 g_log (log_module, G_LOG_LEVEL_CRITICAL, \ 246 "[%s()] " format, PRETTY_FUNC_NAME , ## args); \ 247 } while (0) 248 249 /** Log a warning */ 250 #define PWARN(format, args...) do { \ 251 g_log (log_module, G_LOG_LEVEL_WARNING, \ 252 "[%s()] " format, PRETTY_FUNC_NAME , ## args); \ 253 } while (0) 254 255 /** Print an informational note */ 256 #define PINFO(format, args...) do { \ 257 if (qof_log_check(log_module, QOF_LOG_INFO)) { \ 258 g_log (log_module, G_LOG_LEVEL_INFO, \ 259 "[%s] " format, PRETTY_FUNC_NAME , ## args); \ 260 } \ 261 } while (0) 262 263 /** Print a debugging message */ 264 #define DEBUG(format, args...) do { \ 265 if (qof_log_check(log_module, QOF_LOG_DEBUG)) { \ 266 g_log (log_module, G_LOG_LEVEL_DEBUG, \ 267 "[%s] " format, PRETTY_FUNC_NAME , ## args); \ 268 } \ 269 } while(0) 270 271 /** Print a function entry debugging message */ 272 #define ENTER(format, args...) do { \ 273 if (qof_log_check(log_module, QOF_LOG_DEBUG)) { \ 274 g_log (log_module, G_LOG_LEVEL_DEBUG, \ 275 "[enter %s:%s()] " format, __FILE__, \ 276 PRETTY_FUNC_NAME , ## args); \ 277 qof_log_indent(); \ 278 } \ 279 } while (0) 280 281 /** Print a function exit debugging message. **/ 282 #define LEAVE(format, args...) do { \ 283 if (qof_log_check(log_module, QOF_LOG_DEBUG)) { \ 284 qof_log_dedent(); \ 285 g_log (log_module, G_LOG_LEVEL_DEBUG, \ 286 "[leave %s()] " format, \ 287 PRETTY_FUNC_NAME , ## args); \ 288 } \ 289 } while (0) 290 291 #endif /* _MSC_VER */ 292 293 /** Replacement for @c g_return_val_if_fail, but calls LEAVE if the test fails. **/ 294 #define gnc_leave_return_val_if_fail(test, val) do { \ 295 if (! (test)) { LEAVE(""); } \ 296 g_return_val_if_fail(test, val); \ 297 } while (0); 298 299 /** Replacement for @c g_return_if_fail, but calls LEAVE if the test fails. **/ 300 #define gnc_leave_return_if_fail(test) do { \ 301 if (! (test)) { LEAVE(""); } \ 302 g_return_if_fail(test); \ 303 } while (0); 304 305 306 #ifdef __cplusplus 307 } 308 #endif 309 310 #endif /* _QOF_LOG_H */ 311 312 /** @} */ 313