1 martin 1.66 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.67 //
|
3 martin 1.66 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.67 //
|
10 martin 1.66 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.67 //
|
17 martin 1.66 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.67 //
|
20 martin 1.66 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.67 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.66 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.67 //
|
28 martin 1.66 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.13 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <iostream>
33 #include <fstream>
|
34 kumpf 1.23 #include <cstring>
|
35 mreddy 1.55 #include <Pegasus/Common/Logger.h>
|
36 marek 1.59 #include <Pegasus/Common/Tracer.h>
|
37 mreddy 1.55 #include <Pegasus/Common/System.h>
38 #include <Pegasus/Common/FileSystem.h>
|
39 kumpf 1.48 #include <Pegasus/Common/MessageLoader.h>
|
40 kumpf 1.54 #include <Pegasus/Common/Executor.h>
|
41 mreddy 1.55 #include <Pegasus/Common/Mutex.h>
|
42 kumpf 1.16
|
43 marek 1.47 #if defined(PEGASUS_USE_SYSLOGS)
44 # include <syslog.h>
45 #endif
46
|
47 mike 1.13 PEGASUS_USING_STD;
48
49 PEGASUS_NAMESPACE_BEGIN
50
|
51 mreddy 1.55
|
52 mike 1.13 const Uint32 Logger::TRACE = (1 << 0);
53 const Uint32 Logger::INFORMATION = (1 << 1);
54 const Uint32 Logger::WARNING = (1 << 2);
55 const Uint32 Logger::SEVERE = (1 << 3);
56 const Uint32 Logger::FATAL = (1 << 4);
57
|
58 david 1.26 static char const* LOGLEVEL_LIST[] =
59 {
60 "TRACE",
61 "INFORMATION",
62 "WARNING",
63 "SEVERE",
64 "FATAL"
65 };
66
|
67 mike 1.13 LoggerRep* Logger::_rep = 0;
68 String Logger::_homeDirectory = ".";
|
69 kumpf 1.16
|
70 david 1.26 const Uint32 Logger::_NUM_LOGLEVEL = 5;
71
|
72 kumpf 1.57 Uint32 Logger::_severityMask;
|
73 david 1.26
|
74 mreddy 1.65
|
75 kumpf 1.57 ///////////////////////////////////////////////////////////////////////////////
76 //
77 // LoggerRep
78 //
79 ///////////////////////////////////////////////////////////////////////////////
|
80 kumpf 1.16
|
81 kumpf 1.57 #if defined(PEGASUS_USE_SYSLOGS)
|
82 mike 1.13
|
83 kumpf 1.57 class LoggerRep
84 {
85 public:
|
86 david 1.26
|
87 kumpf 1.57 LoggerRep(const String& homeDirectory)
|
88 mike 1.13 {
|
89 kumpf 1.57 # ifdef PEGASUS_OS_ZOS
90 logIdentity = strdup(System::CIMSERVER.getCString());
91 // If System Log is used open it
92 System::openlog(logIdentity, LOG_PID, LOG_DAEMON);
93 # endif
94 }
|
95 mike 1.13
|
96 kumpf 1.57 ~LoggerRep()
97 {
98 # ifdef PEGASUS_OS_ZOS
99 System::closelog();
100 free(logIdentity);
101 # endif
102 }
|
103 mike 1.13
|
104 kumpf 1.57 // Actual logging is done in this routine
105 void log(Logger::LogFileType logFileType,
106 const String& systemId,
107 Uint32 logLevel,
108 const String localizedMsg)
109 {
110 // Log the message
111 System::syslog(systemId, logLevel, localizedMsg.getCString());
112 }
113
114 private:
115
116 # ifdef PEGASUS_OS_ZOS
117 char* logIdentity;
118 # endif
119 };
120
121 #else // !defined(PEGASUS_USE_SYSLOGS)
122
123 static const char* fileNames[] =
124 {
125 kumpf 1.57 "PegasusTrace.log",
126 "PegasusStandard.log",
127 "PegasusAudit.log",
|
128 ouyang.jian 1.60 "PegasusError.log"
|
129 kumpf 1.57 };
130 static const char* lockFileName = "PegasusLog.lock";
131
132 /*
133 _constructFileName builds the absolute file name from homeDirectory
|
134 mreddy 1.55 and fileName.
135 */
136 static CString _constructFileName(
137 const String& homeDirectory,
138 const char * fileName)
139 {
|
140 mike 1.13 String result;
|
141 kumpf 1.57 result.reserveCapacity(
142 (Uint32)(homeDirectory.size() + 1 + strlen(fileName)));
|
143 kumpf 1.20 result.append(homeDirectory);
144 result.append('/');
|
145 mreddy 1.55 result.append(fileName);
|
146 kumpf 1.22 return result.getCString();
|
147 mike 1.13 }
148
149 class LoggerRep
150 {
151 public:
152
153 LoggerRep(const String& homeDirectory)
154 {
|
155 kumpf 1.40 // Add test for home directory set.
|
156 mike 1.13
|
157 kumpf 1.40 // If home directory does not exist, create it.
158 CString lgDir = homeDirectory.getCString();
|
159 mike 1.13
|
160 kumpf 1.40 if (!System::isDirectory(lgDir))
161 System::makeDirectory(lgDir);
|
162 mike 1.13
|
163 kumpf 1.40 // KS: I put the second test in just in case some trys to create
164 // a completly erronous directory. At least we will get a message
|
165 kumpf 1.48 if (!System::isDirectory(lgDir))
166 {
167 MessageLoaderParms parms("Common.Logger.LOGGING_DISABLED",
168 "Logging Disabled");
|
169 kumpf 1.40
|
170 kumpf 1.48 cerr << MessageLoader::getMessage(parms);
|
171 kumpf 1.40 }
172
|
173 mreddy 1.55 //Filelocks are not used for VMS
|
174 kumpf 1.57 # if !defined(PEGASUS_OS_VMS)
|
175 mreddy 1.55 _loggerLockFileName = _constructFileName(homeDirectory, lockFileName);
176
177 // Open and close a file to make sure that the file exists, on which
178 // file lock is requested
179 FILE *fileLockFilePointer;
180 fileLockFilePointer = fopen(_loggerLockFileName, "a+");
181 if(fileLockFilePointer)
182 {
183 fclose(fileLockFilePointer);
184 }
|
185 kumpf 1.57 # endif
|
186 mreddy 1.55
187 _logFileNames[Logger::TRACE_LOG] = _constructFileName(homeDirectory,
188 fileNames[Logger::TRACE_LOG]);
|
189 kumpf 1.40
|
190 mreddy 1.55 _logFileNames[Logger::STANDARD_LOG] = _constructFileName(homeDirectory,
191 fileNames[Logger::STANDARD_LOG]);
|
192 kumpf 1.40
|
193 kumpf 1.57 # ifdef PEGASUS_ENABLE_AUDIT_LOGGER
|
194 mreddy 1.55 _logFileNames[Logger::AUDIT_LOG] = _constructFileName(homeDirectory,
195 fileNames[Logger::AUDIT_LOG]);
|
196 kumpf 1.57 # endif
|
197 thilo.boehm 1.46
|
198 mreddy 1.55 _logFileNames[Logger::ERROR_LOG] = _constructFileName(homeDirectory,
199 fileNames[Logger::ERROR_LOG]);
|
200 marek 1.47 }
201
202 ~LoggerRep()
203 {
|
204 mreddy 1.55 }
205
206 // Actual logging is done in this routine
207 void log(Logger::LogFileType logFileType,
208 const String& systemId,
209 Uint32 logLevel,
210 const String localizedMsg)
211 {
212 // Prepend the systemId to the incoming message
213 String messageString(systemId);
214 messageString.append(": ");
215 messageString.append(localizedMsg); // l10n
|
216 marek 1.47
|
217 mreddy 1.55 // Get the logLevel String
218 // This converts bitmap to string based on highest order
219 // bit set
220 // ATTN: KS Fix this more efficiently.
221 const char* tmp = "";
222 if (logLevel & Logger::TRACE) tmp = "TRACE ";
223 if (logLevel & Logger::INFORMATION) tmp = "INFO ";
224 if (logLevel & Logger::WARNING) tmp = "WARNING ";
225 if (logLevel & Logger::SEVERE) tmp = "SEVERE ";
226 if (logLevel & Logger::FATAL) tmp = "FATAL ";
|
227 mike 1.13
|
228 mreddy 1.55 # ifndef PEGASUS_OS_VMS
|
229 kumpf 1.68 // Acquire AutoMutex (for thread sync)
|
230 mreddy 1.55 // and AutoFileLock (for Process Sync).
231 AutoMutex am(_mutex);
232 AutoFileLock fileLock(_loggerLockFileName);
233
234 Uint32 logFileSize = 0;
235
236 // Read logFileSize to check if the logfile needs to be pruned.
|
237 kumpf 1.68 FileSystem::getFileSize(String(_logFileNames[logFileType]),
|
238 mreddy 1.55 logFileSize);
239
|
240 mreddy 1.65 // Check if the size of the logfile is exceeding _maxLogFileSizeBytes.
241 if ( logFileSize > _maxLogFileSizeBytes)
|
242 kumpf 1.57 {
|
243 mreddy 1.55 // Prepare appropriate file name based on the logFileType.
244 // Eg: if Logfile name is PegasusStandard.log, pruned logfile name
245 // will be PegasusStandard-062607-122302.log,where 062607-122302
246 // is the time stamp.
247 String prunedLogfile(_logFileNames[logFileType],
248 (Uint32)strlen(_logFileNames[logFileType]) - 4);
249 prunedLogfile.append('-');
250
251 // Get timestamp,remove illegal chars in file name'/' and ':'
252 // (: is illegal Open VMS) from the time stamp. Append the time
253 // info to the file name.
|
254 mike 1.13
|
255 mreddy 1.55 String timeStamp = System::getCurrentASCIITime();
|
256 ajay.rao 1.69 for ( unsigned int i = 0; i < timeStamp.size(); i++ )
|
257 mreddy 1.55 {
|
258 ajay.rao 1.69 if( timeStamp[i] == '/' || timeStamp[i] == ':')
|
259 mreddy 1.55 {
260 timeStamp.remove(i, 1);
261 }
262 }
263 prunedLogfile.append(timeStamp);
|
264 mike 1.13
|
265 mreddy 1.55 // Append '.log' to the file
266 prunedLogfile.append( ".log");
|
267 mike 1.13
|
268 mreddy 1.55 // Rename the logfile
269 FileSystem::renameFile(String(_logFileNames[logFileType]),
270 prunedLogfile);
271
272 } // Check if the logfile needs to be pruned.
273 # endif // ifndef PEGASUS_OS_VMS
274
275 // Open Logfile. Based on the value of logFileType, one of the five
276 // Logfiles will be opened.
277 ofstream logFileStream;
278 logFileStream.open(_logFileNames[logFileType], ios::app);
279 logFileStream << System::getCurrentASCIITime()
280 << " " << tmp << (const char *)messageString.getCString() << endl;
281 logFileStream.close();
|
282 mike 1.13 }
283
|
284 mreddy 1.65 static void setMaxLogFileSize(Uint32 maxLogFileSizeBytes)
285 {
286 _maxLogFileSizeBytes = maxLogFileSizeBytes;
287 }
|
288 mike 1.13 private:
289
|
290 mreddy 1.55 CString _logFileNames[int(Logger::NUM_LOGS)];
|
291 kumpf 1.57
|
292 mreddy 1.65 static Uint32 _maxLogFileSizeBytes;
|
293 kumpf 1.57 # ifndef PEGASUS_OS_VMS
|
294 mreddy 1.55 CString _loggerLockFileName;
295 Mutex _mutex;
|
296 kumpf 1.57 # endif
|
297 mike 1.13 };
298
|
299 mreddy 1.65 Uint32 LoggerRep::_maxLogFileSizeBytes;
300
|
301 kumpf 1.57 #endif // !defined(PEGASUS_USE_SYSLOGS)
302
303
304 ///////////////////////////////////////////////////////////////////////////////
305 //
306 // Logger
307 //
308 ///////////////////////////////////////////////////////////////////////////////
309
|
310 david 1.26 void Logger::_putInternal(
|
311 mike 1.13 LogFileType logFileType,
312 const String& systemId,
|
313 kumpf 1.48 const Uint32 logComponent, // FUTURE: Support logComponent mask
|
314 david 1.26 Uint32 logLevel,
|
315 kumpf 1.63 const String& message)
|
316 mike 1.13 {
|
317 kumpf 1.63 if (!_rep)
318 _rep = new LoggerRep(_homeDirectory);
|
319 chuck 1.29
|
320 kumpf 1.63 // Call the actual logging routine is in LoggerRep.
321 _rep->log(logFileType, systemId, logLevel, message);
|
322 kumpf 1.68
|
323 thilo.boehm 1.64 // PEP 315
324 // The trace can be routed into the log. The logged trace messages are
|
325 kumpf 1.68 // logged with logFileType of Logger::TRACE_LOG.
|
326 thilo.boehm 1.64 // To avoid a cirular writing of these messages, log messages with
327 // logFileType of Logger::TRACE_LOG are never send to the trace.
|
328 kumpf 1.63 if (Logger::TRACE_LOG != logFileType)
329 {
|
330 thilo.boehm 1.64 // For all other logFileType's send the log messages to the trace.
331 // But do not write log messages to trace when the trace facility is
332 // set to log. This avoids double messages.
|
333 kumpf 1.63 if (Tracer::TRACE_FACILITY_LOG != Tracer::getTraceFacility())
334 {
335 PEG_TRACE_CSTRING(
336 TRC_LOGMSG,
337 Tracer::LEVEL1,
338 (const char*) message.getCString());
|
339 kumpf 1.40 }
|
340 david 1.26 }
341 }
|
342 mike 1.13
|
343 mike 1.42 ////////////////////////////////////////////////////////////////////////////////
344 //
345 // Public methods start here:
346 //
347 ////////////////////////////////////////////////////////////////////////////////
348
|
349 david 1.26 void Logger::put(
|
350 kumpf 1.40 LogFileType logFileType,
351 const String& systemId,
352 Uint32 logLevel,
353 const String& formatString,
354 const Formatter::Arg& arg0,
355 const Formatter::Arg& arg1,
356 const Formatter::Arg& arg2,
357 const Formatter::Arg& arg3,
358 const Formatter::Arg& arg4,
359 const Formatter::Arg& arg5,
360 const Formatter::Arg& arg6,
361 const Formatter::Arg& arg7,
362 const Formatter::Arg& arg8,
363 const Formatter::Arg& arg9)
|
364 chuck 1.29 {
|
365 mike 1.42 if (wouldLog(logLevel))
366 {
367 Logger::_putInternal(logFileType, systemId, 0, logLevel,
|
368 kumpf 1.63 Formatter::format(formatString, arg0, arg1, arg2, arg3,
369 arg4, arg5, arg6, arg7, arg8, arg9));
|
370 mike 1.42 }
|
371 karl 1.37 }
372
373 void Logger::put(
|
374 kumpf 1.40 LogFileType logFileType,
375 const String& systemId,
376 Uint32 logLevel,
377 const String& formatString)
|
378 karl 1.37 {
|
379 mike 1.42 if (wouldLog(logLevel))
380 {
|
381 kumpf 1.63 Logger::_putInternal(logFileType, systemId, 0, logLevel, formatString);
|
382 mike 1.42 }
383 }
|
384 karl 1.37
|
385 mike 1.42 void Logger::put(
386 LogFileType logFileType,
387 const String& systemId,
388 Uint32 logLevel,
389 const String& formatString,
390 const Formatter::Arg& arg0)
391 {
392 if (wouldLog(logLevel))
393 {
394 Logger::_putInternal(logFileType, systemId, 0, logLevel,
|
395 kumpf 1.63 Formatter::format(formatString, arg0));
|
396 mike 1.42 }
|
397 karl 1.37 }
398
399 void Logger::put(
|
400 kumpf 1.40 LogFileType logFileType,
401 const String& systemId,
402 Uint32 logLevel,
403 const String& formatString,
|
404 mike 1.42 const Formatter::Arg& arg0,
405 const Formatter::Arg& arg1)
|
406 karl 1.37 {
|
407 mike 1.42 if (wouldLog(logLevel))
408 {
409 Logger::_putInternal(logFileType, systemId, 0, logLevel,
|
410 kumpf 1.63 Formatter::format(formatString, arg0, arg1));
|
411 mike 1.42 }
412 }
|
413 karl 1.37
|
414 mike 1.42 void Logger::put(
415 LogFileType logFileType,
416 const String& systemId,
417 Uint32 logLevel,
418 const String& formatString,
419 const Formatter::Arg& arg0,
420 const Formatter::Arg& arg1,
421 const Formatter::Arg& arg2)
422 {
423 if (wouldLog(logLevel))
424 {
425 Logger::_putInternal(logFileType, systemId, 0, logLevel,
|
426 kumpf 1.63 Formatter::format(formatString, arg0, arg1, arg2));
|
427 mike 1.42 }
|
428 chuck 1.29 }
429
430 void Logger::put_l(
|
431 kumpf 1.40 LogFileType logFileType,
432 const String& systemId,
433 Uint32 logLevel,
|
434 kumpf 1.63 const MessageLoaderParms& msgParms)
|
435 mike 1.42 {
436 if (wouldLog(logLevel))
437 {
|
438 kumpf 1.63 MessageLoaderParms parms = msgParms;
439 parms.useProcessLocale = true;
|
440 mike 1.42 Logger::_putInternal(logFileType, systemId, 0, logLevel,
|
441 kumpf 1.63 MessageLoader::getMessage(parms));
|
442 mike 1.42 }
|
443 david 1.26 }
444
445 void Logger::trace(
|
446 kumpf 1.40 LogFileType logFileType,
447 const String& systemId,
448 const Uint32 logComponent,
|
449 kumpf 1.62 const String& message)
|
450 chuck 1.29 {
|
451 mike 1.42 if (wouldLog(Logger::TRACE))
452 {
453 Logger::_putInternal(logFileType, systemId, logComponent, Logger::TRACE,
|
454 kumpf 1.63 message);
|
455 mike 1.42 }
|
456 mike 1.13 }
457
458 void Logger::setHomeDirectory(const String& homeDirectory)
459 {
460 _homeDirectory = homeDirectory;
461 }
|
462 david 1.26
463 void Logger::setlogLevelMask( const String logLevelList )
464 {
|
465 karl 1.37 Uint32 logLevelType = 0;
|
466 david 1.26 String logLevelName = logLevelList;
467
468 // Check if logLevel has been specified
469 if (logLevelName != String::EMPTY)
470 {
471 // initialise _severityMask
472 _severityMask = 0;
473
|
474 kumpf 1.40 // Set logLevelType to indicate the level of logging
|
475 david 1.26 // required by the user.
|
476 kumpf 1.40 if (String::equalNoCase(logLevelName,"TRACE"))
477 {
478 logLevelType = Logger::TRACE;
479 }
480 else if (String::equalNoCase(logLevelName,"INFORMATION"))
481 {
482 logLevelType = Logger::INFORMATION;
483 }
484 else if (String::equalNoCase(logLevelName,"WARNING"))
485 {
486 logLevelType = Logger::WARNING;
487 }
488 else if (String::equalNoCase(logLevelName,"SEVERE"))
489 {
490 logLevelType = Logger::SEVERE;
491 }
492 else if (String::equalNoCase(logLevelName,"FATAL"))
493 {
494 logLevelType = Logger::FATAL;
495 }
496 // Setting _severityMask. NOTE: When adding new logLevels
|
497 david 1.26 // it is essential that they are adding in ascending order
498 // based on priority. Once a case statement is true we will
499 // continue to set all following log levels with a higher
500 // priority.
|
501 kumpf 1.40 switch(logLevelType)
502 {
503 case Logger::TRACE:
504 _severityMask |= Logger::TRACE;
505 case Logger::INFORMATION:
506 _severityMask |= Logger::INFORMATION;
507 case Logger::WARNING:
508 _severityMask |= Logger::WARNING;
509 case Logger::SEVERE:
510 _severityMask |= Logger::SEVERE;
511 case Logger::FATAL:
512 _severityMask |= Logger::FATAL;
513 }
|
514 kumpf 1.54
515 Executor::updateLogLevel(logLevelName.getCString());
|
516 david 1.26 }
517 else
518 {
|
519 kumpf 1.40 // Property logLevel not specified, set default value.
520 _severityMask = ~Logger::TRACE;
|
521 kumpf 1.54 Executor::updateLogLevel("INFORMATION");
|
522 david 1.26 }
523 }
524
|
525 mike 1.42 Boolean Logger::isValidlogLevel(const String logLevel)
|
526 david 1.26 {
527 // Validate the logLevel and modify the logLevel argument
528 // to reflect the invalid logLevel
529
530 Uint32 index=0;
531 String logLevelName = String::EMPTY;
532 Boolean validlogLevel=false;
533
534 logLevelName = logLevel;
535
536 if (logLevelName != String::EMPTY)
537 {
|
538 kumpf 1.40 // Lookup the index for logLevel name in _logLevel_LIST
539 index = 0;
540 validlogLevel = false;
541
542 while (index < _NUM_LOGLEVEL)
543 {
544 if (String::equalNoCase(logLevelName, LOGLEVEL_LIST[index]))
545 {
546 // Found logLevel, break from the loop
547 validlogLevel = true;
548 break;
549 }
550 else
551 {
552 index++;
553 }
554 }
|
555 david 1.26 }
556 else
557 {
|
558 kumpf 1.40 // logLevels is empty, it is a valid value so return true
|
559 kumpf 1.57 return true;
|
560 david 1.26 }
561
562 return validlogLevel;
563 }
564
|
565 mreddy 1.65 #if !defined (PEGASUS_USE_SYSLOGS)
566 void Logger::setMaxLogFileSize(Uint32 maxLogFileSizeBytes)
567 {
568 LoggerRep::setMaxLogFileSize(maxLogFileSizeBytes);
569 }
570 #endif
571
|
572 mike 1.13 PEGASUS_NAMESPACE_END
|