mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-26 05:56:14 +01:00
Add g_log_variant(): structured log that accepts a GVariant
This makes the structured logging available to other languages via introspection. https://bugzilla.gnome.org/show_bug.cgi?id=770971
This commit is contained in:
parent
9323378834
commit
e7bdd5d189
@ -1177,6 +1177,7 @@ g_log_set_default_handler
|
||||
|
||||
<SUBSECTION>
|
||||
g_log_structured
|
||||
g_log_variant
|
||||
GLogField
|
||||
g_log_structured_array
|
||||
G_DEBUG_HERE
|
||||
|
110
glib/gmessages.c
110
glib/gmessages.c
@ -1602,6 +1602,116 @@ g_log_structured (const gchar *log_domain,
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_log_variant:
|
||||
* @log_domain: log domain, usually %G_LOG_DOMAIN
|
||||
* @log_level: log level, either from #GLogLevelFlags, or a user-defined
|
||||
* level
|
||||
* @fields: a dictionary (#GVariant of the type %G_VARIANT_TYPE_VARDICT)
|
||||
* containing the key-value pairs of message data.
|
||||
*
|
||||
* Log a message with structured data, accepting the data within a #GVariant. This
|
||||
* version is especially useful for use in other languages, via introspection.
|
||||
*
|
||||
* The only mandatory item in the @fields dictionary is the "MESSAGE" which must
|
||||
* contain the text shown to the user.
|
||||
*
|
||||
* The values in the @fields dictionary are likely to be of type String
|
||||
* (#G_VARIANT_TYPE_STRING). Array of bytes (#G_VARIANT_TYPE_BYTESTRING) is also
|
||||
* supported. In this case the message is handled as binary and will be forwarded
|
||||
* to the log writer as such. The size of the array should not be higher than
|
||||
* %G_MAXSSIZE. Otherwise it will be truncated to this size. For other types
|
||||
* g_variant_print() will be used to convert the value into a string.
|
||||
*
|
||||
* For more details on its usage and about the parameters, see g_log_structured().
|
||||
*
|
||||
* Since: 2.50
|
||||
*/
|
||||
|
||||
void
|
||||
g_log_variant (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
GVariant *fields)
|
||||
{
|
||||
GVariantIter iter;
|
||||
GVariant *value;
|
||||
gchar *key;
|
||||
GArray *fields_array;
|
||||
GLogField field;
|
||||
GSList *values_list, *print_list;
|
||||
|
||||
g_return_if_fail (g_variant_is_of_type (fields, G_VARIANT_TYPE_VARDICT));
|
||||
|
||||
values_list = print_list = NULL;
|
||||
fields_array = g_array_new (FALSE, FALSE, sizeof (GLogField));
|
||||
|
||||
field.key = "PRIORITY";
|
||||
field.value = log_level_to_priority (log_level);
|
||||
field.length = -1;
|
||||
g_array_append_val (fields_array, field);
|
||||
|
||||
if (log_domain)
|
||||
{
|
||||
field.key = "GLIB_DOMAIN";
|
||||
field.value = log_domain;
|
||||
field.length = -1;
|
||||
g_array_append_val (fields_array, field);
|
||||
}
|
||||
|
||||
g_variant_iter_init (&iter, fields);
|
||||
while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
|
||||
{
|
||||
gboolean defer_unref = TRUE;
|
||||
|
||||
field.key = key;
|
||||
field.length = -1;
|
||||
|
||||
if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
|
||||
{
|
||||
field.value = g_variant_get_string (value, NULL);
|
||||
}
|
||||
else if (g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING))
|
||||
{
|
||||
gsize s;
|
||||
field.value = g_variant_get_fixed_array (value, &s, sizeof (guchar));
|
||||
if (G_LIKELY (s <= G_MAXSSIZE))
|
||||
{
|
||||
field.length = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
_g_fprintf (stderr,
|
||||
"Byte array too large (%" G_GSIZE_FORMAT " bytes)"
|
||||
" passed to g_log_variant(). Truncating to " G_STRINGIFY (G_MAXSSIZE)
|
||||
" bytes.", s);
|
||||
field.length = G_MAXSSIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *s = g_variant_print (value, FALSE);
|
||||
field.value = s;
|
||||
print_list = g_slist_prepend (print_list, s);
|
||||
defer_unref = FALSE;
|
||||
}
|
||||
|
||||
g_array_append_val (fields_array, field);
|
||||
|
||||
if (G_LIKELY (defer_unref))
|
||||
values_list = g_slist_prepend (values_list, value);
|
||||
else
|
||||
g_variant_unref (value);
|
||||
}
|
||||
|
||||
/* Log it. */
|
||||
g_log_structured_array (log_level, (GLogField *) fields_array->data, fields_array->len);
|
||||
|
||||
g_array_free (fields_array, TRUE);
|
||||
g_slist_free_full (values_list, (GDestroyNotify) g_variant_unref);
|
||||
g_slist_free_full (print_list, g_free);
|
||||
}
|
||||
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
static GLogWriterOutput _g_log_writer_fallback (GLogLevelFlags log_level,
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib/gmacros.h>
|
||||
#include <glib/gvariant.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -196,6 +197,11 @@ void g_log_structured_array (GLogLevelFlags log_level,
|
||||
const GLogField *fields,
|
||||
gsize n_fields);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_50
|
||||
void g_log_variant (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
GVariant *fields);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_50
|
||||
void g_log_set_writer_func (GLogWriterFunc func,
|
||||
gpointer user_data,
|
||||
|
@ -345,6 +345,8 @@ compare_fields (const GLogField *f1, gsize n1, const GLogField *f2, gsize n2)
|
||||
}
|
||||
|
||||
static GSList *expected_messages = NULL;
|
||||
static const guchar binary_field[] = {1, 2, 3, 4, 5};
|
||||
|
||||
|
||||
static GLogWriterOutput
|
||||
expect_log_writer (GLogLevelFlags log_level,
|
||||
@ -500,6 +502,58 @@ test_structured_logging_roundtrip3 (void)
|
||||
g_assert (expected_messages == NULL);
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
create_variant_fields (void)
|
||||
{
|
||||
GVariant *binary;
|
||||
GVariantBuilder builder;
|
||||
|
||||
binary = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, binary_field, G_N_ELEMENTS (binary_field), sizeof (binary_field[0]));
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&builder, "{sv}", "MESSAGE_ID", g_variant_new_string ("06d4df59e6c24647bfe69d2c27ef0b4e"));
|
||||
g_variant_builder_add (&builder, "{sv}", "MESSAGE", g_variant_new_string ("This is a debug message"));
|
||||
g_variant_builder_add (&builder, "{sv}", "MY_APPLICATION_CUSTOM_FIELD", g_variant_new_string ("some debug string"));
|
||||
g_variant_builder_add (&builder, "{sv}", "MY_APPLICATION_CUSTOM_FIELD_BINARY", binary);
|
||||
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
static void
|
||||
test_structured_logging_variant1 (void)
|
||||
{
|
||||
GVariant *v = create_variant_fields ();
|
||||
|
||||
log_count = 0;
|
||||
g_log_set_writer_func (null_log_writer, NULL, NULL);
|
||||
|
||||
g_log_variant ("some-domain", G_LOG_LEVEL_MESSAGE, v);
|
||||
g_variant_unref (v);
|
||||
g_assert_cmpint (log_count, ==, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_structured_logging_variant2 (void)
|
||||
{
|
||||
const GLogField fields[] = {
|
||||
{ "GLIB_DOMAIN", "some-domain", -1 },
|
||||
{ "PRIORITY", "5", -1 },
|
||||
{ "MESSAGE", "This is a debug message", -1 },
|
||||
{ "MESSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e", -1 },
|
||||
{ "MY_APPLICATION_CUSTOM_FIELD", "some debug string", -1 },
|
||||
{ "MY_APPLICATION_CUSTOM_FIELD_BINARY", binary_field, sizeof (binary_field) }
|
||||
};
|
||||
ExpectedMessage expected = { fields, 6 };
|
||||
GVariant *v = create_variant_fields ();
|
||||
|
||||
expected_messages = g_slist_append (NULL, &expected);
|
||||
g_log_set_writer_func (expect_log_writer, NULL, NULL);
|
||||
|
||||
g_log_variant ("some-domain", G_LOG_LEVEL_MESSAGE, v);
|
||||
g_variant_unref (v);
|
||||
g_assert (expected_messages == NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -531,6 +585,8 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/structured-logging/roundtrip1", test_structured_logging_roundtrip1);
|
||||
g_test_add_func ("/structured-logging/roundtrip2", test_structured_logging_roundtrip2);
|
||||
g_test_add_func ("/structured-logging/roundtrip3", test_structured_logging_roundtrip3);
|
||||
g_test_add_func ("/structured-logging/variant1", test_structured_logging_variant1);
|
||||
g_test_add_func ("/structured-logging/variant2", test_structured_logging_variant2);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user