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 void osrfLogCleanup( void ) {
24 free(_osrfLogAppname);
25 _osrfLogAppname = NULL;
28 _osrfLogType = OSRF_LOG_TYPE_STDERR;
32 void osrfLogInit( int type, const char* appname, int maxlevel ) {
34 if(appname) osrfLogSetAppname(appname);
35 osrfLogSetLevel(maxlevel);
36 if( type == OSRF_LOG_TYPE_SYSLOG )
37 openlog(_osrfLogAppname, 0, _osrfLogFacility );
40 static void _osrfLogSetXid( const char* xid ) {
42 if(_osrfLogXid) free(_osrfLogXid);
43 _osrfLogXid = strdup(xid);
47 void osrfLogClearXid( void ) { _osrfLogSetXid(""); }
48 void osrfLogSetXid(char* xid) {
49 if(!_osrfLogIsClient) _osrfLogSetXid(xid);
51 void osrfLogForceXid(char* xid) {
55 void osrfLogMkXid( void ) {
56 if(_osrfLogIsClient) {
57 static int _osrfLogXidInc = 0; /* increments with each new xid for uniqueness */
59 snprintf(buf, sizeof(buf), "%s%d", _osrfLogXidPfx, _osrfLogXidInc);
65 char* osrfLogGetXid( void ) {
69 void osrfLogSetIsClient(int is) {
70 _osrfLogIsClient = is;
72 /* go ahead and create the xid prefix so it will be consistent later */
74 snprintf(buff, sizeof(buff), "%d%ld", (int)time(NULL), (long) getpid());
75 _osrfLogXidPfx = buff;
78 /** Sets the type of logging to perform. See log types */
79 static void osrfLogSetType( int logtype ) {
83 case OSRF_LOG_TYPE_FILE :
84 case OSRF_LOG_TYPE_SYSLOG :
85 case OSRF_LOG_TYPE_STDERR :
86 _osrfLogType = logtype;
89 fprintf(stderr, "Unrecognized log type. Logging to stderr\n");
90 _osrfLogType = OSRF_LOG_TYPE_STDERR;
95 void osrfLogToStderr( void )
97 if( OSRF_NO_LOG_TYPE == _prevLogType ) {
98 _prevLogType = _osrfLogType;
99 _osrfLogType = OSRF_LOG_TYPE_STDERR;
103 void osrfRestoreLogType( void )
105 if( _prevLogType != OSRF_NO_LOG_TYPE ) {
106 _osrfLogType = _prevLogType;
107 _prevLogType = OSRF_NO_LOG_TYPE;
111 void osrfLogSetFile( const char* logfile ) {
113 if(_osrfLogFile) free(_osrfLogFile);
114 _osrfLogFile = strdup(logfile);
117 void osrfLogSetActivityEnabled( int enabled ) {
118 _osrfLogActivityEnabled = enabled;
121 void osrfLogSetAppname( const char* appname ) {
123 if(_osrfLogAppname) free(_osrfLogAppname);
124 _osrfLogAppname = strdup(appname);
126 /* if syslogging, re-open the log with the appname */
127 if( _osrfLogType == OSRF_LOG_TYPE_SYSLOG) {
129 openlog(_osrfLogAppname, 0, _osrfLogFacility);
133 void osrfLogSetSyslogFacility( int facility ) {
134 _osrfLogFacility = facility;
136 void osrfLogSetSyslogActFacility( int facility ) {
137 _osrfLogActFacility = facility;
140 /** Sets the global log level. Any log statements with a higher level
141 * than "level" will not be logged */
142 void osrfLogSetLevel( int loglevel ) {
143 _osrfLogLevel = loglevel;
146 /** Gets the current global log level. **/
147 int osrfLogGetLevel( void ) {
148 return _osrfLogLevel;
151 void osrfLogError( const char* file, int line, const char* msg, ... ) {
153 if( _osrfLogLevel < OSRF_LOG_ERROR ) return;
154 VA_LIST_TO_STRING( msg );
155 _osrfLogDetail( OSRF_LOG_ERROR, file, line, VA_BUF );
158 void osrfLogWarning( const char* file, int line, const char* msg, ... ) {
160 if( _osrfLogLevel < OSRF_LOG_WARNING ) return;
161 VA_LIST_TO_STRING( msg );
162 _osrfLogDetail( OSRF_LOG_WARNING, file, line, VA_BUF );
165 void osrfLogInfo( const char* file, int line, const char* msg, ... ) {
167 if( _osrfLogLevel < OSRF_LOG_INFO ) return;
168 VA_LIST_TO_STRING( msg );
169 _osrfLogDetail( OSRF_LOG_INFO, file, line, VA_BUF );
172 void osrfLogDebug( const char* file, int line, const char* msg, ... ) {
174 if( _osrfLogLevel < OSRF_LOG_DEBUG ) return;
175 VA_LIST_TO_STRING( msg );
176 _osrfLogDetail( OSRF_LOG_DEBUG, file, line, VA_BUF );
179 void osrfLogInternal( const char* file, int line, const char* msg, ... ) {
181 if( _osrfLogLevel < OSRF_LOG_INTERNAL ) return;
182 VA_LIST_TO_STRING( msg );
183 _osrfLogDetail( OSRF_LOG_INTERNAL, file, line, VA_BUF );
186 void osrfLogActivity( const char* file, int line, const char* msg, ... ) {
188 if( _osrfLogLevel >= OSRF_LOG_INFO
189 || ( _osrfLogActivityEnabled && _osrfLogLevel >= OSRF_LOG_ACTIVITY ) )
191 VA_LIST_TO_STRING( msg );
193 if( _osrfLogActivityEnabled && _osrfLogLevel >= OSRF_LOG_ACTIVITY )
194 _osrfLogDetail( OSRF_LOG_ACTIVITY, file, line, VA_BUF );
196 /* also log at info level */
197 if( _osrfLogLevel >= OSRF_LOG_INFO )
198 _osrfLogDetail( OSRF_LOG_INFO, file, line, VA_BUF );
202 /** Actually does the logging */
203 static void _osrfLogDetail( int level, const char* filename, int line, char* msg ) {
205 if(!filename) filename = "";
207 char* label = "INFO"; /* level name */
208 int lvl = LOG_INFO; /* syslog level */
209 int fac = _osrfLogFacility;
217 case OSRF_LOG_WARNING:
232 case OSRF_LOG_INTERNAL:
237 case OSRF_LOG_ACTIVITY:
240 fac = _osrfLogActFacility;
244 char* xid = (_osrfLogXid) ? _osrfLogXid : "";
246 int logtype = _osrfLogType;
247 if( logtype == OSRF_LOG_TYPE_FILE && !_osrfLogFile )
249 // No log file defined? Temporarily reroute to stderr
250 logtype = OSRF_LOG_TYPE_STDERR;
253 if( logtype == OSRF_LOG_TYPE_SYSLOG ) {
256 /* give syslog some breathing room, and be cute about it */
257 strncat(buf, msg, 1535);
262 syslog( fac | lvl, "[%s:%ld:%s:%d:%s] %s", label, (long) getpid(), filename, line, xid, buf );
265 else if( logtype == OSRF_LOG_TYPE_FILE )
266 _osrfLogToFile( "[%s:%ld:%s:%d:%s] %s", label, (long) getpid(), filename, line, xid, msg );
268 else if( logtype == OSRF_LOG_TYPE_STDERR )
269 fprintf( stderr, "[%s:%ld:%s:%d:%s] %s\n", label, (long) getpid(), filename, line, xid, msg );
273 static void _osrfLogToFile( const char* msg, ... ) {
276 if(!_osrfLogFile) return;
277 VA_LIST_TO_STRING(msg);
279 if(!_osrfLogAppname) _osrfLogAppname = strdup("osrf");
282 time_t t = time(NULL);
283 struct tm* tms = localtime(&t);
284 strftime(datebuf, sizeof( datebuf ), "%Y-%m-%d %H:%M:%S", tms);
286 FILE* file = fopen(_osrfLogFile, "a");
289 "Unable to fopen log file %s for writing; logging to standard error\n", _osrfLogFile);
290 fprintf(stderr, "%s %s %s\n", _osrfLogAppname, datebuf, VA_BUF );
295 fprintf(file, "%s %s %s\n", _osrfLogAppname, datebuf, VA_BUF );
296 if( fclose(file) != 0 )
297 fprintf( stderr, "Error closing log file: %s", strerror(errno));
302 int osrfLogFacilityToInt( const char* facility ) {
303 if(!facility) return LOG_LOCAL0;
304 if(strlen(facility) < 6) return LOG_LOCAL0;
305 switch( facility[5] ) {
306 case '0': return LOG_LOCAL0;
307 case '1': return LOG_LOCAL1;
308 case '2': return LOG_LOCAL2;
309 case '3': return LOG_LOCAL3;
310 case '4': return LOG_LOCAL4;
311 case '5': return LOG_LOCAL5;
312 case '6': return LOG_LOCAL6;
313 case '7': return LOG_LOCAL7;