1# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4import datetime 5import logging 6import logging.handlers 7import os 8import socket 9import time 10 11from config import rpm_config 12 13import common 14from autotest_lib.site_utils import log_socket_server 15from autotest_lib.site_utils.rpm_control_system import rpm_infrastructure_exception 16 17LOGGING_FORMAT = rpm_config.get('GENERAL', 'logging_format') 18RECEIVERS = rpm_config.get('RPM_INFRASTRUCTURE', 19 'email_notification_recipients').split(',') 20SUBJECT_LINE = (rpm_config.get('GENERAL', 'email_subject_line_format') % 21 socket.gethostname()) 22 23 24class SuspendableSMTPHandler(logging.handlers.SMTPHandler): 25 """SMTPHandler that can have it's emails suspended.""" 26 _suspend_start_time = datetime.datetime.now() 27 _suspend_time_hrs = 0 28 29 30 def suspend_emails(self, hours): 31 """Suspend email notifications. 32 33 @param hours: How many hours to suspend email notifications. 34 """ 35 self._suspend_start_time = datetime.datetime.now() 36 self._suspend_time_hrs = int(hours, 0) 37 38 39 def resume_emails(self): 40 """Resume email notifications.""" 41 self._suspend_time_hrs = 0 42 43 44 def emit(self, record): 45 """Emit a log record. 46 47 This subclassed version only emits the log record if emails are not 48 suspended. 49 50 @param record: Log record object we want to emit/record. 51 """ 52 if datetime.datetime.now() < (self._suspend_start_time + 53 datetime.timedelta(hours=self._suspend_time_hrs)): 54 return 55 record.msg += ('\n\nTo disable these emails use rpm_client from your ' 56 'local checkout. For a 12 hour suspension run: ' 57 'site_utils/rpm_control_system/rpm_client.py -d 12') 58 return super(SuspendableSMTPHandler, self).emit(record) 59 60 61def set_up_logging_to_file(log_dir, log_filename_format=None): 62 """ 63 Correctly set up logging to have the correct format/level, log to a file, 64 and send out email notifications in case of error level messages. 65 66 @param log_dir: The directory in which log files should be created. 67 @param log_filename_format: Format to use to create the log file. 68 69 @returns email_handler: Logging handler used to send out email alerts. 70 """ 71 logging.basicConfig(filename=_logfile_path(log_dir, log_filename_format), 72 level=logging.INFO, format=LOGGING_FORMAT) 73 _set_common_logger_options() 74 75 76def start_log_server(log_dir, log_filename_format): 77 """Start log server to accept logging through a TCP server. 78 79 @param log_dir: The directory in which log files should be created. 80 @param log_filename_format: Format to use to create the log file. 81 """ 82 log_filename = _logfile_path(log_dir, log_filename_format) 83 log_socket_server.LogSocketServer.start(filename=log_filename, 84 level=logging.INFO, 85 format=LOGGING_FORMAT) 86 87 88def set_up_logging_to_server(): 89 """Sets up logging option when using a logserver.""" 90 if log_socket_server.LogSocketServer.port is None: 91 raise rpm_infrastructure_exception.RPMLoggingSetupError( 92 'set_up_logging failed: Log server port is unknown.') 93 socketHandler = logging.handlers.SocketHandler( 94 'localhost', log_socket_server.LogSocketServer.port) 95 logging.getLogger().addHandler(socketHandler) 96 _set_common_logger_options() 97 98 99def _logfile_path(log_dir, log_filename_format): 100 """Get file name of log based on given log_filename_format. 101 102 @param log_filename_format: Format to use to create the log file. 103 """ 104 log_filename = time.strftime(log_filename_format) 105 if not os.path.isdir(log_dir): 106 os.makedirs(log_dir) 107 return os.path.join(log_dir, log_filename) 108 109 110def _set_common_logger_options(): 111 """Sets the options common to both file and server based logging.""" 112 logger = logging.getLogger() 113 if rpm_config.getboolean('GENERAL', 'debug'): 114 logger.setLevel(logging.DEBUG) 115 email_handler = SuspendableSMTPHandler('localhost', 'rpm@google.com', 116 RECEIVERS, SUBJECT_LINE, None) 117 email_handler.setLevel(logging.ERROR) 118 email_handler.setFormatter(logging.Formatter(LOGGING_FORMAT)) 119 logger.addHandler(email_handler) 120