1 #include <opensrf/log.h>
3 #define OSRF_NO_LOG_TYPE -1
5 static int _prevLogType = OSRF_NO_LOG_TYPE;
6 static int _osrfLogType = OSRF_LOG_TYPE_STDERR;
7 static int _osrfLogFacility = LOG_LOCAL0;
8 static int _osrfLogActFacility = LOG_LOCAL1;
9 static char* _osrfLogFile = NULL;
10 static char* _osrfLogAppname = NULL;
11 static int _osrfLogLevel = OSRF_LOG_INFO;
12 static int _osrfLogActivityEnabled = 1;
13 static int _osrfLogIsClient = 0;
15 static char* _osrfLogXid = NULL; /* current xid */
16 static char* _osrfLogXidPfx = NULL; /* xid prefix string */
18 static void osrfLogSetType( int logtype );
19 static void _osrfLogDetail( int level, const char* filename, int line, char* msg );
20 static void _osrfLogToFile( const char* msg, ... );
21 static void _osrfLogSetXid( const char* xid );
23 #define OSRF_LOG_GO(f,li,m,l) \
25 VA_LIST_TO_STRING(m); \
26 _osrfLogDetail( l, f, li, VA_BUF );
28 void osrfLogCleanup( void ) {
29 free(_osrfLogAppname);
30 _osrfLogAppname = NULL;
33 _osrfLogType = OSRF_LOG_TYPE_STDERR;
37 void osrfLogInit( int type, const char* appname, int maxlevel ) {
39 if(appname) osrfLogSetAppname(appname);
40 osrfLogSetLevel(maxlevel);
41 if( type == OSRF_LOG_TYPE_SYSLOG )
42 openlog(_osrfLogAppname, 0, _osrfLogFacility );
45 static void _osrfLogSetXid( const char* xid ) {
47 if(_osrfLogXid) free(_osrfLogXid);
48 _osrfLogXid = strdup(xid);
52 void osrfLogClearXid( void ) { _osrfLogSetXid(""); }
53 void osrfLogSetXid(char* xid) {
54 if(!_osrfLogIsClient) _osrfLogSetXid(xid);
57 void osrfLogMkXid( void ) {
58 if(_osrfLogIsClient) {
59 static int _osrfLogXidInc = 0; /* increments with each new xid for uniqueness */
62 snprintf(buf, 32, "%s%d", _osrfLogXidPfx, _osrfLogXidInc);
68 char* osrfLogGetXid( void ) {
72 void osrfLogSetIsClient(int is) {
73 _osrfLogIsClient = is;
75 /* go ahead and create the xid prefix so it will be consistent later */
77 memset(buff, 0x0, 32);
78 snprintf(buff, 32, "%d%ld", (int)time(NULL), (long) getpid());
79 _osrfLogXidPfx = buff;
82 /** Sets the type of logging to perform. See log types */
83 static void osrfLogSetType( int logtype ) {
87 case OSRF_LOG_TYPE_FILE :
88 case OSRF_LOG_TYPE_SYSLOG :
89 case OSRF_LOG_TYPE_STDERR :
90 _osrfLogType = logtype;
93 fprintf(stderr, "Unrecognized log type. Logging to stderr\n");
94 _osrfLogType = OSRF_LOG_TYPE_STDERR;
99 void osrfLogToStderr( void )
101 if( OSRF_NO_LOG_TYPE == _prevLogType ) {
102 _prevLogType = _osrfLogType;
103 _osrfLogType = OSRF_LOG_TYPE_STDERR;
107 void osrfRestoreLogType( void )
109 if( _prevLogType != OSRF_NO_LOG_TYPE ) {
110 _osrfLogType = _prevLogType;
111 _prevLogType = OSRF_NO_LOG_TYPE;
115 void osrfLogSetFile( const char* logfile ) {
117 if(_osrfLogFile) free(_osrfLogFile);
118 _osrfLogFile = strdup(logfile);
121 void osrfLogSetActivityEnabled( int enabled ) {
122 _osrfLogActivityEnabled = enabled;
125 void osrfLogSetAppname( const char* appname ) {
127 if(_osrfLogAppname) free(_osrfLogAppname);
128 _osrfLogAppname = strdup(appname);
130 /* if syslogging, re-open the log with the appname */
131 if( _osrfLogType == OSRF_LOG_TYPE_SYSLOG) {
133 openlog(_osrfLogAppname, 0, _osrfLogFacility);
137 void osrfLogSetSyslogFacility( int facility ) {
138 _osrfLogFacility = facility;
140 void osrfLogSetSyslogActFacility( int facility ) {
141 _osrfLogActFacility = facility;
144 /** Sets the global log level. Any log statements with a higher level
145 * than "level" will not be logged */
146 void osrfLogSetLevel( int loglevel ) {
147 _osrfLogLevel = loglevel;
150 /** Gets the current global log level. **/
151 int osrfLogGetLevel( void ) {
152 return _osrfLogLevel;
155 void osrfLogError( const char* file, int line, const char* msg, ... )
156 { OSRF_LOG_GO(file, line, msg, OSRF_LOG_ERROR); }
157 void osrfLogWarning( const char* file, int line, const char* msg, ... )
158 { OSRF_LOG_GO(file, line, msg, OSRF_LOG_WARNING); }
159 void osrfLogInfo( const char* file, int line, const char* msg, ... )
160 { OSRF_LOG_GO(file, line, msg, OSRF_LOG_INFO); }
161 void osrfLogDebug( const char* file, int line, const char* msg, ... )
162 { OSRF_LOG_GO(file, line, msg, OSRF_LOG_DEBUG); }
163 void osrfLogInternal( const char* file, int line, const char* msg, ... )
164 { OSRF_LOG_GO(file, line, msg, OSRF_LOG_INTERNAL); }
165 void osrfLogActivity( const char* file, int line, const char* msg, ... ) {
166 OSRF_LOG_GO(file, line, msg, OSRF_LOG_ACTIVITY);
167 _osrfLogDetail( OSRF_LOG_INFO, file, line, VA_BUF ); /* also log at info level */
170 /** Actually does the logging */
171 static void _osrfLogDetail( int level, const char* filename, int line, char* msg ) {
173 if( level == OSRF_LOG_ACTIVITY && ! _osrfLogActivityEnabled ) return;
174 if( level > _osrfLogLevel ) return;
176 if(!filename) filename = "";
178 char* label = "INFO"; /* level name */
179 int lvl = LOG_INFO; /* syslog level */
180 int fac = _osrfLogFacility;
188 case OSRF_LOG_WARNING:
203 case OSRF_LOG_INTERNAL:
208 case OSRF_LOG_ACTIVITY:
211 fac = _osrfLogActFacility;
215 char* xid = (_osrfLogXid) ? _osrfLogXid : "";
217 int logtype = _osrfLogType;
218 if( logtype == OSRF_LOG_TYPE_FILE && !_osrfLogFile )
220 // No log file defined? Temporarily reroute to stderr
221 logtype = OSRF_LOG_TYPE_STDERR;
224 if( logtype == OSRF_LOG_TYPE_SYSLOG ) {
226 memset(buf, 0x0, 1536);
227 /* give syslog some breathing room, and be cute about it */
228 strncat(buf, msg, 1535);
233 syslog( fac | lvl, "[%s:%ld:%s:%d:%s] %s", label, (long) getpid(), filename, line, xid, buf );
236 else if( logtype == OSRF_LOG_TYPE_FILE )
237 _osrfLogToFile( "[%s:%ld:%s:%d:%s] %s", label, (long) getpid(), filename, line, xid, msg );
239 else if( logtype == OSRF_LOG_TYPE_STDERR )
240 fprintf( stderr, "[%s:%ld:%s:%d:%s] %s\n", label, (long) getpid(), filename, line, xid, msg );
244 static void _osrfLogToFile( const char* msg, ... ) {
247 if(!_osrfLogFile) return;
248 VA_LIST_TO_STRING(msg);
250 if(!_osrfLogAppname) _osrfLogAppname = strdup("osrf");
253 time_t t = time(NULL);
254 struct tm* tms = localtime(&t);
255 strftime(datebuf, sizeof( datebuf ), "%Y-%m-%d %H:%M:%S", tms);
257 FILE* file = fopen(_osrfLogFile, "a");
260 "Unable to fopen log file %s for writing; logging to standard error\n", _osrfLogFile);
261 fprintf(stderr, "%s %s %s\n", _osrfLogAppname, datebuf, VA_BUF );
266 fprintf(file, "%s %s %s\n", _osrfLogAppname, datebuf, VA_BUF );
267 if( fclose(file) != 0 )
268 fprintf( stderr, "Error closing log file: %s", strerror(errno));
273 int osrfLogFacilityToInt( char* facility ) {
274 if(!facility) return LOG_LOCAL0;
275 if(strlen(facility) < 6) return LOG_LOCAL0;
276 switch( facility[5] ) {
277 case '0': return LOG_LOCAL0;
278 case '1': return LOG_LOCAL1;
279 case '2': return LOG_LOCAL2;
280 case '3': return LOG_LOCAL3;
281 case '4': return LOG_LOCAL4;
282 case '5': return LOG_LOCAL5;
283 case '6': return LOG_LOCAL6;
284 case '7': return LOG_LOCAL7;