From 1187f147af7a63583ff3acc62cf2cfe9fa7e8882 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Fri, 6 Apr 2018 23:18:26 -0300 Subject: [PATCH] log: Reimplement logging and debugging This commit replaces the old rudimentary log handler by a shinier version of it. It also introduces the debugging macros that I usually add to the apps, including the CC_TRACE_MSG() macro for tracing. --- meson.build | 8 ++ meson_options.txt | 1 + shell/cc-application.c | 6 +- shell/cc-debug.h.in | 229 +++++++++++++++++++++++++++++++++++++++++ shell/cc-log.c | 107 +++++++++++++++++++ shell/cc-log.h | 25 +++++ shell/cc-shell-log.c | 62 ----------- shell/cc-shell-log.h | 32 ------ shell/meson.build | 13 ++- 9 files changed, 386 insertions(+), 97 deletions(-) create mode 100644 shell/cc-debug.h.in create mode 100644 shell/cc-log.c create mode 100644 shell/cc-log.h delete mode 100644 shell/cc-shell-log.c delete mode 100644 shell/cc-shell-log.h diff --git a/meson.build b/meson.build index 20aeb9fc1..dfc14f106 100644 --- a/meson.build +++ b/meson.build @@ -25,6 +25,9 @@ host_is_linux_not_s390 = host_is_linux and not host_machine.cpu().contains('s390 cc = meson.get_compiler('c') +# Tracing +enable_tracing = get_option('tracing') + config_h = configuration_data() # defines @@ -269,5 +272,10 @@ output += '** NetworkManager (Network panel): ' + host_is_linux.to_string() + '\ output += '** wacom (Wacom tablet panel): ' + host_is_linux_not_s390.to_string() + '\n' output += '** Wayland: ' + enable_wayland.to_string() + '\n' output += '** gnome-session libexecdir: ' + gnome_session_libexecdir + '\n' + +if enable_tracing + output += '** Tracing enabled \n' +endif + output += 'End options' message(output) diff --git a/meson_options.txt b/meson_options.txt index 7498af4d6..a01c11553 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,4 +2,5 @@ option('cheese', type: 'boolean', value: true, description: 'build with cheese w option('documentation', type: 'boolean', value: false, description: 'build documentation') option('gnome_session_libexecdir', type: 'string', value: '', description: 'Directory for gnome-session\'s libexecdir') option('ibus', type: 'boolean', value: true, description: 'build with IBus support') +option('tracing', type: 'boolean', value: false, description: 'add extra debugging information') option('wayland', type: 'boolean', value: true, description: 'build with Wayland support') diff --git a/shell/cc-application.c b/shell/cc-application.c index 144cbeeb6..3f828f3a6 100644 --- a/shell/cc-application.c +++ b/shell/cc-application.c @@ -26,9 +26,9 @@ #include #include "cc-application.h" +#include "cc-log.h" #include "cc-object-storage.h" #include "cc-panel-loader.h" -#include "cc-shell-log.h" #include "cc-window.h" #if defined(HAVE_WACOM) || defined(HAVE_CHEESE) @@ -158,7 +158,9 @@ cc_application_command_line (GApplication *application, options = g_application_command_line_get_options_dict (command_line); debug = g_variant_dict_contains (options, "verbose"); - cc_shell_log_set_debug (debug); + + if (debug) + cc_log_init (); gtk_window_present (GTK_WINDOW (self->window)); diff --git a/shell/cc-debug.h.in b/shell/cc-debug.h.in new file mode 100644 index 000000000..72962970d --- /dev/null +++ b/shell/cc-debug.h.in @@ -0,0 +1,229 @@ +/* cc-debug.h.in + * + * Copyright © 2018 Georges Basile Stavracas Neto + * + * 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, see . + */ + +#pragma once + +#include + +/** + * SECTION:cc-debug + * @short_description: Debugging macros + * @title:Debugging + * @stability:stable + * + * Macros used for tracing and debugging code. These + * are only valid when Calendar is compiled with tracing + * suppoer (pass `--enable-tracing` to the configure + * script to do that). + */ + +G_BEGIN_DECLS + +#ifndef CC_ENABLE_TRACE +# define CC_ENABLE_TRACE @ENABLE_TRACING@ +#endif +#if CC_ENABLE_TRACE != 1 +# undef CC_ENABLE_TRACE +#endif + +/** + * CC_LOG_LEVEL_TRACE: (skip) + */ +#ifndef CC_LOG_LEVEL_TRACE +# define CC_LOG_LEVEL_TRACE ((GLogLevelFlags)(1 << G_LOG_LEVEL_USER_SHIFT)) +#endif + +#ifdef CC_ENABLE_TRACE + +/** + * CC_TRACE_MSG: + * @fmt: printf-like format of the message + * @...: arguments for @fmt + * + * Prints a trace message. + */ +# define CC_TRACE_MSG(fmt, ...) \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " MSG: %s():%d: " fmt, \ + G_STRFUNC, __LINE__, ##__VA_ARGS__) + +/** + * CC_PROBE: + * + * Prints a probing message. Put this macro in the code when + * you want to check the program reaches a certain section + * of code. + */ +# define CC_PROBE \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, "PROBE: %s():%d", \ + G_STRFUNC, __LINE__) + +/** + * CC_TODO: + * @_msg: the message to print + * + * Prints a TODO message. + */ +# define CC_TODO(_msg) \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " TODO: %s():%d: %s", \ + G_STRFUNC, __LINE__, _msg) + +/** + * CC_ENTRY: + * + * Prints an entry message. This shouldn't be used in + * critical functions. Place this at the beggining of + * the function, before any assertion. + */ +# define CC_ENTRY \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, "ENTRY: %s():%d", \ + G_STRFUNC, __LINE__) + +/** + * CC_EXIT: + * + * Prints an exit message. This shouldn't be used in + * critical functions. Place this at the end of + * the function, after any relevant code. If the + * function returns something, use CC_RETURN() + * instead. + */ +# define CC_EXIT \ + G_STMT_START { \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " EXIT: %s():%d", \ + G_STRFUNC, __LINE__); \ + return; \ + } G_STMT_END + +/** + * CC_GOTO: + * @_l: goto tag + * + * Logs a goto jump. + */ +# define CC_GOTO(_l) \ + G_STMT_START { \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " GOTO: %s():%d ("#_l")",\ + G_STRFUNC, __LINE__); \ + goto _l; \ + } G_STMT_END + +/** + * CC_RETURN: + * @_r: the return value. + * + * Prints an exit message, and returns @_r. See #CC_EXIT. + */ +# define CC_RETURN(_r) \ + G_STMT_START { \ + g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " EXIT: %s():%d ", \ + G_STRFUNC, __LINE__); \ + return _r; \ + } G_STMT_END + +#else + +/** + * CC_TODO: + * @_msg: the message to print + * + * Prints a TODO message. + */ +# define CC_TODO(_msg) + +/** + * CC_PROBE: + * + * Prints a probing message. + */ +# define CC_PROBE + +/** + * CC_TRACE_MSG: + * @fmt: printf-like format of the message + * @...: arguments for @fmt + * + * Prints a trace message. + */ +# define CC_TRACE_MSG(fmt, ...) + +/** + * CC_ENTRY: + * + * Prints a probing message. This shouldn't be used in + * critical functions. Place this at the beggining of + * the function, before any assertion. + */ +# define CC_ENTRY + +/** + * CC_GOTO: + * @_l: goto tag + * + * Logs a goto jump. + */ +# define CC_GOTO(_l) goto _l + +/** + * CC_EXIT: + * + * Prints an exit message. This shouldn't be used in + * critical functions. Place this at the end of + * the function, after any relevant code. If the + * function returns somethin, use CC_RETURN() + * instead. + */ +# define CC_EXIT return + +/** + * CC_RETURN: + * @_r: the return value. + * + * Prints an exit message, and returns @_r. See #CC_EXIT. + */ +# define CC_RETURN(_r) return _r +#endif + +/** + * _CC_BUG: (skip) + */ +#define _CC_BUG(Component, Description, File, Line, Func, ...) \ + G_STMT_START { \ + g_printerr ("-----------------------------------------------------------------\n"); \ + g_printerr ("You've found a bug in Calendar 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 + +/** + * CC_BUG: + * @Component: the component + * @Description: the description + * @...: extra arguments + * + * Logs a bug-friendly message. + */ +#define CC_BUG(Component, Description, ...) \ + _CC_BUG(Component, Description, __FILE__, __LINE__, G_STRFUNC, ##__VA_ARGS__) + +G_END_DECLS diff --git a/shell/cc-log.c b/shell/cc-log.c new file mode 100644 index 000000000..5f6645cbe --- /dev/null +++ b/shell/cc-log.c @@ -0,0 +1,107 @@ +/* cc-shell-log.c + * + * Copyright © 2018 Georges Basile Stavracas Neto + * + * 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, see . + */ + +#include "cc-debug.h" +#include "cc-log.h" + +#include +#include + +G_LOCK_DEFINE_STATIC (channel_lock); + +GIOChannel *standard_channel = NULL; + +static const gchar* ignored_domains[] = +{ + "GdkPixbuf", + NULL +}; + +static const gchar * +log_level_str (GLogLevelFlags log_level) +{ + switch (((gulong)log_level & G_LOG_LEVEL_MASK)) + { + case G_LOG_LEVEL_ERROR: return " \033[1;31mERROR\033[0m"; + case G_LOG_LEVEL_CRITICAL: return "\033[1;35mCRITICAL\033[0m"; + case G_LOG_LEVEL_WARNING: return " \033[1;33mWARNING\033[0m"; + case G_LOG_LEVEL_MESSAGE: return " \033[1;34mMESSAGE\033[0m"; + case G_LOG_LEVEL_INFO: return " \033[1;32mINFO\033[0m"; + case G_LOG_LEVEL_DEBUG: return " \033[1;32mDEBUG\033[0m"; + case CC_LOG_LEVEL_TRACE: return " \033[1;36mTRACE\033[0m"; + default: return " UNKNOWN"; + } +} + +static void +log_handler (const gchar *domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + GTimeVal tv; + struct tm tt; + time_t t; + const gchar *level; + gchar ftime[32]; + gchar *buffer; + + /* Skip ignored log domains */ + if (domain && g_strv_contains (ignored_domains, domain)) + return; + + level = log_level_str (log_level); + g_get_current_time (&tv); + t = (time_t) tv.tv_sec; + tt = *localtime (&t); + strftime (ftime, sizeof (ftime), "%H:%M:%S", &tt); + buffer = g_strdup_printf ("%s.%04ld %24s: %s: %s\n", + ftime, + tv.tv_usec / 1000, + domain, + level, + message); + + /* Safely write to the channel */ + G_LOCK (channel_lock); + + g_io_channel_write_chars (standard_channel, buffer, -1, NULL, NULL); + g_io_channel_flush (standard_channel, NULL); + + G_UNLOCK (channel_lock); + + g_free (buffer); +} + +void +cc_log_init (void) +{ + static gsize initialized = FALSE; + + if (g_once_init_enter (&initialized)) + { + standard_channel = g_io_channel_unix_new (STDOUT_FILENO); + + g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + + g_log_set_default_handler (log_handler, NULL); + + g_once_init_leave (&initialized, TRUE); + } +} + diff --git a/shell/cc-log.h b/shell/cc-log.h new file mode 100644 index 000000000..2d04c0ba7 --- /dev/null +++ b/shell/cc-log.h @@ -0,0 +1,25 @@ +/* cc-log.h + * + * Copyright © 2018 Georges Basile Stavracas Neto + * + * 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, see . + */ + +#pragma once + +G_BEGIN_DECLS + +void cc_log_init (void); + +G_END_DECLS diff --git a/shell/cc-shell-log.c b/shell/cc-shell-log.c deleted file mode 100644 index 14a122722..000000000 --- a/shell/cc-shell-log.c +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2009 Red Hat, Inc. - * - * 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, see . - * - */ - - -#include "config.h" - -#include -#include - -#include "cc-shell-log.h" - -static int log_levels = G_LOG_LEVEL_CRITICAL | - G_LOG_LEVEL_ERROR | - G_LOG_LEVEL_WARNING | - G_LOG_LEVEL_MESSAGE | - G_LOG_LEVEL_INFO | - G_LOG_LEVEL_DEBUG; - -static void -cc_shell_log_default_handler (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer unused_data) -{ - if ((log_level & log_levels) == 0) - return; - - g_log_default_handler (log_domain, log_level, message, unused_data); -} - -void -cc_shell_log_init (void) -{ - g_log_set_default_handler (cc_shell_log_default_handler, NULL); -} - -void -cc_shell_log_set_debug (gboolean debug) -{ - - if (debug) { - g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); - log_levels |= (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO); - g_debug ("Enabling debugging"); - } -} diff --git a/shell/cc-shell-log.h b/shell/cc-shell-log.h deleted file mode 100644 index 132a19dcf..000000000 --- a/shell/cc-shell-log.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2009 Red Hat, Inc. - * - * 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, see . - * - */ - -#ifndef __CC_SHELL_LOG_H -#define __CC_SHELL_LOG_H - -#include - -G_BEGIN_DECLS - -void cc_shell_log_init (void); -void cc_shell_log_set_debug (gboolean debug); - -G_END_DECLS - -#endif /* __CC_SHELL_LOG_H */ diff --git a/shell/meson.build b/shell/meson.build index 0946ada74..62270358c 100644 --- a/shell/meson.build +++ b/shell/meson.build @@ -46,12 +46,12 @@ common_sources = files( 'cc-application.c', 'cc-editable-entry.c', 'cc-hostname-entry.c', + 'cc-log.c', 'cc-object-storage.c', 'cc-panel-loader.c', 'cc-panel.c', 'cc-shell-category-view.c', 'cc-shell-item-view.c', - 'cc-shell-log.c', 'cc-shell.c', 'hostname-helper.c', 'list-box-helper.c', @@ -91,6 +91,17 @@ if host_is_linux_not_s390 shell_deps += wacom_deps endif +# Debug +debug_conf = configuration_data() +debug_conf.set('BUGREPORT_URL', 'http://bugzilla.gnome.org/enter_bug.cgi?product=' + meson.project_name()) +debug_conf.set10('ENABLE_TRACING', enable_tracing) + +sources += configure_file( + input: 'cc-debug.h.in', + output: 'cc-debug.h', + configuration: debug_conf +) + executable( meson.project_name(), sources,