feat(command): improve command logging

This commit is contained in:
2023-03-21 23:08:27 +03:00
parent 265c80f082
commit 34dcb5a991
+41 -16
View File
@@ -1,11 +1,14 @@
__all__ = ( __all__ = (
"CommandError", "CommandError",
"CommandLogger",
"CommandExecutor", "CommandExecutor",
) )
import logging import logging
import os
import subprocess import subprocess
import threading
from pathlib import Path from pathlib import Path
logger = logging.getLogger("command") logger = logging.getLogger("command")
@@ -14,7 +17,31 @@ logger = logging.getLogger("command")
class CommandError(RuntimeError): class CommandError(RuntimeError):
@property @property
def output(self): def output(self):
return self.args[0].decode("utf-8").strip() return self.args[0]
class CommandLogger(threading.Thread):
def __init__(self, level: int):
super().__init__()
self.daemon = False
self.level = level
self.fdRead, self.fdWrite = os.pipe()
self.pipeReader = os.fdopen(self.fdRead)
self.lines = []
self.start()
def fileno(self):
return self.fdWrite
def run(self):
for line in iter(self.pipeReader.readline, ""):
logger.log(self.level, line.strip("\n"))
self.lines.append(line)
self.pipeReader.close()
def close(self):
os.close(self.fdWrite)
class CommandExecutor: class CommandExecutor:
@@ -25,19 +52,17 @@ class CommandExecutor:
def run(self, basepath: Path): def run(self, basepath: Path):
self._logger.debug(self._command) self._logger.debug(self._command)
result = subprocess.run( out_logger = CommandLogger(logging.TRACE)
self._command.split(" "), err_logger = CommandLogger(logging.TRACE)
cwd=basepath, try:
stdout=subprocess.PIPE, result = subprocess.run(
stderr=subprocess.PIPE, self._command.split(" "),
) cwd=basepath,
self._logstd(result.stdout, logging.TRACE) stdout=out_logger,
self._logstd(result.stderr, logging.TRACE) stderr=err_logger,
)
finally:
out_logger.close()
err_logger.close()
if result.returncode != 0: if result.returncode != 0:
raise CommandError(result.stderr) raise CommandError("".join(err_logger.lines or out_logger.lines))
@classmethod
def _logstd(cls, data: bytes, level: int):
if data:
output = data.decode("utf-8").strip()
cls._logger.log(level, f"\n{output}\n")