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

Unified Diff: appengine/swarming/swarming_bot/logging_utils.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 side-by-side diff with in-line comments
Download patch
Index: appengine/swarming/swarming_bot/logging_utils.py
diff --git a/appengine/swarming/swarming_bot/logging_utils.py b/appengine/swarming/swarming_bot/logging_utils.py
deleted file mode 100644
index efddb9c99c8da8360341115449ff09bc87aa0568..0000000000000000000000000000000000000000
--- a/appengine/swarming/swarming_bot/logging_utils.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# Copyright 2014 The Swarming Authors. All rights reserved.
-# Use of this source code is governed by the Apache v2.0 license that can be
-# found in the LICENSE file.
-
-"""Utility relating to logging.
-
-TODO(maruel): Merge buffering and output related code from client/utils/tools.py
-in a single file.
-"""
-
-import codecs
-import logging
-import logging.handlers
-import os
-import sys
-import tempfile
-import time
-
-
-# This works around file locking issue on Windows specifically in the case of
-# long lived child processes.
-#
-# Python opens files with inheritable handle and without file sharing by
-# default. This causes the RotatingFileHandler file handle to be duplicated in
-# the subprocesses even if the log file is not used in it. Because of this
-# handle in the child process, when the RotatingFileHandler tries to os.rename()
-# the file in the parent process, it fails with:
-# WindowsError: [Error 32] The process cannot access the file because
-# it is being used by another process
-if sys.platform == 'win32':
- import msvcrt # pylint: disable=F0401
- import _subprocess # pylint: disable=F0401
-
- # TODO(maruel): Make it work in cygwin too if necessary. This would have to
- # use ctypes.cdll.kernel32 instead of _subprocess and msvcrt.
-
- def _duplicate(handle):
- target_process = _subprocess.GetCurrentProcess()
- return _subprocess.DuplicateHandle(
- _subprocess.GetCurrentProcess(), handle, target_process,
- 0, False, _subprocess.DUPLICATE_SAME_ACCESS).Detach()
-
-
- class NoInheritRotatingFileHandler(logging.handlers.RotatingFileHandler):
- def _open(self):
- """Opens the current file without handle inheritance."""
- if self.encoding is None:
- with open(self.baseFilename, self.mode) as stream:
- newosf = _duplicate(msvcrt.get_osfhandle(stream.fileno()))
- new_fd = msvcrt.open_osfhandle(newosf, os.O_APPEND)
- return os.fdopen(new_fd, self.mode)
- return codecs.open(self.baseFilename, self.mode, self.encoding)
-
-
-else: # Not Windows.
-
-
- NoInheritRotatingFileHandler = logging.handlers.RotatingFileHandler
-
-
-class CaptureLogs(object):
- """Captures all the logs in a context."""
- def __init__(self, prefix, root=None):
- handle, self._path = tempfile.mkstemp(prefix=prefix, suffix='.log')
- os.close(handle)
- self._handler = logging.FileHandler(self._path, 'w')
- self._handler.setLevel(logging.DEBUG)
- formatter = UTCFormatter(
- '%(process)d %(asctime)s: %(levelname)-5s %(message)s')
- self._handler.setFormatter(formatter)
- self._root = root or logging.getLogger()
- self._root.addHandler(self._handler)
- assert self._root.isEnabledFor(logging.DEBUG)
-
- def read(self):
- """Returns the current content of the logs.
-
- This also closes the log capture so future logs will not be captured.
- """
- self._disconnect()
- assert self._path
- try:
- with open(self._path, 'rb') as f:
- return f.read()
- except IOError as e:
- return 'Failed to read %s: %s' % (self._path, e)
-
- def close(self):
- """Closes and delete the log."""
- self._disconnect()
- if self._path:
- try:
- os.remove(self._path)
- except OSError as e:
- logging.error('Failed to delete log file %s: %s', self._path, e)
- self._path = None
-
- def __enter__(self):
- return self
-
- def __exit__(self, _exc_type, _exc_value, _traceback):
- self.close()
-
- def _disconnect(self):
- if self._handler:
- self._root.removeHandler(self._handler)
- self._handler.close()
- self._handler = None
-
-
-class UTCFormatter(logging.Formatter):
- converter = time.gmtime
-
- def formatTime(self, record, datefmt=None):
- """Change is ',' to '.'."""
- ct = self.converter(record.created)
- if datefmt:
- return time.strftime(datefmt, ct)
- else:
- t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
- return "%s.%03d" % (t, record.msecs)
-
-
-def find_stderr(root=None):
- """Returns the logging.handler streaming to stderr, if any."""
- for log in (root or logging.getLogger()).handlers:
- if getattr(log, 'stream', None) is sys.stderr:
- return log
-
-
-def prepare_logging(filename, root=None):
- """Prepare logging for scripts.
-
- Makes it log in UTC all the time. Prepare a rotating file based log.
- """
- assert not find_stderr(root)
- formatter = UTCFormatter(
- '%(process)d %(asctime)s: %(levelname)-5s %(message)s')
-
- # It is a requirement that the root logger is set to DEBUG, so the messages
- # are not lost. It defaults to WARNING otherwise.
- logger = root or logging.getLogger()
- logger.setLevel(logging.DEBUG)
-
- stderr = logging.StreamHandler()
- stderr.setFormatter(formatter)
- # Default to ERROR.
- stderr.setLevel(logging.ERROR)
- logger.addHandler(stderr)
-
- # Setup up logging to a constant file so we can debug issues where
- # the results aren't properly sent to the result URL.
- if filename:
- try:
- rotating_file = NoInheritRotatingFileHandler(
- filename, maxBytes=10 * 1024 * 1024, backupCount=5)
- rotating_file.setLevel(logging.DEBUG)
- rotating_file.setFormatter(formatter)
- logger.addHandler(rotating_file)
- except Exception:
- # May happen on cygwin. Do not crash.
- logging.exception('Failed to open %s', filename)
-
-
-def set_console_level(level, root=None):
- """Reset the console (stderr) logging level."""
- handler = find_stderr(root)
- handler.setLevel(level)

Powered by Google App Engine
This is Rietveld 408576698