]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/libopensrf/log.c
Fix a bug whereby, if there was only one <service> entry for the
[OpenSRF.git] / src / libopensrf / log.c
1 #include <opensrf/log.h>
2
3 #define OSRF_NO_LOG_TYPE -1
4
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;
14
15 static char* _osrfLogXid            = NULL; /* current xid */
16 static char* _osrfLogXidPfx         = NULL; /* xid prefix string */
17
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 );
22
23 void osrfLogCleanup( void ) {
24         free(_osrfLogAppname);
25         _osrfLogAppname = NULL;
26         free(_osrfLogFile);
27         _osrfLogFile = NULL;
28         _osrfLogType = OSRF_LOG_TYPE_STDERR;
29 }
30
31
32 void osrfLogInit( int type, const char* appname, int maxlevel ) {
33         osrfLogSetType(type);
34         if(appname) osrfLogSetAppname(appname);
35         osrfLogSetLevel(maxlevel);
36         if( type == OSRF_LOG_TYPE_SYSLOG ) 
37                 openlog(_osrfLogAppname, 0, _osrfLogFacility );
38 }
39
40 static void _osrfLogSetXid( const char* xid ) {
41    if(xid) {
42       if(_osrfLogXid) free(_osrfLogXid);
43       _osrfLogXid = strdup(xid);
44    }
45 }
46
47 void osrfLogClearXid( void ) { _osrfLogSetXid(""); }
48 void osrfLogSetXid(char* xid) {
49    if(!_osrfLogIsClient) _osrfLogSetXid(xid);
50 }
51 void osrfLogForceXid(char* xid) {
52    _osrfLogSetXid(xid);
53 }
54
55 void osrfLogMkXid( void ) {
56    if(_osrfLogIsClient) {
57       static int _osrfLogXidInc = 0; /* increments with each new xid for uniqueness */
58       char buf[32];
59       snprintf(buf, sizeof(buf), "%s%d", _osrfLogXidPfx, _osrfLogXidInc);
60       _osrfLogSetXid(buf);
61       _osrfLogXidInc++;
62    }
63 }
64
65 char* osrfLogGetXid( void ) {
66    return _osrfLogXid;
67 }
68
69 void osrfLogSetIsClient(int is) {
70    _osrfLogIsClient = is;
71    if(!is) return;
72    /* go ahead and create the xid prefix so it will be consistent later */
73    static char buff[32];
74    snprintf(buff, sizeof(buff), "%d%ld", (int)time(NULL), (long) getpid());
75    _osrfLogXidPfx = buff;
76 }
77
78 /** Sets the type of logging to perform.  See log types */
79 static void osrfLogSetType( int logtype ) {
80
81         switch( logtype )
82         {
83                 case OSRF_LOG_TYPE_FILE :
84                 case OSRF_LOG_TYPE_SYSLOG :
85                 case OSRF_LOG_TYPE_STDERR :
86                         _osrfLogType = logtype;
87                         break;
88                 default :
89                         fprintf(stderr, "Unrecognized log type.  Logging to stderr\n");
90                         _osrfLogType = OSRF_LOG_TYPE_STDERR;
91                         break;
92         }
93 }
94
95 void osrfLogToStderr( void )
96 {
97         if( OSRF_NO_LOG_TYPE == _prevLogType ) {
98                 _prevLogType = _osrfLogType;
99                 _osrfLogType = OSRF_LOG_TYPE_STDERR;
100         }
101 }
102
103 void osrfRestoreLogType( void )
104 {
105         if( _prevLogType != OSRF_NO_LOG_TYPE ) {
106                 _osrfLogType = _prevLogType;
107                 _prevLogType = OSRF_NO_LOG_TYPE;
108         }
109 }
110
111 void osrfLogSetFile( const char* logfile ) {
112         if(!logfile) return;
113         if(_osrfLogFile) free(_osrfLogFile);
114         _osrfLogFile = strdup(logfile);
115 }
116
117 void osrfLogSetActivityEnabled( int enabled ) {
118         _osrfLogActivityEnabled = enabled;
119 }
120
121 void osrfLogSetAppname( const char* appname ) {
122         if(!appname) return;
123         if(_osrfLogAppname) free(_osrfLogAppname);
124         _osrfLogAppname = strdup(appname);
125
126         /* if syslogging, re-open the log with the appname */
127         if( _osrfLogType == OSRF_LOG_TYPE_SYSLOG) {
128                 closelog();
129                 openlog(_osrfLogAppname, 0, _osrfLogFacility);
130         }
131 }
132
133 void osrfLogSetSyslogFacility( int facility ) {
134         _osrfLogFacility = facility;
135 }
136 void osrfLogSetSyslogActFacility( int facility ) {
137         _osrfLogActFacility = facility;
138 }
139
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;
144 }
145
146 /** Gets the current global log level. **/
147 int osrfLogGetLevel( void ) {
148         return _osrfLogLevel;
149 }
150
151 void osrfLogError( const char* file, int line, const char* msg, ... ) {
152         if( !msg ) return;
153         if( _osrfLogLevel < OSRF_LOG_ERROR ) return;
154         VA_LIST_TO_STRING( msg );
155         _osrfLogDetail( OSRF_LOG_ERROR, file, line, VA_BUF );
156 }
157
158 void osrfLogWarning( const char* file, int line, const char* msg, ... ) {
159         if( !msg ) return;
160         if( _osrfLogLevel < OSRF_LOG_WARNING ) return;
161         VA_LIST_TO_STRING( msg );
162         _osrfLogDetail( OSRF_LOG_WARNING, file, line, VA_BUF );
163 }
164
165 void osrfLogInfo( const char* file, int line, const char* msg, ... ) {
166         if( !msg ) return;
167         if( _osrfLogLevel < OSRF_LOG_INFO ) return;
168         VA_LIST_TO_STRING( msg );
169         _osrfLogDetail( OSRF_LOG_INFO, file, line, VA_BUF );
170 }
171
172 void osrfLogDebug( const char* file, int line, const char* msg, ... ) {
173         if( !msg ) return;
174         if( _osrfLogLevel < OSRF_LOG_DEBUG ) return;
175         VA_LIST_TO_STRING( msg );
176         _osrfLogDetail( OSRF_LOG_DEBUG, file, line, VA_BUF );
177 }
178
179 void osrfLogInternal( const char* file, int line, const char* msg, ... ) {
180         if( !msg ) return;
181         if( _osrfLogLevel < OSRF_LOG_INTERNAL ) return;
182         VA_LIST_TO_STRING( msg );
183         _osrfLogDetail( OSRF_LOG_INTERNAL, file, line, VA_BUF );
184 }
185
186 void osrfLogActivity( const char* file, int line, const char* msg, ... ) {
187         if( !msg ) return;
188         if( _osrfLogLevel >= OSRF_LOG_INFO
189                 || ( _osrfLogActivityEnabled && _osrfLogLevel >= OSRF_LOG_ACTIVITY ) )
190         {
191                 VA_LIST_TO_STRING( msg );
192
193                 if( _osrfLogActivityEnabled && _osrfLogLevel >= OSRF_LOG_ACTIVITY )
194                         _osrfLogDetail( OSRF_LOG_ACTIVITY, file, line, VA_BUF );
195
196                 /* also log at info level */
197                 if( _osrfLogLevel >= OSRF_LOG_INFO )
198                         _osrfLogDetail( OSRF_LOG_INFO, file, line, VA_BUF );
199         }
200 }
201
202 /** Actually does the logging */
203 static void _osrfLogDetail( int level, const char* filename, int line, char* msg ) {
204
205         if(!filename) filename = "";
206
207         char* label = "INFO";           /* level name */
208         int lvl = LOG_INFO;     /* syslog level */
209         int fac = _osrfLogFacility;
210
211         switch( level ) {
212                 case OSRF_LOG_ERROR:            
213                         label = "ERR "; 
214                         lvl = LOG_ERR;
215                         break;
216
217                 case OSRF_LOG_WARNING:  
218                         label = "WARN"; 
219                         lvl = LOG_WARNING;
220                         break;
221
222                 case OSRF_LOG_INFO:             
223                         label = "INFO"; 
224                         lvl = LOG_INFO;
225                         break;
226
227                 case OSRF_LOG_DEBUG:    
228                         label = "DEBG"; 
229                         lvl = LOG_DEBUG;
230                         break;
231
232                 case OSRF_LOG_INTERNAL: 
233                         label = "INT "; 
234                         lvl = LOG_DEBUG;
235                         break;
236
237                 case OSRF_LOG_ACTIVITY: 
238                         label = "ACT"; 
239                         lvl = LOG_INFO;
240                         fac = _osrfLogActFacility;
241                         break;
242         }
243
244    char* xid = (_osrfLogXid) ? _osrfLogXid : "";
245
246    int logtype = _osrfLogType;
247    if( logtype == OSRF_LOG_TYPE_FILE && !_osrfLogFile )
248    {
249            // No log file defined?  Temporarily reroute to stderr
250            logtype = OSRF_LOG_TYPE_STDERR;
251    }
252
253    if( logtype == OSRF_LOG_TYPE_SYSLOG ) {
254                 char buf[1536];  
255                 buf[0] = '\0';
256                 /* give syslog some breathing room, and be cute about it */
257                 strncat(buf, msg, 1535);
258                 buf[1532] = '.';
259                 buf[1533] = '.';
260                 buf[1534] = '.';
261                 buf[1535] = '\0';
262                 syslog( fac | lvl, "[%s:%ld:%s:%d:%s] %s", label, (long) getpid(), filename, line, xid, buf );
263         }
264
265         else if( logtype == OSRF_LOG_TYPE_FILE )
266                 _osrfLogToFile( "[%s:%ld:%s:%d:%s] %s", label, (long) getpid(), filename, line, xid, msg );
267
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 );
270 }
271
272
273 static void _osrfLogToFile( const char* msg, ... ) {
274
275         if(!msg) return;
276         if(!_osrfLogFile) return;
277         VA_LIST_TO_STRING(msg);
278
279         if(!_osrfLogAppname) _osrfLogAppname = strdup("osrf");
280
281         char datebuf[36];
282         time_t t = time(NULL);
283         struct tm* tms = localtime(&t);
284         strftime(datebuf, sizeof( datebuf ), "%Y-%m-%d %H:%M:%S", tms);
285
286         FILE* file = fopen(_osrfLogFile, "a");
287         if(!file) {
288                 fprintf(stderr,
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 );
291
292                 return;
293         }
294
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));
298
299 }
300
301
302 int osrfLogFacilityToInt( 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;
314         }
315         return LOG_LOCAL0;
316 }
317
318