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.
This commit is contained in:
Georges Basile Stavracas Neto 2018-04-06 23:18:26 -03:00
parent 85296f1eba
commit 1187f147af
9 changed files with 386 additions and 97 deletions

View file

@ -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)

View file

@ -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')

View file

@ -26,9 +26,9 @@
#include <gio/gio.h>
#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));

229
shell/cc-debug.h.in Normal file
View file

@ -0,0 +1,229 @@
/* cc-debug.h.in
*
* Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
/**
* 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

107
shell/cc-log.c Normal file
View file

@ -0,0 +1,107 @@
/* cc-shell-log.c
*
* Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "cc-debug.h"
#include "cc-log.h"
#include <unistd.h>
#include <glib.h>
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);
}
}

25
shell/cc-log.h Normal file
View file

@ -0,0 +1,25 @@
/* cc-log.h
*
* Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
G_BEGIN_DECLS
void cc_log_init (void);
G_END_DECLS

View file

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <glib.h>
#include <glib/gstdio.h>
#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");
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __CC_SHELL_LOG_H
#define __CC_SHELL_LOG_H
#include <glib.h>
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 */

View file

@ -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,