| OLD | NEW |
| 1 # Copyright 2015 The LUCI Authors. All rights reserved. | 1 # Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed by the Apache v2.0 license that can be | 2 # Use of this source code is governed by the Apache v2.0 license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Utility relating to logging.""" | 5 """Utility relating to logging.""" |
| 6 | 6 |
| 7 import argparse | 7 import argparse |
| 8 import codecs | 8 import codecs |
| 9 import ctypes | 9 import ctypes |
| 10 import logging | 10 import logging |
| 11 import logging.handlers | 11 import logging.handlers |
| 12 import optparse | 12 import optparse |
| 13 import os | 13 import os |
| 14 import sys | 14 import sys |
| 15 import tempfile | 15 import tempfile |
| 16 import time | 16 import time |
| 17 | 17 |
| 18 import file_path |
| 18 | 19 |
| 19 # This works around file locking issue on Windows specifically in the case of | 20 # This works around file locking issue on Windows specifically in the case of |
| 20 # long lived child processes. | 21 # long lived child processes. |
| 21 # | 22 # |
| 22 # Python opens files with inheritable handle and without file sharing by | 23 # Python opens files with inheritable handle and without file sharing by |
| 23 # default. This causes the RotatingFileHandler file handle to be duplicated in | 24 # default. This causes the RotatingFileHandler file handle to be duplicated in |
| 24 # the subprocesses even if the log file is not used in it. Because of this | 25 # the subprocesses even if the log file is not used in it. Because of this |
| 25 # handle in the child process, when the RotatingFileHandler tries to os.rename() | 26 # handle in the child process, when the RotatingFileHandler tries to os.rename() |
| 26 # the file in the parent process, it fails with: | 27 # the file in the parent process, it fails with: |
| 27 # WindowsError: [Error 32] The process cannot access the file because | 28 # WindowsError: [Error 32] The process cannot access the file because |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 stderr = logging.StreamHandler() | 193 stderr = logging.StreamHandler() |
| 193 stderr.setFormatter(formatter) | 194 stderr.setFormatter(formatter) |
| 194 stderr.addFilter(Filter()) | 195 stderr.addFilter(Filter()) |
| 195 # Default to ERROR. | 196 # Default to ERROR. |
| 196 stderr.setLevel(logging.ERROR) | 197 stderr.setLevel(logging.ERROR) |
| 197 logger.addHandler(stderr) | 198 logger.addHandler(stderr) |
| 198 | 199 |
| 199 # Setup up logging to a constant file so we can debug issues where | 200 # Setup up logging to a constant file so we can debug issues where |
| 200 # the results aren't properly sent to the result URL. | 201 # the results aren't properly sent to the result URL. |
| 201 if filename: | 202 if filename: |
| 203 file_path.ensure_tree(os.path.dirname(os.path.abspath(unicode(filename)))) |
| 202 try: | 204 try: |
| 203 rotating_file = NoInheritRotatingFileHandler( | 205 rotating_file = NoInheritRotatingFileHandler( |
| 204 filename, maxBytes=10 * 1024 * 1024, backupCount=5, | 206 filename, maxBytes=10 * 1024 * 1024, backupCount=5, |
| 205 encoding='utf-8') | 207 encoding='utf-8') |
| 206 rotating_file.setLevel(logging.DEBUG) | 208 rotating_file.setLevel(logging.DEBUG) |
| 207 rotating_file.setFormatter(formatter) | 209 rotating_file.setFormatter(formatter) |
| 208 rotating_file.addFilter(Filter()) | 210 rotating_file.addFilter(Filter()) |
| 209 logger.addHandler(rotating_file) | 211 logger.addHandler(rotating_file) |
| 210 except Exception: | 212 except Exception: |
| 211 # May happen on cygwin. Do not crash. | 213 # May happen on cygwin. Do not crash. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 | 293 |
| 292 def parse_args(self, *args, **kwargs): | 294 def parse_args(self, *args, **kwargs): |
| 293 # Make sure this group is always the last one. | 295 # Make sure this group is always the last one. |
| 294 self._add_logging_group() | 296 self._add_logging_group() |
| 295 | 297 |
| 296 args = super(ArgumentParserWithLogging, self).parse_args(*args, **kwargs) | 298 args = super(ArgumentParserWithLogging, self).parse_args(*args, **kwargs) |
| 297 prepare_logging(self.enable_log_file and args.log_file, self.logger_root) | 299 prepare_logging(self.enable_log_file and args.log_file, self.logger_root) |
| 298 set_console_level( | 300 set_console_level( |
| 299 LEVELS[min(len(LEVELS) - 1, args.verbose)], self.logger_root) | 301 LEVELS[min(len(LEVELS) - 1, args.verbose)], self.logger_root) |
| 300 return args | 302 return args |
| OLD | NEW |