git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[StGIT PATCH 4/4] Add optional logging of subprocess execution

From
Karl Hasselström <kha@treskal.com>
Date
Aug 26, 2007, 20:33 UTC
Message-ID
<20070826203344.16265.66280.stgit@yoghurt>
In-Reply-To
<20070826202724.16265.85821.stgit@yoghurt>

Now that the subprocess calling has been refactored and is in a nice shape, it's quite simple to add some logging facilities. This patch adds two separate log modes, switched by the STG_SUBPROCESS_LOG environment variable:

  * Setting it to "debug" prints the executable name and all
    arguments, and the subprocess return value.
  * Setting it to "profile" prints just the executable name, and the
    (wallclock) time elapsed during the call.
  * Not setting it will disable logging, of course.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
 stgit/run.py |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/stgit/run.py b/stgit/run.py
index 1bc4759..719ecb7 100644
--- a/stgit/run.py
+++ b/stgit/run.py
@@ -22,11 +22,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 # to stay Python 2.3 compatible.
 import popen2, os
 
+import datetime
+
+from  stgit.out import *
+
 class RunException(Exception):
     """Thrown when something bad happened when we tried to run the
     subprocess."""
     pass
 
+_all_log_modes = ['debug', 'profile']
+_log_mode = os.environ.get('STG_SUBPROCESS_LOG', '')
+if _log_mode and not _log_mode in _all_log_modes:
+    out.warn(('Unknown log mode "%s" specified in $STG_SUBPROCESS_LOG.'
+              % _log_mode),
+             'Valid values are: %s' % ', '.join(_all_log_modes))
+
 class Run:
     exc = RunException
     def __init__(self, *cmd):
@@ -37,6 +48,18 @@ class Run:
         self.__good_retvals = [0]
         self.__env = None
         self.__indata = None
+    def __log_start(self, cmd):
+        if _log_mode == 'debug':
+            out.start('Running subprocess %s' % cmd)
+        elif _log_mode == 'profile':
+            out.start('Running subprocess %s' % cmd[0])
+            self.__starttime = datetime.datetime.now()
+    def __log_end(self, retcode):
+        if _log_mode == 'debug':
+            out.done('return code: %d' % retcode)
+        elif _log_mode == 'profile':
+            duration = datetime.datetime.now() - self.__starttime
+            out.done('%1.3f s' % (duration.microseconds/1e6 + duration.seconds))
     def __run_io(self, cmd):
         """Run with captured IO. Note: arguments are parsed by the
         shell. We single-quote them, so don't use anything with single
@@ -47,6 +70,7 @@ class Run:
             ecmd = (['env'] + ['%s=%s' % (key, val)
                                for key, val in self.__env.iteritems()]
                     + cmd)
+        self.__log_start(ecmd)
         p = popen2.Popen3(' '.join(["'%s'" % c for c in ecmd]), True)
         if self.__indata != None:
             p.tochild.write(self.__indata)
@@ -54,6 +78,7 @@ class Run:
         outdata = p.fromchild.read()
         errdata = p.childerr.read()
         self.exitcode = p.wait() >> 8
+        self.__log_end(self.exitcode)
         if errdata or self.exitcode not in self.__good_retvals:
             raise self.exc('%s failed with code %d:\n%s'
                            % (cmd[0], self.exitcode, errdata))
@@ -63,7 +88,9 @@ class Run:
         the shell."""
         assert self.__env == None
         assert self.__indata == None
+        self.__log_start(cmd)
         self.exitcode = os.spawnvp(os.P_WAIT, cmd[0], cmd)
+        self.__log_end(self.exitcode)
         if not self.exitcode in self.__good_retvals:
             raise self.exc('%s failed with code %d'
                            % (cmd[0], self.exitcode))
Previous: Karl HasselströmNext: Catalin Marinas
Message 5 of 14 in “Clean up subprocess calling”
  1. 0/4 Clean up subprocess callingKarl Hasselström, Aug 26, 2007
  2. 1/4 Refactor output handling to break circular dependencyKarl Hasselström, Aug 26, 2007
  3. 2/4 Refactor subprocess creationKarl Hasselström, Aug 26, 2007
  4. 3/4 Assert that the argument to Run is a sequence of stringsKarl Hasselström, Aug 26, 2007
  5. 4/4 Add optional logging of subprocess executionKarl Hasselström, Aug 26, 2007
  6. Catalin MarinasAug 29, 2007
  7. Karl HasselströmAug 29, 2007
  8. Karl HasselströmAug 29, 2007
  9. Catalin MarinasSep 3, 2007
  10. Catalin MarinasSep 3, 2007
  11. Karl HasselströmSep 3, 2007
  12. 0/2 Break Python 2.3 compatibilityKarl Hasselström, Sep 3, 2007
  13. 1/2 Use subprocess.Popen to call git executablesKarl Hasselström, Sep 3, 2007
  14. 2/2 Use the builtin set() instead of sets.Set()Karl Hasselström, Sep 3, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.