(file) Return to Logger.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  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 // Maximum logfile size is defined as 32 MB = 32 * 1024 * 1024
 54             # define PEGASUS_MAX_LOGFILE_SIZE 0X2000000
 55             
 56 mike   1.13 const Uint32 Logger::TRACE = (1 << 0);
 57             const Uint32 Logger::INFORMATION = (1 << 1);
 58             const Uint32 Logger::WARNING = (1 << 2);
 59             const Uint32 Logger::SEVERE = (1 << 3);
 60             const Uint32 Logger::FATAL = (1 << 4);
 61             
 62 david  1.26 static char const* LOGLEVEL_LIST[] =
 63             {
 64                 "TRACE",
 65                 "INFORMATION",
 66                 "WARNING",
 67                 "SEVERE",
 68                 "FATAL"
 69             };
 70             
 71 mike   1.13 LoggerRep* Logger::_rep = 0;
 72             String Logger::_homeDirectory = ".";
 73 kumpf  1.16 
 74 david  1.26 const Uint32 Logger::_NUM_LOGLEVEL = 5;
 75             
 76 kumpf  1.57 Uint32 Logger::_severityMask;
 77 david  1.26 
 78 kumpf  1.57 ///////////////////////////////////////////////////////////////////////////////
 79             //
 80             // LoggerRep
 81             //
 82             ///////////////////////////////////////////////////////////////////////////////
 83 kumpf  1.16 
 84 kumpf  1.57 #if defined(PEGASUS_USE_SYSLOGS)
 85 mike   1.13 
 86 kumpf  1.57 class LoggerRep
 87             {
 88             public:
 89 david  1.26 
 90 kumpf  1.57     LoggerRep(const String& homeDirectory)
 91 mike   1.13     {
 92 kumpf  1.57 # ifdef PEGASUS_OS_ZOS
 93                     logIdentity = strdup(System::CIMSERVER.getCString());
 94                     // If System Log is used open it
 95                     System::openlog(logIdentity, LOG_PID, LOG_DAEMON);
 96             # endif
 97                 }
 98 mike   1.13 
 99 kumpf  1.57     ~LoggerRep()
100                 {
101             # ifdef PEGASUS_OS_ZOS
102                     System::closelog();
103                     free(logIdentity);
104             # endif
105                 }
106 mike   1.13 
107 kumpf  1.57     // Actual logging is done in this routine
108                 void log(Logger::LogFileType logFileType,
109                     const String& systemId,
110                     Uint32 logLevel,
111                     const String localizedMsg)
112                 {
113                     // Log the message
114                     System::syslog(systemId, logLevel, localizedMsg.getCString());
115                 }
116             
117             private:
118             
119             # ifdef PEGASUS_OS_ZOS
120                 char* logIdentity;
121             # endif
122             };
123             
124             #else    // !defined(PEGASUS_USE_SYSLOGS)
125             
126             static const char* fileNames[] =
127             {
128 kumpf  1.57     "PegasusTrace.log",
129                 "PegasusStandard.log",
130                 "PegasusAudit.log",
131 ouyang.jian 1.60     "PegasusError.log"
132 kumpf       1.57 };
133                  static const char* lockFileName = "PegasusLog.lock";
134                  
135                  /*
136                      _constructFileName builds the absolute file name from homeDirectory
137 mreddy      1.55     and fileName.
138                  */
139                  static CString _constructFileName(
140                      const String& homeDirectory,
141                      const char * fileName)
142                  {
143 mike        1.13     String result;
144 kumpf       1.57     result.reserveCapacity(
145                          (Uint32)(homeDirectory.size() + 1 + strlen(fileName)));
146 kumpf       1.20     result.append(homeDirectory);
147                      result.append('/');
148 mreddy      1.55     result.append(fileName);
149 kumpf       1.22     return result.getCString();
150 mike        1.13 }
151                  
152                  class LoggerRep
153                  {
154                  public:
155                  
156                      LoggerRep(const String& homeDirectory)
157                      {
158 kumpf       1.40         // Add test for home directory set.
159 mike        1.13 
160 kumpf       1.40         // If home directory does not exist, create it.
161                          CString lgDir = homeDirectory.getCString();
162 mike        1.13 
163 kumpf       1.40         if (!System::isDirectory(lgDir))
164                              System::makeDirectory(lgDir);
165 mike        1.13 
166 kumpf       1.40         // KS: I put the second test in just in case some trys to create
167                          // a completly erronous directory.  At least we will get a message
168 kumpf       1.48         if (!System::isDirectory(lgDir))
169                          {
170                              MessageLoaderParms parms("Common.Logger.LOGGING_DISABLED",
171                                  "Logging Disabled");
172 kumpf       1.40 
173 kumpf       1.48             cerr << MessageLoader::getMessage(parms);
174 kumpf       1.40         }
175                  
176 mreddy      1.55        //Filelocks are not used for VMS
177 kumpf       1.57 # if !defined(PEGASUS_OS_VMS)
178 mreddy      1.55         _loggerLockFileName = _constructFileName(homeDirectory, lockFileName);
179                  
180                          // Open and close a file to make sure that the file exists, on which
181                          // file lock is requested
182                          FILE *fileLockFilePointer;
183                          fileLockFilePointer = fopen(_loggerLockFileName, "a+");
184                          if(fileLockFilePointer)
185                          {
186                              fclose(fileLockFilePointer);
187                          }
188 kumpf       1.57 # endif
189 mreddy      1.55 
190                          _logFileNames[Logger::TRACE_LOG] = _constructFileName(homeDirectory,
191                                                                 fileNames[Logger::TRACE_LOG]);
192 kumpf       1.40 
193 mreddy      1.55         _logFileNames[Logger::STANDARD_LOG] = _constructFileName(homeDirectory,
194                                                                 fileNames[Logger::STANDARD_LOG]);
195 kumpf       1.40 
196 kumpf       1.57 # ifdef PEGASUS_ENABLE_AUDIT_LOGGER
197 mreddy      1.55         _logFileNames[Logger::AUDIT_LOG] = _constructFileName(homeDirectory,
198                                                                 fileNames[Logger::AUDIT_LOG]);
199 kumpf       1.57 # endif
200 thilo.boehm 1.46 
201 mreddy      1.55         _logFileNames[Logger::ERROR_LOG] = _constructFileName(homeDirectory,
202                                                                 fileNames[Logger::ERROR_LOG]);
203 marek       1.47     }
204                  
205                      ~LoggerRep()
206                      {
207 mreddy      1.55     }
208                  
209                      // Actual logging is done in this routine
210                      void log(Logger::LogFileType logFileType,
211                          const String& systemId,
212                          Uint32 logLevel,
213                          const String localizedMsg)
214                      {
215                          // Prepend the systemId to the incoming message
216                          String messageString(systemId);
217                          messageString.append(": ");
218                          messageString.append(localizedMsg);  // l10n
219 marek       1.47 
220 mreddy      1.55         // Get the logLevel String
221                          // This converts bitmap to string based on highest order
222                          // bit set
223                          // ATTN: KS Fix this more efficiently.
224                          const char* tmp = "";
225                          if (logLevel & Logger::TRACE) tmp =       "TRACE   ";
226                          if (logLevel & Logger::INFORMATION) tmp = "INFO    ";
227                          if (logLevel & Logger::WARNING) tmp =     "WARNING ";
228                          if (logLevel & Logger::SEVERE) tmp =      "SEVERE  ";
229                          if (logLevel & Logger::FATAL) tmp =       "FATAL   ";
230 mike        1.13 
231 mreddy      1.55 # ifndef PEGASUS_OS_VMS
232                          // Acquire AutoMutex (for thread sync) 
233                          // and AutoFileLock (for Process Sync).
234                          AutoMutex am(_mutex);
235                          AutoFileLock fileLock(_loggerLockFileName);
236                  
237                          Uint32  logFileSize = 0;
238                  
239                          // Read logFileSize to check if the logfile needs to be pruned.
240                          FileSystem::getFileSize(String(_logFileNames[logFileType]), 
241                                                         logFileSize);
242                  
243                          // Check if the size of the logfile is exceeding 32MB.
244                          if ( logFileSize > PEGASUS_MAX_LOGFILE_SIZE)
245 kumpf       1.57         {
246 mreddy      1.55             // Prepare appropriate file name based on the logFileType.
247                              // Eg: if Logfile name is PegasusStandard.log, pruned logfile name
248                              // will be PegasusStandard-062607-122302.log,where 062607-122302
249                              // is the time stamp.
250                              String prunedLogfile(_logFileNames[logFileType],
251                                                  (Uint32)strlen(_logFileNames[logFileType]) - 4);
252                              prunedLogfile.append('-');
253                  
254                              // Get timestamp,remove illegal chars in file name'/' and ':'
255                              // (: is illegal Open VMS) from the time stamp. Append the time
256                              // info to the file name.
257 mike        1.13 
258 mreddy      1.55             String timeStamp = System::getCurrentASCIITime();
259                              for (unsigned int i=0; i<=timeStamp.size(); i++)
260                              {
261                                  if(timeStamp[i] == '/' || timeStamp[i] == ':')
262                                  {
263                                      timeStamp.remove(i, 1);
264                                  }
265                              }
266                              prunedLogfile.append(timeStamp);
267 mike        1.13 
268 mreddy      1.55             // Append '.log' to the file
269                              prunedLogfile.append( ".log");
270 mike        1.13 
271 mreddy      1.55             // Rename the logfile
272                              FileSystem::renameFile(String(_logFileNames[logFileType]),
273                                                     prunedLogfile);
274                  
275                          } // Check if the logfile needs to be pruned.
276                  # endif  // ifndef PEGASUS_OS_VMS
277                  
278                          // Open Logfile. Based on the value of logFileType, one of the five
279                          // Logfiles will be opened.
280                          ofstream logFileStream;
281                          logFileStream.open(_logFileNames[logFileType], ios::app);
282                          logFileStream << System::getCurrentASCIITime()
283                             << " " << tmp << (const char *)messageString.getCString() << endl;
284                          logFileStream.close();
285 mike        1.13     }
286                  
287                  private:
288                  
289 mreddy      1.55     CString _logFileNames[int(Logger::NUM_LOGS)];
290 kumpf       1.57 
291                  # ifndef PEGASUS_OS_VMS
292 mreddy      1.55     CString _loggerLockFileName;
293                      Mutex _mutex;
294 kumpf       1.57 # endif
295 mike        1.13 };
296                  
297 kumpf       1.57 #endif    // !defined(PEGASUS_USE_SYSLOGS)
298                  
299                  
300                  ///////////////////////////////////////////////////////////////////////////////
301                  //
302                  // Logger
303                  //
304                  ///////////////////////////////////////////////////////////////////////////////
305                  
306 david       1.26 void Logger::_putInternal(
307 mike        1.13     LogFileType logFileType,
308                      const String& systemId,
309 kumpf       1.48     const Uint32 logComponent, // FUTURE: Support logComponent mask
310 david       1.26     Uint32 logLevel,
311 kumpf       1.63     const String& message)
312 mike        1.13 {
313 kumpf       1.63     if (!_rep)
314                         _rep = new LoggerRep(_homeDirectory);
315 chuck       1.29 
316 kumpf       1.63     // Call the actual logging routine is in LoggerRep.
317                      _rep->log(logFileType, systemId, logLevel, message);
318                      
319                      // route log message to trace too -> component LogMessages
320                      if (Logger::TRACE_LOG != logFileType)
321                      {
322                          // do not write log message to trace when trace facility is
323                          // the log to avoid double messages
324                          if (Tracer::TRACE_FACILITY_LOG != Tracer::getTraceFacility())
325                          {
326                              PEG_TRACE_CSTRING(
327                                  TRC_LOGMSG,
328                                  Tracer::LEVEL1,
329                                  (const char*) message.getCString());
330 kumpf       1.40         }
331 david       1.26     }
332                  }
333 mike        1.13 
334 mike        1.42 ////////////////////////////////////////////////////////////////////////////////
335                  //
336                  // Public methods start here:
337                  //
338                  ////////////////////////////////////////////////////////////////////////////////
339                  
340 david       1.26 void Logger::put(
341 kumpf       1.40     LogFileType logFileType,
342                      const String& systemId,
343                      Uint32 logLevel,
344                      const String& formatString,
345                      const Formatter::Arg& arg0,
346                      const Formatter::Arg& arg1,
347                      const Formatter::Arg& arg2,
348                      const Formatter::Arg& arg3,
349                      const Formatter::Arg& arg4,
350                      const Formatter::Arg& arg5,
351                      const Formatter::Arg& arg6,
352                      const Formatter::Arg& arg7,
353                      const Formatter::Arg& arg8,
354                      const Formatter::Arg& arg9)
355 chuck       1.29 {
356 mike        1.42     if (wouldLog(logLevel))
357                      {
358                          Logger::_putInternal(logFileType, systemId, 0, logLevel,
359 kumpf       1.63             Formatter::format(formatString, arg0, arg1, arg2, arg3,
360                                  arg4, arg5, arg6, arg7, arg8, arg9));
361 mike        1.42     }
362 karl        1.37 }
363                  
364                  void Logger::put(
365 kumpf       1.40     LogFileType logFileType,
366                      const String& systemId,
367                      Uint32 logLevel,
368                      const String& formatString)
369 karl        1.37 {
370 mike        1.42     if (wouldLog(logLevel))
371                      {
372 kumpf       1.63         Logger::_putInternal(logFileType, systemId, 0, logLevel, formatString);
373 mike        1.42     }
374                  }
375 karl        1.37 
376 mike        1.42 void Logger::put(
377                      LogFileType logFileType,
378                      const String& systemId,
379                      Uint32 logLevel,
380                      const String& formatString,
381                      const Formatter::Arg& arg0)
382                  {
383                      if (wouldLog(logLevel))
384                      {
385                          Logger::_putInternal(logFileType, systemId, 0, logLevel,
386 kumpf       1.63             Formatter::format(formatString, arg0));
387 mike        1.42     }
388 karl        1.37 }
389                  
390                  void Logger::put(
391 kumpf       1.40     LogFileType logFileType,
392                      const String& systemId,
393                      Uint32 logLevel,
394                      const String& formatString,
395 mike        1.42     const Formatter::Arg& arg0,
396                      const Formatter::Arg& arg1)
397 karl        1.37 {
398 mike        1.42     if (wouldLog(logLevel))
399                      {
400                          Logger::_putInternal(logFileType, systemId, 0, logLevel,
401 kumpf       1.63             Formatter::format(formatString, arg0, arg1));
402 mike        1.42     }
403                  }
404 karl        1.37 
405 mike        1.42 void Logger::put(
406                      LogFileType logFileType,
407                      const String& systemId,
408                      Uint32 logLevel,
409                      const String& formatString,
410                      const Formatter::Arg& arg0,
411                      const Formatter::Arg& arg1,
412                      const Formatter::Arg& arg2)
413                  {
414                      if (wouldLog(logLevel))
415                      {
416                          Logger::_putInternal(logFileType, systemId, 0, logLevel,
417 kumpf       1.63             Formatter::format(formatString, arg0, arg1, arg2));
418 mike        1.42     }
419 chuck       1.29 }
420                  
421                  void Logger::put_l(
422 kumpf       1.40     LogFileType logFileType,
423                      const String& systemId,
424                      Uint32 logLevel,
425 kumpf       1.63     const MessageLoaderParms& msgParms)
426 mike        1.42 {
427                      if (wouldLog(logLevel))
428                      {
429 kumpf       1.63         MessageLoaderParms parms = msgParms;
430                          parms.useProcessLocale = true;
431 mike        1.42         Logger::_putInternal(logFileType, systemId, 0, logLevel,
432 kumpf       1.63             MessageLoader::getMessage(parms));
433 mike        1.42     }
434 david       1.26 }
435                  
436                  void Logger::trace(
437 kumpf       1.40     LogFileType logFileType,
438                      const String& systemId,
439                      const Uint32 logComponent,
440 kumpf       1.62     const String& message)
441 chuck       1.29 {
442 mike        1.42     if (wouldLog(Logger::TRACE))
443                      {
444                          Logger::_putInternal(logFileType, systemId, logComponent, Logger::TRACE,
445 kumpf       1.63             message);
446 mike        1.42     }
447 mike        1.13 }
448                  
449                  void Logger::setHomeDirectory(const String& homeDirectory)
450                  {
451                      _homeDirectory = homeDirectory;
452                  }
453 david       1.26 
454                  void Logger::setlogLevelMask( const String logLevelList )
455                  {
456 karl        1.37     Uint32 logLevelType = 0;
457 david       1.26     String logLevelName      = logLevelList;
458                  
459                      // Check if logLevel has been specified
460                      if (logLevelName != String::EMPTY)
461                      {
462                          // initialise _severityMask
463                          _severityMask = 0;
464                  
465 kumpf       1.40         // Set logLevelType to indicate the level of logging
466 david       1.26         // required by the user.
467 kumpf       1.40         if (String::equalNoCase(logLevelName,"TRACE"))
468                          {
469                              logLevelType =  Logger::TRACE;
470                          }
471                          else if (String::equalNoCase(logLevelName,"INFORMATION"))
472                          {
473                              logLevelType =  Logger::INFORMATION;
474                          }
475                          else if (String::equalNoCase(logLevelName,"WARNING"))
476                          {
477                              logLevelType = Logger::WARNING;
478                          }
479                          else if (String::equalNoCase(logLevelName,"SEVERE"))
480                          {
481                              logLevelType = Logger::SEVERE;
482                          }
483                          else if (String::equalNoCase(logLevelName,"FATAL"))
484                          {
485                              logLevelType = Logger::FATAL;
486                          }
487                          // Setting _severityMask.  NOTE:  When adding new logLevels
488 david       1.26         // it is essential that they are adding in ascending order
489                          // based on priority.  Once a case statement is true we will
490                          // continue to set all following log levels with a higher
491                          // priority.
492 kumpf       1.40         switch(logLevelType)
493                          {
494                              case Logger::TRACE:
495                                    _severityMask |= Logger::TRACE;
496                              case Logger::INFORMATION:
497                                    _severityMask |= Logger::INFORMATION;
498                              case Logger::WARNING:
499                                    _severityMask |= Logger::WARNING;
500                              case Logger::SEVERE:
501                                    _severityMask |= Logger::SEVERE;
502                              case Logger::FATAL:
503                                    _severityMask |= Logger::FATAL;
504                          }
505 kumpf       1.54 
506                          Executor::updateLogLevel(logLevelName.getCString());
507 david       1.26     }
508                      else
509                      {
510 kumpf       1.40         // Property logLevel not specified, set default value.
511                          _severityMask = ~Logger::TRACE;
512 kumpf       1.54         Executor::updateLogLevel("INFORMATION");
513 david       1.26     }
514                  }
515                  
516 mike        1.42 Boolean Logger::isValidlogLevel(const String logLevel)
517 david       1.26 {
518                      // Validate the logLevel and modify the logLevel argument
519                      // to reflect the invalid logLevel
520                  
521                      Uint32    index=0;
522                      String    logLevelName = String::EMPTY;
523                      Boolean   validlogLevel=false;
524                  
525                      logLevelName = logLevel;
526                  
527                      if (logLevelName != String::EMPTY)
528                      {
529 kumpf       1.40         // Lookup the index for logLevel name in _logLevel_LIST
530                          index = 0;
531                          validlogLevel = false;
532                  
533                          while (index < _NUM_LOGLEVEL)
534                          {
535                              if (String::equalNoCase(logLevelName, LOGLEVEL_LIST[index]))
536                              {
537                                  // Found logLevel, break from the loop
538                                  validlogLevel = true;
539                                  break;
540                              }
541                              else
542                              {
543                                  index++;
544                              }
545                          }
546 david       1.26     }
547                      else
548                      {
549 kumpf       1.40         // logLevels is empty, it is a valid value so return true
550 kumpf       1.57         return true;
551 david       1.26     }
552                  
553                      return validlogLevel;
554                  }
555                  
556 mike        1.13 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2