X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fmisc%2Flogger.c;h=7f7ed6c7b33a0c775df8eb4eea3c3687f476318d;hb=c26e0c1f56645085164cb1a98caf99f2a8a485f6;hp=2cf84a740f79e644a338b00c401d98dfad656d50;hpb=44e62217a16765805c5a3ef8440375395d56e86c;p=vlc diff --git a/modules/misc/logger.c b/modules/misc/logger.c index 2cf84a740f..7f7ed6c7b3 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. *****************************************************************************/ /***************************************************************************** @@ -29,17 +29,14 @@ # include "config.h" #endif -#include +#include #include #include -#include +#include #include -#include /* ENOMEM */ - -#ifdef UNDER_CE -# define _IONBF 0x0004 -#endif +#include +#include #define MODE_TEXT 0 #define MODE_HTML 1 @@ -52,9 +49,7 @@ #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_HEADER "\xEF\xBB\xBF-- logger module started --\n" #define TEXT_FOOTER "-- logger module stopped --\n" #define HTML_HEADER \ @@ -67,14 +62,14 @@ " \n" \ " \n" \ "
\n" \
-    "      -- logger module started --\n"
+    "      -- logger module started --\n"
 #define HTML_FOOTER \
-    "      -- logger module stopped --\n" \
+    "      -- logger module stopped --\n" \
     "    
\n" \ " \n" \ "\n" -#if HAVE_SYSLOG_H +#ifdef HAVE_SYSLOG_H #include #endif @@ -83,13 +78,9 @@ *****************************************************************************/ 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; + FILE *p_file; + const char *footer; }; /***************************************************************************** @@ -97,61 +88,96 @@ 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 TextPrint ( const msg_item_t *, FILE * ); -static void HtmlPrint ( const msg_item_t *, FILE * ); +static void TextPrint(void *, int, const msg_item_t *, const char *, va_list); +static void HtmlPrint(void *, int, const msg_item_t *, const char *, va_list); #ifdef HAVE_SYSLOG_H -static void SyslogPrint ( const msg_item_t *); +static void SyslogPrint(void *, int, const msg_item_t *, const char *, + va_list); #endif -static void DoRRD( intf_thread_t *p_intf ); - /***************************************************************************** * Module descriptor *****************************************************************************/ -static const char *mode_list[] = { "text", "html" +static const char *const mode_list[] = { "text", "html" #ifdef HAVE_SYSLOG_H ,"syslog" #endif }; -static const char *mode_list_text[] = { N_("Text"), "HTML" +static const char *const mode_list_text[] = { N_("Text"), "HTML" #ifdef HAVE_SYSLOG_H , "syslog" #endif }; #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.") - set_category( CAT_ADVANCED ); - set_subcategory( SUBCAT_ADVANCED_MISC ); +vlc_module_begin () + set_shortname( N_( "Logging" ) ) + set_description( N_("File logging") ) - add_file( "logfile", NULL, NULL, - N_("Log filename"), N_("Specify the log filename."), false ); - change_unsafe(); - add_string( "logmode", "text", NULL, LOGMODE_TEXT, LOGMODE_LONGTEXT, - false ); - change_string_list( mode_list, mode_list_text, 0 ); + set_category( CAT_ADVANCED ) + set_subcategory( SUBCAT_ADVANCED_MISC ) - add_file( "rrd-file", NULL, NULL, N_("RRD output file") , - N_("Output data for RRDTool in this file." ), true ); + add_savefile( "logfile", NULL, + N_("Log filename"), N_("Specify the log filename."), false ) + add_string( "logmode", "text", LOGMODE_TEXT, LOGMODE_LONGTEXT, + false ) + change_string_list( mode_list, mode_list_text, 0 ) +#ifdef HAVE_SYSLOG_H + add_string( "syslog-facility", fac_name[0], SYSLOG_FACILITY_TEXT, + SYSLOG_FACILITY_LONGTEXT, true ) + change_string_list( fac_name, fac_name, 0 ) +#endif + add_integer( "log-verbose", -1, 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 @@ -159,123 +185,110 @@ 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; 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 ) - { - msg_Err( p_intf, "out of memory" ); - return -1; - } + p_sys = p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) ); + if( p_sys == NULL ) + return VLC_ENOMEM; + + msg_callback_t cb = TextPrint; + const char *filename = LOG_FILE_TEXT, *header = TEXT_HEADER; + p_sys->footer = TEXT_FOOTER; - psz_mode = var_CreateGetString( p_intf, "logmode" ); - if( psz_mode ) + char *mode = var_InheritString( p_intf, "logmode" ); + if( mode != NULL ) { - if( !strcmp( psz_mode, "text" ) ) + if( !strcmp( mode, "html" ) ) { - p_intf->p_sys->i_mode = MODE_TEXT; - } - else if( !strcmp( psz_mode, "html" ) ) - { - p_intf->p_sys->i_mode = MODE_HTML; + p_sys->footer = HTML_FOOTER; + header = HTML_HEADER; + cb = HtmlPrint; } #ifdef HAVE_SYSLOG_H - else if( !strcmp( psz_mode, "syslog" ) ) + else if( !strcmp( mode, "syslog" ) ) + cb = SyslogPrint; +#endif + else if( strcmp( mode, "text" ) ) + msg_Warn( p_intf, "invalid log mode `%s', using `text'", mode ); + free( mode ); + } + +#ifdef HAVE_SYSLOG_H + if( cb == SyslogPrint ) + { + int i_facility; + char *psz_facility = var_InheritString( p_intf, "syslog-facility" ); + if( psz_facility ) { - p_intf->p_sys->i_mode = MODE_SYSLOG; + 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 ); } -#endif else { - msg_Warn( p_intf, "invalid log mode `%s', using `text'", psz_mode ); - p_intf->p_sys->i_mode = MODE_TEXT; + msg_Warn( p_intf, "no syslog facility specified, using `%s'", + fac_name[0] ); + i_facility = fac_number[0]; } - free( psz_mode ); + openlog( "vlc", LOG_PID|LOG_NDELAY, i_facility ); + p_sys->p_file = NULL; } else +#endif { - 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 ) - { - 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, + filename ) == -1 ) psz_file = NULL; -#else - switch( p_intf->p_sys->i_mode ) - { - case MODE_HTML: - psz_file = strdup( LOG_FILE_HTML ); - break; - case MODE_TEXT: - default: - psz_file = strdup( LOG_FILE_TEXT ); - break; - } + free(home); + filename = psz_file; #endif msg_Warn( p_intf, "no log filename provided, using `%s'", - psz_file ); + filename ); } + else + filename = psz_file; /* 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 ) - { - msg_Err( p_intf, "error opening logfile `%s'", psz_file ); - free( p_intf->p_sys ); - free( psz_file ); - return -1; - } - setvbuf( p_intf->p_sys->p_file, NULL, _IONBF, 0 ); - + msg_Dbg( p_intf, "opening logfile `%s'", filename ); + p_sys->p_file = vlc_fopen( filename, "at" ); free( psz_file ); - - switch( p_intf->p_sys->i_mode ) + if( p_sys->p_file == NULL ) { - case MODE_HTML: - LOG_STRING( HTML_HEADER, p_intf->p_sys->p_file ); - break; - case MODE_TEXT: - default: - LOG_STRING( TEXT_HEADER, p_intf->p_sys->p_file ); - break; + msg_Err( p_intf, "error opening logfile `%s': %m", filename ); + free( p_sys ); + return VLC_EGENERIC; } - + setvbuf( p_sys->p_file, NULL, _IONBF, 0 ); + fputs( header, p_sys->p_file ); } - else - { - p_intf->p_sys->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; - - 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" ); - } - - p_intf->p_sys->p_sub = msg_Subscribe( p_intf ); - p_intf->pf_run = Run; - return 0; + p_sys->p_sub = vlc_Subscribe( cb, p_intf ); + return VLC_SUCCESS; } /***************************************************************************** @@ -284,178 +297,111 @@ 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 ); + vlc_Unsubscribe( p_sys->p_sub ); - switch( p_intf->p_sys->i_mode ) - { - case MODE_HTML: - LOG_STRING( HTML_FOOTER, p_intf->p_sys->p_file ); - break; - case MODE_TEXT: + /* Close the log file */ #ifdef HAVE_SYSLOG_H - case MODE_SYSLOG: + if( p_sys->p_file == NULL ) closelog(); - break; + else #endif - default: - LOG_STRING( TEXT_FOOTER, p_intf->p_sys->p_file ); - break; + { + fputs( p_sys->footer, p_sys->p_file ); + fclose( p_sys->p_file ); } - /* Close the log file */ - if( p_intf->p_sys->i_mode != MODE_SYSLOG ) - fclose( p_intf->p_sys->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 ) +static bool IgnoreMessage( intf_thread_t *p_intf, int type ) { - while( !p_intf->b_die ) - { - 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 ); + /* TODO: cache value... */ + int verbosity = var_InheritInteger( p_intf, "log-verbose" ); + if (verbosity == -1) + verbosity = var_InheritInteger( p_intf, "verbose" ); - msleep( INTF_IDLE_SLEEP ); - } + return verbosity < 0 || verbosity < (type - VLC_MSG_ERR); } -/***************************************************************************** - * 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 ); +/* + * Logging callbacks + */ - if( p_sub->i_start != i_stop ) - { - /* 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; -#ifdef HAVE_SYSLOG_H - case MODE_SYSLOG: - SyslogPrint( &p_sub->p_msg[i_start] ); - break; -#endif - case MODE_TEXT: - default: - TextPrint( &p_sub->p_msg[i_start], p_file ); - break; - } - } +static const char ppsz_type[4][9] = { + "", + " error", + " warning", + " debug", +}; - vlc_mutex_lock( p_sub->p_lock ); - p_sub->i_start = i_start; - vlc_mutex_unlock( p_sub->p_lock ); - } -} +static void TextPrint( void *opaque, int type, const msg_item_t *item, + const char *fmt, va_list ap ) +{ + intf_thread_t *p_intf = opaque; + FILE *stream = p_intf->p_sys->p_file; -static const char *ppsz_type[4] = { ": ", " error: ", - " warning: ", " debug: " }; + if( IgnoreMessage( p_intf, type ) ) + return; -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 ); + int canc = vlc_savecancel(); + flockfile( stream ); + fprintf( stream, "%s%s: ", item->psz_module, ppsz_type[type] ); + vfprintf( stream, fmt, ap ); + putc_unlocked( '\n', stream ); + funlockfile( stream ); + vlc_restorecancel( canc ); } #ifdef HAVE_SYSLOG_H -static void SyslogPrint( const msg_item_t *p_msg ) +static void SyslogPrint( void *opaque, int type, const msg_item_t *item, + const char *fmt, va_list ap ) { static const int i_prio[4] = { LOG_INFO, LOG_ERR, LOG_WARNING, LOG_DEBUG }; - 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 ); + intf_thread_t *p_intf = opaque; + char *str; + int i_priority = i_prio[type]; + + if( IgnoreMessage( p_intf, type ) + || unlikely(vasprintf( &str, fmt, ap ) == -1) ) + return; + + int canc = vlc_savecancel(); + if( item->psz_header != NULL ) + syslog( i_priority, "[%s] %s%s: %s", item->psz_header, + item->psz_module, ppsz_type[type], str ); else - syslog( i_priority, "%s%s: %s", p_msg->psz_module, - ppsz_type[p_msg->i_type], p_msg->psz_msg ); - + syslog( i_priority, "%s%s: %s", + item->psz_module, ppsz_type[type], str ); + vlc_restorecancel( canc ); + free( str ); } #endif -static void HtmlPrint( const msg_item_t *p_msg, FILE *p_file ) +static void HtmlPrint( void *opaque, int type, const msg_item_t *item, + const char *fmt, va_list ap ) { - 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 const unsigned color[4] = { + 0xffffff, 0xff6666, 0xffff66, 0xaaaaaa, + }; -static void DoRRD( intf_thread_t *p_intf ) -{ - if( mdate() - p_intf->p_sys->last_update < 1000000 ) + intf_thread_t *p_intf = opaque; + FILE *stream = p_intf->p_sys->p_file; + + if( IgnoreMessage( p_intf, type ) ) return; - p_intf->p_sys->last_update = mdate(); - if( p_intf->p_libvlc->p_stats ) - { - time(&p_intf->p_sys->now); - lldiv_t din = lldiv( p_intf->p_libvlc->p_stats->f_input_bitrate * 1000000, - 1000 ); - lldiv_t ddm = lldiv( p_intf->p_libvlc->p_stats->f_demux_bitrate * 1000000, - 1000 ); - lldiv_t dout = lldiv( p_intf->p_libvlc->p_stats->f_output_bitrate * 1000000, - 1000 ); - fprintf( p_intf->p_sys->p_rrd, - "%"PRIi64":%lld.%03u:%lld.%03u:%lld.%03u\n", - (uintmax_t)p_intf->p_sys->now, - din.quot, (unsigned int)din.rem, - ddm.quot, (unsigned int)ddm.rem, - dout.quot, (unsigned int)dout.rem ); - fflush( p_intf->p_sys->p_rrd ); - } + int canc = vlc_savecancel(); + flockfile( stream ); + fprintf( stream, "%s%s: ", + item->psz_module, ppsz_type[type], color[type] ); + /* FIXME: encode special ASCII characters */ + fprintf( stream, fmt, ap ); + fputs( "\n", stream ); + funlockfile( stream ); + vlc_restorecancel( canc ); }