diff options
author | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2009-06-18 07:54:55 +0800 |
---|---|---|
committer | Jonny Lamb <jonny.lamb@collabora.co.uk> | 2009-06-18 08:05:56 +0800 |
commit | 6914121ce5169769207613166e14c077259c863b (patch) | |
tree | 0ea43898ab34d033e0cd8f3f7f3bd7eb851f8a19 | |
parent | a7785586abe2bf770185fdf8be1855552c476600 (diff) | |
download | gsoc2013-empathy-6914121ce5169769207613166e14c077259c863b.tar gsoc2013-empathy-6914121ce5169769207613166e14c077259c863b.tar.gz gsoc2013-empathy-6914121ce5169769207613166e14c077259c863b.tar.bz2 gsoc2013-empathy-6914121ce5169769207613166e14c077259c863b.tar.lz gsoc2013-empathy-6914121ce5169769207613166e14c077259c863b.tar.xz gsoc2013-empathy-6914121ce5169769207613166e14c077259c863b.tar.zst gsoc2013-empathy-6914121ce5169769207613166e14c077259c863b.zip |
Implement o.fd.Tp.Debug. (Fixes #580631)
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r-- | libempathy/Makefile.am | 2 | ||||
-rw-r--r-- | libempathy/empathy-debug.c | 74 | ||||
-rw-r--r-- | libempathy/empathy-debug.h | 4 | ||||
-rw-r--r-- | libempathy/empathy-debugger.c | 270 | ||||
-rw-r--r-- | libempathy/empathy-debugger.h | 88 | ||||
-rw-r--r-- | src/empathy.c | 31 |
6 files changed, 461 insertions, 8 deletions
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index 6a42bba9a..87b728464 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -34,6 +34,7 @@ libempathy_la_SOURCES = \ empathy-contact-manager.c \ empathy-contact-monitor.c \ empathy-debug.c \ + empathy-debugger.c \ empathy-dispatcher.c \ empathy-dispatch-operation.c \ empathy-ft-factory.c \ @@ -82,6 +83,7 @@ libempathy_headers = \ empathy-contact-manager.h \ empathy-contact-monitor.h \ empathy-debug.h \ + empathy-debugger.h \ empathy-dispatcher.h \ empathy-dispatch-operation.h \ empathy-ft-factory.h \ diff --git a/libempathy/empathy-debug.c b/libempathy/empathy-debug.c index 47482d5fc..99111deec 100644 --- a/libempathy/empathy-debug.c +++ b/libempathy/empathy-debug.c @@ -33,6 +33,8 @@ #include "empathy-debug.h" +#include "empathy-debugger.h" + #ifdef ENABLE_DEBUG static EmpathyDebugFlags flags = 0; @@ -75,18 +77,74 @@ empathy_debug_flag_is_set (EmpathyDebugFlags flag) return (flag & flags) != 0; } +GHashTable *flag_to_keys = NULL; + +static const gchar * +debug_flag_to_key (EmpathyDebugFlags flag) +{ + if (flag_to_keys == NULL) + { + guint i; + + flag_to_keys = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, g_free); + + for (i = 0; keys[i].value; i++) + { + GDebugKey key = (GDebugKey) keys[i]; + g_hash_table_insert (flag_to_keys, GUINT_TO_POINTER (key.value), + g_strdup (key.key)); + } + } + + return g_hash_table_lookup (flag_to_keys, GUINT_TO_POINTER (flag)); +} + +void +empathy_debug_free (void) +{ + if (flag_to_keys == NULL) + return; + + g_hash_table_destroy (flag_to_keys); + flag_to_keys = NULL; +} + +static void +log_to_debugger (EmpathyDebugFlags flag, + const gchar *message) +{ + EmpathyDebugger *dbg = empathy_debugger_get_singleton (); + gchar *domain; + GTimeVal now; + + g_get_current_time (&now); + + domain = g_strdup_printf ("%s/%s", G_LOG_DOMAIN, debug_flag_to_key (flag)); + + empathy_debugger_add_message (dbg, &now, domain, G_LOG_LEVEL_DEBUG, message); + + g_free (domain); +} + void empathy_debug (EmpathyDebugFlags flag, - const gchar *format, - ...) + const gchar *format, + ...) { + gchar *message; + va_list args; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + va_end (args); + + log_to_debugger (flag, message); + if (flag & flags) - { - va_list args; - va_start (args, format); - g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args); - va_end (args); - } + g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s", message); + + g_free (message); } #else diff --git a/libempathy/empathy-debug.h b/libempathy/empathy-debug.h index 7d05db6ab..9df728922 100644 --- a/libempathy/empathy-debug.h +++ b/libempathy/empathy-debug.h @@ -46,6 +46,7 @@ typedef enum gboolean empathy_debug_flag_is_set (EmpathyDebugFlags flag); void empathy_debug (EmpathyDebugFlags flag, const gchar *format, ...) G_GNUC_PRINTF (2, 3); +void empathy_debug_free (void); void empathy_debug_set_flags (const gchar *flags_string); G_END_DECLS @@ -88,4 +89,7 @@ G_END_DECLS #define DEBUGGING 0 #endif /* !defined (ENABLE_DEBUG) */ + +#define gabble_debug_free() G_STMT_START { } G_STMT_END + #endif /* defined (DEBUG_FLAG) */ diff --git a/libempathy/empathy-debugger.c b/libempathy/empathy-debugger.c new file mode 100644 index 000000000..04873120c --- /dev/null +++ b/libempathy/empathy-debugger.c @@ -0,0 +1,270 @@ +/* + * Telepathy debug interface implementation + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "empathy-debugger.h" +#include "config.h" + +#include <telepathy-glib/dbus.h> + +#include "extensions/extensions.h" + +static EmpathyDebugger *singleton = NULL; + +static void +debug_iface_init (gpointer g_iface, gpointer iface_data); + +G_DEFINE_TYPE_WITH_CODE (EmpathyDebugger, empathy_debugger, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init); + G_IMPLEMENT_INTERFACE (EMP_TYPE_SVC_DEBUG, debug_iface_init)); + +/* properties */ +enum +{ + PROP_ENABLED = 1, + NUM_PROPERTIES +}; + +static EmpDebugLevel +log_level_flags_to_debug_level (GLogLevelFlags level) +{ + if (level & G_LOG_LEVEL_ERROR) + return EMP_DEBUG_LEVEL_ERROR; + else if (level & G_LOG_LEVEL_CRITICAL) + return EMP_DEBUG_LEVEL_CRITICAL; + else if (level & G_LOG_LEVEL_WARNING) + return EMP_DEBUG_LEVEL_WARNING; + else if (level & G_LOG_LEVEL_MESSAGE) + return EMP_DEBUG_LEVEL_MESSAGE; + else if (level & G_LOG_LEVEL_INFO) + return EMP_DEBUG_LEVEL_INFO; + else if (level & G_LOG_LEVEL_DEBUG) + return EMP_DEBUG_LEVEL_DEBUG; + else + /* Fall back to DEBUG if all else fails */ + return EMP_DEBUG_LEVEL_DEBUG; +} + +static EmpathyDebugMessage * +debug_message_new (GTimeVal *timestamp, + const gchar *domain, + GLogLevelFlags level, + const gchar *string) +{ + EmpathyDebugMessage *msg; + + msg = g_slice_new0 (EmpathyDebugMessage); + msg->timestamp = timestamp->tv_sec + timestamp->tv_usec / 1e6; + msg->domain = g_strdup (domain); + msg->level = log_level_flags_to_debug_level (level); + msg->string = g_strdup (string); + return msg; +} + +static void +debug_message_free (EmpathyDebugMessage *msg) +{ + g_free (msg->domain); + g_free (msg->string); + g_slice_free (EmpathyDebugMessage, msg); +} + +static void +empathy_debugger_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyDebugger *self = EMPATHY_DEBUGGER (object); + + switch (property_id) + { + case PROP_ENABLED: + g_value_set_boolean (value, self->enabled); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_debugger_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyDebugger *self = EMPATHY_DEBUGGER (object); + + switch (property_id) + { + case PROP_ENABLED: + self->enabled = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_debugger_finalize (GObject *object) +{ + EmpathyDebugger *self = EMPATHY_DEBUGGER (object); + + g_queue_foreach (self->messages, (GFunc) debug_message_free, NULL); + g_queue_free (self->messages); + self->messages = NULL; + + G_OBJECT_CLASS (empathy_debugger_parent_class)->finalize (object); +} + +static void +empathy_debugger_class_init (EmpathyDebuggerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + static TpDBusPropertiesMixinPropImpl debug_props[] = { + { "Enabled", "enabled", "enabled" }, + { NULL } + }; + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { EMP_IFACE_DEBUG, + tp_dbus_properties_mixin_getter_gobject_properties, + tp_dbus_properties_mixin_setter_gobject_properties, + debug_props, + }, + { NULL } + }; + + object_class->get_property = empathy_debugger_get_property; + object_class->set_property = empathy_debugger_set_property; + object_class->finalize = empathy_debugger_finalize; + + g_object_class_install_property (object_class, PROP_ENABLED, + g_param_spec_boolean ("enabled", "Enabled?", + "True if the new-debug-message signal is enabled.", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (EmpathyDebuggerClass, dbus_props_class)); +} + +static void +get_messages (EmpSvcDebug *self, + DBusGMethodInvocation *context) +{ + EmpathyDebugger *dbg = EMPATHY_DEBUGGER (self); + GPtrArray *messages; + static GType struct_type = 0; + GList *i; + guint j; + + if (G_UNLIKELY (struct_type == 0)) + { + struct_type = dbus_g_type_get_struct ( + "GValueArray", G_TYPE_DOUBLE, G_TYPE_STRING, G_TYPE_UINT, + G_TYPE_STRING, G_TYPE_INVALID); + } + + messages = g_ptr_array_sized_new (g_queue_get_length (dbg->messages)); + + for (i = dbg->messages->head; i; i = i->next) + { + GValue gvalue = { 0 }; + EmpathyDebugMessage *message = (EmpathyDebugMessage *) i->data; + + g_value_init (&gvalue, struct_type); + g_value_take_boxed (&gvalue, + dbus_g_type_specialized_construct (struct_type)); + dbus_g_type_struct_set (&gvalue, + 0, message->timestamp, + 1, message->domain, + 2, message->level, + 3, message->string, + G_MAXUINT); + g_ptr_array_add (messages, g_value_get_boxed (&gvalue)); + } + + emp_svc_debug_return_from_get_messages (context, messages); + + for (j = 0; j < messages->len; j++) + g_boxed_free (struct_type, messages->pdata[j]); + + g_ptr_array_free (messages, TRUE); +} + +static void +debug_iface_init (gpointer g_iface, + gpointer iface_data) +{ + EmpSvcDebugClass *klass = (EmpSvcDebugClass *) g_iface; + + emp_svc_debug_implement_get_messages (klass, get_messages); +} + +static void +empathy_debugger_init (EmpathyDebugger *self) +{ + self->messages = g_queue_new (); +} + +EmpathyDebugger * +empathy_debugger_get_singleton (void) +{ + if (G_UNLIKELY (singleton == NULL)) + { + DBusGConnection *bus; + + singleton = g_object_new (EMPATHY_TYPE_DEBUGGER, NULL); + bus = tp_get_bus (); + dbus_g_connection_register_g_object (bus, + "/org/freedesktop/Telepathy/debug", (GObject *) singleton); + } + + return singleton; +} + +void +empathy_debugger_add_message (EmpathyDebugger *self, + GTimeVal *timestamp, + const gchar *domain, + GLogLevelFlags level, + const gchar *string) +{ + EmpathyDebugMessage *new_msg; + + if (g_queue_get_length (self->messages) >= DEBUG_MESSAGE_LIMIT) + { + EmpathyDebugMessage *old_head = + (EmpathyDebugMessage *) g_queue_pop_head (self->messages); + + debug_message_free (old_head); + } + + new_msg = debug_message_new (timestamp, domain, level, string); + g_queue_push_tail (self->messages, new_msg); + + if (self->enabled) + { + emp_svc_debug_emit_new_debug_message (self, new_msg->timestamp, + domain, new_msg->level, string); + } +} diff --git a/libempathy/empathy-debugger.h b/libempathy/empathy-debugger.h new file mode 100644 index 000000000..f3fdc7070 --- /dev/null +++ b/libempathy/empathy-debugger.h @@ -0,0 +1,88 @@ +/* + * header for Telepathy debug interface implementation + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _EMPATHY_DEBUGGER +#define _EMPATHY_DEBUGGER + +#include <glib-object.h> + +#include <telepathy-glib/properties-mixin.h> +#include <telepathy-glib/dbus-properties-mixin.h> + +#include "extensions/extensions.h" + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_DEBUGGER empathy_debugger_get_type() + +#define EMPATHY_DEBUGGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_DEBUGGER, EmpathyDebugger)) + +#define EMPATHY_DEBUGGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_DEBUGGER, EmpathyDebuggerClass)) + +#define EMPATHY_IS_DEBUGGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_DEBUGGER)) + +#define EMPATHY_IS_DEBUGGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_DEBUGGER)) + +#define EMPATHY_DEBUGGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_DEBUGGER, EmpathyDebuggerClass)) + +/* On the basis that messages are around 60 bytes on average, and that 50kb is + * a reasonable maximum size for a frame buffer. + */ + +#define DEBUG_MESSAGE_LIMIT 800 + +typedef struct { + gdouble timestamp; + gchar *domain; + EmpDebugLevel level; + gchar *string; +} EmpathyDebugMessage; + +typedef struct { + GObject parent; + + gboolean enabled; + GQueue *messages; +} EmpathyDebugger; + +typedef struct { + GObjectClass parent_class; + TpDBusPropertiesMixinClass dbus_props_class; +} EmpathyDebuggerClass; + +GType empathy_debugger_get_type (void); + +EmpathyDebugger * +empathy_debugger_get_singleton (void); + +void +empathy_debugger_add_message (EmpathyDebugger *self, + GTimeVal *timestamp, + const gchar *domain, + GLogLevelFlags level, + const gchar *string); + +G_END_DECLS + +#endif /* _EMPATHY_DEBUGGER */ diff --git a/src/empathy.c b/src/empathy.c index f23ce9145..fc6b5118c 100644 --- a/src/empathy.c +++ b/src/empathy.c @@ -48,6 +48,7 @@ #include <libempathy/empathy-call-factory.h> #include <libempathy/empathy-chatroom-manager.h> #include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-debugger.h> #include <libempathy/empathy-dispatcher.h> #include <libempathy/empathy-dispatch-operation.h> #include <libempathy/empathy-log-manager.h> @@ -450,6 +451,31 @@ new_call_handler_cb (EmpathyCallFactory *factory, EmpathyCallHandler *handler, gtk_widget_show (GTK_WIDGET (window)); } +#ifdef ENABLE_DEBUG +static void +default_log_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + g_log_default_handler (log_domain, log_level, message, NULL); + + /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the + * debugger as they already have in empathy_debug. */ + if (log_level != G_LOG_LEVEL_DEBUG + || tp_strdiff (log_domain, G_LOG_DOMAIN)) { + EmpathyDebugger *dbg; + GTimeVal now; + + dbg = empathy_debugger_get_singleton (); + g_get_current_time (&now); + + empathy_debugger_add_message (dbg, &now, log_domain, + log_level, message); + } +} +#endif /* ENABLE_DEBUG */ + int main (int argc, char *argv[]) { @@ -514,6 +540,11 @@ main (int argc, char *argv[]) gtk_window_set_default_icon_name ("empathy"); textdomain (GETTEXT_PACKAGE); +#ifdef ENABLE_DEBUG + /* Set up debugger */ + g_log_set_default_handler (default_log_handler, NULL); +#endif + /* Setting up the bacon connection */ startup_timestamp = get_startup_timestamp (); connection = bacon_message_connection_new ("empathy"); |