diff --git a/build-aux/flatpak/org.gnome.Settings.json b/build-aux/flatpak/org.gnome.Settings.json index fe2e7892d..64cdefbcf 100644 --- a/build-aux/flatpak/org.gnome.Settings.json +++ b/build-aux/flatpak/org.gnome.Settings.json @@ -637,7 +637,6 @@ } ], "config-opts" : [ - "-Dtracing=true", "-Dprofile=development" ] } diff --git a/meson.build b/meson.build index 3ef24027f..77b745429 100644 --- a/meson.build +++ b/meson.build @@ -25,9 +25,6 @@ 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() py = import('python') @@ -313,7 +310,6 @@ configure_file( summary({ 'Documentation': get_option('documentation'), 'Tests': get_option('tests'), - 'Tracing': enable_tracing, 'Optimized': control_center_optimized, }) diff --git a/meson_options.txt b/meson_options.txt index 461ae34e7..8ee7b6e0e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,7 +3,6 @@ option('ibus', type: 'boolean', value: true, description: 'build with IBus suppo option('privileged_group', type: 'string', value: 'wheel', description: 'name of group that has elevated permissions') option('snap', type: 'boolean', value: false, description: 'build with Snap support') option('tests', type: 'boolean', value: true, description: 'build tests') -option('tracing', type: 'boolean', value: false, description: 'add extra debugging information') option('wayland', type: 'boolean', value: true, description: 'build with Wayland support') option('profile', type: 'combo', choices: ['default','development'], value: 'default') option('malcontent', type: 'boolean', value: false, description: 'build with malcontent support') diff --git a/panels/network/cc-wifi-panel.c b/panels/network/cc-wifi-panel.c index e53bae7f0..247a39bdb 100644 --- a/panels/network/cc-wifi-panel.c +++ b/panels/network/cc-wifi-panel.c @@ -26,7 +26,7 @@ #include "cc-list-row.h" #include "shell/cc-application.h" -#include "shell/cc-debug.h" +#include "shell/cc-log.h" #include "shell/cc-object-storage.h" #include diff --git a/panels/wacom/cc-wacom-panel.c b/panels/wacom/cc-wacom-panel.c index 36aca068f..25f4f07ac 100644 --- a/panels/wacom/cc-wacom-panel.c +++ b/panels/wacom/cc-wacom-panel.c @@ -26,7 +26,7 @@ #include #include "shell/cc-application.h" -#include "shell/cc-debug.h" +#include "shell/cc-log.h" #include "cc-wacom-panel.h" #include "cc-wacom-page.h" #include "cc-wacom-ekr-page.h" diff --git a/panels/wwan/cc-wwan-device-page.c b/panels/wwan/cc-wwan-device-page.c index 13aa87a1b..dd4a3ce45 100644 --- a/panels/wwan/cc-wwan-device-page.c +++ b/panels/wwan/cc-wwan-device-page.c @@ -42,7 +42,6 @@ #include "cc-wwan-resources.h" #include "shell/cc-application.h" -#include "shell/cc-debug.h" #include "shell/cc-object-storage.h" /** diff --git a/panels/wwan/cc-wwan-panel.c b/panels/wwan/cc-wwan-panel.c index 066a61598..52e8f5ce9 100644 --- a/panels/wwan/cc-wwan-panel.c +++ b/panels/wwan/cc-wwan-panel.c @@ -36,7 +36,7 @@ #include "cc-wwan-resources.h" #include "shell/cc-application.h" -#include "shell/cc-debug.h" +#include "shell/cc-log.h" #include "shell/cc-object-storage.h" typedef enum { diff --git a/shell/cc-application.c b/shell/cc-application.c index a51568bae..2ae0fbe2d 100644 --- a/shell/cc-application.c +++ b/shell/cc-application.c @@ -53,11 +53,16 @@ static void help_activated (GSimpleAction *action, GVariant *parameter, gpointer user_data); +static gboolean cmd_verbose_cb (const char *option_name, + const char *value, + gpointer data, + GError **error); + G_DEFINE_TYPE (CcApplication, cc_application, ADW_TYPE_APPLICATION) const GOptionEntry all_options[] = { { "version", 0, 0, G_OPTION_ARG_NONE, NULL, N_("Display version number"), NULL }, - { "verbose", 'v', 0, G_OPTION_ARG_NONE, NULL, N_("Enable verbose mode"), NULL }, + { "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, cmd_verbose_cb, N_("Enable verbose mode"), NULL }, { "search", 's', 0, G_OPTION_ARG_STRING, NULL, N_("Search for the string"), "SEARCH" }, { "list", 'l', 0, G_OPTION_ARG_NONE, NULL, N_("List possible panel names and exit"), NULL }, { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, NULL, N_("Panel to display"), N_("[PANEL] [ARGUMENT…]") }, @@ -90,6 +95,17 @@ help_activated (GSimpleAction *action, GDK_CURRENT_TIME); } +static gboolean +cmd_verbose_cb (const char *option_name, + const char *value, + gpointer data, + GError **error) +{ + cc_log_increase_verbosity (); + + return TRUE; +} + static void launch_panel_activated (GSimpleAction *action, GVariant *parameter, diff --git a/shell/cc-debug.h.in b/shell/cc-debug.h.in deleted file mode 100644 index 226f82e03..000000000 --- a/shell/cc-debug.h.in +++ /dev/null @@ -1,229 +0,0 @@ -/* 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 Settings 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 Settings 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 index dba4f5a26..e4434b3ca 100644 --- a/shell/cc-log.c +++ b/shell/cc-log.c @@ -1,6 +1,8 @@ -/* cc-shell-log.c +/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ +/* cc-log.c * * Copyright © 2018 Georges Basile Stavracas Neto + * Copyright 2022 Mohammed Sadiq * * 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 @@ -14,88 +16,464 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * Author(s): + * Georges Basile Stavracas Neto + * Mohammed Sadiq + * + * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "cc-debug.h" +#include +#include +#include +#include +#include + #include "cc-log.h" -#include -#include +#define DEFAULT_DOMAIN_PREFIX "cc" -G_LOCK_DEFINE_STATIC (channel_lock); +char *domains; +static int verbosity; +gboolean any_domain; +gboolean no_anonymize; +gboolean stderr_is_journal; +gboolean fatal_criticals, fatal_warnings; -GIOChannel *standard_channel = NULL; - -static const gchar* ignored_domains[] = +/* Copied from GLib, LGPLv2.1+ */ +static void +_g_log_abort (gboolean breakpoint) { - "GdkPixbuf", - NULL -}; + gboolean debugger_present; -static const gchar * -log_level_str (GLogLevelFlags log_level) -{ - switch (((gulong)log_level & G_LOG_LEVEL_MASK)) + if (g_test_subprocess ()) { - 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"; + /* If this is a test case subprocess then it probably caused + * this error message on purpose, so just exit() rather than + * abort()ing, to avoid triggering any system crash-reporting + * daemon. + */ + _exit (1); } + +#ifdef G_OS_WIN32 + debugger_present = IsDebuggerPresent (); +#else + /* Assume GDB is attached. */ + debugger_present = TRUE; +#endif /* !G_OS_WIN32 */ + + if (debugger_present && breakpoint) + G_BREAKPOINT (); + else + g_abort (); +} + +static gboolean +should_show_log_for_level (GLogLevelFlags log_level, + int verbosity_level) +{ + if (verbosity_level >= 5) + return TRUE; + + if (log_level & CC_LOG_LEVEL_TRACE) + return verbosity_level >= 4; + + if (log_level & G_LOG_LEVEL_DEBUG) + return verbosity_level >= 3; + + if (log_level & G_LOG_LEVEL_INFO) + return verbosity_level >= 2; + + if (log_level & G_LOG_LEVEL_MESSAGE) + return verbosity_level >= 1; + + return FALSE; +} + +static gboolean +matches_domain (const char *log_domains, + const char *domain) +{ + g_auto(GStrv) domain_list = NULL; + + if (!log_domains || !*log_domains || + !domain || !*domain) + return FALSE; + + domain_list = g_strsplit (log_domains, ",", -1); + + for (guint i = 0; domain_list[i]; i++) + { + if (g_str_has_prefix (domain, domain_list[i])) + return TRUE; + } + + return FALSE; +} + +static gboolean +should_log (const char *log_domain, + GLogLevelFlags log_level) +{ + g_assert (log_domain); + + /* Ignore custom flags set */ + log_level = log_level & ~CC_LOG_DETAILED; + + /* Don't skip serious logs */ + if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)) + return TRUE; + + if (any_domain && domains) { + /* If domain is “all” show logs upto debug regardless of the verbosity */ + if (log_level & ~CC_LOG_LEVEL_TRACE) + return TRUE; + + /* If the log is trace level, log if verbosity >= 4 */ + return verbosity >= 4; + } + + if (!domains && g_str_has_prefix (log_domain, DEFAULT_DOMAIN_PREFIX)) + return should_show_log_for_level (log_level, verbosity); + + if (domains && matches_domain (domains, log_domain)) + return should_show_log_for_level (log_level, verbosity); + + /* If we didn't handle domains in the preceding statement, + * we should no longer log them */ + if (domains) + return FALSE; + + /* GdkPixbuf and Gvc logs are too much verbose, skip unless asked not to. */ + if (verbosity < 8 && + (g_strcmp0 (log_domain, "GdkPixbuf") == 0 || + g_strcmp0 (log_domain, "Gvc") == 0) && + (!domains || !strstr (domains, log_domain))) + return FALSE; + + if (verbosity >= 6) + return TRUE; + + return FALSE; } static void -log_handler (const gchar *domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) +log_str_append_log_domain (GString *log_str, + const char *log_domain, + gboolean color) { - g_autoptr(GDateTime) now = NULL; - const gchar *level; - g_autofree gchar *ftime = NULL; - g_autofree gchar *buffer = NULL; + static const char *colors[] = { + "\033[1;32m", + "\033[1;33m", + "\033[1;35m", + "\033[1;36m", + "\033[1;91m", + "\033[1;92m", + "\033[1;93m", + "\033[1;94m", + "\033[1;95m", + "\033[1;96m", + }; + guint i; - /* Skip ignored log domains */ - if (domain && g_strv_contains (ignored_domains, domain)) - return; + g_assert (log_domain && *log_domain); - level = log_level_str (log_level); - now = g_date_time_new_now_local (); - ftime = g_date_time_format (now, "%H:%M:%S"); - buffer = g_strdup_printf ("%s.%04d %24s: %s: %s\n", - ftime, - g_date_time_get_microsecond (now) / 1000, - domain, - level, - message); + i = g_str_hash (log_domain) % G_N_ELEMENTS (colors); - /* Safely write to the channel */ - G_LOCK (channel_lock); + if (color) + g_string_append (log_str, colors[i]); + g_string_append_printf (log_str, "%20s", log_domain); - g_io_channel_write_chars (standard_channel, buffer, -1, NULL, NULL); - g_io_channel_flush (standard_channel, NULL); + if (color) + g_string_append (log_str, "\033[0m"); +} - G_UNLOCK (channel_lock); +static const char * +get_log_level_prefix (GLogLevelFlags log_level, + gboolean use_color) +{ + /* Ignore custom flags set */ + log_level = log_level & ~CC_LOG_DETAILED; + + if (use_color) + { + switch ((int)log_level) /* Same colors as used in GLib */ + { + 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;32mMESSAGE\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"; + } + } + else + { + switch ((int)log_level) + { + case G_LOG_LEVEL_ERROR: return " ERROR"; + case G_LOG_LEVEL_CRITICAL: return "CRITICAL"; + case G_LOG_LEVEL_WARNING: return " WARNING"; + case G_LOG_LEVEL_MESSAGE: return " MESSAGE"; + case G_LOG_LEVEL_INFO: return " INFO"; + case G_LOG_LEVEL_DEBUG: return " DEBUG"; + case CC_LOG_LEVEL_TRACE: return " TRACE"; + default: return " UNKNOWN"; + } + } +} + +static GLogWriterOutput +cc_log_write (GLogLevelFlags log_level, + const char *log_domain, + const char *log_message, + const GLogField *fields, + gsize n_fields, + gpointer user_data) +{ + g_autoptr(GString) log_str = NULL; + FILE *stream = stdout; + gboolean can_color; + + if (stderr_is_journal && + g_log_writer_journald (log_level, fields, n_fields, user_data) == G_LOG_WRITER_HANDLED) + return G_LOG_WRITER_HANDLED; + + if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)) + stream = stderr; + + log_str = g_string_new (NULL); + + /* Add local time */ + { + char buffer[32]; + struct tm tm_now; + time_t sec_now; + gint64 now; + + now = g_get_real_time (); + sec_now = now / G_USEC_PER_SEC; + tm_now = *localtime (&sec_now); + strftime (buffer, sizeof (buffer), "%H:%M:%S", &tm_now); + + g_string_append_printf (log_str, "%s.%04d ", buffer, + (int)((now % G_USEC_PER_SEC) / 100)); + } + + can_color = g_log_writer_supports_color (fileno (stream)); + log_str_append_log_domain (log_str, log_domain, can_color); + g_string_append_printf (log_str, "[%5d]:", getpid ()); + + g_string_append_printf (log_str, "%s: ", get_log_level_prefix (log_level, can_color)); + + if (log_level & CC_LOG_DETAILED) + { + const char *code_func = NULL, *code_line = NULL; + for (guint i = 0; i < n_fields; i++) + { + const GLogField *field = &fields[i]; + + if (!code_func && g_strcmp0 (field->key, "CODE_FUNC") == 0) + code_func = field->value; + else if (!code_line && g_strcmp0 (field->key, "CODE_LINE") == 0) + code_line = field->value; + + if (code_func && code_line) + break; + } + + if (code_func) + { + g_string_append_printf (log_str, "%s():", code_func); + + if (code_line) + g_string_append_printf (log_str, "%s:", code_line); + g_string_append_c (log_str, ' '); + } + } + + g_string_append (log_str, log_message); + + fprintf (stream, "%s\n", log_str->str); + fflush (stream); + + if (fatal_criticals && + (log_level & G_LOG_LEVEL_CRITICAL)) + log_level |= G_LOG_FLAG_FATAL; + else if (fatal_warnings && + (log_level & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING))) + log_level |= G_LOG_FLAG_FATAL; + + if (log_level & (G_LOG_FLAG_FATAL | G_LOG_LEVEL_ERROR)) + _g_log_abort (!(log_level & G_LOG_FLAG_RECURSION)); + + return G_LOG_WRITER_HANDLED; +} + +static GLogWriterOutput +cc_log_handler (GLogLevelFlags log_level, + const GLogField *fields, + gsize n_fields, + gpointer user_data) +{ + const char *log_domain = NULL; + const char *log_message = NULL; + + for (guint i = 0; (!log_domain || !log_message) && i < n_fields; i++) + { + const GLogField *field = &fields[i]; + + if (g_strcmp0 (field->key, "GLIB_DOMAIN") == 0) + log_domain = field->value; + else if (g_strcmp0 (field->key, "MESSAGE") == 0) + log_message = field->value; + } + + if (!log_domain) + log_domain = "**"; + + if (!log_message) + log_message = "(NULL) message"; + + if (!should_log (log_domain, log_level)) + return G_LOG_WRITER_HANDLED; + + return cc_log_write (log_level, log_domain, log_message, + fields, n_fields, user_data); +} + +static void +cc_log_finalize (void) +{ + g_clear_pointer (&domains, g_free); } void cc_log_init (void) { - static gsize initialized = FALSE; + static gsize initialized = 0; if (g_once_init_enter (&initialized)) { - standard_channel = g_io_channel_unix_new (STDOUT_FILENO); + domains = g_strdup (g_getenv ("G_MESSAGES_DEBUG")); - g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + if (domains && !*domains) + g_clear_pointer (&domains, g_free); - g_log_set_default_handler (log_handler, NULL); + if (!domains || g_str_equal (domains, "all")) + any_domain = TRUE; - g_once_init_leave (&initialized, TRUE); + if (domains && strstr (domains, "no-anonymize")) + { + any_domain = TRUE; + no_anonymize = TRUE; + g_clear_pointer (&domains, g_free); + } + + if (g_strcmp0 (g_getenv ("G_DEBUG"), "fatal-criticals") == 0) + fatal_criticals = TRUE; + else if (g_strcmp0 (g_getenv ("G_DEBUG"), "fatal-warnings") == 0) + fatal_warnings = TRUE; + + stderr_is_journal = g_log_writer_is_journald (fileno (stderr)); + g_log_set_writer_func (cc_log_handler, NULL, NULL); + g_once_init_leave (&initialized, 1); + atexit (cc_log_finalize); } } +void +cc_log_increase_verbosity (void) +{ + verbosity++; +} + +int +cc_log_get_verbosity (void) +{ + return verbosity; +} + +void +cc_log (const char *domain, + GLogLevelFlags log_level, + const char *value, + const char *file, + const char *line, + const char *func, + const char *message_format, + ...) +{ + g_autoptr(GString) str = NULL; + va_list args; + + if (!message_format || !*message_format) + return; + + if (!should_log (domain, log_level)) + return; + + str = g_string_new (NULL); + va_start (args, message_format); + g_string_append_vprintf (str, message_format, args); + va_end (args); + + cc_log_anonymize_value (str, value); + g_log_structured (domain, log_level, + "CODE_FILE", file, + "CODE_LINE", line, + "CODE_FUNC", func, + "MESSAGE", "%s", str->str); +} + +void +cc_log_anonymize_value (GString *str, + const char *value) +{ + gunichar c, next_c, prev_c; + + if (!value || !*value) + return; + + g_assert (str); + + if (str->len && str->str[str->len - 1] != ' ') + g_string_append_c (str, ' '); + + if (no_anonymize) + { + g_string_append (str, value); + return; + } + + if (!g_utf8_validate (value, -1, NULL)) + { + g_string_append (str, "******"); + return; + } + + c = g_utf8_get_char (value); + g_string_append_unichar (str, c); + + value = g_utf8_next_char (value); + + while (*value) + { + prev_c = c; + c = g_utf8_get_char (value); + + value = g_utf8_next_char (value); + next_c = g_utf8_get_char (value); + + if (!g_unichar_isalnum (c)) + g_string_append_unichar (str, c); + else if (!g_unichar_isalnum (prev_c) || !g_unichar_isalnum (next_c)) + g_string_append_unichar (str, c); + else + g_string_append_c (str, '#'); + } +} diff --git a/shell/cc-log.h b/shell/cc-log.h index 2d04c0ba7..eee0e11bc 100644 --- a/shell/cc-log.h +++ b/shell/cc-log.h @@ -1,6 +1,8 @@ +/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* cc-log.h * - * Copyright © 2018 Georges Basile Stavracas Neto + * Copyright 2018 Georges Basile Stavracas Neto + * Copyright 2021 Mohammed Sadiq * * 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 @@ -14,12 +16,75 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * Author(s): + * Georges Basile Stavracas Neto + * Mohammed Sadiq + * + * SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once +#include + G_BEGIN_DECLS -void cc_log_init (void); +#ifndef CC_LOG_LEVEL_TRACE +# define CC_LOG_LEVEL_TRACE ((GLogLevelFlags)(1 << G_LOG_LEVEL_USER_SHIFT)) +# define CC_LOG_DETAILED ((GLogLevelFlags)(1 << (G_LOG_LEVEL_USER_SHIFT + 1))) +#endif + +#define CC_DEBUG_MSG(fmt, ...) \ + cc_log (G_LOG_DOMAIN, \ + G_LOG_LEVEL_DEBUG | CC_LOG_DETAILED, \ + NULL, __FILE__, G_STRINGIFY (__LINE__), \ + G_STRFUNC, fmt, ##__VA_ARGS__) +#define CC_TRACE_MSG(fmt, ...) \ + cc_log (G_LOG_DOMAIN, \ + CC_LOG_LEVEL_TRACE | CC_LOG_DETAILED, \ + NULL, __FILE__, G_STRINGIFY (__LINE__), \ + G_STRFUNC, fmt, ##__VA_ARGS__) +#define CC_TRACE(fmt, ...) \ + cc_log (G_LOG_DOMAIN, \ + CC_LOG_LEVEL_TRACE, \ + NULL, __FILE__, G_STRINGIFY (__LINE__), \ + G_STRFUNC, fmt, ##__VA_ARGS__) +#define CC_TODO(_msg) \ + g_log_structured (G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, \ + "MESSAGE", " TODO: %s():%d: %s", \ + G_STRFUNC, __LINE__, _msg) +#define CC_ENTRY \ + g_log_structured (G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, \ + "MESSAGE", "ENTRY: %s():%d", \ + G_STRFUNC, __LINE__) +#define CC_EXIT \ + G_STMT_START { \ + g_log_structured (G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, \ + "MESSAGE", "EXIT: %s():%d", \ + G_STRFUNC, __LINE__); \ + return; \ + } G_STMT_END +#define CC_RETURN(_r) \ + G_STMT_START { \ + g_log_structured (G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, \ + "MESSAGE", "EXIT: %s():%d ", \ + G_STRFUNC, __LINE__); \ + return _r; \ + } G_STMT_END + +void cc_log_init (void); +void cc_log_increase_verbosity (void); +int cc_log_get_verbosity (void); +void cc_log (const char *domain, + GLogLevelFlags log_level, + const char *value, + const char *file, + const char *line, + const char *func, + const char *message_format, + ...) G_GNUC_PRINTF (7, 8); +void cc_log_anonymize_value (GString *str, + const char *value); G_END_DECLS diff --git a/shell/cc-panel-list.c b/shell/cc-panel-list.c index 185b16d0a..d8823b8b5 100644 --- a/shell/cc-panel-list.c +++ b/shell/cc-panel-list.c @@ -22,7 +22,7 @@ #include -#include "cc-debug.h" +#include "cc-log.h" #include "cc-panel-list.h" #include "cc-util.h" diff --git a/shell/cc-window.c b/shell/cc-window.c index 15d71247f..4ffdc8a70 100644 --- a/shell/cc-window.c +++ b/shell/cc-window.c @@ -24,7 +24,7 @@ #include -#include "cc-debug.h" +#include "cc-log.h" #include "cc-window.h" #include diff --git a/shell/main.c b/shell/main.c index 4a6125e1f..7ba5b3465 100644 --- a/shell/main.c +++ b/shell/main.c @@ -30,6 +30,7 @@ #include #endif +#include "cc-log.h" #include "cc-application.h" static void @@ -52,6 +53,7 @@ main (gint argc, textdomain (GETTEXT_PACKAGE); setlocale (LC_ALL, ""); + cc_log_init (); initialize_dependencies (&argc, &argv); diff --git a/shell/meson.build b/shell/meson.build index 8fe111a02..4811f0c82 100644 --- a/shell/meson.build +++ b/shell/meson.build @@ -56,17 +56,6 @@ common_sources = files( generated_sources = files() -# Debug -debug_conf = configuration_data() -debug_conf.set('BUGREPORT_URL', 'https://gitlab.gnome.org/GNOME/' + meson.project_name() + '/issues/new') -debug_conf.set10('ENABLE_TRACING', enable_tracing) - -generated_sources += configure_file( - input : 'cc-debug.h.in', - output : 'cc-debug.h', - configuration : debug_conf -) - #Resources resource_data = files( 'cc-panel-list.ui',