mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-29 18:48:44 +00:00
gstinfo: Add new API for getting debug log lines
If you're using a custom log handler, you had to reverse-engineer the debug log format and create your own format function. Now, you can call `gst_debug_log_get_line()` and it will return a string (without ANSI escape color codes) representation instead. This is useful in situations when you need to log the ordinary gst_debug log to a resource that can't be opened as a `FILE` handle. Also includes a test.
This commit is contained in:
parent
8140da74ba
commit
72daeee2c4
3 changed files with 126 additions and 30 deletions
110
gst/gstinfo.c
110
gst/gstinfo.c
|
@ -1079,6 +1079,7 @@ gst_debug_construct_win_color (guint colorinfo)
|
|||
#endif
|
||||
#define PID_FMT "%5d"
|
||||
#define CAT_FMT "%20s %s:%d:%s:%s"
|
||||
#define NOCOLOR_PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
static const guchar levelcolormap_w32[GST_LEVEL_COUNT] = {
|
||||
|
@ -1123,6 +1124,81 @@ static const gchar *levelcolormap[GST_LEVEL_COUNT] = {
|
|||
"\033[37m" /* GST_LEVEL_MEMDUMP */
|
||||
};
|
||||
|
||||
static void
|
||||
_gst_debug_log_preamble (GstDebugMessage * message, GObject * object,
|
||||
const gchar ** file, const gchar ** message_str, gchar ** obj_str,
|
||||
GstClockTime * elapsed)
|
||||
{
|
||||
gchar c;
|
||||
|
||||
/* Get message string first because printing it might call into our custom
|
||||
* printf format extension mechanism which in turn might log something, e.g.
|
||||
* from inside gst_structure_to_string() when something can't be serialised.
|
||||
* This means we either need to do this outside of any critical section or
|
||||
* use a recursive lock instead. As we always need the message string in all
|
||||
* code paths, we might just as well get it here first thing and outside of
|
||||
* the win_print_mutex critical section. */
|
||||
*message_str = gst_debug_message_get (message);
|
||||
|
||||
/* __FILE__ might be a file name or an absolute path or a
|
||||
* relative path, irrespective of the exact compiler used,
|
||||
* in which case we want to shorten it to the filename for
|
||||
* readability. */
|
||||
c = (*file)[0];
|
||||
if (c == '.' || c == '/' || c == '\\' || (c != '\0' && (*file)[1] == ':')) {
|
||||
*file = gst_path_basename (*file);
|
||||
}
|
||||
|
||||
if (object) {
|
||||
*obj_str = gst_debug_print_object (object);
|
||||
} else {
|
||||
*obj_str = (gchar *) "";
|
||||
}
|
||||
|
||||
*elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ());
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_debug_log_get_line:
|
||||
* @category: category to log
|
||||
* @level: level of the message
|
||||
* @file: the file that emitted the message, usually the __FILE__ identifier
|
||||
* @function: the function that emitted the message
|
||||
* @line: the line from that the message was emitted, usually __LINE__
|
||||
* @object: (transfer none) (allow-none): the object this message relates to,
|
||||
* or %NULL if none
|
||||
* @message: the actual message
|
||||
*
|
||||
* Returns the string representation for the specified debug log message
|
||||
* formatted in the same way as gst_debug_log_default() (the default handler),
|
||||
* without color. The purpose is to make it easy for custom log output
|
||||
* handlers to get a log output that is identical to what the default handler
|
||||
* would write out.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
gchar *
|
||||
gst_debug_log_get_line (GstDebugCategory * category, GstDebugLevel level,
|
||||
const gchar * file, const gchar * function, gint line,
|
||||
GObject * object, GstDebugMessage * message)
|
||||
{
|
||||
GstClockTime elapsed;
|
||||
gchar *ret, *obj_str = NULL;
|
||||
const gchar *message_str;
|
||||
|
||||
_gst_debug_log_preamble (message, object, &file, &message_str, &obj_str,
|
||||
&elapsed);
|
||||
|
||||
ret = g_strdup_printf ("%" GST_TIME_FORMAT NOCOLOR_PRINT_FMT,
|
||||
GST_TIME_ARGS (elapsed), getpid (), g_thread_self (),
|
||||
gst_debug_level_get_name (level), gst_debug_category_get_name
|
||||
(category), file, line, function, obj_str, message_str);
|
||||
|
||||
if (object != NULL)
|
||||
g_free (obj_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_debug_log_default:
|
||||
* @category: category to log
|
||||
|
@ -1156,37 +1232,13 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
|
|||
GstDebugColorMode color_mode;
|
||||
const gchar *message_str;
|
||||
FILE *log_file = user_data ? user_data : stderr;
|
||||
gchar c;
|
||||
|
||||
/* Get message string first because printing it might call into our custom
|
||||
* printf format extension mechanism which in turn might log something, e.g.
|
||||
* from inside gst_structure_to_string() when something can't be serialised.
|
||||
* This means we either need to do this outside of any critical section or
|
||||
* use a recursive lock instead. As we always need the message string in all
|
||||
* code paths, we might just as well get it here first thing and outside of
|
||||
* the win_print_mutex critical section. */
|
||||
message_str = gst_debug_message_get (message);
|
||||
|
||||
/* __FILE__ might be a file name or an absolute path or a
|
||||
* relative path, irrespective of the exact compiler used,
|
||||
* in which case we want to shorten it to the filename for
|
||||
* readability. */
|
||||
c = file[0];
|
||||
if (c == '.' || c == '/' || c == '\\' || (c != '\0' && file[1] == ':')) {
|
||||
file = gst_path_basename (file);
|
||||
}
|
||||
_gst_debug_log_preamble (message, object, &file, &message_str, &obj,
|
||||
&elapsed);
|
||||
|
||||
pid = getpid ();
|
||||
color_mode = gst_debug_get_color_mode ();
|
||||
|
||||
if (object) {
|
||||
obj = gst_debug_print_object (object);
|
||||
} else {
|
||||
obj = (gchar *) "";
|
||||
}
|
||||
|
||||
elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ());
|
||||
|
||||
if (color_mode != GST_DEBUG_COLOR_MODE_OFF) {
|
||||
#ifdef G_OS_WIN32
|
||||
G_LOCK (win_print_mutex);
|
||||
|
@ -1251,13 +1303,11 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
|
|||
#endif
|
||||
} else {
|
||||
/* no color, all platforms */
|
||||
#define PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n"
|
||||
fprintf (log_file, "%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed),
|
||||
pid, g_thread_self (), gst_debug_level_get_name (level),
|
||||
fprintf (log_file, "%" GST_TIME_FORMAT NOCOLOR_PRINT_FMT, GST_TIME_ARGS
|
||||
(elapsed), pid, g_thread_self (), gst_debug_level_get_name (level),
|
||||
gst_debug_category_get_name (category), file, line, function, obj,
|
||||
message_str);
|
||||
fflush (log_file);
|
||||
#undef PRINT_FMT
|
||||
}
|
||||
|
||||
if (object != NULL)
|
||||
|
|
|
@ -388,6 +388,15 @@ const gchar *
|
|||
GST_API
|
||||
const gchar * gst_debug_message_get (GstDebugMessage * message);
|
||||
|
||||
GST_API
|
||||
gchar * gst_debug_log_get_line (GstDebugCategory * category,
|
||||
GstDebugLevel level,
|
||||
const gchar * file,
|
||||
const gchar * function,
|
||||
gint line,
|
||||
GObject * object,
|
||||
GstDebugMessage * message) G_GNUC_NO_INSTRUMENT;
|
||||
|
||||
GST_API
|
||||
void gst_debug_log_default (GstDebugCategory * category,
|
||||
GstDebugLevel level,
|
||||
|
@ -397,6 +406,7 @@ void gst_debug_log_default (GstDebugCategory * category,
|
|||
GObject * object,
|
||||
GstDebugMessage * message,
|
||||
gpointer user_data) G_GNUC_NO_INSTRUMENT;
|
||||
|
||||
GST_API
|
||||
const gchar * gst_debug_level_get_name (GstDebugLevel level);
|
||||
|
||||
|
|
|
@ -228,6 +228,41 @@ GST_START_TEST (info_log_handler)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
compare_gst_log_func (GstDebugCategory * category, GstDebugLevel level,
|
||||
const gchar * file, const gchar * function, gint line, GObject * object,
|
||||
GstDebugMessage * message, gpointer user_data)
|
||||
{
|
||||
gboolean match;
|
||||
gchar *log_line;
|
||||
|
||||
fail_unless_equals_pointer (user_data, NULL);
|
||||
|
||||
log_line = gst_debug_log_get_line (category, level, file, function, line,
|
||||
object, message);
|
||||
|
||||
match = g_pattern_match_simple ("*:*:*.*0x*DEBUG*check*gstinfo.c:*"
|
||||
":info_log_handler_get_line: test message\n", log_line);
|
||||
fail_unless_equals_int (match, TRUE);
|
||||
g_free (log_line);
|
||||
}
|
||||
|
||||
GST_START_TEST (info_log_handler_get_line)
|
||||
{
|
||||
gst_debug_remove_log_function (gst_debug_log_default);
|
||||
gst_debug_add_log_function (compare_gst_log_func, NULL, NULL);
|
||||
|
||||
gst_debug_set_default_threshold (GST_LEVEL_LOG);
|
||||
GST_DEBUG ("test message");
|
||||
|
||||
/* clean up */
|
||||
gst_debug_set_default_threshold (GST_LEVEL_NONE);
|
||||
gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
|
||||
gst_debug_remove_log_function (compare_gst_log_func);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (info_dump_mem)
|
||||
{
|
||||
GstDebugCategory *cat = NULL;
|
||||
|
@ -498,6 +533,7 @@ gst_info_suite (void)
|
|||
tcase_add_test (tc_chain, info_segment_format_printf_extension);
|
||||
tcase_add_test (tc_chain, info_ptr_format_printf_extension);
|
||||
tcase_add_test (tc_chain, info_log_handler);
|
||||
tcase_add_test (tc_chain, info_log_handler_get_line);
|
||||
tcase_add_test (tc_chain, info_dump_mem);
|
||||
tcase_add_test (tc_chain, info_fixme);
|
||||
tcase_add_test (tc_chain, info_old_printf_extensions);
|
||||
|
|
Loading…
Reference in a new issue