vedro-profiling 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: vedro-profiling
3
+ Version: 0.0.1
4
+ Summary: Vedro plugin for measuring docker resource usage.
5
+ Home-page: https://github.com/lolimpo/vedro-profiling
6
+ Author: Nikita Mikheev
7
+ Author-email: thelol1mpo@gmail.com
8
+ License: Apache-2.0
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Typing :: Typed
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: vedro<2.0.0,>=1.13.0
18
+ Requires-Dist: docker<8.0.0,>=7.0.0
19
+ Requires-Dist: matplotlib<4.0.0,>=3.10.0
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: license
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
30
+
31
+ # Vedro profiling
32
+
33
+ Vedro plugin for measuring docker resource usage of tests.
@@ -0,0 +1,3 @@
1
+ # Vedro profiling
2
+
3
+ Vedro plugin for measuring docker resource usage of tests.
@@ -0,0 +1,18 @@
1
+ [flake8]
2
+ exclude = venv,__pycache__
3
+ max_line_length = 99
4
+ statistics = true
5
+
6
+ [isort]
7
+ line_length = 99
8
+ multi_line_output = 3
9
+ include_trailing_comma = true
10
+ skip = venv,__pycache__
11
+
12
+ [mypy]
13
+ ignore_missing_imports = false
14
+
15
+ [egg_info]
16
+ tag_build =
17
+ tag_date = 0
18
+
@@ -0,0 +1,39 @@
1
+ from setuptools import find_packages, setup
2
+
3
+ from vedro_profiling import version
4
+
5
+
6
+ def find_required():
7
+ with open("requirements.txt") as f:
8
+ return f.read().splitlines()
9
+
10
+
11
+ def find_dev_required():
12
+ with open("requirements-dev.txt") as f:
13
+ return f.read().splitlines()
14
+
15
+
16
+ setup(
17
+ name="vedro-profiling",
18
+ version=version,
19
+ description="Vedro plugin for measuring docker resource usage.",
20
+ long_description=open("README.md").read(),
21
+ long_description_content_type="text/markdown",
22
+ author="Nikita Mikheev",
23
+ author_email="thelol1mpo@gmail.com",
24
+ python_requires=">=3.10",
25
+ url="https://github.com/lolimpo/vedro-profiling",
26
+ license="Apache-2.0",
27
+ packages=find_packages(exclude=["tests", "tests.*"]),
28
+ package_data={"vedro_profiling": ["py.typed"]},
29
+ install_requires=find_required(),
30
+ tests_require=find_dev_required(),
31
+ classifiers=[
32
+ "License :: OSI Approved :: Apache Software License",
33
+ "Programming Language :: Python :: 3.10",
34
+ "Programming Language :: Python :: 3.11",
35
+ "Programming Language :: Python :: 3.12",
36
+ "Programming Language :: Python :: 3.13",
37
+ "Typing :: Typed"
38
+ ]
39
+ )
@@ -0,0 +1,5 @@
1
+ from ._vedro_profiling import VedroProfiling, VedroProfilingPlugin
2
+
3
+ version = "0.0.1"
4
+
5
+ __all__ = ("VedroProfiling", "VedroProfilingPlugin", "version",)
@@ -0,0 +1,136 @@
1
+ import json
2
+ import threading
3
+ import time
4
+ from collections import defaultdict
5
+ from typing import Any, DefaultDict, Optional, Type
6
+
7
+ import docker
8
+ from matplotlib import pyplot as plt
9
+ from vedro.core import Dispatcher, Plugin, PluginConfig
10
+ from vedro.events import ArgParsedEvent, ArgParseEvent, CleanupEvent, StartupEvent
11
+
12
+
13
+ class VedroProfilingPlugin(Plugin):
14
+ """
15
+ Adds docker profiling support to the Vedro framework.
16
+ """
17
+
18
+ def __init__(self, config: Type["VedroProfiling"]):
19
+ super().__init__(config)
20
+ self._poll_time: float = config.poll_time
21
+ self._enable_profiling: bool = config.enable_profiling
22
+ self._draw_plots: bool = config.draw_plots
23
+ self._stats: DefaultDict[str, Any] = defaultdict(lambda: {"CPU": [], "MEM": []})
24
+
25
+ self._client = docker.from_env()
26
+ self._running: bool = False
27
+ self._thread: Optional[threading.Thread] = None
28
+
29
+ def subscribe(self, dispatcher: Dispatcher) -> None:
30
+ dispatcher.listen(ArgParseEvent, self.on_arg_parse) \
31
+ .listen(ArgParsedEvent, self.on_arg_parsed) \
32
+ .listen(StartupEvent, self.on_startup) \
33
+ .listen(CleanupEvent, self.on_cleanup)
34
+
35
+ def on_arg_parse(self, event: ArgParseEvent) -> None:
36
+ group = event.arg_parser.add_argument_group("VedroProfiling")
37
+ group.add_argument(
38
+ "--enable-profiling",
39
+ action="store_true",
40
+ default=self._enable_profiling,
41
+ help="Enable recording of containers stats during scenario execution"
42
+ )
43
+ group.add_argument(
44
+ "--draw-plots",
45
+ action="store_true",
46
+ default=self._draw_plots,
47
+ help="Draw CPU/MEM plots after test run"
48
+ )
49
+
50
+ def on_arg_parsed(self, event: ArgParsedEvent) -> None:
51
+ self._enable_profiling = event.args.enable_profiling
52
+ self._draw_plots = event.args.draw_plots
53
+
54
+ def _collect_stats(self) -> None:
55
+ containers = self._client.containers.list()
56
+ while self._running:
57
+ for container in containers:
58
+ stats = container.stats(decode=None, stream=False)
59
+
60
+ cpu_delta = (stats["cpu_stats"]["cpu_usage"]["total_usage"] -
61
+ stats["precpu_stats"]["cpu_usage"]["total_usage"])
62
+ system_delta = (stats["cpu_stats"]["system_cpu_usage"] -
63
+ stats["precpu_stats"]["system_cpu_usage"])
64
+
65
+ if system_delta > 0 and stats["cpu_stats"].get("online_cpus"):
66
+ cpu_percent = ((cpu_delta / system_delta) *
67
+ stats["cpu_stats"]["online_cpus"] * 100)
68
+ self._stats[container.name]["CPU"].append(cpu_percent)
69
+
70
+ mem = stats["memory_stats"]["usage"]
71
+ self._stats[container.name]["MEM"].append(mem / 1e6) # in MB
72
+ time.sleep(self._poll_time)
73
+
74
+ def on_startup(self, event: StartupEvent) -> None:
75
+ if not self._enable_profiling:
76
+ return
77
+
78
+ if not self._client.containers.list():
79
+ raise RuntimeError("No running containers found for profiling.")
80
+
81
+ self._running = True
82
+ self._thread = threading.Thread(target=self._collect_stats, daemon=True)
83
+ self._thread.start()
84
+
85
+ def _generate_plots(self) -> None:
86
+ for name, metrics in self._stats.items():
87
+ ticks = list(range(len(metrics["CPU"])))
88
+
89
+ # CPU plot
90
+ plt.figure()
91
+ plt.plot(ticks, metrics["CPU"], label="CPU (%)")
92
+ plt.xlabel("Tick")
93
+ plt.ylabel("CPU Usage (%)")
94
+ plt.title(f"{name} - CPU Usage")
95
+ plt.legend()
96
+ plt.tight_layout()
97
+ plt.savefig(f"{name}_cpu.png")
98
+ plt.close()
99
+
100
+ # Memory plot
101
+ plt.figure()
102
+ plt.plot(ticks, metrics["MEM"], label="Memory (MB)")
103
+ plt.xlabel("Tick")
104
+ plt.ylabel("Memory Usage (MB)")
105
+ plt.title(f"{name} - Memory Usage")
106
+ plt.legend()
107
+ plt.tight_layout()
108
+ plt.savefig(f"{name}_mem.png")
109
+ plt.close()
110
+
111
+ def on_cleanup(self, event: CleanupEvent) -> None:
112
+ if not self._enable_profiling:
113
+ return
114
+
115
+ self._running = False
116
+ if self._thread and self._thread.is_alive():
117
+ self._thread.join()
118
+
119
+ with open("./profiling.log", "w") as profiling_log:
120
+ json.dump(dict(self._stats), profiling_log, indent=2)
121
+
122
+ if self._draw_plots:
123
+ self._generate_plots()
124
+
125
+
126
+ class VedroProfiling(PluginConfig):
127
+ plugin = VedroProfilingPlugin
128
+
129
+ # Enable stats collection
130
+ enable_profiling: bool = False
131
+
132
+ # Enable plots drawing for given profile snapshot
133
+ draw_plots: bool = False
134
+
135
+ # Poll time for stats in seconds
136
+ poll_time: float = 1.0
File without changes
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: vedro-profiling
3
+ Version: 0.0.1
4
+ Summary: Vedro plugin for measuring docker resource usage.
5
+ Home-page: https://github.com/lolimpo/vedro-profiling
6
+ Author: Nikita Mikheev
7
+ Author-email: thelol1mpo@gmail.com
8
+ License: Apache-2.0
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Typing :: Typed
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: vedro<2.0.0,>=1.13.0
18
+ Requires-Dist: docker<8.0.0,>=7.0.0
19
+ Requires-Dist: matplotlib<4.0.0,>=3.10.0
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: description
24
+ Dynamic: description-content-type
25
+ Dynamic: home-page
26
+ Dynamic: license
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
30
+
31
+ # Vedro profiling
32
+
33
+ Vedro plugin for measuring docker resource usage of tests.
@@ -0,0 +1,11 @@
1
+ README.md
2
+ setup.cfg
3
+ setup.py
4
+ vedro_profiling/__init__.py
5
+ vedro_profiling/_vedro_profiling.py
6
+ vedro_profiling/py.typed
7
+ vedro_profiling.egg-info/PKG-INFO
8
+ vedro_profiling.egg-info/SOURCES.txt
9
+ vedro_profiling.egg-info/dependency_links.txt
10
+ vedro_profiling.egg-info/requires.txt
11
+ vedro_profiling.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ vedro<2.0.0,>=1.13.0
2
+ docker<8.0.0,>=7.0.0
3
+ matplotlib<4.0.0,>=3.10.0
@@ -0,0 +1 @@
1
+ vedro_profiling