fastapi-radar 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl
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.
Potentially problematic release.
This version of fastapi-radar might be problematic. Click here for more details.
- fastapi_radar/api.py +32 -11
- fastapi_radar/capture.py +1 -1
- fastapi_radar/dashboard/dist/assets/index-BG-z4GnL.js +328 -0
- fastapi_radar/dashboard/dist/assets/index-DSKnLYuE.css +1 -0
- fastapi_radar/dashboard/dist/index.html +2 -2
- fastapi_radar/middleware.py +1 -1
- fastapi_radar/radar.py +8 -5
- {fastapi_radar-0.1.0.dist-info → fastapi_radar-0.1.2.dist-info}/METADATA +2 -2
- fastapi_radar-0.1.2.dist-info/RECORD +17 -0
- fastapi_radar/dashboard/dist/assets/index-BK3IXW8U.css +0 -1
- fastapi_radar/dashboard/dist/assets/index-DS-t-RQ1.js +0 -268
- fastapi_radar-0.1.0.dist-info/RECORD +0 -17
- {fastapi_radar-0.1.0.dist-info → fastapi_radar-0.1.2.dist-info}/WHEEL +0 -0
- {fastapi_radar-0.1.0.dist-info → fastapi_radar-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {fastapi_radar-0.1.0.dist-info → fastapi_radar-0.1.2.dist-info}/top_level.txt +0 -0
fastapi_radar/api.py
CHANGED
|
@@ -10,6 +10,13 @@ from pydantic import BaseModel
|
|
|
10
10
|
from .models import CapturedRequest, CapturedQuery, CapturedException
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
def round_float(value: Optional[float], decimals: int = 2) -> Optional[float]:
|
|
14
|
+
"""Round a float value to specified decimal places."""
|
|
15
|
+
if value is None:
|
|
16
|
+
return None
|
|
17
|
+
return round(value, decimals)
|
|
18
|
+
|
|
19
|
+
|
|
13
20
|
class RequestSummary(BaseModel):
|
|
14
21
|
id: int
|
|
15
22
|
request_id: str
|
|
@@ -72,7 +79,7 @@ class DashboardStats(BaseModel):
|
|
|
72
79
|
|
|
73
80
|
|
|
74
81
|
def create_api_router(get_session_context) -> APIRouter:
|
|
75
|
-
router = APIRouter(prefix="/api
|
|
82
|
+
router = APIRouter(prefix="/__radar/api", tags=["radar"])
|
|
76
83
|
|
|
77
84
|
def get_db():
|
|
78
85
|
"""Dependency function for FastAPI to get database session."""
|
|
@@ -91,11 +98,22 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
91
98
|
query = session.query(CapturedRequest)
|
|
92
99
|
|
|
93
100
|
if status_code:
|
|
94
|
-
|
|
101
|
+
# Handle status code ranges (e.g., 200 for 2xx, 400 for 4xx)
|
|
102
|
+
if status_code in [200, 300, 400, 500]:
|
|
103
|
+
# Filter by status code range
|
|
104
|
+
lower_bound = status_code
|
|
105
|
+
upper_bound = status_code + 100
|
|
106
|
+
query = query.filter(
|
|
107
|
+
CapturedRequest.status_code >= lower_bound,
|
|
108
|
+
CapturedRequest.status_code < upper_bound
|
|
109
|
+
)
|
|
110
|
+
else:
|
|
111
|
+
# Exact status code match
|
|
112
|
+
query = query.filter(CapturedRequest.status_code == status_code)
|
|
95
113
|
if method:
|
|
96
114
|
query = query.filter(CapturedRequest.method == method)
|
|
97
115
|
if search:
|
|
98
|
-
query = query.filter(CapturedRequest.path.
|
|
116
|
+
query = query.filter(CapturedRequest.path.ilike(f"%{search}%"))
|
|
99
117
|
|
|
100
118
|
requests = (
|
|
101
119
|
query.order_by(desc(CapturedRequest.created_at))
|
|
@@ -111,7 +129,7 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
111
129
|
method=req.method,
|
|
112
130
|
path=req.path,
|
|
113
131
|
status_code=req.status_code,
|
|
114
|
-
duration_ms=req.duration_ms,
|
|
132
|
+
duration_ms=round_float(req.duration_ms),
|
|
115
133
|
query_count=len(req.queries),
|
|
116
134
|
has_exception=len(req.exceptions) > 0,
|
|
117
135
|
created_at=req.created_at,
|
|
@@ -142,7 +160,7 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
142
160
|
status_code=request.status_code,
|
|
143
161
|
response_body=request.response_body,
|
|
144
162
|
response_headers=request.response_headers,
|
|
145
|
-
duration_ms=request.duration_ms,
|
|
163
|
+
duration_ms=round_float(request.duration_ms),
|
|
146
164
|
client_ip=request.client_ip,
|
|
147
165
|
created_at=request.created_at,
|
|
148
166
|
queries=[
|
|
@@ -150,7 +168,7 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
150
168
|
"id": q.id,
|
|
151
169
|
"sql": q.sql,
|
|
152
170
|
"parameters": q.parameters,
|
|
153
|
-
"duration_ms": q.duration_ms,
|
|
171
|
+
"duration_ms": round_float(q.duration_ms),
|
|
154
172
|
"rows_affected": q.rows_affected,
|
|
155
173
|
"connection_name": q.connection_name,
|
|
156
174
|
"created_at": q.created_at.isoformat(),
|
|
@@ -175,12 +193,15 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
175
193
|
offset: int = Query(0, ge=0),
|
|
176
194
|
slow_only: bool = Query(False),
|
|
177
195
|
slow_threshold: int = Query(100),
|
|
196
|
+
search: Optional[str] = None,
|
|
178
197
|
session: Session = Depends(get_db),
|
|
179
198
|
):
|
|
180
199
|
query = session.query(CapturedQuery)
|
|
181
200
|
|
|
182
201
|
if slow_only:
|
|
183
202
|
query = query.filter(CapturedQuery.duration_ms >= slow_threshold)
|
|
203
|
+
if search:
|
|
204
|
+
query = query.filter(CapturedQuery.sql.ilike(f"%{search}%"))
|
|
184
205
|
|
|
185
206
|
queries = (
|
|
186
207
|
query.order_by(desc(CapturedQuery.created_at))
|
|
@@ -195,7 +216,7 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
195
216
|
request_id=q.request_id,
|
|
196
217
|
sql=q.sql,
|
|
197
218
|
parameters=q.parameters,
|
|
198
|
-
duration_ms=q.duration_ms,
|
|
219
|
+
duration_ms=round_float(q.duration_ms),
|
|
199
220
|
rows_affected=q.rows_affected,
|
|
200
221
|
connection_name=q.connection_name,
|
|
201
222
|
created_at=q.created_at,
|
|
@@ -236,7 +257,7 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
236
257
|
|
|
237
258
|
@router.get("/stats", response_model=DashboardStats)
|
|
238
259
|
async def get_stats(
|
|
239
|
-
hours: int = Query(1, ge=1, le=
|
|
260
|
+
hours: int = Query(1, ge=1, le=720), # Allow up to 30 days
|
|
240
261
|
slow_threshold: int = Query(100),
|
|
241
262
|
session: Session = Depends(get_db),
|
|
242
263
|
):
|
|
@@ -284,12 +305,12 @@ def create_api_router(get_session_context) -> APIRouter:
|
|
|
284
305
|
|
|
285
306
|
return DashboardStats(
|
|
286
307
|
total_requests=total_requests,
|
|
287
|
-
avg_response_time=avg_response_time,
|
|
308
|
+
avg_response_time=round_float(avg_response_time),
|
|
288
309
|
total_queries=total_queries,
|
|
289
|
-
avg_query_time=avg_query_time,
|
|
310
|
+
avg_query_time=round_float(avg_query_time),
|
|
290
311
|
total_exceptions=len(exceptions),
|
|
291
312
|
slow_queries=slow_queries,
|
|
292
|
-
requests_per_minute=requests_per_minute,
|
|
313
|
+
requests_per_minute=round_float(requests_per_minute),
|
|
293
314
|
)
|
|
294
315
|
|
|
295
316
|
@router.delete("/clear")
|
fastapi_radar/capture.py
CHANGED