Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport the JSON CEE patch from GStreamer upstream project #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
gstreamer1.5 (1.8.1-1kurento1) UNRELEASED; urgency=medium
gstreamer1.5 (1.8.1-1kurento2) testing; urgency=medium

[ Jose Antonio Santos Cadenas ]
* Change debian format
Expand All @@ -20,8 +20,9 @@ gstreamer1.5 (1.8.1-1kurento1) UNRELEASED; urgency=medium
[ Juan Navarro ]
* Ubuntu 18.04: Fix dependency & disable docs
* debian/control: Disable docs for Bionic build
* debian/rules: Run pre-build command with dh-autoreconf

-- Juan Navarro <[email protected]> Wed, 06 Feb 2019 13:12:53 +0100
-- Juan Navarro <[email protected]> Mon, 14 Oct 2019 17:20:56 +0200

gstreamer1.5 (1.5.0.1) experimental; urgency=medium

Expand Down
209 changes: 206 additions & 3 deletions gst/gstinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,12 @@
# include <dlfcn.h>
#endif
#include <stdio.h> /* fprintf */
#include <stdint.h> /* uintptr_t */
#include <glib/gstdio.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h> /* getpid on UNIX */
# include <syslog.h>
#endif
#ifdef HAVE_PROCESS_H
# include <process.h> /* getpid on win32 */
Expand All @@ -109,6 +111,18 @@
# include <windows.h> /* GetStdHandle, windows console */
#endif

/* for getaddrinfo */
#ifdef G_OS_WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#else
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif

#include "gst_private.h"
#include "gstutils.h"
#include "gstquark.h"
Expand All @@ -125,6 +139,17 @@
#include "printf/printf.h"
#include "printf/printf-extension.h"

#ifndef LOG_ERR
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#endif

static char *gst_info_printf_pointer_extension_func (const char *format,
void *ptr);

Expand Down Expand Up @@ -256,6 +281,13 @@ static GSList *__log_functions = NULL;
#define PRETTY_TAGS_DEFAULT TRUE
static gboolean pretty_tags = PRETTY_TAGS_DEFAULT;

#define STRUCTURED_JSON_CEE_DEFAULT FALSE
static gboolean structured_json_cee = STRUCTURED_JSON_CEE_DEFAULT;

static const gchar *log_pname = 0;
static const gchar *log_appname = 0;
static const gchar *log_hostname = 0;

static volatile gint G_GNUC_MAY_ALIAS __default_level = GST_LEVEL_DEFAULT;
static volatile gint G_GNUC_MAY_ALIAS __use_color = GST_DEBUG_COLOR_MODE_ON;

Expand Down Expand Up @@ -406,6 +438,50 @@ _priv_gst_debug_init (void)
if (env) {
gst_debug_set_threshold_from_string (env, FALSE);
}

env = g_getenv ("GST_DEBUG_STRUCTURED");
if (env != NULL) {
if (strstr (env, "JSON_CEE")) {
structured_json_cee = TRUE;
/* pname, hostname and time are mandatory for CEE */
#if defined(__APPLE__) || defined(__FreeBSD__)
log_pname = getprogname ();
#elif defined(_GNU_SOURCE)
log_pname = program_invocation_name;
#else
log_pname = "?";
#endif
/* if running multiple instances of the same pname, user
can set a different appname for each instance */
log_appname = g_getenv ("GST_DEBUG_APPNAME");
if (log_appname == NULL) {
log_appname = log_pname;
}
{
struct addrinfo hints, *info;
int gai_result;

char hostname[1024];
hostname[1023] = '\0';
gethostname (hostname, 1023);

memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;

if ((gai_result = getaddrinfo (hostname, 0, &hints, &info)) != 0) {
log_hostname = "?";
} else if (info == NULL) {
log_hostname = "?";
} else {
log_hostname = g_strdup (info->ai_canonname);
}

freeaddrinfo (info);
}
}
}
}

/* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */
Expand Down Expand Up @@ -1011,7 +1087,7 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
GObject * object, GstDebugMessage * message, gpointer user_data)
{
gint pid;
GstClockTime elapsed;
GstClockTime elapsed, now;
gchar *obj = NULL;
GstDebugColorMode color_mode;
FILE *log_file = user_data ? user_data : stderr;
Expand All @@ -1036,8 +1112,33 @@ gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
}

elapsed = GST_CLOCK_DIFF (_priv_gst_start_time, gst_util_get_timestamp ());

if (color_mode != GST_DEBUG_COLOR_MODE_OFF) {
now = g_get_real_time () * 1000;

if (structured_json_cee == TRUE) {
GTimeVal tv;
uint64_t tv_ns = GST_TIME_AS_NSECONDS (now) % GST_SECOND;
struct tm _tm;
#define ISO8601_BUF_SIZE 32
char iso8601buf[ISO8601_BUF_SIZE + 1];
#define MAX_JSON_MSG_LEN 16384 /* SDP bodies can be quite big, heavy on stack */
gchar message_encoded[MAX_JSON_MSG_LEN + 1];
GST_TIME_TO_TIMEVAL (now, tv);
gmtime_r (&tv.tv_sec, &_tm);
strftime (iso8601buf, ISO8601_BUF_SIZE, "%FT%T", &_tm);
gst_debug_escape_json (gst_debug_message_get (message), message_encoded,
MAX_JSON_MSG_LEN);
#define PRINT_FMT "\"proc\":{\"id\":\"%d\",\"tid\":%ju},\"pri\":\"%s\",\"subsys\":\"%s\",\"file\":{\"name\":\"%s\",\"line\":%d},\"native\":{\"function\":\"%s\",\"object\":\"%s\"},\"msg\":\"%s\",\"pname\":\"%s\",\"appname\":\"%s\",\"hostname\":\"%s\",\"gstreamer\":{\"level\":%d},\"syslog\":{\"level\":%d}}\n"
fprintf (log_file,
"{\"time\":\"%s.%09luZ\",\"native\":{\"time\":{\"elapsed\":%lu}},"
PRINT_FMT, iso8601buf, tv_ns, elapsed, pid,
(uintptr_t) g_thread_self (),
gst_debug_level_get_name_cee (level),
gst_debug_category_get_name (category), file, line, function, obj,
message_encoded, log_pname, log_appname, log_hostname,
level, gst_debug_level_get_syslog (level));
fflush (log_file);
#undef PRINT_FMT
} else if (color_mode != GST_DEBUG_COLOR_MODE_OFF) {
#ifdef G_OS_WIN32
/* We take a lock to keep colors and content together.
* Maybe there is a better way but for now this will do the right
Expand Down Expand Up @@ -1154,6 +1255,108 @@ gst_debug_level_get_name (GstDebugLevel level)
}
}

/**
* gst_debug_level_get_name_cee:
* @level: the level to get the name for
*
* Get the CEE level string for the specified GStreamer debug level
*
* Returns: the CEE level name
*/
const gchar *
gst_debug_level_get_name_cee (GstDebugLevel level)
{
switch (level) {
case GST_LEVEL_NONE:
return "";
case GST_LEVEL_ERROR:
return "ERROR";
case GST_LEVEL_WARNING:
return "WARN";
case GST_LEVEL_INFO:
case GST_LEVEL_DEBUG:
case GST_LEVEL_LOG:
case GST_LEVEL_FIXME:
case GST_LEVEL_TRACE:
case GST_LEVEL_MEMDUMP:
return "DEBUG";
default:
g_warning ("invalid level specified for gst_debug_level_get_name_cee");
return "";
}
}

/**
* gst_debug_level_get_syslog:
* @level: the level to get the Syslog level for
*
* Get the Syslog level value for the specified GStreamer debug level
*
* Returns: the Syslog level value
*/
int
gst_debug_level_get_syslog (GstDebugLevel level)
{
switch (level) {
case GST_LEVEL_NONE:
return LOG_CRIT;
case GST_LEVEL_ERROR:
return LOG_ERR;
case GST_LEVEL_WARNING:
return LOG_WARNING;
case GST_LEVEL_FIXME:
return LOG_NOTICE;
case GST_LEVEL_INFO:
return LOG_INFO;
case GST_LEVEL_DEBUG:
case GST_LEVEL_LOG:
case GST_LEVEL_TRACE:
case GST_LEVEL_MEMDUMP:
return LOG_DEBUG;
default:
g_warning ("invalid level specified for gst_debug_level_get_syslog");
return LOG_CRIT;
}
}

/**
* gst_debug_escape_json:
* @src: the raw string to be encoded
* @dest: a buffer to store the encoded string
* @dest_size: the maximum number of bytes buffer can accept
*
* Encode @src into a JSON-escaped string as defined in
* RFC 7159 section 7
* https://datatracker.ietf.org/doc/html/rfc7159#section-7
*
* The output is silently truncated if it would be
* longer than @dest_size
*/
void
gst_debug_escape_json (const gchar * src, gchar * dest, gsize dest_size)
{
static const char *json_special = "\"\\/\b\f\n\r\t";
static const char *json_special_replace = "\"\\/bfnrt";
const gchar *src_p = src;
gchar *dest_p = dest, *dest_end = dest + dest_size - 6;
for (; *src_p != 0 && dest_p < dest_end; dest_p++) {
const char *special = strchr (json_special, (char) (*src_p));
if (special != NULL) {
const char *replace = json_special_replace + (special - json_special);
*(dest_p++) = '\\';
*dest_p = *replace;
} else if (*src_p < 0x20) {
/* Everything below 0x20 must be escaped */
snprintf (dest_p, 7, "\\u%04X", *src_p);
dest_p += 5;
} else {
*dest_p = *src_p;
}
src_p++;
}
*dest_p = 0;
}

/**
* gst_debug_add_log_function:
* @func: the function to use
Expand Down
6 changes: 6 additions & 0 deletions gst/gstinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,12 @@ void gst_debug_log_default (GstDebugCategory * category,

const gchar * gst_debug_level_get_name (GstDebugLevel level);

const gchar * gst_debug_level_get_name_cee (GstDebugLevel level);

int gst_debug_level_get_syslog (GstDebugLevel level);

void gst_debug_escape_json(const gchar *src, gchar *dest, gsize dest_size);

void gst_debug_add_log_function (GstLogFunction func,
gpointer user_data,
GDestroyNotify notify);
Expand Down