diff --git a/libpurple/debug.h b/libpurple/debug.h
--- a/libpurple/debug.h
+++ b/libpurple/debug.h
@@ -1,4 +1,6 @@
-/* purple
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -15,8 +17,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION)
@@ -25,10 +26,11 @@
 
 #ifndef PURPLE_DEBUG_H
 #define PURPLE_DEBUG_H
+
 /**
  * SECTION:debug
  * @section_id: libpurple-debug
- * @short_description: <filename>debug.h</filename>
+ * @short_description: Developer Logging API
  * @title: Debug API
  */
 
@@ -49,17 +51,16 @@
 
 /**
  * PurpleDebugLevel:
- * @PURPLE_DEBUG_ALL:     All debug levels.
- * @PURPLE_DEBUG_MISC:    General chatter.
- * @PURPLE_DEBUG_INFO:    General operation Information.
+ * @PURPLE_DEBUG_ALL: All debug levels.
+ * @PURPLE_DEBUG_MISC: General chatter.
+ * @PURPLE_DEBUG_INFO: General operation Information.
  * @PURPLE_DEBUG_WARNING: Warnings.
- * @PURPLE_DEBUG_ERROR:   Errors.
- * @PURPLE_DEBUG_FATAL:   Fatal errors.
+ * @PURPLE_DEBUG_ERROR: Errors.
+ * @PURPLE_DEBUG_FATAL: Fatal errors.
  *
- * Debug levels.
+ * Available debug levels.
  */
-typedef enum
-{
+typedef enum {
 	PURPLE_DEBUG_ALL = 0,
 	PURPLE_DEBUG_MISC,
 	PURPLE_DEBUG_INFO,
@@ -77,119 +78,107 @@
  *
  * Debug UI operations.
  */
-struct _PurpleDebugUiInterface
-{
+struct _PurpleDebugUiInterface {
 	/*< private >*/
 	GTypeInterface parent_iface;
 
 	/*< public >*/
-	void (*print)(PurpleDebugUi *self,
-	              PurpleDebugLevel level, const char *category,
-	              const char *arg_s);
-	gboolean (*is_enabled)(PurpleDebugUi *self,
-	                       PurpleDebugLevel level,
-	                       const char *category);
+	void (*print)(PurpleDebugUi *self, PurpleDebugLevel level, const gchar *category, const gchar *arg_s);
+	gboolean (*is_enabled)(PurpleDebugUi *self, PurpleDebugLevel level, const gchar *category);
 
 	/*< private >*/
-	void (*_purple_reserved1)(PurpleDebugUi *self);
-	void (*_purple_reserved2)(PurpleDebugUi *self);
-	void (*_purple_reserved3)(PurpleDebugUi *self);
-	void (*_purple_reserved4)(PurpleDebugUi *self);
+	gpointer reserved[4];
 };
 
-/**************************************************************************/
-/* Debug API                                                              */
-/**************************************************************************/
 /**
  * purple_debug:
- * @level:    The debug level.
+ * @level: The debug level.
  * @category: The category (or %NULL).
- * @format:   The format string.
+ * @format: The format string.
  * @...:  The parameters to insert into the format string.
  *
  * Outputs debug information.
  */
-void purple_debug(PurpleDebugLevel level, const char *category,
-				const char *format, ...) G_GNUC_PRINTF(3, 4);
+void purple_debug(PurpleDebugLevel level, const gchar *category, const gchar *format, ...) G_GNUC_PRINTF(3, 4);
 
 /**
  * purple_debug_misc:
- * @category: The category (or %NULL).
- * @format:   The format string.
+ * @category: The category or %NULL.
+ * @format: The format string.
  * @...:  The parameters to insert into the format string.
  *
  * Outputs misc. level debug information.
  *
- * This is a wrapper for purple_debug(), and uses PURPLE_DEBUG_MISC as
- * the level.
+ * This is a wrapper for purple_debug(), and uses #PURPLE_DEBUG_MISC as the
+ * level.
  *
  * See purple_debug().
  */
-void purple_debug_misc(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+void purple_debug_misc(const gchar *category, const gchar *format, ...) G_GNUC_PRINTF(2, 3);
 
 /**
  * purple_debug_info:
  * @category: The category (or %NULL).
- * @format:   The format string.
- * @...:  The parameters to insert into the format string.
+ * @format: The format string.
+ * @...: The parameters to insert into the format string.
  *
  * Outputs info level debug information.
  *
- * This is a wrapper for purple_debug(), and uses PURPLE_DEBUG_INFO as
- * the level.
- *
- * See purple_debug().
- */
-void purple_debug_info(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
-
-/**
- * purple_debug_warning:
- * @category: The category (or %NULL).
- * @format:   The format string.
- * @...:  The parameters to insert into the format string.
- *
- * Outputs warning level debug information.
- *
- * This is a wrapper for purple_debug(), and uses PURPLE_DEBUG_WARNING as
+ * This is a wrapper for purple_debug(), and uses #PURPLE_DEBUG_INFO as
  * the level.
  *
  * See purple_debug().
  */
-void purple_debug_warning(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+void purple_debug_info(const gchar *category, const gchar *format, ...) G_GNUC_PRINTF(2, 3);
+
+/**
+ * purple_debug_warning:
+ * @category: The category or %NULL.
+ * @format: The format string.
+ * @...: The parameters to insert into the format string.
+ *
+ * Outputs warning level debug information.
+ *
+ * This is a wrapper for purple_debug(), and uses #PURPLE_DEBUG_WARNING as the
+ * level.
+ *
+ * See purple_debug().
+ */
+void purple_debug_warning(const gchar *category, const gchar *format, ...) G_GNUC_PRINTF(2, 3);
 
 /**
  * purple_debug_error:
- * @category: The category (or %NULL).
- * @format:   The format string.
- * @...:  The parameters to insert into the format string.
+ * @category: The category or %NULL.
+ * @format: The format string.
+ * @...: The parameters to insert into the format string.
  *
  * Outputs error level debug information.
  *
- * This is a wrapper for purple_debug(), and uses PURPLE_DEBUG_ERROR as
- * the level.
+ * This is a wrapper for purple_debug(), and uses #PURPLE_DEBUG_ERROR as the
+ * level.
  *
  * See purple_debug().
  */
-void purple_debug_error(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+void purple_debug_error(const gchar *category, const gchar *format, ...) G_GNUC_PRINTF(2, 3);
 
 /**
  * purple_debug_fatal:
  * @category: The category (or %NULL).
- * @format:   The format string.
- * @...:  The parameters to insert into the format string.
+ * @format: The format string.
+ * @...: The parameters to insert into the format string.
  *
  * Outputs fatal error level debug information.
  *
- * This is a wrapper for purple_debug(), and uses PURPLE_DEBUG_ERROR as
- * the level.
+ * This is a wrapper for purple_debug(), and uses #PURPLE_DEBUG_ERROR as the
+ * level.
  *
  * See purple_debug().
  */
-void purple_debug_fatal(const char *category, const char *format, ...) G_GNUC_PRINTF(2, 3);
+void purple_debug_fatal(const gchar *category, const gchar *format, ...) G_GNUC_PRINTF(2, 3);
 
 /**
  * purple_debug_set_enabled:
- * @enabled: TRUE to enable debug output or FALSE to disable it.
+ * @enabled: %TRUE to enable debug output or %FALSE to disable it.
  *
  * Enable or disable printing debug output to the console.
  */
@@ -200,16 +189,16 @@
  *
  * Check if console debug output is enabled.
  *
- * Returns: TRUE if debugging is enabled, FALSE if it is not.
+ * Returns: %TRUE if debugging is enabled, %FALSE if it is not.
  */
 gboolean purple_debug_is_enabled(void);
 
 /**
  * purple_debug_set_verbose:
- * @verbose: TRUE to enable verbose debugging or FALSE to disable it.
+ * @verbose: %TRUE to enable verbose debugging or %FALSE to disable it.
  *
  * Enable or disable verbose debugging.  This ordinarily should only be called
- * by #purple_debug_init, but there are cases where this can be useful for
+ * by purple_debug_init(), but there are cases where this can be useful for
  * plugins.
  */
 void purple_debug_set_verbose(gboolean verbose);
@@ -219,18 +208,18 @@
  *
  * Check if verbose logging is enabled.
  *
- * Returns: TRUE if verbose debugging is enabled, FALSE if it is not.
+ * Returns: %TRUE if verbose debugging is enabled, %FALSE if it is not.
  */
 gboolean purple_debug_is_verbose(void);
 
 /**
  * purple_debug_set_unsafe:
- * @unsafe: TRUE to enable debug logging of messages that could
- *        potentially contain passwords and other sensitive information.
- *        FALSE to disable it.
+ * @unsafe: %TRUE to enable debug logging of messages that could potentially
+ *          contain passwords and other sensitive information. %FALSE to
+ *          disable it.
  *
- * Enable or disable unsafe debugging.  This ordinarily should only be called
- * by #purple_debug_init, but there are cases where this can be useful for
+ * Enable or disable unsafe debugging. This ordinarily should only be called by
+ * purple_debug_init(), but there are cases where this can be useful for
  * plugins.
  */
 void purple_debug_set_unsafe(gboolean unsafe);
@@ -238,48 +227,82 @@
 /**
  * purple_debug_is_unsafe:
  *
- * Check if unsafe debugging is enabled.  Defaults to FALSE.
+ * Check if unsafe debugging is enabled. Defaults to %FALSE.
  *
- * Returns: TRUE if the debug logging of all messages is enabled, FALSE
- *         if messages that could potentially contain passwords and other
- *         sensitive information are not logged.
+ * Returns: %TRUE if the debug logging of all messages is enabled, %FALSE if
+ *          messages that could potentially contain passwords and other
+ *          sensitive information are not logged.
  */
 gboolean purple_debug_is_unsafe(void);
 
 /**
  * purple_debug_set_colored:
- * @colored: TRUE to enable colored output, FALSE to disable it.
+ * @colored: %TRUE to enable colored output, %FALSE to disable it.
  *
  * Enable or disable colored output for bash console.
  */
 void purple_debug_set_colored(gboolean colored);
 
-/**************************************************************************/
-/* UI Registration Functions                                              */
-/**************************************************************************/
+/******************************************************************************
+ * UI Registration Functions
+ *****************************************************************************/
 
 /**
  * purple_debug_set_ui:
- * @ops: The UI operations structure.
+ * @ui: The UI operations structure.
  *
  * Sets the UI operations structure to be used when outputting debug
  * information.
+ *
+ * Since: 3.0.0
  */
-void purple_debug_set_ui(PurpleDebugUi *ops);
+void purple_debug_set_ui(PurpleDebugUi *ui);
 
 /**
  * purple_debug_get_ui:
  *
- * Returns the UI operations structure used when outputting debug
- * information.
+ * Get the #PurpleDebugUi instance used for outputting debug information.
  *
- * Returns: (transfer none): The UI operations structure in use.
+ * Returns: (transfer none): The #PurpleDebugUi instance in use.
+ *
+ * Since: 3.0.0
  */
 PurpleDebugUi *purple_debug_get_ui(void);
 
-/**************************************************************************/
-/* Debug Subsystem                                                        */
-/**************************************************************************/
+/**
+ * purple_debug_ui_is_enabled:
+ * @ui: The #PurpleDebugUi instance.
+ * @level: The #PurpleLogLevel.
+ * @category: An optional category.
+ *
+ * Checks if the ui should output messages at the given level and optional
+ * category.
+ *
+ * Typically this function will not need to be called outside of libpurple.
+ *
+ * Returns: %TRUE if the given level and category will be output by @ui, %FALSE
+ *          otherwise.
+ *
+ * Since: 3.0.0
+ */
+gboolean purple_debug_ui_is_enabled(PurpleDebugUi *ui, PurpleDebugLevel level, const gchar *category);
+
+/**
+ * purple_debug_ui_print:
+ * @ui: The #PurpleDebugUi instance.
+ * @level: The #PurpleDebugLevel.
+ * @category: An optional category.
+ * @arg_s: The debug string to output.
+ *
+ * Outputs @arg_s vi @ui with the given @level and optional @category.
+ *
+ * Since: 3.0.0
+ */
+void purple_debug_ui_print(PurpleDebugUi *ui, PurpleDebugLevel level, const gchar *category, const gchar *arg_s);
+
+/******************************************************************************
+ * Debug Subsystem
+ *****************************************************************************/
 
 /**
  * purple_debug_init:
diff --git a/libpurple/debug.c b/libpurple/debug.c
--- a/libpurple/debug.c
+++ b/libpurple/debug.c
@@ -1,4 +1,6 @@
-/* purple
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
  *
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -15,13 +17,11 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
-#include "internal.h"
+
 #include "debug.h"
 #include "prefs.h"
-#include "util.h"
 
 static PurpleDebugUi *debug_ui = NULL;
 
@@ -48,78 +48,78 @@
 static gboolean debug_colored = FALSE;
 
 static void
-purple_debug_vargs(PurpleDebugLevel level, const char *category,
-				 const char *format, va_list args)
+purple_debug_vargs(PurpleDebugLevel level, const gchar *category,
+                   const gchar *format, va_list args)
 {
-	PurpleDebugUi *ops;
-	PurpleDebugUiInterface *iface;
-	char *arg_s = NULL;
+	PurpleDebugUi *ui;
+	gchar *arg_s = NULL;
+
+	if(!debug_enabled) {
+		return;
+	}
 
 	g_return_if_fail(level != PURPLE_DEBUG_ALL);
 	g_return_if_fail(format != NULL);
 
-	ops = purple_debug_get_ui();
-	if (!ops)
+	ui = purple_debug_get_ui();
+	if(!ui) {
 		return;
-	iface = PURPLE_DEBUG_UI_GET_IFACE(ops);
-	if (!iface)
-		return;
+	}
 
-	if (!debug_enabled &&
-	    ((iface->print == NULL) ||
-	     (iface->is_enabled && !iface->is_enabled(ops, level, category)))) {
+	if(!purple_debug_ui_is_enabled(ui, level, category)) {
 		return;
 	}
 
 	arg_s = g_strdup_vprintf(format, args);
 	g_strchomp(arg_s); /* strip trailing linefeeds */
 
-	if (debug_enabled) {
+	if(debug_enabled) {
+		GDateTime *now = NULL;
 		gchar *ts_s;
-		const char *mdate;
-		time_t mtime = time(NULL);
 		const gchar *format_pre, *format_post;
 
 		format_pre = "";
 		format_post = "";
 
-		if (!debug_colored)
+		if(!debug_colored) {
 			format_pre = "";
-		else if (level == PURPLE_DEBUG_MISC)
+		} else if(level == PURPLE_DEBUG_MISC) {
 			format_pre = "\033[0;37m";
-		else if (level == PURPLE_DEBUG_INFO)
+		} else if(level == PURPLE_DEBUG_INFO) {
 			format_pre = "";
-		else if (level == PURPLE_DEBUG_WARNING)
+		} else if(level == PURPLE_DEBUG_WARNING) {
 			format_pre = "\033[0;33m";
-		else if (level == PURPLE_DEBUG_ERROR)
+		} else if(level == PURPLE_DEBUG_ERROR) {
 			format_pre = "\033[1;31m";
-		else if (level == PURPLE_DEBUG_FATAL)
+		} else if(level == PURPLE_DEBUG_FATAL) {
 			format_pre = "\033[1;33;41m";
+		}
 
-		if (format_pre[0] != '\0')
+		if(format_pre[0] != '\0') {
 			format_post = "\033[0m";
+		}
 
-		mdate = purple_utf8_strftime("%H:%M:%S", localtime(&mtime));
-		ts_s = g_strdup_printf("(%s) ", mdate);
+		now = g_date_time_new_now_local();
+		ts_s = g_date_time_format(now, "(%H:%M:%S)");
 
-		if (category == NULL)
-			g_print("%s%s%s%s\n", format_pre, ts_s, arg_s, format_post);
-		else
-			g_print("%s%s%s: %s%s\n", format_pre, ts_s, category, arg_s, format_post);
+		if(category == NULL) {
+			g_print("%s%s %s%s\n", format_pre, ts_s, arg_s, format_post);
+		} else {
+			g_print("%s%s %s: %s%s\n", format_pre, ts_s, category, arg_s,
+			        format_post);
+		}
 
 		g_free(ts_s);
 	}
 
-	if (iface->print != NULL) {
-		iface->print(ops, level, category, arg_s);
-	}
+	purple_debug_ui_print(ui, level, category, arg_s);
 
 	g_free(arg_s);
 }
 
 void
-purple_debug(PurpleDebugLevel level, const char *category,
-		   const char *format, ...)
+purple_debug(PurpleDebugLevel level, const gchar *category,
+             const gchar *format, ...)
 {
 	va_list args;
 
@@ -132,8 +132,7 @@
 }
 
 void
-purple_debug_misc(const char *category, const char *format, ...)
-{
+purple_debug_misc(const gchar *category, const gchar *format, ...) {
 	va_list args;
 
 	g_return_if_fail(format != NULL);
@@ -144,8 +143,7 @@
 }
 
 void
-purple_debug_info(const char *category, const char *format, ...)
-{
+purple_debug_info(const gchar *category, const gchar *format, ...) {
 	va_list args;
 
 	g_return_if_fail(format != NULL);
@@ -156,8 +154,7 @@
 }
 
 void
-purple_debug_warning(const char *category, const char *format, ...)
-{
+purple_debug_warning(const gchar *category, const gchar *format, ...) {
 	va_list args;
 
 	g_return_if_fail(format != NULL);
@@ -168,8 +165,7 @@
 }
 
 void
-purple_debug_error(const char *category, const char *format, ...)
-{
+purple_debug_error(const gchar *category, const gchar *format, ...) {
 	va_list args;
 
 	g_return_if_fail(format != NULL);
@@ -180,8 +176,7 @@
 }
 
 void
-purple_debug_fatal(const char *category, const char *format, ...)
-{
+purple_debug_fatal(const gchar *category, const gchar *format, ...) {
 	va_list args;
 
 	g_return_if_fail(format != NULL);
@@ -192,77 +187,100 @@
 }
 
 void
-purple_debug_set_enabled(gboolean enabled)
-{
+purple_debug_set_enabled(gboolean enabled) {
 	debug_enabled = enabled;
 }
 
 gboolean
-purple_debug_is_enabled()
-{
+purple_debug_is_enabled() {
 	return debug_enabled;
 }
 
 void
-purple_debug_set_ui(PurpleDebugUi *ops)
-{
-	g_set_object(&debug_ui, ops);
+purple_debug_set_ui(PurpleDebugUi *ui) {
+	g_set_object(&debug_ui, ui);
 }
 
 gboolean
-purple_debug_is_verbose()
-{
+purple_debug_is_verbose() {
 	return debug_verbose;
 }
 
 void
-purple_debug_set_verbose(gboolean verbose)
-{
+purple_debug_set_verbose(gboolean verbose) {
 	debug_verbose = verbose;
 }
 
 gboolean
-purple_debug_is_unsafe()
-{
+purple_debug_is_unsafe() {
 	return debug_unsafe;
 }
 
 void
-purple_debug_set_unsafe(gboolean unsafe)
-{
+purple_debug_set_unsafe(gboolean unsafe) {
 	debug_unsafe = unsafe;
 }
 
 void
-purple_debug_set_colored(gboolean colored)
-{
+purple_debug_set_colored(gboolean colored) {
 	debug_colored = colored;
 }
 
 PurpleDebugUi *
-purple_debug_get_ui(void)
+purple_debug_get_ui(void) {
+	return debug_ui;
+}
+
+gboolean
+purple_debug_ui_is_enabled(PurpleDebugUi *ui, PurpleDebugLevel level,
+                           const gchar *category)
 {
-	return debug_ui;
+	PurpleDebugUiInterface *iface = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_DEBUG_UI(ui), FALSE);
+
+	iface = PURPLE_DEBUG_UI_GET_IFACE(ui);
+	if(iface != NULL && iface->is_enabled != NULL) {
+		return iface->is_enabled(ui, level, category);
+	}
+
+	return FALSE;
+}
+
+void
+purple_debug_ui_print(PurpleDebugUi *ui, PurpleDebugLevel level,
+                      const gchar *category, const gchar *arg_s)
+{
+	PurpleDebugUiInterface *iface = NULL;
+
+	g_return_if_fail(PURPLE_IS_DEBUG_UI(ui));
+
+	if(!purple_debug_ui_is_enabled(ui, level, category)) {
+		return;
+	}
+
+	iface = PURPLE_DEBUG_UI_GET_IFACE(ui);
+	if(iface != NULL && iface->print != NULL) {
+		iface->print(ui, level, category, arg_s);
+	}
 }
 
 G_DEFINE_INTERFACE(PurpleDebugUi, purple_debug_ui, G_TYPE_OBJECT);
 
 static void
-purple_debug_ui_default_init(PurpleDebugUiInterface *iface)
-{
-    /* add properties and signals to the interface here */
+purple_debug_ui_default_init(PurpleDebugUiInterface *iface) {
 }
 
 void
-purple_debug_init(void)
-{
+purple_debug_init(void) {
 	/* Read environment variables once per init */
-	if(g_getenv("PURPLE_UNSAFE_DEBUG"))
+	if(g_getenv("PURPLE_UNSAFE_DEBUG")) {
 		purple_debug_set_unsafe(TRUE);
+	}
 
-	if(g_getenv("PURPLE_VERBOSE_DEBUG"))
+	if(g_getenv("PURPLE_VERBOSE_DEBUG")) {
 		purple_debug_set_verbose(TRUE);
+	}
 
 	purple_prefs_add_none("/purple/debug");
 }
-
