Skip to content

Commit

Permalink
feat: added plot for cpu and memory in statistics pane
Browse files Browse the repository at this point in the history
  • Loading branch information
pommee committed Aug 26, 2024
1 parent 2c85707 commit 8e21518
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 92 deletions.
6 changes: 1 addition & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
.PHONY: dev format format-fix

dev:
ifeq ($(VIRTUAL_ENV),)
poetry shell
else
textual run --dev application.main:UI
endif
poetry run textual run --dev application.main:UI

format:
ruff format --quiet && ruff check --quiet
Expand Down
12 changes: 10 additions & 2 deletions application/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
ListView,
TabbedContent,
)
from textual_plotext import PlotextPlot
from yaspin import yaspin

from application.docker_manager import DockerManager, NoVisibleContainers
Expand Down Expand Up @@ -348,13 +349,20 @@ def action_environment(self):
environment_log.write(f"{key}: {value}")
self.set_header_statuses()

def action_statistics(self):
async def action_statistics(self):
self.query_one(TabbedContent).active = "statisticspane"
statistics_plot: PlotextPlot = self.query_one("#statistics_plot")

statistics_plot.border_title = self.docker_manager.selected_container.name
self.set_header_statuses()
self._write_statistics_log()

@work
async def _write_statistics_log(self):
statistics_log: LogLines = self.query_one("#statistics_log")
statistics_log.clear()
statistics_log.border_title = self.docker_manager.selected_container.name
statistics_log.write(yaml.dump(self.docker_manager.statistics, indent=2))
self.set_header_statuses()

def action_shell(self):
self.query_one(TabbedContent).active = "shellpane"
Expand Down
10 changes: 10 additions & 0 deletions application/widget/content.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import time
from threading import Event, Thread
from typing import Any

Expand All @@ -17,6 +18,7 @@
from application.docker_manager import DockerManager
from application.widget.log_viewer import LogLines
from application.widget.shell import ShellPane
from application.widget.statistics import Statistics


class ContentWindow(Widget):
Expand Down Expand Up @@ -78,6 +80,8 @@ def compose(self) -> ComposeResult:
environment.scroll_end(animate=False)
yield environment
with TabPane("Statistics", id="statisticspane"):
yield Statistics()

statistics = LogLines(
id="statistics_log",
highlight=True,
Expand Down Expand Up @@ -205,6 +209,7 @@ def live_statistics_task(self):
try:
stats = self._fetch_container_stats()
cpu, memory = self._parse_stats(stats)
self._update_plots_if_visible(cpu, memory)
self._update_logs(cpu, memory)
except Exception:
stop_event.set()
Expand All @@ -227,6 +232,11 @@ def _parse_stats(self, stats: dict[Any, Any]):
# TODO: Correctly handle this case.
return "N/A", "N/A"

def _update_plots_if_visible(self, cpu: str, memory: str):
if self.query_one(TabbedContent).active == "statisticspane":
current_time = time.strftime("%M:%S")
self.query_one(Statistics).update(cpu, memory, current_time)

def _update_logs(self, cpu: str, memory: str):
logs.border_subtitle = f"cpu: {cpu} | ram: {memory} | logs: {len(logs.lines)}"

Expand Down
58 changes: 58 additions & 0 deletions application/widget/statistics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from __future__ import annotations

from textual.reactive import var
from textual_plotext import PlotextPlot


class Statistics(PlotextPlot):
cpu_marker: var[str] = var("braille")
memory_marker: var[str] = var("braille")

def __init__(
self,
*,
name: str | None = None,
classes: str | None = None,
disabled: bool = False,
) -> None:
super().__init__(
name=name, id="statistics_plot", classes=classes, disabled=disabled
)
self._cpu_data: list[float] = []
self._memory_data: list[float] = []
self._time: list[str] = []

def on_mount(self) -> None:
"""Initialize the plot."""
self.plt.date_form("M:S")

def replot(self) -> None:
"""Redraw the plot with updated CPU and memory usage data."""
self.plt.clear_data()
self.plt.plot(
self._time, self._cpu_data, marker=self.cpu_marker, label="CPU (%)"
)
self.plt.plot(
self._time,
self._memory_data,
marker=self.memory_marker,
label="Memory (MB)",
)
self.refresh()

def update(self, cpu_usage: str, memory: str, timestamp: str) -> None:
"""Update the data for the CPU and memory usage plot.
Args:
cpu_usage: The current CPU usage percentage.
memory: The current memory usage in MB.
timestamp: The current time as a string.
"""
self._cpu_data.append(float(cpu_usage.replace("%", "")))
self._memory_data.append(float(memory.replace("MB", "")))
self._time.append(timestamp)
self.replot()

def _watch_marker(self) -> None:
"""React to the marker being changed."""
self.replot()
Loading

0 comments on commit 8e21518

Please sign in to comment.