X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Flogger.c;h=e8347227c3d6ac559d8f1b92fc910acb68f36de6;hb=519fe4ca46c9c415856835cbfe5d6b8710ca7203;hp=2e33baa4eff60e3d91f0b71791d668215b408861;hpb=902e6ae85be4f261a9b061b2f24299715e4a6e80;p=vlc diff --git a/modules/misc/logger.c b/modules/misc/logger.c index 2e33baa4ef..e8347227c3 100644 --- a/modules/misc/logger.c +++ b/modules/misc/logger.c @@ -1,7 +1,7 @@ /***************************************************************************** * logger.c : file logging plugin for vlc ***************************************************************************** - * Copyright (C) 2002 the VideoLAN team + * Copyright (C) 2002-2008 the VideoLAN team * $Id$ * * Authors: Samuel Hocevar @@ -16,9 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 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 02110-1301, USA. + * 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 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -32,14 +32,10 @@ #include #include #include -#include +#include #include -#include /* ENOMEM */ - -#ifdef UNDER_CE -# define _IONBF 0x0004 -#endif +#include #define MODE_TEXT 0 #define MODE_HTML 1 @@ -52,8 +48,6 @@ #define LOG_FILE_TEXT "vlc-log.txt" #define LOG_FILE_HTML "vlc-log.html" -#define LOG_STRING( msg, file ) fwrite( msg, strlen( msg ), 1, file ); - #define TEXT_HEADER "-- logger module started --\n" #define TEXT_FOOTER "-- logger module stopped --\n" @@ -74,22 +68,24 @@ " \n" \ "\n" -#if HAVE_SYSLOG_H +#ifdef HAVE_SYSLOG_H #include #endif +struct msg_cb_data_t +{ + intf_thread_t *p_intf; + FILE *p_file; + int i_mode; +}; + /***************************************************************************** * intf_sys_t: description and status of log interface *****************************************************************************/ struct intf_sys_t { - int i_mode; - FILE *p_rrd; - mtime_t last_update; - time_t now; /* timestamp for rrd-log */ - - FILE * p_file; /* The log file */ msg_subscription_t *p_sub; + msg_cb_data_t msg; }; /***************************************************************************** @@ -97,17 +93,14 @@ struct intf_sys_t *****************************************************************************/ static int Open ( vlc_object_t * ); static void Close ( vlc_object_t * ); -static void Run ( intf_thread_t * ); -static void FlushQueue ( msg_subscription_t *, FILE *, int, int ); +static void Overflow (msg_cb_data_t *p_sys, msg_item_t *p_item, unsigned overruns); static void TextPrint ( const msg_item_t *, FILE * ); static void HtmlPrint ( const msg_item_t *, FILE * ); #ifdef HAVE_SYSLOG_H static void SyslogPrint ( const msg_item_t *); #endif -static void DoRRD( intf_thread_t *p_intf ); - /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -123,34 +116,73 @@ static const char *const mode_list_text[] = { N_("Text"), "HTML" }; #define LOGMODE_TEXT N_("Log format") -#ifdef HAVE_SYSLOG_H +#ifndef HAVE_SYSLOG_H #define LOGMODE_LONGTEXT N_("Specify the log format. Available choices are " \ - "\"text\" (default), \"html\", and \"syslog\" (special mode to send to " \ - "syslog instead of file.") + "\"text\" (default) and \"html\".") #else + #define LOGMODE_LONGTEXT N_("Specify the log format. Available choices are " \ - "\"text\" (default) and \"html\".") + "\"text\" (default), \"html\", and \"syslog\" (special mode to send to " \ + "syslog instead of file.") + +#define SYSLOG_FACILITY_TEXT N_("Syslog facility") +#define SYSLOG_FACILITY_LONGTEXT N_("Select the syslog facility where logs " \ + "will be forwarded. Available choices are \"user\" (default), \"daemon\", " \ + "and \"local0\" through \"local7\".") + +/* First in list is the default facility used. */ +#define DEFINE_SYSLOG_FACILITY \ + DEF( "user", LOG_USER ), \ + DEF( "daemon", LOG_DAEMON ), \ + DEF( "local0", LOG_LOCAL0 ), \ + DEF( "local1", LOG_LOCAL1 ), \ + DEF( "local2", LOG_LOCAL2 ), \ + DEF( "local3", LOG_LOCAL3 ), \ + DEF( "local4", LOG_LOCAL4 ), \ + DEF( "local5", LOG_LOCAL5 ), \ + DEF( "local6", LOG_LOCAL6 ), \ + DEF( "local7", LOG_LOCAL7 ) + +#define DEF( a, b ) a +static const char *const fac_name[] = { DEFINE_SYSLOG_FACILITY }; +#undef DEF +#define DEF( a, b ) b +static const int fac_number[] = { DEFINE_SYSLOG_FACILITY }; +#undef DEF +enum { fac_entries = sizeof(fac_name)/sizeof(fac_name[0]) }; +#undef DEFINE_SYSLOG_FACILITY + #endif -vlc_module_begin(); - set_shortname( N_( "Logging" ) ); - set_description( N_("File logging") ); +#define LOGVERBOSE_TEXT N_("Verbosity") +#define LOGVERBOSE_LONGTEXT N_("Select the verbosity to use for log or -1 to " \ +"use the same verbosity given by --verbose.") + +vlc_module_begin () + set_shortname( N_( "Logging" ) ) + set_description( N_("File logging") ) - set_category( CAT_ADVANCED ); - set_subcategory( SUBCAT_ADVANCED_MISC ); + set_category( CAT_ADVANCED ) + set_subcategory( SUBCAT_ADVANCED_MISC ) add_file( "logfile", NULL, NULL, - N_("Log filename"), N_("Specify the log filename."), false ); + N_("Log filename"), N_("Specify the log filename."), false ) add_string( "logmode", "text", NULL, LOGMODE_TEXT, LOGMODE_LONGTEXT, - false ); - change_string_list( mode_list, mode_list_text, 0 ); - - add_file( "rrd-file", NULL, NULL, N_("RRD output file") , - N_("Output data for RRDTool in this file." ), true ); + false ) + change_string_list( mode_list, mode_list_text, 0 ) +#ifdef HAVE_SYSLOG_H + add_string( "syslog-facility", fac_name[0], NULL, SYSLOG_FACILITY_TEXT, + SYSLOG_FACILITY_LONGTEXT, true ) + change_string_list( fac_name, fac_name, 0 ) +#endif + add_integer( "log-verbose", -1, NULL, LOGVERBOSE_TEXT, LOGVERBOSE_LONGTEXT, + false ) + + add_obsolete_string( "rrd-file" ) - set_capability( "interface", 0 ); - set_callbacks( Open, Close ); -vlc_module_end(); + set_capability( "interface", 0 ) + set_callbacks( Open, Close ) +vlc_module_end () /***************************************************************************** * Open: initialize and create stuff @@ -158,59 +190,61 @@ vlc_module_end(); static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; - char *psz_mode, *psz_file, *psz_rrd_file; + intf_sys_t *p_sys; + char *psz_mode; CONSOLE_INTRO_MSG; - msg_Info( p_intf, "using logger..." ); + msg_Info( p_intf, "using logger." ); /* Allocate instance and initialize some members */ - p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) ); - if( p_intf->p_sys == NULL ) - return -1; + p_sys = p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) ); + if( p_sys == NULL ) + return VLC_ENOMEM; + p_sys->msg.p_intf = p_intf; + p_sys->msg.i_mode = MODE_TEXT; psz_mode = var_CreateGetString( p_intf, "logmode" ); if( psz_mode ) { if( !strcmp( psz_mode, "text" ) ) - { - p_intf->p_sys->i_mode = MODE_TEXT; - } + ; else if( !strcmp( psz_mode, "html" ) ) { - p_intf->p_sys->i_mode = MODE_HTML; + p_sys->msg.i_mode = MODE_HTML; } #ifdef HAVE_SYSLOG_H else if( !strcmp( psz_mode, "syslog" ) ) { - p_intf->p_sys->i_mode = MODE_SYSLOG; + p_sys->msg.i_mode = MODE_SYSLOG; } #endif else { msg_Warn( p_intf, "invalid log mode `%s', using `text'", psz_mode ); - p_intf->p_sys->i_mode = MODE_TEXT; + p_sys->msg.i_mode = MODE_TEXT; } - free( psz_mode ); } else { msg_Warn( p_intf, "no log mode specified, using `text'" ); - p_intf->p_sys->i_mode = MODE_TEXT; } - if( p_intf->p_sys->i_mode != MODE_SYSLOG ) + if( p_sys->msg.i_mode != MODE_SYSLOG ) { - psz_file = config_GetPsz( p_intf, "logfile" ); + char *psz_file = var_InheritString( p_intf, "logfile" ); if( !psz_file ) { #ifdef __APPLE__ - if( asprintf( &psz_file, "%s/"LOG_DIR"/%s", config_GetHomeDir(), - (p_intf->p_sys->i_mode == MODE_HTML) ? LOG_FILE_HTML - : LOG_FILE_TEXT ) == -1 ) + char *home = config_GetUserDir(VLC_DOCUMENTS_DIR); + if( home == NULL + || asprintf( &psz_file, "%s/"LOG_DIR"/%s", home, + (p_sys->msg.i_mode == MODE_HTML) ? LOG_FILE_HTML + : LOG_FILE_TEXT ) == -1 ) psz_file = NULL; + free(home); #else - switch( p_intf->p_sys->i_mode ) + switch( p_sys->msg.i_mode ) { case MODE_HTML: psz_file = strdup( LOG_FILE_HTML ); @@ -227,52 +261,68 @@ static int Open( vlc_object_t *p_this ) /* Open the log file and remove any buffering for the stream */ msg_Dbg( p_intf, "opening logfile `%s'", psz_file ); - p_intf->p_sys->p_file = utf8_fopen( psz_file, "at" ); - if( p_intf->p_sys->p_file == NULL ) + p_sys->msg.p_file = vlc_fopen( psz_file, "at" ); + if( p_sys->msg.p_file == NULL ) { msg_Err( p_intf, "error opening logfile `%s'", psz_file ); - free( p_intf->p_sys ); + free( p_sys ); free( psz_file ); return -1; } - setvbuf( p_intf->p_sys->p_file, NULL, _IONBF, 0 ); + setvbuf( p_sys->msg.p_file, NULL, _IONBF, 0 ); free( psz_file ); - switch( p_intf->p_sys->i_mode ) + switch( p_sys->msg.i_mode ) { case MODE_HTML: - LOG_STRING( HTML_HEADER, p_intf->p_sys->p_file ); + fputs( HTML_HEADER, p_sys->msg.p_file ); break; case MODE_TEXT: default: - LOG_STRING( TEXT_HEADER, p_intf->p_sys->p_file ); + fputs( TEXT_HEADER, p_sys->msg.p_file ); break; } } else { - p_intf->p_sys->p_file = NULL; + p_sys->msg.p_file = NULL; #ifdef HAVE_SYSLOG_H - openlog( "vlc", LOG_PID|LOG_NDELAY, LOG_DAEMON ); -#endif - } - - p_intf->p_sys->last_update = 0; - p_intf->p_sys->p_rrd = NULL; + int i_facility; + char *psz_facility = var_CreateGetString( p_intf, "syslog-facility" ); + if( psz_facility ) + { + bool b_valid = 0; + for( size_t i = 0; i < fac_entries; ++i ) + { + if( !strcmp( psz_facility, fac_name[i] ) ) + { + i_facility = fac_number[i]; + b_valid = 1; + break; + } + } + if( !b_valid ) + { + msg_Warn( p_intf, "invalid syslog facility `%s', using `%s'", + psz_facility, fac_name[0] ); + i_facility = fac_number[0]; + } + free( psz_facility ); + } + else + { + msg_Warn( p_intf, "no syslog facility specified, using `%s'", + fac_name[0] ); + i_facility = fac_number[0]; + } - psz_rrd_file = config_GetPsz( p_intf, "rrd-file" ); - if( psz_rrd_file && *psz_rrd_file ) - { - p_intf->p_sys->p_rrd = utf8_fopen( psz_rrd_file, "w" ); - if (p_intf->p_sys->p_rrd != NULL) - setvbuf (p_intf->p_sys->p_rrd, NULL, _IOLBF, BUFSIZ); + openlog( "vlc", LOG_PID|LOG_NDELAY, i_facility ); +#endif } - free( psz_rrd_file ); - p_intf->p_sys->p_sub = msg_Subscribe( p_intf ); - p_intf->pf_run = Run; + p_sys->p_sub = msg_Subscribe( p_intf->p_libvlc, Overflow, &p_sys->msg ); return 0; } @@ -283,127 +333,93 @@ static int Open( vlc_object_t *p_this ) static void Close( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; + intf_sys_t *p_sys = p_intf->p_sys; /* Flush the queue and unsubscribe from the message queue */ - FlushQueue( p_intf->p_sys->p_sub, p_intf->p_sys->p_file, - p_intf->p_sys->i_mode, - var_CreateGetInteger( p_intf, "verbose" ) ); - msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub ); + /* FIXME: flush */ + msg_Unsubscribe( p_sys->p_sub ); - switch( p_intf->p_sys->i_mode ) + switch( p_sys->msg.i_mode ) { case MODE_HTML: - LOG_STRING( HTML_FOOTER, p_intf->p_sys->p_file ); + fputs( HTML_FOOTER, p_sys->msg.p_file ); break; - case MODE_TEXT: #ifdef HAVE_SYSLOG_H case MODE_SYSLOG: closelog(); break; #endif + case MODE_TEXT: default: - LOG_STRING( TEXT_FOOTER, p_intf->p_sys->p_file ); + fputs( TEXT_FOOTER, p_sys->msg.p_file ); break; } /* Close the log file */ - if( p_intf->p_sys->i_mode != MODE_SYSLOG ) - fclose( p_intf->p_sys->p_file ); + if( p_sys->msg.p_file ) + fclose( p_sys->msg.p_file ); /* Destroy structure */ - free( p_intf->p_sys ); + free( p_sys ); } -/***************************************************************************** - * Run: rc thread - ***************************************************************************** - * This part of the interface is in a separate thread so that we can call - * exec() from within it without annoying the rest of the program. - *****************************************************************************/ -static void Run( intf_thread_t *p_intf ) +/** + * Log a message + */ +static void Overflow (msg_cb_data_t *p_sys, msg_item_t *p_item, unsigned overruns) { - for( ;; ) + VLC_UNUSED(overruns); + int verbosity = var_CreateGetInteger( p_sys->p_intf, "log-verbose" ); + if (verbosity == -1) + verbosity = var_CreateGetInteger( p_sys->p_intf, "verbose" ); + + switch( p_item->i_type ) { - int canc = vlc_savecancel(); - FlushQueue( p_intf->p_sys->p_sub, p_intf->p_sys->p_file, - p_intf->p_sys->i_mode, - var_CreateGetInteger( p_intf, "verbose" ) ); - if( p_intf->p_sys->p_rrd ) - DoRRD( p_intf ); - - vlc_restorecancel( canc ); - /* FIXME: this is WRONG. */ - msleep( INTF_IDLE_SLEEP ); + case VLC_MSG_INFO: + case VLC_MSG_ERR: + if( verbosity < 0 ) return; + break; + case VLC_MSG_WARN: + if( verbosity < 1 ) return; + break; + case VLC_MSG_DBG: + if( verbosity < 2 ) return; + break; } -} -/***************************************************************************** - * FlushQueue: flush the message queue into the log - *****************************************************************************/ -static void FlushQueue( msg_subscription_t *p_sub, FILE *p_file, int i_mode, - int i_verbose ) -{ - int i_start, i_stop; - vlc_mutex_lock( p_sub->p_lock ); - i_stop = *p_sub->pi_stop; - vlc_mutex_unlock( p_sub->p_lock ); + int canc = vlc_savecancel(); - if( p_sub->i_start != i_stop ) + switch( p_sys->i_mode ) { - /* Append all messages to log file */ - for( i_start = p_sub->i_start; - i_start != i_stop; - i_start = (i_start+1) % VLC_MSG_QSIZE ) - { - switch( p_sub->p_msg[i_start].i_type ) - { - case VLC_MSG_ERR: - if( i_verbose < 0 ) continue; - break; - case VLC_MSG_INFO: - if( i_verbose < 0 ) continue; - break; - case VLC_MSG_WARN: - if( i_verbose < 1 ) continue; - break; - case VLC_MSG_DBG: - if( i_verbose < 2 ) continue; - break; - } - - switch( i_mode ) - { - case MODE_HTML: - HtmlPrint( &p_sub->p_msg[i_start], p_file ); - break; + case MODE_HTML: + HtmlPrint( p_item, p_sys->p_file ); + break; #ifdef HAVE_SYSLOG_H - case MODE_SYSLOG: - SyslogPrint( &p_sub->p_msg[i_start] ); - break; + case MODE_SYSLOG: + SyslogPrint( p_item ); + break; #endif - case MODE_TEXT: - default: - TextPrint( &p_sub->p_msg[i_start], p_file ); - break; - } - } - - vlc_mutex_lock( p_sub->p_lock ); - p_sub->i_start = i_start; - vlc_mutex_unlock( p_sub->p_lock ); + case MODE_TEXT: + default: + TextPrint( p_item, p_sys->p_file ); + break; } + + vlc_restorecancel( canc ); } -static const char *ppsz_type[4] = { ": ", " error: ", - " warning: ", " debug: " }; +static const char ppsz_type[4][11] = { + ": ", + " error: ", + " warning: ", + " debug: ", +}; static void TextPrint( const msg_item_t *p_msg, FILE *p_file ) { - LOG_STRING( p_msg->psz_module, p_file ); - LOG_STRING( ppsz_type[p_msg->i_type], p_file ); - LOG_STRING( p_msg->psz_msg, p_file ); - LOG_STRING( "\n", p_file ); + utf8_fprintf( p_file, "%s%s%s\n", p_msg->psz_module, + ppsz_type[p_msg->i_type], p_msg->psz_msg ); } #ifdef HAVE_SYSLOG_H @@ -413,11 +429,10 @@ static void SyslogPrint( const msg_item_t *p_msg ) int i_priority = i_prio[p_msg->i_type]; if( p_msg->psz_header ) - syslog( i_priority, "%s%s %s: %s", p_msg->psz_header, - ppsz_type[p_msg->i_type], - p_msg->psz_module, p_msg->psz_msg ); + syslog( i_priority, "%s %s%s%s", p_msg->psz_header, p_msg->psz_module, + ppsz_type[p_msg->i_type], p_msg->psz_msg ); else - syslog( i_priority, "%s%s: %s", p_msg->psz_module, + syslog( i_priority, "%s%s%s", p_msg->psz_module, ppsz_type[p_msg->i_type], p_msg->psz_msg ); } @@ -425,36 +440,14 @@ static void SyslogPrint( const msg_item_t *p_msg ) static void HtmlPrint( const msg_item_t *p_msg, FILE *p_file ) { - static const char *ppsz_color[4] = { "", - "", - "", - "" }; - - LOG_STRING( p_msg->psz_module, p_file ); - LOG_STRING( ppsz_type[p_msg->i_type], p_file ); - LOG_STRING( ppsz_color[p_msg->i_type], p_file ); - LOG_STRING( p_msg->psz_msg, p_file ); - LOG_STRING( "\n", p_file ); -} - -static void DoRRD( intf_thread_t *p_intf ) -{ - mtime_t now = mdate(); - if( now - p_intf->p_sys->last_update < 1000000 ) - return; - p_intf->p_sys->last_update = now; - - if( p_intf->p_libvlc->p_stats ) - { - time(&p_intf->p_sys->now); - lldiv_t in = lldiv( p_intf->p_libvlc->p_stats->f_input_bitrate * 1000000, - 1000 ); - lldiv_t dm = lldiv( p_intf->p_libvlc->p_stats->f_demux_bitrate * 1000000, - 1000 ); - lldiv_t out = lldiv( p_intf->p_libvlc->p_stats->f_output_bitrate * 1000000, - 1000 ); - fprintf( p_intf->p_sys->p_rrd, - "%"PRIi64":%lld.%03llu:%lld.%03llu:%lld.%03llu\n", - now, in.quot, in.rem, dm.quot, dm.rem, out.quot, out.rem ); - } + static const char ppsz_color[4][30] = { + "", + "", + "", + "", + }; + + fprintf( p_file, "%s%s%s%s\n", p_msg->psz_module, + ppsz_type[p_msg->i_type], ppsz_color[p_msg->i_type], + p_msg->psz_msg ); }