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