Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 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. |
Simran Basi | 4e3d118 | 2013-06-25 16:12:30 -0700 | [diff] [blame] | 4 | import datetime |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 5 | import logging |
| 6 | import logging.handlers |
Scott Zawalski | 201d6be | 2012-09-21 15:56:25 -0400 | [diff] [blame] | 7 | import os |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 8 | import socket |
| 9 | import time |
| 10 | |
| 11 | from config import rpm_config |
Dan Shi | 1a34c36 | 2014-04-11 16:37:04 -0700 | [diff] [blame^] | 12 | from autotest_lib.site_utils import log_socket_server |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 13 | |
| 14 | LOGGING_FORMAT = rpm_config.get('GENERAL', 'logging_format') |
Simran Basi | 4e3d118 | 2013-06-25 16:12:30 -0700 | [diff] [blame] | 15 | RECEIVERS = rpm_config.get('RPM_INFRASTRUCTURE', |
| 16 | 'email_notification_recipients').split(',') |
| 17 | SUBJECT_LINE = (rpm_config.get('GENERAL', 'email_subject_line_format') % |
| 18 | socket.gethostname()) |
| 19 | |
| 20 | |
| 21 | class SuspendableSMTPHandler(logging.handlers.SMTPHandler): |
| 22 | """SMTPHandler that can have it's emails suspended.""" |
| 23 | _suspend_start_time = datetime.datetime.now() |
| 24 | _suspend_time_hrs = 0 |
| 25 | |
| 26 | |
| 27 | def suspend_emails(self, hours): |
| 28 | """Suspend email notifications. |
| 29 | |
| 30 | @param hours: How many hours to suspend email notifications. |
| 31 | """ |
| 32 | self._suspend_start_time = datetime.datetime.now() |
| 33 | self._suspend_time_hrs = int(hours, 0) |
| 34 | |
| 35 | |
| 36 | def resume_emails(self): |
| 37 | """Resume email notifications.""" |
| 38 | self._suspend_time_hrs = 0 |
| 39 | |
| 40 | |
| 41 | def emit(self, record): |
| 42 | """Emit a log record. |
| 43 | |
| 44 | This subclassed version only emits the log record if emails are not |
| 45 | suspended. |
| 46 | |
| 47 | @param record: Log record object we want to emit/record. |
| 48 | """ |
| 49 | if datetime.datetime.now() < (self._suspend_start_time + |
| 50 | datetime.timedelta(hours=self._suspend_time_hrs)): |
| 51 | return |
| 52 | record.msg += ('\n\nTo disable these emails use rpm_client from your ' |
| 53 | 'local checkout. For a 12 hour suspension run: ' |
| 54 | 'site_utils/rpm_control_system/rpm_client.py -d 12') |
| 55 | return super(SuspendableSMTPHandler, self).emit(record) |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 56 | |
| 57 | |
Dan Shi | 1a34c36 | 2014-04-11 16:37:04 -0700 | [diff] [blame^] | 58 | def get_log_filename(log_filename_format): |
| 59 | """Get file name of log based on given log_filename_format. |
| 60 | |
| 61 | @param log_filename_format: Format to use to create the log file. |
| 62 | |
| 63 | @raise Exception: If log_filename_format is None. |
| 64 | """ |
| 65 | if not log_filename_format: |
| 66 | raise Exception('log_filename_format must be set.') |
| 67 | |
| 68 | log_filename = os.path.abspath(time.strftime(log_filename_format)) |
| 69 | log_dir = os.path.dirname(log_filename) |
| 70 | if not os.path.isdir(log_dir): |
| 71 | os.makedirs(log_dir) |
| 72 | return log_filename |
| 73 | |
| 74 | |
| 75 | def set_up_logging(log_filename_format=None, use_log_server=False): |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 76 | """ |
| 77 | Correctly set up logging to have the correct format/level, log to a file, |
| 78 | and send out email notifications in case of error level messages. |
Simran Basi | 4e3d118 | 2013-06-25 16:12:30 -0700 | [diff] [blame] | 79 | |
| 80 | @param log_filename_format: Format to use to create the log file. |
Dan Shi | 1a34c36 | 2014-04-11 16:37:04 -0700 | [diff] [blame^] | 81 | @param use_log_server: True if log to a TCP server. |
Simran Basi | 4e3d118 | 2013-06-25 16:12:30 -0700 | [diff] [blame] | 82 | |
| 83 | @returns email_handler: Logging handler used to send out email alerts. |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 84 | """ |
Dan Shi | 1a34c36 | 2014-04-11 16:37:04 -0700 | [diff] [blame^] | 85 | if use_log_server: |
| 86 | socketHandler = logging.handlers.SocketHandler( |
| 87 | 'localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT) |
| 88 | logging.getLogger().addHandler(socketHandler) |
| 89 | else: |
| 90 | log_filename = get_log_filename(log_filename_format) |
| 91 | logging.basicConfig(filename=log_filename, level=logging.INFO, |
| 92 | format=LOGGING_FORMAT) |
| 93 | |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 94 | if rpm_config.getboolean('GENERAL', 'debug'): |
| 95 | logging.getLogger().setLevel(logging.DEBUG) |
Dan Shi | 1a34c36 | 2014-04-11 16:37:04 -0700 | [diff] [blame^] | 96 | |
Simran Basi | 4e3d118 | 2013-06-25 16:12:30 -0700 | [diff] [blame] | 97 | email_handler = SuspendableSMTPHandler('localhost', 'rpm@google.com', |
| 98 | RECEIVERS, SUBJECT_LINE, None) |
Simran Basi | 7498d20 | 2012-07-10 15:21:28 -0700 | [diff] [blame] | 99 | email_handler.setLevel(logging.ERROR) |
| 100 | email_handler.setFormatter(logging.Formatter(LOGGING_FORMAT)) |
Scott Zawalski | 201d6be | 2012-09-21 15:56:25 -0400 | [diff] [blame] | 101 | logging.getLogger('').addHandler(email_handler) |
Dan Shi | 1a34c36 | 2014-04-11 16:37:04 -0700 | [diff] [blame^] | 102 | return email_handler |
| 103 | |
| 104 | |
| 105 | def start_log_server(log_filename_format): |
| 106 | """Start log server to accept logging through a TCP server. |
| 107 | |
| 108 | @param log_filename_format: Format to use to create the log file. |
| 109 | """ |
| 110 | log_filename = get_log_filename(log_filename_format) |
| 111 | log_socket_server.LogSocketServer.start(filename=log_filename, |
| 112 | level=logging.INFO, |
| 113 | format=LOGGING_FORMAT) |