Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: client/utils/tools.py

Issue 1233303003: Migrate and merge logging_utils from swarming_bot into client/utils. (Closed) Base URL: git@github.com:luci/luci-py.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2013 The Swarming Authors. All rights reserved. 1 # Copyright 2013 The Swarming Authors. All rights reserved.
2 # Use of this source code is governed under the Apache License, Version 2.0 that 2 # Use of this source code is governed under the Apache License, Version 2.0 that
3 # can be found in the LICENSE file. 3 # can be found in the LICENSE file.
4 4
5 """Various utility functions and classes not specific to any single area.""" 5 """Various utility functions and classes not specific to any single area."""
6 6
7 import argparse
8 import atexit 7 import atexit
9 import cStringIO 8 import cStringIO
10 import functools 9 import functools
11 import json 10 import json
12 import logging 11 import logging
13 import logging.handlers
14 import optparse
15 import os 12 import os
16 import re 13 import re
17 import sys 14 import sys
18 import threading 15 import threading
19 import time 16 import time
20 17
21 import utils 18 import utils
22 from utils import zip_package 19 from utils import zip_package
23 20
24 21
25 # Path to (possibly extracted from zip) cacert.pem bundle file. 22 # Path to (possibly extracted from zip) cacert.pem bundle file.
26 # See get_cacerts_bundle(). 23 # See get_cacerts_bundle().
27 _ca_certs = None 24 _ca_certs = None
28 _ca_certs_lock = threading.Lock() 25 _ca_certs_lock = threading.Lock()
29 26
30 27
31 # @cached decorators registered by report_cache_stats_at_exit. 28 # @cached decorators registered by report_cache_stats_at_exit.
32 _caches = [] 29 _caches = []
33 _caches_lock = threading.Lock() 30 _caches_lock = threading.Lock()
34 31
35 32
36 class OptionParserWithLogging(optparse.OptionParser):
37 """Adds --verbose option."""
38
39 # Set to True to enable --log-file options.
40 enable_log_file = True
41
42 def __init__(self, verbose=0, log_file=None, **kwargs):
43 kwargs.setdefault('description', sys.modules['__main__'].__doc__)
44 optparse.OptionParser.__init__(self, **kwargs)
45 self.group_logging = optparse.OptionGroup(self, 'Logging')
46 self.group_logging.add_option(
47 '-v', '--verbose',
48 action='count',
49 default=verbose,
50 help='Use multiple times to increase verbosity')
51 if self.enable_log_file:
52 self.group_logging.add_option(
53 '-l', '--log-file',
54 default=log_file,
55 help='The name of the file to store rotating log details')
56 self.group_logging.add_option(
57 '--no-log', action='store_const', const='', dest='log_file',
58 help='Disable log file')
59
60 def parse_args(self, *args, **kwargs):
61 # Make sure this group is always the last one.
62 self.add_option_group(self.group_logging)
63
64 options, args = optparse.OptionParser.parse_args(self, *args, **kwargs)
65 levels = [logging.ERROR, logging.INFO, logging.DEBUG]
66 level = levels[min(len(levels) - 1, options.verbose)]
67
68 logging_console = logging.StreamHandler()
69 logging_console.setFormatter(logging.Formatter(
70 '%(levelname)5s %(relativeCreated)6d %(module)15s(%(lineno)3d): '
71 '%(message)s'))
72 logging_console.setLevel(level)
73 logging.getLogger().setLevel(level)
74 logging.getLogger().addHandler(logging_console)
75
76 if self.enable_log_file and options.log_file:
77 # This is necessary otherwise attached handler will miss the messages.
78 logging.getLogger().setLevel(logging.DEBUG)
79
80 logging_rotating_file = logging.handlers.RotatingFileHandler(
81 options.log_file,
82 maxBytes=10 * 1024 * 1024,
83 backupCount=5,
84 encoding='utf-8')
85 # log files are always at DEBUG level.
86 logging_rotating_file.setLevel(logging.DEBUG)
87 logging_rotating_file.setFormatter(logging.Formatter(
88 '%(asctime)s %(levelname)-8s %(module)15s(%(lineno)3d): %(message)s'))
89 logging.getLogger().addHandler(logging_rotating_file)
90
91 return options, args
92
93
94 class ArgumentParserWithLogging(argparse.ArgumentParser):
95 """Adds --verbose option."""
96
97 # Set to True to enable --log-file options.
98 enable_log_file = True
99
100 def __init__(self, verbose=0, log_file=None, **kwargs):
101 kwargs.setdefault('description', sys.modules['__main__'].__doc__)
102 kwargs.setdefault('conflict_handler', 'resolve')
103 self.__verbose = verbose
104 self.__log_file = log_file
105 super(ArgumentParserWithLogging, self).__init__(**kwargs)
106
107 def _add_logging_group(self):
108 group = self.add_argument_group('Logging')
109 group.add_argument(
110 '-v', '--verbose',
111 action='count',
112 default=self.__verbose,
113 help='Use multiple times to increase verbosity')
114 if self.enable_log_file:
115 group.add_argument(
116 '-l', '--log-file',
117 default=self.__log_file,
118 help='The name of the file to store rotating log details')
119 group.add_argument(
120 '--no-log', action='store_const', const='', dest='log_file',
121 help='Disable log file')
122
123 def parse_args(self, *args, **kwargs):
124 # Make sure this group is always the last one.
125 self._add_logging_group()
126
127 args = super(ArgumentParserWithLogging, self).parse_args(*args, **kwargs)
128 levels = [logging.ERROR, logging.INFO, logging.DEBUG]
129 level = levels[min(len(levels) - 1, args.verbose)]
130
131 logging_console = logging.StreamHandler()
132 logging_console.setFormatter(logging.Formatter(
133 '%(levelname)5s %(relativeCreated)6d %(module)15s(%(lineno)3d): '
134 '%(message)s'))
135 logging_console.setLevel(level)
136 logging.getLogger().setLevel(level)
137 logging.getLogger().addHandler(logging_console)
138
139 if self.enable_log_file and args.log_file:
140 # This is necessary otherwise attached handler will miss the messages.
141 logging.getLogger().setLevel(logging.DEBUG)
142
143 logging_rotating_file = logging.handlers.RotatingFileHandler(
144 args.log_file,
145 maxBytes=10 * 1024 * 1024,
146 backupCount=5,
147 encoding='utf-8')
148 # log files are always at DEBUG level.
149 logging_rotating_file.setLevel(logging.DEBUG)
150 logging_rotating_file.setFormatter(logging.Formatter(
151 '%(asctime)s %(levelname)-8s %(module)15s(%(lineno)3d): %(message)s'))
152 logging.getLogger().addHandler(logging_rotating_file)
153
154 return args
155
156
157 class Profiler(object): 33 class Profiler(object):
158 """Context manager that records time spend inside its body.""" 34 """Context manager that records time spend inside its body."""
159 def __init__(self, name): 35 def __init__(self, name):
160 self.name = name 36 self.name = name
161 self.start_time = None 37 self.start_time = None
162 38
163 def __enter__(self): 39 def __enter__(self):
164 self.start_time = time.time() 40 self.start_time = time.time()
165 return self 41 return self
166 42
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 a zip archive, we need to extract the file first. 309 a zip archive, we need to extract the file first.
434 """ 310 """
435 global _ca_certs 311 global _ca_certs
436 with _ca_certs_lock: 312 with _ca_certs_lock:
437 if _ca_certs is not None and os.path.exists(_ca_certs): 313 if _ca_certs is not None and os.path.exists(_ca_certs):
438 return _ca_certs 314 return _ca_certs
439 # Some rogue process clears /tmp and causes cacert.pem to disappear. Extract 315 # Some rogue process clears /tmp and causes cacert.pem to disappear. Extract
440 # to current directory instead. We use our own bundled copy of cacert.pem. 316 # to current directory instead. We use our own bundled copy of cacert.pem.
441 _ca_certs = zip_package.extract_resource(utils, 'cacert.pem', temp_dir='.') 317 _ca_certs = zip_package.extract_resource(utils, 'cacert.pem', temp_dir='.')
442 return _ca_certs 318 return _ca_certs
OLDNEW
« client/utils/logging_utils.py ('K') | « client/utils/logging_utils_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698