From c828849620a310aa596dc01571701b89aafbb333 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Wed, 10 Apr 2013 16:30:13 +0100 Subject: [PATCH] tvhlog: add UI debug to allow run-time updates to the debugging config --- src/main.c | 3 + src/tvhlog.c | 19 ++++++ src/tvhlog.h | 1 + src/webui/extjs.c | 85 +++++++++++++++++++++++++ src/webui/static/app/tvheadend.js | 3 + src/webui/static/app/tvhlog.js | 102 ++++++++++++++++++++++++++++++ 6 files changed, 213 insertions(+) create mode 100644 src/webui/static/app/tvhlog.js diff --git a/src/main.c b/src/main.c index 02ee83a3..80a66e4a 100644 --- a/src/main.c +++ b/src/main.c @@ -131,6 +131,9 @@ const tvh_caps_t tvheadend_capabilities[] = { #endif #if ENABLE_TIMESHIFT { "timeshift", ×hift_enabled }, +#endif +#if ENABLE_TRACE + { "trace", NULL }, #endif { NULL, NULL } }; diff --git a/src/tvhlog.c b/src/tvhlog.c index 342bbb76..bbb11d03 100644 --- a/src/tvhlog.c +++ b/src/tvhlog.c @@ -56,6 +56,25 @@ tvhlog_init ( int level, int options, const char *path ) pthread_mutex_init(&tvhlog_mutex, NULL); } +/* Get subsys */ +void tvhlog_get_subsys ( char *subsys, size_t len ) +{ + size_t c = 0; + int first = 1; + htsmsg_field_t *f; + *subsys = '\0'; + if (tvhlog_subsys) { + HTSMSG_FOREACH(f, tvhlog_subsys) { + if (f->hmf_type != HMF_S64) continue; + c += snprintf(subsys+c, len-c, "%c%s%s", + f->hmf_s64 ? '+' : '-', + f->hmf_name, + first ? "" : ","); + first = 0; + } + } +} + /* Set subsys */ void tvhlog_set_subsys ( const char *subsys ) { diff --git a/src/tvhlog.h b/src/tvhlog.h index c36a3c44..bde46a50 100644 --- a/src/tvhlog.h +++ b/src/tvhlog.h @@ -34,6 +34,7 @@ extern pthread_mutex_t tvhlog_mutex; /* Initialise */ void tvhlog_init ( int level, int options, const char *path ); void tvhlog_set_subsys ( const char *subsys ); +void tvhlog_get_subsys ( char *subsys, size_t len ); void tvhlogv ( const char *file, int line, int notify, int severity, const char *subsys, const char *fmt, va_list args ); diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 6e793562..fd10ef8a 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -146,6 +146,7 @@ extjs_root(http_connection_t *hc, const char *remain, void *opaque) extjs_load(hq, "static/app/dvr.js"); extjs_load(hq, "static/app/epggrab.js"); extjs_load(hq, "static/app/config.js"); + extjs_load(hq, "static/app/tvhlog.js"); extjs_load(hq, "static/app/status.js"); /** @@ -2054,6 +2055,89 @@ extjs_config(http_connection_t *hc, const char *remain, void *opaque) return 0; } +/** + * + */ +static int +extjs_tvhlog(http_connection_t *hc, const char *remain, void *opaque) +{ + htsbuf_queue_t *hq = &hc->hc_reply; + const char *op = http_arg_get(&hc->hc_req_args, "op"); + htsmsg_t *out, *m; + + if(op == NULL) + return 400; + + pthread_mutex_lock(&global_lock); + + if(http_access_verify(hc, ACCESS_ADMIN)) { + pthread_mutex_unlock(&global_lock); + return HTTP_STATUS_UNAUTHORIZED; + } + + pthread_mutex_unlock(&global_lock); + + /* Basic settings */ + if(!strcmp(op, "loadSettings")) { + char str[2048]; + + /* Get config */ + pthread_mutex_lock(&tvhlog_mutex); + m = htsmsg_create_map(); + htsmsg_add_u32(m, "tvhlog_level", tvhlog_level); + htsmsg_add_u32(m, "tvhlog_trace", tvhlog_level > LOG_DEBUG); + tvhlog_get_subsys(str, sizeof(str)); + htsmsg_add_str(m, "tvhlog_subsys", str); + htsmsg_add_str(m, "tvhlog_path", tvhlog_path ?: ""); + htsmsg_add_u32(m, "tvhlog_options", tvhlog_options); + htsmsg_add_u32(m, "tvhlog_dbg_syslog", + tvhlog_options & TVHLOG_OPT_DBG_SYSLOG); + pthread_mutex_unlock(&tvhlog_mutex); + + if (!m) return HTTP_STATUS_BAD_REQUEST; + out = json_single_record(m, "config"); + + /* Save settings */ + } else if (!strcmp(op, "saveSettings") ) { + const char *str; + + pthread_mutex_lock(&tvhlog_mutex); + if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_level"))) + tvhlog_level = atoi(str); + if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_trace"))) + tvhlog_level = LOG_TRACE; + else + tvhlog_level = LOG_DEBUG; + if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_path"))) { + free(tvhlog_path); + if (*str) + tvhlog_path = strdup(str); + else + tvhlog_path = NULL; + } + if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_options"))) + tvhlog_options = atoi(str); + if ((str = http_arg_get(&hc->hc_req_args, "tvhlog_dbg_syslog"))) + tvhlog_options |= TVHLOG_OPT_DBG_SYSLOG; + else + tvhlog_options &= ~TVHLOG_OPT_DBG_SYSLOG; + tvhlog_set_subsys(http_arg_get(&hc->hc_req_args, "tvhlog_subsys")); + pthread_mutex_unlock(&tvhlog_mutex); + + out = htsmsg_create_map(); + htsmsg_add_u32(out, "success", 1); + + } else { + return HTTP_STATUS_BAD_REQUEST; + } + + htsmsg_json_serialize(out, hq, 0); + htsmsg_destroy(out); + http_output_content(hc, "text/x-json; charset=UTF-8"); + + return 0; +} + /** * Capability check */ @@ -2174,6 +2258,7 @@ extjs_start(void) #if ENABLE_TIMESHIFT http_path_add("/timeshift", NULL, extjs_timeshift, ACCESS_ADMIN); #endif + http_path_add("/tvhlog", NULL, extjs_tvhlog, ACCESS_ADMIN); #if ENABLE_LINUXDVB extjs_start_dvb(); diff --git a/src/webui/static/app/tvheadend.js b/src/webui/static/app/tvheadend.js index 1db51311..761be214 100644 --- a/src/webui/static/app/tvheadend.js +++ b/src/webui/static/app/tvheadend.js @@ -320,6 +320,9 @@ function accessUpdate(o) { tabs1.push(tvheadend.conf_csa); } + /* Debug */ + tabs1.push(new tvheadend.tvhlog); + tvheadend.confpanel = new Ext.TabPanel({ activeTab : 0, autoScroll : true, diff --git a/src/webui/static/app/tvhlog.js b/src/webui/static/app/tvhlog.js new file mode 100644 index 00000000..5737405f --- /dev/null +++ b/src/webui/static/app/tvhlog.js @@ -0,0 +1,102 @@ +tvheadend.tvhlog = function() { + /* + * Basic Config + */ + var confreader = new Ext.data.JsonReader({ + root : 'config' + }, [ 'tvhlog_path', 'tvhlog_dbg_syslog', 'tvhlog_subsys', 'tvhlog_trace' ]); + + /* **************************************************************** + * Form Fields + * ***************************************************************/ + + var tvhlogLogPath = new Ext.form.TextField({ + fieldLabel : 'Debug Log Path', + name : 'tvhlog_path', + allowBlank : true, + width: 400 + }); + + var tvhlogToSyslog = new Ext.form.Checkbox({ + name: 'tvhlog_dbg_syslog', + fieldLabel: 'Debug to syslog' + }); + + var tvhlogTrace = new Ext.form.Checkbox({ + name: 'tvhlog_trace', + fieldLabel: 'Debug trace (low-level stuff)' + }); + + var tvhlogSubsys = new Ext.form.TextField({ + fieldLabel : 'Debug Subsystems', + name : 'tvhlog_subsys', + allowBlank : true, + width: 400 + }); + + /* **************************************************************** + * Form + * ***************************************************************/ + + var saveButton = new Ext.Button({ + text : "Save configuration", + tooltip : 'Save changes made to configuration below', + iconCls : 'save', + handler : saveChanges + }); + + var helpButton = new Ext.Button({ + text : 'Help', + handler : function() { + new tvheadend.help('Debug Configuration', 'config_tvhlog.html'); + } + }); + + var confpanel = new Ext.form.FormPanel({ + title : 'Debugging', + iconCls : 'wrench', + border : false, + bodyStyle : 'padding:15px', + labelAlign : 'left', + labelWidth : 200, + waitMsgTarget : true, + reader : confreader, + layout : 'form', + defaultType : 'textfield', + autoHeight : true, + items : [ tvhlogLogPath, tvhlogToSyslog, + tvhlogTrace, tvhlogSubsys ], + tbar : [ saveButton, '->', helpButton ] + }); + + /* **************************************************************** + * Load/Save + * ***************************************************************/ + + confpanel.on('render', function() { + confpanel.getForm().load({ + url : 'tvhlog', + params : { + op : 'loadSettings' + }, + success : function(form, action) { + confpanel.enable(); + } + }); + }); + + function saveChanges() { + confpanel.getForm().submit({ + url : 'tvhlog', + params : { + op : 'saveSettings' + }, + waitMsg : 'Saving Data...', + failure : function(form, action) { + Ext.Msg.alert('Save failed', action.result.errormsg); + } + }); + } + + return confpanel; +}