1#Licensed to the Apache Software Foundation (ASF) under one 2#or more contributor license agreements. See the NOTICE file 3#distributed with this work for additional information 4#regarding copyright ownership. The ASF licenses this file 5#to you under the Apache License, Version 2.0 (the 6#"License"); you may not use this file except in compliance 7#with the License. You may obtain a copy of the License at 8 9# http://www.apache.org/licenses/LICENSE-2.0 10 11#Unless required by applicable law or agreed to in writing, software 12#distributed under the License is distributed on an "AS IS" BASIS, 13#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14#See the License for the specific language governing permissions and 15#limitations under the License. 16"""hodLogger provides a customized interface to Python's core logging package. 17""" 18 19import sys, os, re, logging, logging.handlers, inspect, pprint, types 20from tcp import get_address_tuple 21 22fileFormatString = '[%(asctime)s] %(levelname)s/%(levelno)s \ 23%(module)s:%(lineno)s - %(message)s' 24 25streamFormatString = '%(levelname)s - %(message)s' 26 27debugStreamFormatString = '[%(asctime)s] %(levelname)s/%(levelno)s \ 28%(module)s:%(lineno)s - %(message)s' 29 30syslogFormatString = '(%(process)d) %(levelname)s/%(levelno)s \ 31%(module)s:%(lineno)s - %(message)s' 32 33smtpFormatString = '[%(asctime)s] %(levelname)s/%(levelno)s \ 34%(module)s:%(lineno)s\n\n%(message)s' 35 36fileFormater = logging.Formatter(fileFormatString) 37streamFormater = logging.Formatter(streamFormatString) 38debugStreamFormater = logging.Formatter(debugStreamFormatString) 39syslogFormater = logging.Formatter(syslogFormatString) 40smtpFormater = logging.Formatter(smtpFormatString) 41 42defaultFileLevel = 3 43defaultStreamLevel = 4 44defaultSyslogLevel = 3 45defaultSmtpLevel = 0 46 47hodLogLevelMap = { 0 : logging.CRITICAL, 48 1 : logging.ERROR, 49 2 : logging.WARNING, 50 3 : logging.INFO, 51 4 : logging.DEBUG } 52 53hodStreamFormatMap = { 0 : streamFormater, 54 1 : streamFormater, 55 2 : streamFormater, 56 3 : streamFormater, 57 4 : debugStreamFormater } 58 59rehodLogLevelMap = {} 60for key in hodLogLevelMap.keys(): 61 rehodLogLevelMap[hodLogLevelMap[key]] = key 62 63 64reModule = re.compile("^(.*)\..*$") 65 66hodLogs = {} 67 68class hodRotatingFileHandler(logging.handlers.RotatingFileHandler): 69 """ This class needs to be used in place of RotatingFileHandler when 70 the 2.4.0 Python interpreter is used.""" 71 72 def emit(self, record): 73 """ 74 Emit a record. 75 76 If a formatter is specified, it is used to format the record. 77 The record is then written to the stream with a trailing newline 78 [N.B. this may be removed depending on feedback]. If exception 79 information is present, it is formatted using 80 traceback.print_exception and appended to the stream. 81 82 ***** 83 84 THIS IS A HACK, when instances of hodLogger get passed to the child of 85 a child thread for some reason self.stream gets closed. This version 86 of emit re-opens self.stream if it is closed. After testing it appears 87 that self.stream is only closed once after the second thread is 88 initialized so there is not performance penalty to this hack. This 89 problem only exists in python 2.4. 90 91 ***** 92 """ 93 try: 94 if self.shouldRollover(record): 95 self.doRollover() 96 try: 97 msg = self.format(record) 98 fs = "%s\n" 99 if not hasattr(types, "UnicodeType"): #if no unicode support... 100 self.stream.write(fs % msg) 101 else: 102 try: 103 self.stream.write(fs % msg) 104 except UnicodeError: 105 self.stream.write(fs % msg.encode("UTF-8")) 106 except ValueError: 107 self.stream = open(self.baseFilename, self.mode) 108 self.stream.write(fs % msg) 109 110 self.flush() 111 except: 112 self.handleError(record) 113 except: 114 self.handleError(record) 115 116 def shouldRollover(self, record): 117 """ 118 Determine if rollover should occur. 119 120 Basically, see if the supplied record would cause the file to exceed 121 the size limit we have. 122 123 ***** 124 125 THIS IS A HACK, when instances of hodLogger get passed to the child of 126 a child thread for some reason self.stream gets closed. This version 127 of emit re-opens self.stream if it is closed. After testing it appears 128 that self.stream is only closed once after the second thread is 129 initialized so there is not performance penalty to this hack. This 130 problem only exists in python 2.4. 131 132 ***** 133 """ 134 if self.maxBytes > 0: # are we rolling over? 135 msg = "%s\n" % self.format(record) 136 137 try: 138 #due to non-posix-compliant Windows feature 139 self.stream.seek(0, 2) 140 except ValueError: 141 self.stream = open(self.baseFilename, self.mode) 142 self.stream.seek(0, 2) 143 144 if self.stream.tell() + len(msg) >= self.maxBytes: 145 return 1 146 return 0 147 148class hodCustomLoggingLogger(logging.Logger): 149 """ Slight extension of the logging.Logger class used by the hodLog class. 150 """ 151 def findCaller(self): 152 """ findCaller() is supposed to return the callers file name and line 153 number of the caller. This was broken when the logging package was 154 wrapped by hodLog. We should return much more relevant info now. 155 """ 156 157 callerModule = '' 158 callerLine = 0 159 160 currentModule = os.path.basename(__file__) 161 currentModule = reModule.sub("\g<1>", currentModule) 162 163 frames = inspect.stack() 164 for i in range(len(frames)): 165 frameModule = os.path.basename(frames[i][1]) 166 frameModule = reModule.sub("\g<1>", frameModule) 167 if frameModule == currentModule: 168 previousFrameModule = os.path.basename(frames[i+1][1]) 169 previousFrameModule = reModule.sub("\g<1>", 170 previousFrameModule) 171 callerFile = frames[i+1][1] 172 callerLine = frames[i+1][2] 173 continue 174 175 returnValues = (callerFile, callerLine) 176 if sys.version.startswith('2.4.4') or sys.version.startswith('2.5'): 177 returnValues = (callerFile, callerLine, None) 178 179 return returnValues 180 181class hodLog: 182 """ Cluster management logging class. 183 184 logging levels: 0 - log only critical messages 185 1 - log critical and error messages 186 2 - log critical, error, and warning messages 187 3 - log critical, error, warning, and info messages 188 4 - log critical, error, warning, info, and debug 189 messages""" 190 191 def __init__(self, appName): 192 """Constructs a hodLogger object. 193 194 appName - name of logging application, log filenames will be 195 prepended with this name""" 196 197 self.__appName = appName 198 199 # initialize a dictionary to hold loggerNames 200 self.__loggerNames = {} 201 202 # initialize a dictionary to track log handlers and handler classes 203 self.__logObjs = { 'file' : {}, 'smtp' : {}, 204 'syslog' : {}, 'strm' : {} } 205 206 # use a custom logging.Logger class 207 logging.setLoggerClass(hodCustomLoggingLogger) 208 209 # get the root app logger 210 self.__logger = logging.getLogger(appName) 211 self.__logger.setLevel(logging.DEBUG) 212 213 hodLogs[self.__appName] = self 214 215 def __attr__(self, attrname): 216 """loggerNames - list of defined logger names""" 217 218 if attrname == "loggerNames": return self.__loggerNames.keys() 219 else: raise AttributeError, attrname 220 221 def __repr__(self): 222 """Returns a string representation of a hodLog object of the form: 223 224 LOG_NAME 225 file: FILENAME (level LEVEL) 226 smtp: SMTP_SERVER from FROM_ADDRESS (level LEVEL) 227 strm: STRM_OBJECT (level LEVEL) 228 ... """ 229 230 hodLogString = "hodLog: %s\n\n" % self.__appName 231 for loggerName in self.__loggerNames.keys(): 232 hodLogString = "%s logger: %s\n" % (hodLogString, loggerName) 233 handlerClasses = self.__logObjs.keys() 234 handlerClasses.sort() 235 for handlerClass in handlerClasses: 236 try: 237 loggerLevelName = logging.getLevelName( 238 self.__logObjs[handlerClass][loggerName]['level']) 239 hodLogString = "%s %s: %s (level %s)\n" % ( 240 hodLogString, handlerClass, 241 self.__logObjs[handlerClass][loggerName]['data'], 242 loggerLevelName) 243 except: 244 hodLogString = "%s %s: none\n" % ( 245 hodLogString, handlerClass) 246 hodLogString = "%s\n" % hodLogString 247 248 return hodLogString 249 250 # 'private' method which adds handlers to self.__logObjs 251 def __add_to_handlers(self, handlerClass, loggerName, handler, data, 252 level): 253 self.__logObjs[handlerClass][loggerName] = {} 254 self.__logObjs[handlerClass][loggerName]['handler'] = handler 255 self.__logObjs[handlerClass][loggerName]['data'] = data 256 self.__logObjs[handlerClass][loggerName]['level'] = level 257 258 # 'private' method which determines whether a hod log level is valid and 259 # returns a valid logging.Logger level 260 def __get_logging_level(self, level, defaultLevel): 261 loggingLevel = '' 262 try: 263 loggingLevel = hodLogLevelMap[int(level)] 264 except: 265 loggingLevel = hodLogLevelMap[defaultLevel] 266 267 return loggingLevel 268 269 # make a logging.logger name rootLogger.childLogger in our case the 270 # appName.componentName 271 def __get_logging_logger_name(self, loggerName): 272 return "%s.%s" % (self.__appName, loggerName) 273 274 def add_logger(self, loggerName): 275 """Adds a logger of name loggerName. 276 277 loggerName - name of component of a given application doing the 278 logging 279 280 Returns a hodLogger object for the just added logger.""" 281 282 try: 283 self.__loggerNames[loggerName] 284 except: 285 loggingLoggerName = self.__get_logging_logger_name(loggerName) 286 logging.getLogger(loggingLoggerName) 287 288 self.__loggerNames[loggerName] = 1 289 290 return hodLogger(self.__appName, loggingLoggerName) 291 292 def add_file(self, logDirectory, maxBytes=0, backupCount=0, 293 level=defaultFileLevel, addToLoggerNames=None): 294 """Adds a file handler to all defined loggers or a specified set of 295 loggers. Each log file will be located in logDirectory and have a 296 name of the form appName-loggerName.log. 297 298 logDirectory - logging directory 299 maxBytes - maximum log size to write in bytes before rotate 300 backupCount - number of rotated logs to keep 301 level - cluster management log level 302 addToLoggerNames - list of logger names to which stream handling 303 will be added""" 304 305 def add_file_handler(loggerName): 306 if not self.__logObjs['file'].has_key(loggerName): 307 loggingLevel = self.__get_logging_level(level, 308 defaultFileLevel) 309 310 logFile = os.path.join(logDirectory, "%s-%s.log" % ( 311 self.__appName, loggerName)) 312 313 logFilePresent = False 314 if(os.path.exists(logFile)): 315 logFilePresent = True 316 317 if sys.version.startswith('2.4'): 318 fileHandler = hodRotatingFileHandler(logFile, 319 maxBytes=maxBytes, backupCount=backupCount) 320 else: 321 fileHandler = logging.handlers.RotatingFileHandler(logFile, 322 maxBytes=maxBytes, backupCount=backupCount) 323 if logFilePresent and backupCount: 324 fileHandler.doRollover() 325 326 fileHandler.setLevel(loggingLevel) 327 fileHandler.setFormatter(fileFormater) 328 329 loggingLoggerName = self.__get_logging_logger_name(loggerName) 330 aLogger = logging.getLogger(loggingLoggerName) 331 aLogger.addHandler(fileHandler) 332 333 fileData = "%s" % logFile 334 self.__add_to_handlers('file', loggerName, fileHandler, 335 fileData, loggingLevel) 336 337 if addToLoggerNames: 338 for loggerName in addToLoggerNames: 339 add_file_handler(loggerName) 340 else: 341 for loggerName in self.__loggerNames: 342 add_file_handler(loggerName) 343 344 def add_stream(self, stream=sys.stderr, level=defaultStreamLevel, 345 addToLoggerNames=None): 346 """Adds a stream handler to all defined loggers or a specified set of 347 loggers. 348 349 stream - a stream such as sys.stderr or sys.stdout 350 level - cluster management log level 351 addToLoggerNames - tupple of logger names to which stream handling 352 will be added""" 353 354 def add_stream_handler(loggerName): 355 if not self.__logObjs['strm'].has_key(loggerName): 356 loggingLevel = self.__get_logging_level(level, 357 defaultStreamLevel) 358 359 streamHandler = logging.StreamHandler(stream) 360 361 streamHandler.setLevel(loggingLevel) 362 363 streamHandler.setFormatter(hodStreamFormatMap[int(level)]) 364 365 loggingLoggerName = self.__get_logging_logger_name(loggerName) 366 aLogger = logging.getLogger(loggingLoggerName) 367 aLogger.addHandler(streamHandler) 368 369 streamData = "%s" % stream 370 self.__add_to_handlers('strm', loggerName, streamHandler, 371 streamData, loggingLevel) 372 373 if addToLoggerNames: 374 for loggerName in addToLoggerNames: 375 add_stream_handler(loggerName) 376 else: 377 for loggerName in self.__loggerNames: 378 add_stream_handler(loggerName) 379 380 def add_syslog(self, address, level=defaultSyslogLevel, 381 addToLoggerNames=None): 382 def add_syslog_handler(loggerName): 383 if not self.__logObjs['syslog'].has_key(loggerName): 384 loggingLevel = self.__get_logging_level(level, 385 defaultSyslogLevel) 386 387 address[1] = int(address[1]) 388 syslogHandler = logging.handlers.SysLogHandler(tuple(address), 389 9) 390 391 syslogHandler.setLevel(loggingLevel) 392 393 syslogHandler.setFormatter(syslogFormater) 394 395 loggingLoggerName = self.__get_logging_logger_name(loggerName) 396 aLogger = logging.getLogger(loggingLoggerName) 397 aLogger.addHandler(syslogHandler) 398 399 syslogData = "%s:%s" % (address[0], address[1]) 400 self.__add_to_handlers('syslog', loggerName, syslogHandler, 401 syslogData, loggingLevel) 402 403 if addToLoggerNames: 404 for loggerName in addToLoggerNames: 405 add_syslog_handler(loggerName) 406 else: 407 for loggerName in self.__loggerNames: 408 add_syslog_handler(loggerName) 409 410 411 def add_smtp(self, mailHost, fromAddress, toAddresses, 412 level=defaultSmtpLevel, addToLoggerNames=None): 413 """Adds an SMTP handler to all defined loggers or a specified set of 414 loggers. 415 416 mailHost - SMTP server to used when sending mail 417 fromAddress - email address to use as the from address when 418 sending mail 419 toAdresses - comma seperated list of email address to which 420 mail will be sent 421 level - cluster management log level 422 addToLoggerNames - tupple of logger names to which smtp handling 423 will be added""" 424 425 def add_email_handler(loggerName): 426 if not self.__logObjs['smtp'].has_key(loggerName): 427 loggingLevel = self.__get_logging_level(level, 428 defaultSmtpLevel) 429 430 subject = loggerName 431 if loggingLevel == 50: 432 subject = "%s - a critical error has occured." % subject 433 elif loggingLevel == 40: 434 subject = "%s - an error has occured." % subject 435 elif loggingLevel == 30: 436 subject = "%s - warning message." % subject 437 elif loggingLevel == 20: 438 subject = "%s - information message." % subject 439 elif loggingLevel == 10: 440 subject = "%s - debugging message." % subject 441 442 mailHostTuple = get_address_tuple(mailHost) 443 emailHandler = logging.handlers.SMTPHandler(mailHostTuple, 444 fromAddress, toAddresses, subject) 445 446 emailHandler.setFormatter(smtpFormater) 447 emailHandler.setLevel(loggingLevel) 448 449 loggingLoggerName = self.__get_logging_logger_name(loggerName) 450 aLogger = logging.getLogger(loggingLoggerName) 451 aLogger.addHandler(emailHandler) 452 453 emailData = "%s from %s" % (mailHost, fromAddress) 454 self.__add_to_handlers('smtp', loggerName, emailHandler, 455 emailData, loggingLevel) 456 457 if addToLoggerNames: 458 for loggerName in addToLoggerNames: 459 add_email_handler(loggerName) 460 else: 461 for loggerName in self.__loggerNames: 462 add_email_handler(loggerName) 463 464 def status(self): 465 statusStruct = {} 466 for loggerName in self.__loggerNames.keys(): 467 statusStruct[loggerName] = [] 468 for handlerClass in self.__logObjs.keys(): 469 loggerDict = {} 470 try: 471 level = self.__logObjs[handlerClass][loggerName]['level'] 472 level = rehodLogLevelMap[level] 473 474 loggerDict['handler'] = handlerClass 475 loggerDict['level'] = level 476 loggerDict['data'] = \ 477 self.__logObjs[handlerClass][loggerName]['data'] 478 except: 479 pass 480 else: 481 statusStruct[loggerName].append(loggerDict) 482 483 return statusStruct 484 485 def lock_handlers(self): 486 for handlerClass in self.__logObjs.keys(): 487 for loggerName in self.__logObjs[handlerClass].keys(): 488 self.__logObjs[handlerClass][loggerName]['handler'].acquire() 489 490 def release_handlers(self): 491 for handlerClass in self.__logObjs.keys(): 492 for loggerName in self.__logObjs[handlerClass].keys(): 493 self.__logObjs[handlerClass][loggerName]['handler'].release() 494 495 def get_level(self, handler, loggerName): 496 return rehodLogLevelMap[self.__logObjs[handler][loggerName]['level']] 497 498 def set_level(self, handler, loggerName, level): 499 """Sets the logging level of a particular logger and logger handler. 500 501 handler - handler (smtp, file, or stream) 502 loggerName - logger to set level on 503 level - level to set logger 504 """ 505 506 level = self.__get_logging_level(level, defaultFileLevel) 507 self.__logObjs[handler][loggerName]['handler'].setLevel(level) 508 self.__logObjs[handler][loggerName]['level'] = level 509 510 if handler == 'stream': 511 self.__logObjs[handler][loggerName]['handler'].setFormatter( 512 hodStreamFormatMap[int(level)]) 513 514 def set_logger_level(self, loggerName, level): 515 status = 0 516 for handlerClass in self.__logObjs.keys(): 517 if self.__logObjs[handlerClass].has_key(loggerName): 518 self.set_level(handlerClass, loggerName, level) 519 else: 520 status = 1 521 522 return status 523 524 def rollover(self, loggerName): 525 status = 0 526 if self.__logObjs['file'].has_key(loggerName): 527 if self.__logObjs['file'][loggerName]['handler'].shouldRollover(): 528 self.__logObjs['file'][loggerName]['handler'].doRollover() 529 else: 530 status = 1 531 532 return status 533 534 def set_max_bytes(self, maxBytes): 535 status = 0 536 if self.__logObjs.has_key('file'): 537 for loggerName in self.__logObjs['file'].keys(): 538 self.__logObjs['file'][loggerName]['handler'].maxBytes = 0 539 else: 540 status = 1 541 542 return status 543 544 def get_logger(self, loggerName): 545 """ Returns a hodLogger object for a logger by name. """ 546 547 loggingLoggerName = self.__get_logging_logger_name(loggerName) 548 return hodLogger(self.__appName, loggingLoggerName) 549 550 def critical(self, loggerName, msg): 551 """Logs a critical message and flushes log buffers. This method really 552 should only be called upon a catastrophic failure. 553 554 loggerName - logger to use 555 msg - message to be logged""" 556 557 loggingLoggerName = self.__get_logging_logger_name(loggerName) 558 logger = logging.getLogger(loggingLoggerName) 559 logger.critical(msg) 560 self.flush() 561 562 def error(self, loggerName, msg): 563 """Logs an error message and flushes log buffers. 564 565 loggerName - logger to use 566 msg - message to be logged""" 567 568 loggingLoggerName = self.__get_logging_logger_name(loggerName) 569 logger = logging.getLogger(loggingLoggerName) 570 logger.error(msg) 571 self.flush() 572 573 def warn(self, loggerName, msg): 574 """Logs a warning message. 575 576 loggerName - logger to use 577 msg - message to be logged""" 578 579 loggingLoggerName = self.__get_logging_logger_name(loggerName) 580 logger = logging.getLogger(loggingLoggerName) 581 logger.warn(msg) 582 583 def info(self, loggerName, msg): 584 """Logs an information message. 585 586 loggerName - logger to use 587 msg - message to be logged""" 588 589 loggingLoggerName = self.__get_logging_logger_name(loggerName) 590 logger = logging.getLogger(loggingLoggerName) 591 logger.info(msg) 592 593 def debug(self, loggerName, msg): 594 """Logs a debugging message. 595 596 loggerName - logger to use 597 msg - message to be logged""" 598 599 loggingLoggerName = self.__get_logging_logger_name(loggerName) 600 logger = logging.getLogger(loggingLoggerName) 601 logger.debug(msg) 602 603 def flush(self): 604 """Flush all log handlers.""" 605 606 for handlerClass in self.__logObjs.keys(): 607 for loggerName in self.__logObjs[handlerClass].keys(): 608 self.__logObjs[handlerClass][loggerName]['handler'].flush() 609 610 def shutdown(self): 611 """Shutdown all logging, flushing all buffers.""" 612 613 for handlerClass in self.__logObjs.keys(): 614 for loggerName in self.__logObjs[handlerClass].keys(): 615 self.__logObjs[handlerClass][loggerName]['handler'].flush() 616 # Causes famous 'ValueError: I/O operation on closed file' 617 # self.__logObjs[handlerClass][loggerName]['handler'].close() 618 619class hodLogger: 620 """ Encapsulates a particular logger from a hodLog object. """ 621 def __init__(self, appName, loggingLoggerName): 622 """Constructs a hodLogger object (a particular logger in a hodLog 623 object). 624 625 loggingLoggerName - name of a logger in hodLog object""" 626 627 self.__appName = appName 628 self.__loggerName = loggingLoggerName 629 self.__logger = logging.getLogger(self.__loggerName) 630 631 def __repr__(self): 632 """Returns a string representation of a hodComponentLog object.""" 633 634 return "%s hodLog" % self.__loggerName 635 636 def __call__(self): 637 pass 638 639 def set_logger_level(self, loggerName, level): 640 641 return hodLogs[self.__appName].set_logger_level(loggerName, level) 642 643 def set_max_bytes(self, maxBytes): 644 645 return hodLogs[self.__appName].set_max_bytes(maxBytes) 646 647 def rollover(self): 648 return hodLogs[self.__appName].rollover(self.__loggerName) 649 650 def get_level(self, handler, loggerName): 651 652 return hodLogs[self.__appName].get_level(handler, loggerName) 653 654 def critical(self, msg): 655 """Logs a critical message and calls sys.exit(1). 656 657 msg - message to be logged""" 658 659 self.__logger.critical(msg) 660 661 def error(self, msg): 662 """Logs an error message. 663 664 msg - message to be logged""" 665 666 self.__logger.error(msg) 667 668 def warn(self, msg): 669 """Logs a warning message. 670 671 msg - message to be logged""" 672 673 self.__logger.warn(msg) 674 675 def info(self, msg): 676 """Logs an information message. 677 678 msg - message to be logged""" 679 680 self.__logger.info(msg) 681 682 def debug(self, msg): 683 """Logs a debugging message. 684 685 msg - message to be logged""" 686 687 self.__logger.debug(msg) 688 689class hodDummyLogger: 690 """ Dummy hodLogger class. Other hod classes requiring a hodLogger default 691 to this hodLogger if no logger is passed.""" 692 693 def __init__(self): 694 """pass""" 695 696 pass 697 698 def __repr__(self): 699 return "dummy hodLogger" 700 701 def __call__(self): 702 """pass""" 703 704 pass 705 706 def set_logger_level(self, loggerName, level): 707 708 return 0 709 710 def set_max_bytes(self, loggerName, maxBytes): 711 712 return 0 713 714 def get_level(self, handler, loggerName): 715 716 return 4 717 718 def rollover(self): 719 720 return 0 721 722 def critical(self, msg): 723 """pass""" 724 725 pass 726 727 def error(self, msg): 728 """pass""" 729 730 pass 731 732 def warn(self, msg): 733 """pass""" 734 735 pass 736 737 def info(self, msg): 738 """pass""" 739 740 pass 741 742 def debug(self, msg): 743 """pass""" 744 745 pass 746 747def ensureLogDir(logDir): 748 """Verify that the passed in log directory exists, and if it doesn't 749 create it.""" 750 if not os.path.exists(logDir): 751 try: 752 old_mask = os.umask(0) 753 os.makedirs(logDir, 01777) 754 os.umask(old_mask) 755 except Exception, e: 756 print >>sys.stderr, "Could not create log directories %s. Exception: %s. Stack Trace: %s" % (logDir, get_exception_error_string(), get_exception_string()) 757 raise e 758 759def getLogger(cfg, logName): 760 if cfg['debug'] > 0: 761 user = cfg['userid'] 762 baseLogger = hodLog(logName) 763 log = baseLogger.add_logger('main') 764 765 if cfg.has_key('log-dir'): 766 serviceId = os.getenv('PBS_JOBID') 767 if serviceId: 768 logDir = os.path.join(cfg['log-dir'], "%s.%s" % (user, serviceId)) 769 else: 770 logDir = os.path.join(cfg['log-dir'], user) 771 if not os.path.exists(logDir): 772 os.mkdir(logDir) 773 774 baseLogger.add_file(logDirectory=logDir, level=cfg['debug'], 775 addToLoggerNames=('main',)) 776 777 try: 778 if cfg.has_key('stream') and cfg['stream']: 779 baseLogger.add_stream(level=cfg['debug'], addToLoggerNames=('main',)) 780 781 if cfg.has_key('syslog-address'): 782 baseLogger.add_syslog(cfg['syslog-address'], 783 level=cfg['debug'], addToLoggerNames=('main',)) 784 except Exception,e: 785 # Caught an exception while initialising logger 786 log.critical("%s Logger failed to initialise. Reason : %s" % (logName, e)) 787 pass 788 return log 789