1 # Copyright 2018 The Chromium 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 5 """Shared logging functions for autotest drone services 6 7 autotest/site_utils/ is home to various upstart jobs and cron jobs that run on 8 autotest drones. All these jobs currently configure logging in different ways. 9 Worse, many of these scripts don't use logging at all, instead print()ing to 10 stdout and use external log file management. 11 12 This library provides a single consistent way to manage log configuration and 13 log directories for these scripts. 14 """ 15 16 from __future__ import absolute_import 17 from __future__ import division 18 from __future__ import print_function 19 20 import logging 21 import logging.config 22 import os 23 24 25 def add_logging_options(parser): 26 """Add logging configuration options to argument parser. 27 28 @param parser: ArgumentParser instance. 29 """ 30 parser.add_argument( 31 '--log-dir', 32 default=None, 33 help='(existing) directory to drop log files in.' 34 ' By default, logs to stderr.', 35 ) 36 37 38 def configure_logging_with_args(parser, args): 39 """Convenience function for calling configure_logging(). 40 41 @param parser: ArgumentParser instance. 42 @param args: Return value from ArgumentParser.parse_args(). 43 """ 44 configure_logging(parser.prog, args.log_dir) 45 46 47 def configure_logging(name, log_dir=None): 48 """Configure logging globally. 49 50 @param name: Name to prepend to log messages. 51 This should be the name of the program. 52 @param log_dir: Path to the (existing) direcotry to create log files in. 53 If None, logs to stderr. 54 """ 55 if log_dir is None: 56 handlers = { 57 'default': { 58 'class': 'logging.StreamHandler', 59 'formatter': 'default' , 60 } 61 } 62 else: 63 handlers = { 64 'default': { 65 'class': 'logging.handlers.TimedRotatingFileHandler', 66 'formatter': 'default' , 67 'filename': os.path.join(log_dir, '%s.log' % name), 68 'when': 'midnight', 69 'backupCount': 14, 70 } 71 } 72 73 74 logging.config.dictConfig({ 75 'version': 1, 76 'handlers': handlers, 77 'formatters': { 78 'default': { 79 'format': ('{name}: ' 80 '%(asctime)s:%(levelname)s' 81 ':%(module)s:%(funcName)s:%(lineno)d' 82 ': %(message)s' 83 .format(name=name)), 84 }, 85 }, 86 'root': { 87 'level': 'INFO', 88 'handlers': ['default'], 89 }, 90 'disable_existing_loggers': False, 91 }) 92