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):
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.
28 # Since one of our handlers always wants debug, set the global level to debug.
29 logging.getLogger().setLevel(logging.DEBUG)
30 stderr_handler = logging.StreamHandler()
31 stderr_handler.setFormatter(
32 logging.Formatter(fmt='%(levelname)s: %(message)s'))
36 stderr_handler.setLevel(logging.DEBUG)
38 stderr_handler.setLevel(logging.INFO)
39 logging.getLogger().addHandler(stderr_handler)
43 file_handler = logging.StreamHandler(file_handle)
44 file_handler.setLevel(logging.DEBUG)
45 file_handler.setFormatter(
46 logging.Formatter(fmt='%(levelname)s: %(message)s'))
47 logging.getLogger().addHandler(file_handler)
53 sys.stdout.write(text)
58 def CheckCall(command, stdout=None, **kwargs):
59 """Modulate command output level based on logging level.
61 If a logging file handle is set, always emit all output to it.
62 If the log level is set at debug or lower, also emit all output to stdout.
63 Otherwise, only emit output on error.
65 command: Command to run.
66 stdout (optional): File name to redirect stdout to.
67 **kwargs: Keyword args.
69 cwd = os.path.abspath(kwargs.get('cwd', os.getcwd()))
70 logging.info('Running: subprocess.check_call(%r, cwd=%r)' % (command, cwd))
73 # Interleave stdout and stderr together and log that.
74 p = subprocess.Popen(command,
75 stdout=subprocess.PIPE,
76 stderr=subprocess.STDOUT,
80 p = subprocess.Popen(command,
81 stdout=open(stdout, 'w'),
82 stderr=subprocess.PIPE,
86 # Capture the output as it comes and emit it immediately.
87 line = output.readline()
90 line = output.readline()
93 raise subprocess.CalledProcessError(cmd=command, returncode=p.returncode)
95 # Flush stdout so it does not get interleaved with future log or buildbot
96 # output which goes to stderr.
100 def CheckOutput(command, **kwargs):
101 """Capture stdout from a command, while logging its stderr.
103 This is essentially subprocess.check_output, but stderr is
104 handled the same way as in log_tools.CheckCall.
106 command: Command to run.
107 **kwargs: Keyword args.
109 cwd = os.path.abspath(kwargs.get('cwd', os.getcwd()))
110 logging.info('Running: subprocess.check_output(%r, cwd=%r)' % (command, cwd))
112 p = subprocess.Popen(command,
113 stdout=subprocess.PIPE,
114 stderr=subprocess.PIPE,
117 # Assume the output will not be huge or take a long time to come, so it
118 # is viable to just consume it all synchronously before logging anything.
119 # TODO(mcgrathr): Shovel stderr bits asynchronously if that ever seems
121 stdout_text, stderr_text = p.communicate()
123 WriteToLog(stderr_text)
126 raise subprocess.CalledProcessError(cmd=command, returncode=p.returncode)
128 # Flush stdout so it does not get interleaved with future log or buildbot
129 # output which goes to stderr.
132 logging.info('Result: %r' % stdout_text)