Home | History | Annotate | Download | only in rpm_control_system
      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.
      4 import datetime
      5 import logging
      6 import logging.handlers
      7 import os
      8 import socket
      9 import time
     10 
     11 from config import rpm_config
     12 
     13 import common
     14 from autotest_lib.site_utils import log_socket_server
     15 from autotest_lib.site_utils.rpm_control_system import rpm_infrastructure_exception
     16 
     17 LOGGING_FORMAT = rpm_config.get('GENERAL', 'logging_format')
     18 RECEIVERS = rpm_config.get('RPM_INFRASTRUCTURE',
     19                            'email_notification_recipients').split(',')
     20 SUBJECT_LINE = (rpm_config.get('GENERAL', 'email_subject_line_format') %
     21                 socket.gethostname())
     22 
     23 
     24 class 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 
     61 def get_log_filename(log_filename_format):
     62     """Get file name of log based on given log_filename_format.
     63 
     64     @param log_filename_format: Format to use to create the log file.
     65 
     66     @raise Exception: If log_filename_format is None.
     67     """
     68     if not log_filename_format:
     69             raise Exception('log_filename_format must be set.')
     70 
     71     log_filename = os.path.abspath(time.strftime(log_filename_format))
     72     log_dir = os.path.dirname(log_filename)
     73     if not os.path.isdir(log_dir):
     74         os.makedirs(log_dir)
     75     return log_filename
     76 
     77 
     78 def set_up_logging(log_filename_format=None, use_log_server=False):
     79     """
     80     Correctly set up logging to have the correct format/level, log to a file,
     81     and send out email notifications in case of error level messages.
     82 
     83     @param log_filename_format: Format to use to create the log file.
     84     @param use_log_server: True if log to a TCP server.
     85 
     86     @returns email_handler: Logging handler used to send out email alerts.
     87     """
     88     if log_socket_server.LogSocketServer.port is None and use_log_server:
     89         # Port is unknown, can't log to the server.
     90         raise rpm_infrastructure_exception.RPMLoggingSetupError(
     91                 'set_up_logging failed: Log server port is unknown.')
     92     if use_log_server:
     93         socketHandler = logging.handlers.SocketHandler(
     94                 'localhost', log_socket_server.LogSocketServer.port)
     95         logging.getLogger().addHandler(socketHandler)
     96     else:
     97         log_filename = get_log_filename(log_filename_format)
     98         logging.basicConfig(filename=log_filename, level=logging.INFO,
     99                             format=LOGGING_FORMAT)
    100 
    101     if rpm_config.getboolean('GENERAL', 'debug'):
    102         logging.getLogger().setLevel(logging.DEBUG)
    103 
    104     email_handler = SuspendableSMTPHandler('localhost', 'rpm (at] google.com',
    105                                            RECEIVERS, SUBJECT_LINE, None)
    106     email_handler.setLevel(logging.ERROR)
    107     email_handler.setFormatter(logging.Formatter(LOGGING_FORMAT))
    108     logging.getLogger('').addHandler(email_handler)
    109     return email_handler
    110 
    111 
    112 def start_log_server(log_filename_format):
    113     """Start log server to accept logging through a TCP server.
    114 
    115     @param log_filename_format: Format to use to create the log file.
    116     """
    117     log_filename = get_log_filename(log_filename_format)
    118     log_socket_server.LogSocketServer.start(filename=log_filename,
    119                                             level=logging.INFO,
    120                                             format=LOGGING_FORMAT)
    121