gem-graph-client/libide/core/ide-debug.h

203 lines
7.7 KiB
C

/* ide-debug.h.in
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_DEBUG_H
#define IDE_DEBUG_H
#include <execinfo.h>
#include <glib.h>
#include "ide-version-macros.h"
G_BEGIN_DECLS
/**
* SECTION:ide-debug
* @title: Debug logging and tracing
* @short_description: tracing and debug facilities for Builder and plugins
*
* The debug macros such as %IDE_ENTRY, %IDE_EXIT, and %IDE_RETURN provide
* helpers for tracing Builder and plugins at runtime.
*
* These tracing macros will compile out when Builder is configured for a
* release build. Otherwise, running Builder with the "-vvvv" command line
* argument will show tracing output.
*
* Since: 3.18
*/
/**
* IDE_ENTRY: (skip)
*
* Traces the entry into a function. Place this at the beginning of your
* function above pre-condition checks.
*
* Since: 3.18
*/
/**
* IDE_EXIT: (skip)
*
* Traces the exit from a function. Use this instead of "return" to return
* and log the function exiting.
*
* Since: 3.18
*/
/**
* IDE_RETURN: (skip)
*
* Similar to %IDE_EXIT but allows providing a return value.
*
* Since: 3.18
*/
/**
* IDE_GOTO: (skip)
* @_l: the label to jump to
*
* Appends to the jump to label to the tracing log and then jumps
* to the label @_l.
*
* Since: 3.18
*/
/**
* IDE_TODO: (skip)
* @_msg: the message to append to the trace log
*
* Appends to the tracing log that unsupported code has been
* reached.
*
* Since: 3.18
*/
/**
* IDE_PROBE: (skip)
*
* Appends to the tracing log that a line of code was reached.
*
* Since: 3.18
*/
/**
* IDE_TRACE_MSG: (skip)
*
* Similar to %IDE_PROBE but allows specifying a log message.
*
* Since: 3.18
*/
#ifndef IDE_ENABLE_TRACE
# define IDE_ENABLE_TRACE 0
#endif
#if IDE_ENABLE_TRACE != 1
# undef IDE_ENABLE_TRACE
#endif
/**
* IDE_LOG_LEVEL_TRACE: (skip)
*/
#ifndef IDE_LOG_LEVEL_TRACE
# define IDE_LOG_LEVEL_TRACE ((GLogLevelFlags)(1 << G_LOG_LEVEL_USER_SHIFT))
#endif
#ifdef IDE_ENABLE_TRACE
_IDE_EXTERN
void ide_trace_function (const gchar *strfunc,
gint64 begin_time_usec,
gint64 end_time_usec);
# define IDE_TRACE_MSG(fmt, ...) \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " MSG: %s():%d: " fmt, \
G_STRFUNC, __LINE__, ##__VA_ARGS__)
# define IDE_PROBE \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, "PROBE: %s():%d", \
G_STRFUNC, __LINE__)
# define IDE_TODO(_msg) \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " TODO: %s():%d: %s", \
G_STRFUNC, __LINE__, _msg)
# define IDE_ENTRY \
gint64 __trace_begin_time = g_get_monotonic_time (); \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, "ENTRY: %s():%d", \
G_STRFUNC, __LINE__)
# define IDE_EXIT \
G_STMT_START { \
ide_trace_function (G_STRFUNC, \
__trace_begin_time, \
g_get_monotonic_time ()); \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " EXIT: %s():%d", \
G_STRFUNC, __LINE__); \
return; \
} G_STMT_END
# define IDE_GOTO(_l) \
G_STMT_START { \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " GOTO: %s():%d ("#_l")", \
G_STRFUNC, __LINE__); \
goto _l; \
} G_STMT_END
# define IDE_RETURN(_r) \
G_STMT_START { \
ide_trace_function (G_STRFUNC, \
__trace_begin_time, \
g_get_monotonic_time ()); \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, " EXIT: %s():%d ", \
G_STRFUNC, __LINE__); \
return _r; \
} G_STMT_END
# define IDE_BACKTRACE \
G_STMT_START { \
gpointer btbuf[64]; \
int btbuflen = backtrace (btbuf, G_N_ELEMENTS (btbuf)); \
char **symnames = backtrace_symbols (btbuf, btbuflen); \
for (guint _i = 0; _i < btbuflen; _i++) { \
g_log(G_LOG_DOMAIN, IDE_LOG_LEVEL_TRACE, "TRACE: [%-2d]: %s", \
_i, symnames[_i]); \
} \
free (symnames); \
} G_STMT_END
#else
# define IDE_TODO(_msg) G_STMT_START { } G_STMT_END
# define IDE_PROBE G_STMT_START { } G_STMT_END
# define IDE_TRACE_MSG(fmt, ...) G_STMT_START { } G_STMT_END
# define IDE_ENTRY G_STMT_START { } G_STMT_END
# define IDE_GOTO(_l) G_STMT_START { goto _l; } G_STMT_END
# define IDE_EXIT G_STMT_START { return; } G_STMT_END
# define IDE_RETURN(_r) G_STMT_START { return _r; } G_STMT_END
# define IDE_BACKTRACE G_STMT_START { } G_STMT_END
#endif
#define _IDE_BUG(Component, Description, File, Line, Func, ...) \
G_STMT_START { \
g_printerr ("-----------------------------------------------------------------\n"); \
g_printerr ("You've found a bug in Builder or one of its dependent libraries.\n"); \
g_printerr ("Please help us help you by filing a bug report at:\n"); \
g_printerr ("\n"); \
g_printerr ("@BUGREPORT_URL@&component=%s\n", Component); \
g_printerr ("\n"); \
g_printerr ("%s:%d in function %s()\n", File, Line, Func); \
g_printerr ("\n"); \
g_printerr (Description"\n", ##__VA_ARGS__); \
g_printerr ("-----------------------------------------------------------------\n"); \
} G_STMT_END
#define IDE_BUG(Component, Description, ...) \
_IDE_BUG(Component, Description, __FILE__, __LINE__, G_STRFUNC, ##__VA_ARGS__)
G_END_DECLS
#endif /* IDE_DEBUG_H */