mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-09 12:25:48 +01:00
gmessages: Expose our default filtering as API
This allows programs that want to change how log messages are printed, such as gnome-terminal (gnome-terminal#42) and Flatpak, to override the log-writer or the legacy log-handler without having to reimplement the G_MESSAGES_DEBUG filtering logic. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
parent
10b0ece9d8
commit
b17b537a7d
@ -1485,6 +1485,7 @@ g_log_writer_journald
|
|||||||
g_log_writer_standard_streams
|
g_log_writer_standard_streams
|
||||||
g_log_writer_default
|
g_log_writer_default
|
||||||
g_log_writer_default_set_use_stderr
|
g_log_writer_default_set_use_stderr
|
||||||
|
g_log_writer_default_would_drop
|
||||||
|
|
||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
g_log_structured_standard
|
g_log_structured_standard
|
||||||
|
119
glib/gmessages.c
119
glib/gmessages.c
@ -127,7 +127,8 @@
|
|||||||
* It is recommended that custom log writer functions re-use the
|
* It is recommended that custom log writer functions re-use the
|
||||||
* `G_MESSAGES_DEBUG` environment variable, rather than inventing a custom one,
|
* `G_MESSAGES_DEBUG` environment variable, rather than inventing a custom one,
|
||||||
* so that developers can re-use the same debugging techniques and tools across
|
* so that developers can re-use the same debugging techniques and tools across
|
||||||
* projects.
|
* projects. Since GLib 2.68, this can be implemented by dropping messages
|
||||||
|
* for which g_log_writer_default_would_drop() returns %TRUE.
|
||||||
*
|
*
|
||||||
* ## Testing for Messages ## {#testing-for-messages}
|
* ## Testing for Messages ## {#testing-for-messages}
|
||||||
*
|
*
|
||||||
@ -2617,6 +2618,95 @@ log_is_old_api (const GLogField *fields,
|
|||||||
g_strcmp0 (fields[0].value, "1") == 0);
|
g_strcmp0 (fields[0].value, "1") == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal version of g_log_writer_default_would_drop(), which can
|
||||||
|
* read from either a log_domain or an array of fields. This avoids
|
||||||
|
* having to iterate through the fields if the @log_level is sufficient
|
||||||
|
* to make the decision.
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
should_drop_message (GLogLevelFlags log_level,
|
||||||
|
const char *log_domain,
|
||||||
|
const GLogField *fields,
|
||||||
|
gsize n_fields)
|
||||||
|
{
|
||||||
|
/* Disable debug message output unless specified in G_MESSAGES_DEBUG. */
|
||||||
|
if (!(log_level & DEFAULT_LEVELS) && !(log_level >> G_LOG_LEVEL_USER_SHIFT))
|
||||||
|
{
|
||||||
|
const gchar *domains;
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
domains = g_getenv ("G_MESSAGES_DEBUG");
|
||||||
|
|
||||||
|
if ((log_level & INFO_LEVELS) == 0 ||
|
||||||
|
domains == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (log_domain == NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; i < n_fields; i++)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (fields[i].key, "GLIB_DOMAIN") == 0)
|
||||||
|
{
|
||||||
|
log_domain = fields[i].value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (domains, "all") != 0 &&
|
||||||
|
(log_domain == NULL || !strstr (domains, log_domain)))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_log_writer_default_would_drop:
|
||||||
|
* @log_domain: (nullable): log domain
|
||||||
|
* @log_level: log level, either from #GLogLevelFlags, or a user-defined
|
||||||
|
* level
|
||||||
|
*
|
||||||
|
* Check whether g_log_writer_default() and g_log_default_handler() would
|
||||||
|
* ignore a message with the given domain and level.
|
||||||
|
*
|
||||||
|
* As with g_log_default_handler(), this function drops debug and informational
|
||||||
|
* messages unless their log domain (or `all`) is listed in the space-separated
|
||||||
|
* `G_MESSAGES_DEBUG` environment variable.
|
||||||
|
*
|
||||||
|
* This can be used when implementing log writers with the same filtering
|
||||||
|
* behaviour as the default, but a different destination or output format:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* if (g_log_writer_default_would_drop (log_level, log_domain))
|
||||||
|
* return G_LOG_WRITER_HANDLED;
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* or to skip an expensive computation if it is only needed for a debugging
|
||||||
|
* message, and `G_MESSAGES_DEBUG` is not set:
|
||||||
|
*
|
||||||
|
* |[<!-- language="C" -->
|
||||||
|
* if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
* {
|
||||||
|
* gchar *result = expensive_computation (my_object);
|
||||||
|
*
|
||||||
|
* g_debug ("my_object result: %s", result);
|
||||||
|
* g_free (result);
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the log message would be dropped by GLib's
|
||||||
|
* default log handlers
|
||||||
|
* Since: 2.68
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
g_log_writer_default_would_drop (GLogLevelFlags log_level,
|
||||||
|
const char *log_domain)
|
||||||
|
{
|
||||||
|
return should_drop_message (log_level, log_domain, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_log_writer_default:
|
* g_log_writer_default:
|
||||||
* @log_level: log level, either from #GLogLevelFlags, or a user-defined
|
* @log_level: log level, either from #GLogLevelFlags, or a user-defined
|
||||||
@ -2661,31 +2751,8 @@ g_log_writer_default (GLogLevelFlags log_level,
|
|||||||
g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED);
|
g_return_val_if_fail (fields != NULL, G_LOG_WRITER_UNHANDLED);
|
||||||
g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED);
|
g_return_val_if_fail (n_fields > 0, G_LOG_WRITER_UNHANDLED);
|
||||||
|
|
||||||
/* Disable debug message output unless specified in G_MESSAGES_DEBUG. */
|
if (should_drop_message (log_level, NULL, fields, n_fields))
|
||||||
if (!(log_level & DEFAULT_LEVELS) && !(log_level >> G_LOG_LEVEL_USER_SHIFT))
|
return G_LOG_WRITER_HANDLED;
|
||||||
{
|
|
||||||
const gchar *domains, *log_domain = NULL;
|
|
||||||
gsize i;
|
|
||||||
|
|
||||||
domains = g_getenv ("G_MESSAGES_DEBUG");
|
|
||||||
|
|
||||||
if ((log_level & INFO_LEVELS) == 0 ||
|
|
||||||
domains == NULL)
|
|
||||||
return G_LOG_WRITER_HANDLED;
|
|
||||||
|
|
||||||
for (i = 0; i < n_fields; i++)
|
|
||||||
{
|
|
||||||
if (g_strcmp0 (fields[i].key, "GLIB_DOMAIN") == 0)
|
|
||||||
{
|
|
||||||
log_domain = fields[i].value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (domains, "all") != 0 &&
|
|
||||||
(log_domain == NULL || !strstr (domains, log_domain)))
|
|
||||||
return G_LOG_WRITER_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark messages as fatal if they have a level set in
|
/* Mark messages as fatal if they have a level set in
|
||||||
* g_log_set_always_fatal().
|
* g_log_set_always_fatal().
|
||||||
|
@ -244,6 +244,9 @@ GLogWriterOutput g_log_writer_default (GLogLevelFlags log_level,
|
|||||||
|
|
||||||
GLIB_AVAILABLE_IN_2_68
|
GLIB_AVAILABLE_IN_2_68
|
||||||
void g_log_writer_default_set_use_stderr (gboolean use_stderr);
|
void g_log_writer_default_set_use_stderr (gboolean use_stderr);
|
||||||
|
GLIB_AVAILABLE_IN_2_68
|
||||||
|
gboolean g_log_writer_default_would_drop (GLogLevelFlags log_level,
|
||||||
|
const char *log_domain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* G_DEBUG_HERE:
|
* G_DEBUG_HERE:
|
||||||
|
@ -139,6 +139,53 @@ test_default_handler_debug_stderr (void)
|
|||||||
g_log ("foo", G_LOG_LEVEL_DEBUG, "6");
|
g_log ("foo", G_LOG_LEVEL_DEBUG, "6");
|
||||||
g_log ("bar", G_LOG_LEVEL_DEBUG, "6");
|
g_log ("bar", G_LOG_LEVEL_DEBUG, "6");
|
||||||
g_log ("baz", G_LOG_LEVEL_DEBUG, "6");
|
g_log ("baz", G_LOG_LEVEL_DEBUG, "6");
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_default_handler_would_drop (void)
|
||||||
|
{
|
||||||
|
g_unsetenv ("G_MESSAGES_DEBUG");
|
||||||
|
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
|
||||||
|
g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
|
||||||
|
g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
|
||||||
|
|
||||||
|
g_setenv ("G_MESSAGES_DEBUG", "bar baz", TRUE);
|
||||||
|
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
|
||||||
|
g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
|
||||||
|
g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
|
||||||
|
|
||||||
|
g_setenv ("G_MESSAGES_DEBUG", "foo bar", TRUE);
|
||||||
|
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
|
||||||
|
|
||||||
|
g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
|
||||||
|
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
|
||||||
|
g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
|
||||||
|
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,6 +240,9 @@ test_default_handler (void)
|
|||||||
g_test_trap_subprocess ("/logging/default-handler/subprocess/0x400", 0, 0);
|
g_test_trap_subprocess ("/logging/default-handler/subprocess/0x400", 0, 0);
|
||||||
g_test_trap_assert_passed ();
|
g_test_trap_assert_passed ();
|
||||||
g_test_trap_assert_stdout ("*LOG-0x400*message7*");
|
g_test_trap_assert_stdout ("*LOG-0x400*message7*");
|
||||||
|
|
||||||
|
g_test_trap_subprocess ("/logging/default-handler/subprocess/would-drop", 0, 0);
|
||||||
|
g_test_trap_assert_passed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -600,6 +650,7 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/logging/default-handler/subprocess/debug", test_default_handler_debug);
|
g_test_add_func ("/logging/default-handler/subprocess/debug", test_default_handler_debug);
|
||||||
g_test_add_func ("/logging/default-handler/subprocess/debug-stderr", test_default_handler_debug_stderr);
|
g_test_add_func ("/logging/default-handler/subprocess/debug-stderr", test_default_handler_debug_stderr);
|
||||||
g_test_add_func ("/logging/default-handler/subprocess/0x400", test_default_handler_0x400);
|
g_test_add_func ("/logging/default-handler/subprocess/0x400", test_default_handler_0x400);
|
||||||
|
g_test_add_func ("/logging/default-handler/subprocess/would-drop", test_default_handler_would_drop);
|
||||||
g_test_add_func ("/logging/warnings", test_warnings);
|
g_test_add_func ("/logging/warnings", test_warnings);
|
||||||
g_test_add_func ("/logging/fatal-log-mask", test_fatal_log_mask);
|
g_test_add_func ("/logging/fatal-log-mask", test_fatal_log_mask);
|
||||||
g_test_add_func ("/logging/set-handler", test_set_handler);
|
g_test_add_func ("/logging/set-handler", test_set_handler);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user