gmessages: Treat DEBUG_INVOCATION=1 same as G_MESSAGES_DEBUG=all

systemd 257 will now set `DEBUG_INVOCATION=1` in the execution context
of services which need to be debugged — for example if they’ve failed
and been restarted (and `RestartMode=debug`).

If we handle `DEBUG_INVOCATION=1` as being equivalent to
`G_MESSAGES_DEBUG=all`, then any processes using GLib’s default log
writer function (or `g_log_writer_default_would_drop()`) automatically
gains support for this feature.

See https://mastodon.social/@pid_eins/113548825942383777

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
This commit is contained in:
Philip Withnall 2024-11-26 15:38:41 +00:00
parent dfe252429c
commit 8b29c53057
No known key found for this signature in database
GPG Key ID: C5C42CFB268637CA
3 changed files with 40 additions and 16 deletions

View File

@ -92,13 +92,14 @@ The default log functions (`g_log_default_handler()` for the old-style API
and `g_log_writer_default()` for the structured API) both drop debug and and `g_log_writer_default()` for the structured API) both drop debug and
informational messages by default, unless the log domains of those messages informational messages by default, unless the log domains of those messages
are listed in the `G_MESSAGES_DEBUG` environment variable (or it is set to are listed in the `G_MESSAGES_DEBUG` environment variable (or it is set to
`all`). `all`), or `DEBUG_INVOCATION=1` is set in the environment.
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` and `DEBUG_INVOCATION` environment variables, rather than
so that developers can re-use the same debugging techniques and tools across inventing a custom one, so that developers can re-use the same debugging
projects. Since GLib 2.68, this can be implemented by dropping messages for techniques and tools across projects. Since GLib 2.68, this can be implemented
which `g_log_writer_default_would_drop()` returns `TRUE`. by dropping messages for which `g_log_writer_default_would_drop()` returns
`TRUE`.
## Testing for Messages ## Testing for Messages

View File

@ -316,8 +316,9 @@
* manually. * manually.
* *
* Such messages are suppressed by the [func@GLib.log_default_handler] and * Such messages are suppressed by the [func@GLib.log_default_handler] and
* [func@GLib.log_writer_default] unless the `G_MESSAGES_DEBUG` environment variable is * [func@GLib.log_writer_default] unless the `G_MESSAGES_DEBUG` or
* set appropriately. If you need to set the allowed domains at runtime, use * `DEBUG_INVOCATION` environment variables are set appropriately. If you need
* to set the allowed domains at runtime, use
* [func@GLib.log_writer_default_set_debug_domains]. * [func@GLib.log_writer_default_set_debug_domains].
* *
* If structured logging is enabled, this will use [func@GLib.log_structured]; * If structured logging is enabled, this will use [func@GLib.log_structured];
@ -341,8 +342,9 @@
* manually. * manually.
* *
* Such messages are suppressed by the [func@GLib.log_default_handler] and * Such messages are suppressed by the [func@GLib.log_default_handler] and
* [func@GLib.log_writer_default] unless the `G_MESSAGES_DEBUG` environment variable is * [func@GLib.log_writer_default] unless the `G_MESSAGES_DEBUG` or
* set appropriately. If you need to set the allowed domains at runtime, use * `DEBUG_INVOCATION` environment variables are set appropriately. If you need
* to set the allowed domains at runtime, use
* [func@GLib.log_writer_default_set_debug_domains]. * [func@GLib.log_writer_default_set_debug_domains].
* *
* If structured logging is enabled, this will use [func@GLib.log_structured]; * If structured logging is enabled, this will use [func@GLib.log_structured];
@ -2705,7 +2707,7 @@ static struct {
* `NULL` or an array with no values means none. Array with a single value `"all"` means all. * `NULL` or an array with no values means none. Array with a single value `"all"` means all.
* *
* Reset the list of domains to be logged, that might be initially set by the * Reset the list of domains to be logged, that might be initially set by the
* `G_MESSAGES_DEBUG` environment variable. * `G_MESSAGES_DEBUG` or `DEBUG_INVOCATION` environment variables.
* *
* This function is thread-safe. * This function is thread-safe.
* *
@ -2737,7 +2739,7 @@ should_drop_message (GLogLevelFlags log_level,
const GLogField *fields, const GLogField *fields,
gsize n_fields) gsize n_fields)
{ {
/* Disable debug message output unless specified in G_MESSAGES_DEBUG. */ /* Disable debug message output unless specified in G_MESSAGES_DEBUG/DEBUG_INVOCATION. */
if (!(log_level & DEFAULT_LEVELS) && if (!(log_level & DEFAULT_LEVELS) &&
!(log_level >> G_LOG_LEVEL_USER_SHIFT) && !(log_level >> G_LOG_LEVEL_USER_SHIFT) &&
!g_log_get_debug_enabled ()) !g_log_get_debug_enabled ())
@ -2750,6 +2752,8 @@ should_drop_message (GLogLevelFlags log_level,
if (G_UNLIKELY (!g_log_global.domains_set)) if (G_UNLIKELY (!g_log_global.domains_set))
{ {
g_log_global.domains = g_strdup (g_getenv ("G_MESSAGES_DEBUG")); g_log_global.domains = g_strdup (g_getenv ("G_MESSAGES_DEBUG"));
if (g_log_global.domains == NULL && g_strcmp0 (g_getenv ("DEBUG_INVOCATION"), "1") == 0)
g_log_global.domains = g_strdup ("all");
g_log_global.domains_set = TRUE; g_log_global.domains_set = TRUE;
} }
@ -2804,7 +2808,8 @@ should_drop_message (GLogLevelFlags log_level,
* *
* As with [func@GLib.log_default_handler], this function drops debug and informational * As with [func@GLib.log_default_handler], this function drops debug and informational
* messages unless their log domain (or `all`) is listed in the space-separated * messages unless their log domain (or `all`) is listed in the space-separated
* `G_MESSAGES_DEBUG` environment variable, or by [func@GLib.log_writer_default_set_debug_domains]. * `G_MESSAGES_DEBUG` environment variable, or `DEBUG_INVOCATION=1` is set in
* the environment, or by [func@GLib.log_writer_default_set_debug_domains].
* *
* This can be used when implementing log writers with the same filtering * This can be used when implementing log writers with the same filtering
* behaviour as the default, but a different destination or output format: * behaviour as the default, but a different destination or output format:
@ -2815,7 +2820,7 @@ should_drop_message (GLogLevelFlags log_level,
* ]| * ]|
* *
* or to skip an expensive computation if it is only needed for a debugging * or to skip an expensive computation if it is only needed for a debugging
* message, and `G_MESSAGES_DEBUG` is not set: * message, and `G_MESSAGES_DEBUG` and `DEBUG_INVOCATION` are not set:
* *
* ```c * ```c
* if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN)) * if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
@ -2862,7 +2867,8 @@ g_log_writer_default_would_drop (GLogLevelFlags log_level,
* *
* As with [func@GLib.log_default_handler], this function drops debug and informational * As with [func@GLib.log_default_handler], this function drops debug and informational
* messages unless their log domain (or `all`) is listed in the space-separated * messages unless their log domain (or `all`) is listed in the space-separated
* `G_MESSAGES_DEBUG` environment variable, or set at runtime by [func@GLib.log_writer_default_set_debug_domains]. * `G_MESSAGES_DEBUG` environment variable, or `DEBUG_INVOCATION=1` is set in
* the environment, or set at runtime by [func@GLib.log_writer_default_set_debug_domains].
* *
* [func@GLib.log_writer_default] uses the mask set by [func@GLib.log_set_always_fatal] to * [func@GLib.log_writer_default] uses the mask set by [func@GLib.log_set_always_fatal] to
* determine which messages are fatal. When using a custom writer function instead it is * determine which messages are fatal. When using a custom writer function instead it is
@ -3005,7 +3011,8 @@ _g_log_writer_fallback (GLogLevelFlags log_level,
* implementations. * implementations.
* *
* Note also that the value of this does not depend on `G_MESSAGES_DEBUG`, nor * Note also that the value of this does not depend on `G_MESSAGES_DEBUG`, nor
* [func@GLib.log_writer_default_set_debug_domains]; see the docs for [func@GLib.log_set_debug_enabled]. * `DEBUG_INVOCATION`, nor [func@GLib.log_writer_default_set_debug_domains]; see
* the docs for [func@GLib.log_set_debug_enabled].
* *
* Returns: `TRUE` if debug output is enabled, `FALSE` otherwise * Returns: `TRUE` if debug output is enabled, `FALSE` otherwise
* *
@ -3023,7 +3030,7 @@ g_log_get_debug_enabled (void)
* *
* Enable or disable debug output from the GLib logging system for all domains. * Enable or disable debug output from the GLib logging system for all domains.
* *
* This value interacts disjunctively with `G_MESSAGES_DEBUG` and * This value interacts disjunctively with `G_MESSAGES_DEBUG`, `DEBUG_INVOCATION` and
* [func@GLib.log_writer_default_set_debug_domains] if any of them would allow * [func@GLib.log_writer_default_set_debug_domains] if any of them would allow
* a debug message to be outputted, it will be. * a debug message to be outputted, it will be.
* *
@ -3355,6 +3362,9 @@ escape_string (GString *string)
* which debug and informational messages are printed. By default * which debug and informational messages are printed. By default
* these messages are not printed. If you need to set the allowed * these messages are not printed. If you need to set the allowed
* domains at runtime, use [func@GLib.log_writer_default_set_debug_domains]. * domains at runtime, use [func@GLib.log_writer_default_set_debug_domains].
* - `DEBUG_INVOCATION`: If set to `1`, this is equivalent to
* `G_MESSAGES_DEBUG=all`. `DEBUG_INVOCATION` is a standard environment
* variable set by systemd to prompt debug output. (Since: 2.84)
* *
* `stderr` is used for levels [flags@GLib.LogLevelFlags.LEVEL_ERROR], * `stderr` is used for levels [flags@GLib.LogLevelFlags.LEVEL_ERROR],
* [flags@GLib.LogLevelFlags.LEVEL_CRITICAL], [flags@GLib.LogLevelFlags.LEVEL_WARNING] and * [flags@GLib.LogLevelFlags.LEVEL_CRITICAL], [flags@GLib.LogLevelFlags.LEVEL_WARNING] and

View File

@ -201,6 +201,15 @@ test_default_handler_debug_stderr (void)
exit (0); exit (0);
} }
static void
test_default_handler_would_drop_env_systemd (void)
{
g_setenv ("DEBUG_INVOCATION", "1", TRUE);
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "bar"));
}
static void static void
test_default_handler_would_drop_env5 (void) test_default_handler_would_drop_env5 (void)
{ {
@ -558,6 +567,9 @@ test_default_handler (void)
g_test_trap_subprocess ("/logging/default-handler/subprocess/would-drop-env5", 0, g_test_trap_subprocess ("/logging/default-handler/subprocess/would-drop-env5", 0,
G_TEST_SUBPROCESS_DEFAULT); G_TEST_SUBPROCESS_DEFAULT);
g_test_trap_assert_passed (); g_test_trap_assert_passed ();
g_test_trap_subprocess ("/logging/default-handler/subprocess/would-drop-env-systemd", 0,
G_TEST_SUBPROCESS_DEFAULT);
g_test_trap_assert_passed ();
g_test_trap_subprocess ("/logging/default-handler/subprocess/would-drop-robustness", 0, g_test_trap_subprocess ("/logging/default-handler/subprocess/would-drop-robustness", 0,
G_TEST_SUBPROCESS_DEFAULT); G_TEST_SUBPROCESS_DEFAULT);
g_test_trap_assert_passed (); g_test_trap_assert_passed ();
@ -1105,6 +1117,7 @@ main (int argc, char *argv[])
g_test_add_func ("/logging/default-handler/subprocess/would-drop-env3", test_default_handler_would_drop_env3); g_test_add_func ("/logging/default-handler/subprocess/would-drop-env3", test_default_handler_would_drop_env3);
g_test_add_func ("/logging/default-handler/subprocess/would-drop-env4", test_default_handler_would_drop_env4); g_test_add_func ("/logging/default-handler/subprocess/would-drop-env4", test_default_handler_would_drop_env4);
g_test_add_func ("/logging/default-handler/subprocess/would-drop-env5", test_default_handler_would_drop_env5); g_test_add_func ("/logging/default-handler/subprocess/would-drop-env5", test_default_handler_would_drop_env5);
g_test_add_func ("/logging/default-handler/subprocess/would-drop-env-systemd", test_default_handler_would_drop_env_systemd);
g_test_add_func ("/logging/default-handler/subprocess/would-drop-robustness", test_default_handler_would_drop_robustness); g_test_add_func ("/logging/default-handler/subprocess/would-drop-robustness", test_default_handler_would_drop_robustness);
g_test_add_func ("/logging/default-handler/subprocess/structured-logging-non-null-terminated-strings", test_default_handler_structured_logging_non_nul_terminated_strings); g_test_add_func ("/logging/default-handler/subprocess/structured-logging-non-null-terminated-strings", test_default_handler_structured_logging_non_nul_terminated_strings);
g_test_add_func ("/logging/warnings", test_warnings); g_test_add_func ("/logging/warnings", test_warnings);