diff --git a/dist/zhurnal-0.2.0-py3-none-any.whl b/dist/zhurnal-0.2.0-py3-none-any.whl new file mode 100644 index 0000000..d495dd6 Binary files /dev/null and b/dist/zhurnal-0.2.0-py3-none-any.whl differ diff --git a/dist/zhurnal-0.2.0.tar.gz b/dist/zhurnal-0.2.0.tar.gz new file mode 100644 index 0000000..c6c9b72 Binary files /dev/null and b/dist/zhurnal-0.2.0.tar.gz differ diff --git a/src/zhurnal.egg-info/PKG-INFO b/src/zhurnal.egg-info/PKG-INFO index 14c61d2..8a6522d 100644 --- a/src/zhurnal.egg-info/PKG-INFO +++ b/src/zhurnal.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: zhurnal -Version: 0.1.0 +Version: 0.2.0 Summary: Process monitoring and management web application Author: retoor Author-email: retoor@molodetz.nl @@ -8,7 +8,7 @@ Requires-Python: >=3.8 Description-Content-Type: text/markdown Requires-Dist: aiohttp Requires-Dist: setuptools -Requires-Dist: app@ git+https://retoor.molodetz.nl/retoor/app.git +Requires-Dist: app @ git+https://retoor.molodetz.nl/retoor/app.git # Zhurnal: Real-Time Process Monitoring Web Interface 🚀 diff --git a/src/zhurnal.egg-info/requires.txt b/src/zhurnal.egg-info/requires.txt index 95a12c3..b326dce 100644 --- a/src/zhurnal.egg-info/requires.txt +++ b/src/zhurnal.egg-info/requires.txt @@ -1,3 +1,3 @@ aiohttp setuptools -app@ git+https://retoor.molodetz.nl/retoor/app.git +app @ git+https://retoor.molodetz.nl/retoor/app.git diff --git a/src/zhurnal/app.py b/src/zhurnal/app.py index 8e4f65b..b418b85 100644 --- a/src/zhurnal/app.py +++ b/src/zhurnal/app.py @@ -209,15 +209,15 @@ class Zhurnal(BaseApplication): self.process_tasks = {} self.shutdown_event = asyncio.Event() super().__init__(*args, **kwargs) - + # Register signal handlers for graceful shutdown loop = asyncio.get_event_loop() for sig in (signal.SIGINT, signal.SIGTERM): loop.add_signal_handler(sig, self.handle_exit) - + self.on_startup.append(self.start_processes) self.on_cleanup.append(self.cleanup_processes) - + self.clients = [] self.router.add_get("/ws", self.websocket_handler) self.router.add_get("/", self.index_handler) @@ -231,12 +231,12 @@ class Zhurnal(BaseApplication): async def cleanup_processes(self, app): """Cleanup all running subprocesses.""" log.info("Cleaning up processes...") - + # Terminate all running processes for command, process_info in list(self.processes.items()): try: # Get the subprocess - process = process_info.get('process') + process = process_info.get("process") if process and process.returncode is None: log.info(f"Terminating process: {command}") try: @@ -250,7 +250,7 @@ class Zhurnal(BaseApplication): process.kill() except Exception as e: log.error(f"Error cleaning up process {command}: {e}") - + # Cancel any running tasks for task in list(self.process_tasks.values()): if not task.done(): @@ -297,13 +297,10 @@ class Zhurnal(BaseApplication): stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) - + # Store process information - self.processes[command] = { - 'process': process, - 'name': process_name - } - + self.processes[command] = {"process": process, "name": process_name} + log.info(f"Running process {process_name}: {command}") async def read_output(app, name, process, f, is_stderr=False): @@ -313,15 +310,17 @@ class Zhurnal(BaseApplication): # Check if shutdown is requested if self.shutdown_event.is_set(): break - + time_current = time.time() time_elapsed = round( time_previous and time_current - time_previous or 0, 4 ) decoded_line = line.decode("utf-8", "ignore").strip() print(decoded_line) - decoded_line = "".join(c for c in decoded_line if c.isprintable()) - + decoded_line = "".join( + c for c in decoded_line if c.isprintable() + ) + # Broadcast to all WebSocket clients for client in app.clients: await client.send_str( @@ -346,7 +345,13 @@ class Zhurnal(BaseApplication): # Read stdout and stderr concurrently await asyncio.gather( read_output(self, f"{process_name}:stdout", process, process.stdout), - read_output(self, f"{process_name}:stderr", process, process.stderr, is_stderr=True) + read_output( + self, + f"{process_name}:stderr", + process, + process.stderr, + is_stderr=True, + ), ) # Wait for process to complete @@ -361,7 +366,7 @@ class Zhurnal(BaseApplication): log.error( f"Process {process_name}:{command} exited with non-zero status {process.returncode}." ) - + except Exception as e: log.error(f"Error running process {process_name}: {e}") finally: @@ -422,5 +427,6 @@ def cli(): app.run(host=args.host, port=args.port) + if __name__ == "__main__": cli()