2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Logging related tools."""
13 # Module-level configuration
17 def SetupLogging(verbose, file_handle=None, quiet=False):
18 """Set up python logging.
21 verbose: If True, log to stderr at DEBUG level and write subprocess output
22 to stdout. Otherwise log to stderr at INFO level and do not print
23 subprocess output unless there is an error.
24 file_handle: If not None, must be a file-like object. All log output will
25 be written at DEBUG level, and all subprocess output will be
26 written, regardless of whether there are errors.
27 quiet: If True, log to stderr at WARNING level only. Only valid if verbose
30 # Since one of our handlers always wants debug, set the global level to debug.
31 logging.getLogger().setLevel(logging.DEBUG)
32 stderr_handler = logging.StreamHandler()
33 stderr_handler.setFormatter(
34 logging.Formatter(fmt='%(levelname)s: %(message)s'))
38 stderr_handler.setLevel(logging.DEBUG)
40 stderr_handler.setLevel(logging.WARN)
42 stderr_handler.setLevel(logging.INFO)
43 logging.getLogger().addHandler(stderr_handler)
47 file_handler = logging.StreamHandler(file_handle)
48 file_handler.setLevel(logging.DEBUG)
49 file_handler.setFormatter(
50 logging.Formatter(fmt='%(levelname)s: %(message)s'))
51 logging.getLogger().addHandler(file_handler)
57 sys.stdout.write(text)
62 def CheckCall(command, stdout=None, **kwargs):
63 """Modulate command output level based on logging level.
65 If a logging file handle is set, always emit all output to it.
66 If the log level is set at debug or lower, also emit all output to stdout.
67 Otherwise, only emit output on error.
69 command: Command to run.
70 stdout (optional): File name to redirect stdout to.
71 **kwargs: Keyword args.
73 cwd = os.path.abspath(kwargs.get('cwd', os.getcwd()))
74 logging.info('Running: subprocess.check_call(%r, cwd=%r)' % (command, cwd))
77 # Interleave stdout and stderr together and log that.
78 p = subprocess.Popen(command,
79 stdout=subprocess.PIPE,
80 stderr=subprocess.STDOUT,
84 p = subprocess.Popen(command,
85 stdout=open(stdout, 'w'),
86 stderr=subprocess.PIPE,
90 # Capture the output as it comes and emit it immediately.
91 line = output.readline()
94 line = output.readline()
97 raise subprocess.CalledProcessError(cmd=command, returncode=p.returncode)
99 # Flush stdout so it does not get interleaved with future log or buildbot
100 # output which goes to stderr.
104 def CheckOutput(command, **kwargs):
105 """Capture stdout from a command, while logging its stderr.
107 This is essentially subprocess.check_output, but stderr is
108 handled the same way as in log_tools.CheckCall.
110 command: Command to run.
111 **kwargs: Keyword args.
113 cwd = os.path.abspath(kwargs.get('cwd', os.getcwd()))
114 logging.info('Running: subprocess.check_output(%r, cwd=%r)' % (command, cwd))
116 p = subprocess.Popen(command,
117 stdout=subprocess.PIPE,
118 stderr=subprocess.PIPE,
121 # Assume the output will not be huge or take a long time to come, so it
122 # is viable to just consume it all synchronously before logging anything.
123 # TODO(mcgrathr): Shovel stderr bits asynchronously if that ever seems
125 stdout_text, stderr_text = p.communicate()
127 WriteToLog(stderr_text)
130 raise subprocess.CalledProcessError(cmd=command, returncode=p.returncode)
132 # Flush stdout so it does not get interleaved with future log or buildbot
133 # output which goes to stderr.
136 logging.info('Result: %r' % stdout_text)