summaryrefslogtreecommitdiffstats
path: root/lib/gs-debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gs-debug.c')
-rw-r--r--lib/gs-debug.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/lib/gs-debug.c b/lib/gs-debug.c
new file mode 100644
index 0000000..ad429a4
--- /dev/null
+++ b/lib/gs-debug.c
@@ -0,0 +1,190 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2016 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2017 Kalev Lember <klember@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "gs-debug.h"
+
+struct _GsDebug
+{
+ GObject parent_instance;
+ GMutex mutex;
+ gboolean use_time;
+};
+
+G_DEFINE_TYPE (GsDebug, gs_debug, G_TYPE_OBJECT)
+
+static GLogWriterOutput
+gs_log_writer_console (GLogLevelFlags log_level,
+ const GLogField *fields,
+ gsize n_fields,
+ gpointer user_data)
+{
+ GsDebug *debug = GS_DEBUG (user_data);
+ const gchar *log_domain = NULL;
+ const gchar *log_message = NULL;
+ g_autofree gchar *tmp = NULL;
+ g_autoptr(GMutexLocker) locker = NULL;
+ g_autoptr(GString) domain = NULL;
+
+ /* enabled */
+ if (g_getenv ("GS_DEBUG") == NULL &&
+ log_level == G_LOG_LEVEL_DEBUG)
+ return G_LOG_WRITER_HANDLED;
+
+ /* get data from arguments */
+ for (gsize i = 0; i < n_fields; i++) {
+ if (g_strcmp0 (fields[i].key, "MESSAGE") == 0) {
+ log_message = fields[i].value;
+ continue;
+ }
+ if (g_strcmp0 (fields[i].key, "GLIB_DOMAIN") == 0) {
+ log_domain = fields[i].value;
+ continue;
+ }
+ }
+
+ /* this is really verbose */
+ if (g_strcmp0 (log_domain, "dconf") == 0 &&
+ log_level == G_LOG_LEVEL_DEBUG)
+ return G_LOG_WRITER_HANDLED;
+
+ /* make threadsafe */
+ locker = g_mutex_locker_new (&debug->mutex);
+ g_assert (locker != NULL);
+
+ /* time header */
+ if (debug->use_time) {
+ g_autoptr(GDateTime) dt = g_date_time_new_now_utc ();
+ tmp = g_strdup_printf ("%02i:%02i:%02i:%04i",
+ g_date_time_get_hour (dt),
+ g_date_time_get_minute (dt),
+ g_date_time_get_second (dt),
+ g_date_time_get_microsecond (dt) / 1000);
+ }
+
+ /* make these shorter */
+ if (g_strcmp0 (log_domain, "PackageKit") == 0) {
+ log_domain = "PK";
+ } else if (g_strcmp0 (log_domain, "GsPlugin") == 0) {
+ log_domain = "Gs";
+ }
+
+ /* pad out domain */
+ domain = g_string_new (log_domain);
+ for (guint i = domain->len; i < 3; i++)
+ g_string_append (domain, " ");
+
+ switch (log_level) {
+ case G_LOG_LEVEL_ERROR:
+ case G_LOG_LEVEL_CRITICAL:
+ case G_LOG_LEVEL_WARNING:
+ /* to screen */
+ if (isatty (fileno (stderr)) == 1) {
+ /* critical in red */
+ if (tmp != NULL)
+ g_printerr ("%c[%dm%s ", 0x1B, 32, tmp);
+ g_printerr ("%s ", domain->str);
+ g_printerr ("%c[%dm%s\n%c[%dm", 0x1B, 31, log_message, 0x1B, 0);
+ } else { /* to file */
+ if (tmp != NULL)
+ g_print ("%s ", tmp);
+ g_print ("%s ", domain->str);
+ g_print ("%s\n", log_message);
+ }
+ break;
+ default:
+ /* to screen */
+ if (isatty (fileno (stdout)) == 1) {
+ /* debug in blue */
+ if (tmp != NULL)
+ g_print ("%c[%dm%s ", 0x1B, 32, tmp);
+ g_print ("%s ", domain->str);
+ g_print ("%c[%dm%s\n%c[%dm", 0x1B, 34, log_message, 0x1B, 0);
+ break;
+ } else { /* to file */
+ if (tmp != NULL)
+ g_print ("%s ", tmp);
+ g_print ("%s ", domain->str);
+ g_print ("%s\n", log_message);
+ }
+ }
+
+ /* success */
+ return G_LOG_WRITER_HANDLED;
+}
+
+static GLogWriterOutput
+gs_log_writer_journald (GLogLevelFlags log_level,
+ const GLogField *fields,
+ gsize n_fields,
+ gpointer user_data)
+{
+ /* important enough to force to the journal */
+ switch (log_level) {
+ case G_LOG_LEVEL_ERROR:
+ case G_LOG_LEVEL_CRITICAL:
+ case G_LOG_LEVEL_WARNING:
+ case G_LOG_LEVEL_INFO:
+ return g_log_writer_journald (log_level, fields, n_fields, user_data);
+ break;
+ default:
+ break;
+ }
+
+ return G_LOG_WRITER_UNHANDLED;
+}
+
+static GLogWriterOutput
+gs_debug_log_writer (GLogLevelFlags log_level,
+ const GLogField *fields,
+ gsize n_fields,
+ gpointer user_data)
+{
+ if (g_log_writer_is_journald (fileno (stderr)))
+ return gs_log_writer_journald (log_level, fields, n_fields, user_data);
+ else
+ return gs_log_writer_console (log_level, fields, n_fields, user_data);
+}
+
+static void
+gs_debug_finalize (GObject *object)
+{
+ GsDebug *debug = GS_DEBUG (object);
+
+ g_mutex_clear (&debug->mutex);
+
+ G_OBJECT_CLASS (gs_debug_parent_class)->finalize (object);
+}
+
+static void
+gs_debug_class_init (GsDebugClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gs_debug_finalize;
+}
+
+static void
+gs_debug_init (GsDebug *debug)
+{
+ g_mutex_init (&debug->mutex);
+ debug->use_time = g_getenv ("GS_DEBUG_NO_TIME") == NULL;
+ g_log_set_writer_func (gs_debug_log_writer,
+ g_object_ref (debug),
+ (GDestroyNotify) g_object_unref);
+}
+
+GsDebug *
+gs_debug_new (void)
+{
+ return GS_DEBUG (g_object_new (GS_TYPE_DEBUG, NULL));
+}