xref: /aosp_15_r20/external/autotest/site_utils/loglib.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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