(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 
 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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2