mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
gst-stats: Add argument for a custom regexp
This is to use gst-stats against GStreamer logs that went through some other logging system. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3935>
This commit is contained in:
parent
ff435c80a2
commit
e2d7fbe94f
1 changed files with 72 additions and 57 deletions
|
@ -30,6 +30,7 @@
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
/* log parser */
|
/* log parser */
|
||||||
|
static GRegex *custom_log = NULL;
|
||||||
static GRegex *raw_log = NULL;
|
static GRegex *raw_log = NULL;
|
||||||
static GRegex *ansi_log = NULL;
|
static GRegex *ansi_log = NULL;
|
||||||
|
|
||||||
|
@ -909,25 +910,36 @@ process_leaf_bins (gpointer key, gpointer value, gpointer user_data)
|
||||||
/* main */
|
/* main */
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
init (void)
|
init (const gchar * tracer_regexp)
|
||||||
{
|
{
|
||||||
/* compile the parser regexps */
|
/* compile the parser regexps */
|
||||||
|
|
||||||
|
if (tracer_regexp) {
|
||||||
|
GError *gerr = NULL;
|
||||||
|
custom_log = g_regex_new (tracer_regexp, 0, 0, &gerr);
|
||||||
|
if (!custom_log) {
|
||||||
|
g_warning ("Could not compile tracer regexp: %s\n", gerr->message);
|
||||||
|
g_clear_error (&gerr);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 0:00:00.004925027 31586 0x1c5c600 DEBUG GST_REGISTRY gstregistry.c:463:gst_registry_add_plugin:<registry0> adding plugin 0x1c79160 for filename "/usr/lib/gstreamer-1.0/libgstxxx.so"
|
/* 0:00:00.004925027 31586 0x1c5c600 DEBUG GST_REGISTRY gstregistry.c:463:gst_registry_add_plugin:<registry0> adding plugin 0x1c79160 for filename "/usr/lib/gstreamer-1.0/libgstxxx.so"
|
||||||
* 0:00:02.719599000 35292 000001C031A49C60 DEBUG GST_TRACER gsttracer.c:162:gst_tracer_register:<registry0> update existing feature 000001C02F9843C0 (latency)
|
* 0:00:02.719599000 35292 000001C031A49C60 DEBUG GST_TRACER gsttracer.c:162:gst_tracer_register:<registry0> update existing feature 000001C02F9843C0 (latency)
|
||||||
*/
|
*/
|
||||||
raw_log = g_regex_new (
|
raw_log = g_regex_new (
|
||||||
/* 1: ts */
|
/* 1: ts */
|
||||||
"^([0-9:.]+) +"
|
"^[0-9:.]+ +"
|
||||||
/* 2: pid */
|
/* 2: pid */
|
||||||
"([0-9]+) +"
|
"[0-9]+ +"
|
||||||
/* 3: thread */
|
/* 3: thread */
|
||||||
"(0?x?[0-9a-fA-F]+) +"
|
"0?x?[0-9a-fA-F]+ +"
|
||||||
/* 4: level */
|
/* 4: level */
|
||||||
"([A-Z]+) +"
|
"TRACE +"
|
||||||
/* 5: category */
|
/* 5: category */
|
||||||
"([a-zA-Z_-]+) +"
|
"[a-zA-Z_-]+ +"
|
||||||
/* 6: file:line:func: */
|
/* 6: file:line:func: */
|
||||||
"([^:]*:[0-9]+:[^:]*:) +"
|
"[^:]*:[0-9]+:[^:]*: +"
|
||||||
/* 7: (obj)? log-text */
|
/* 7: (obj)? log-text */
|
||||||
"(.*)$", 0, 0, NULL);
|
"(.*)$", 0, 0, NULL);
|
||||||
if (!raw_log) {
|
if (!raw_log) {
|
||||||
|
@ -937,20 +949,20 @@ init (void)
|
||||||
|
|
||||||
ansi_log = g_regex_new (
|
ansi_log = g_regex_new (
|
||||||
/* 1: ts */
|
/* 1: ts */
|
||||||
"^([0-9:.]+) +"
|
"^[0-9:.]+ +"
|
||||||
/* 2: pid */
|
/* 2: pid */
|
||||||
"\\\x1b\\[[0-9;]+m *([0-9]+)\\\x1b\\[00m +"
|
"\\\x1b\\[[0-9;]+m *[0-9]+\\\x1b\\[00m +"
|
||||||
/* 3: thread */
|
/* 3: thread */
|
||||||
"(0x[0-9a-fA-F]+) +"
|
"0x[0-9a-fA-F]+ +"
|
||||||
/* 4: level */
|
/* 4: level */
|
||||||
"(?:\\\x1b\\[[0-9;]+m)?([A-Z]+) +\\\x1b\\[00m +"
|
"(?:\\\x1b\\[[0-9;]+m)?TRACE +\\\x1b\\[00m +"
|
||||||
/* 5: category */
|
/* 5: category */
|
||||||
"\\\x1b\\[[0-9;]+m +([a-zA-Z_-]+) +"
|
"\\\x1b\\[[0-9;]+m +[a-zA-Z_-]+ +"
|
||||||
/* 6: file:line:func: */
|
/* 6: file:line:func: */
|
||||||
"([^:]*:[0-9]+:[^:]*:)(?:\\\x1b\\[00m)? +"
|
"[^:]*:[0-9]+:[^:]*:?:\\\x1b\\[00m? +"
|
||||||
/* 7: (obj)? log-text */
|
/* 7: (obj)? log-text */
|
||||||
"(.*)$", 0, 0, NULL);
|
"(.*)$", 0, 0, NULL);
|
||||||
if (!raw_log) {
|
if (!ansi_log) {
|
||||||
GST_WARNING ("failed to compile the 'ansi' parser");
|
GST_WARNING ("failed to compile the 'ansi' parser");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1000,6 +1012,8 @@ done (void)
|
||||||
g_regex_unref (raw_log);
|
g_regex_unref (raw_log);
|
||||||
if (ansi_log)
|
if (ansi_log)
|
||||||
g_regex_unref (ansi_log);
|
g_regex_unref (ansi_log);
|
||||||
|
if (custom_log)
|
||||||
|
g_regex_unref (custom_log);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
|
@ -1177,9 +1191,12 @@ collect_stats (const gchar * filename)
|
||||||
GRegex *parser;
|
GRegex *parser;
|
||||||
GstStructure *s;
|
GstStructure *s;
|
||||||
guint lnr = 0;
|
guint lnr = 0;
|
||||||
gchar *level, *data;
|
gchar *data;
|
||||||
|
|
||||||
if (strchr (line, 27)) {
|
if (custom_log) {
|
||||||
|
parser = custom_log;
|
||||||
|
GST_INFO ("format is 'custom'");
|
||||||
|
} else if (strchr (line, 27)) {
|
||||||
parser = ansi_log;
|
parser = ansi_log;
|
||||||
GST_INFO ("format is 'ansi'");
|
GST_INFO ("format is 'ansi'");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1192,50 +1209,45 @@ collect_stats (const gchar * filename)
|
||||||
while (!feof (log)) {
|
while (!feof (log)) {
|
||||||
if (fgets (line, 5000, log)) {
|
if (fgets (line, 5000, log)) {
|
||||||
if (g_regex_match (parser, line, 0, &match_info)) {
|
if (g_regex_match (parser, line, 0, &match_info)) {
|
||||||
/* filter by level */
|
data = g_match_info_fetch (match_info, 1);
|
||||||
level = g_match_info_fetch (match_info, 4);
|
if ((s = gst_structure_from_string (data, NULL))) {
|
||||||
if (!strcmp (level, "TRACE")) {
|
const gchar *name = gst_structure_get_name (s);
|
||||||
data = g_match_info_fetch (match_info, 7);
|
|
||||||
if ((s = gst_structure_from_string (data, NULL))) {
|
|
||||||
const gchar *name = gst_structure_get_name (s);
|
|
||||||
|
|
||||||
if (!strcmp (name, "new-pad")) {
|
if (!strcmp (name, "new-pad")) {
|
||||||
new_pad_stats (s);
|
new_pad_stats (s);
|
||||||
} else if (!strcmp (name, "new-element")) {
|
} else if (!strcmp (name, "new-element")) {
|
||||||
new_element_stats (s);
|
new_element_stats (s);
|
||||||
} else if (!strcmp (name, "buffer")) {
|
} else if (!strcmp (name, "buffer")) {
|
||||||
do_buffer_stats (s);
|
do_buffer_stats (s);
|
||||||
} else if (!strcmp (name, "event")) {
|
} else if (!strcmp (name, "event")) {
|
||||||
do_event_stats (s);
|
do_event_stats (s);
|
||||||
} else if (!strcmp (name, "message")) {
|
} else if (!strcmp (name, "message")) {
|
||||||
do_message_stats (s);
|
do_message_stats (s);
|
||||||
} else if (!strcmp (name, "query")) {
|
} else if (!strcmp (name, "query")) {
|
||||||
do_query_stats (s);
|
do_query_stats (s);
|
||||||
} else if (!strcmp (name, "thread-rusage")) {
|
} else if (!strcmp (name, "thread-rusage")) {
|
||||||
do_thread_rusage_stats (s);
|
do_thread_rusage_stats (s);
|
||||||
} else if (!strcmp (name, "proc-rusage")) {
|
} else if (!strcmp (name, "proc-rusage")) {
|
||||||
do_proc_rusage_stats (s);
|
do_proc_rusage_stats (s);
|
||||||
} else if (!strcmp (name, "latency")) {
|
} else if (!strcmp (name, "latency")) {
|
||||||
do_latency_stats (s);
|
do_latency_stats (s);
|
||||||
} else if (!strcmp (name, "element-latency")) {
|
} else if (!strcmp (name, "element-latency")) {
|
||||||
do_element_latency_stats (s);
|
do_element_latency_stats (s);
|
||||||
} else if (!strcmp (name, "element-reported-latency")) {
|
} else if (!strcmp (name, "element-reported-latency")) {
|
||||||
do_element_reported_latency (s);
|
do_element_reported_latency (s);
|
||||||
} else if (!strcmp (name, "factory-used")) {
|
} else if (!strcmp (name, "factory-used")) {
|
||||||
do_factory_used (s);
|
do_factory_used (s);
|
||||||
} else {
|
|
||||||
// TODO(ensonic): parse the xxx.class log lines
|
|
||||||
if (!g_str_has_suffix (data, ".class")) {
|
|
||||||
GST_WARNING ("unknown log entry: '%s'", data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gst_structure_free (s);
|
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING ("unknown log entry: '%s'", data);
|
// TODO(ensonic): parse the xxx.class log lines
|
||||||
|
if (!g_str_has_suffix (data, ".class")) {
|
||||||
|
GST_WARNING ("unknown log entry: '%s'", data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_free (data);
|
gst_structure_free (s);
|
||||||
|
} else {
|
||||||
|
GST_WARNING ("unknown log entry: '%s'", data);
|
||||||
}
|
}
|
||||||
g_free (level);
|
g_free (data);
|
||||||
} else {
|
} else {
|
||||||
if (*line) {
|
if (*line) {
|
||||||
GST_WARNING ("foreign log entry: %s:%d:'%s'", filename, lnr,
|
GST_WARNING ("foreign log entry: %s:%d:'%s'", filename, lnr,
|
||||||
|
@ -1263,6 +1275,7 @@ gint
|
||||||
main (gint argc, gchar * argv[])
|
main (gint argc, gchar * argv[])
|
||||||
{
|
{
|
||||||
gchar **filenames = NULL;
|
gchar **filenames = NULL;
|
||||||
|
gchar *tracer_regexp = NULL;
|
||||||
guint num;
|
guint num;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
GOptionContext *ctx;
|
GOptionContext *ctx;
|
||||||
|
@ -1270,6 +1283,8 @@ main (gint argc, gchar * argv[])
|
||||||
GST_TOOLS_GOPTION_VERSION,
|
GST_TOOLS_GOPTION_VERSION,
|
||||||
// TODO(ensonic): add a summary flag, if set read the whole thing, print
|
// TODO(ensonic): add a summary flag, if set read the whole thing, print
|
||||||
// stats once, and exit
|
// stats once, and exit
|
||||||
|
{"tracer-regexp", 't', 0, G_OPTION_ARG_STRING, &tracer_regexp,
|
||||||
|
"Custom Perl regular expression to extract tracer data", "regexp"},
|
||||||
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL}
|
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL}
|
||||||
,
|
,
|
||||||
{NULL}
|
{NULL}
|
||||||
|
@ -1318,7 +1333,7 @@ main (gint argc, gchar * argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init ()) {
|
if (init (tracer_regexp)) {
|
||||||
collect_stats (filenames[0]);
|
collect_stats (filenames[0]);
|
||||||
print_stats ();
|
print_stats ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue