ソースを参照

Port profilers

Casper van der Wel 1 年間 前
コミット
774242a5bb

+ 2 - 0
CHANGES.md

@@ -8,6 +8,8 @@
 
 - Added optional `api_client` subpackage (based on `urllib3`).
 
+- Added `fastapi_profiler` and renamed existing `profiler` to `dramatiq_profiler`.
+
 
 0.5.1 (2023-09-25)
 ------------------

+ 0 - 0
clean_python/testing/profilers.py → clean_python/testing/dramatiq_profiler.py


+ 37 - 0
clean_python/testing/fastapi_profiler.py

@@ -0,0 +1,37 @@
+import re
+from pathlib import Path
+
+import yappi
+from starlette.types import ASGIApp
+from starlette.types import Receive
+from starlette.types import Scope
+from starlette.types import Send
+
+from clean_python import now
+
+
+class ProfilerMiddleware:
+    def __init__(
+        self,
+        app: ASGIApp,
+        *,
+        profile_dir: Path,
+        path: str = ".*",
+    ):
+        self.app = app
+        profile_dir.mkdir(exist_ok=True)
+        self.profile_dir = profile_dir
+        self.path = re.compile(path)
+
+    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
+        if scope["type"] != "http" or not self.path.match(scope["path"]):
+            await self.app(scope, receive, send)
+            return
+
+        yappi.set_clock_type("wall")
+        received = now()
+        with yappi.run():
+            await self.app(scope, receive, send)
+        stats = yappi.convert2pstats(yappi.get_func_stats())
+        stats.dump_stats(self.profile_dir / f"{received.isoformat()}.pstats")
+        yappi.clear_stats()

+ 2 - 0
pyproject.toml

@@ -29,6 +29,8 @@ fluentbit = ["fluent-logger"]
 sql = ["sqlalchemy==2.*", "asyncpg"]
 s3 = ["aioboto3", "boto3"]
 api_client = ["urllib3"]
+profiler = ["yappi"]
+debugger = ["debugpy"]
 
 [project.urls]
 homepage = "https://github.com/nens/clean-python"