sync: 193 file da Baida98/AI@6dc5684d (2026-08-27 21:57 UTC) [deploy-all]

#126
by Baida07 - opened
Files changed (1) hide show
  1. api/performance_rum.py +63 -37
api/performance_rum.py CHANGED
@@ -11,6 +11,7 @@ from __future__ import annotations
11
 
12
  import asyncio
13
  import hashlib
 
14
  import math
15
  import os
16
  import re
@@ -37,6 +38,7 @@ _ALLOWED_NAVIGATION = frozenset({"navigate", "reload", "back-forward", "prerende
37
  _RATE_WINDOW_SECONDS = 60
38
  _RATE_LIMIT = 120
39
  _rate_buckets: dict[str, tuple[float, int]] = {}
 
40
 
41
 
42
  class MetricSample(BaseModel):
@@ -148,24 +150,36 @@ async def ingest_metric(
148
  if not _allow_rate(_rate_key(request, os.getenv("RUM_HASH_SALT", "rum"))):
149
  raise HTTPException(status_code=429, detail="rate limit exceeded")
150
 
151
- await asyncio.to_thread(
152
- _execute,
153
- """
154
- insert into public.rum_samples
155
- (metric, value, release, device, connection_type, navigation_type, bucket_start)
156
- values (%(metric)s, %(value)s, %(release)s, %(device)s, %(connection_type)s,
157
- %(navigation_type)s, %(bucket_start)s)
158
- """,
159
- {
160
- "metric": sample.metric,
161
- "value": sample.value,
162
- "release": sample.release,
163
- "device": sample.device,
164
- "connection_type": sample.connection_type,
165
- "navigation_type": sample.navigation_type,
166
- "bucket_start": _bucket_start(datetime.now(timezone.utc)),
167
- },
168
- )
 
 
 
 
 
 
 
 
 
 
 
 
169
  return {"accepted": True}
170
 
171
 
@@ -183,25 +197,37 @@ async def performance_summary(
183
  if release != "all" and not _RELEASE_RE.fullmatch(release.lower()):
184
  raise HTTPException(status_code=400, detail="invalid release")
185
 
186
- rows = await asyncio.to_thread(
187
- _execute,
188
- """
189
- select metric, release, device,
190
- count(*)::integer as sample_count,
191
- percentile_cont(0.50) within group (order by value) as p50,
192
- percentile_cont(0.75) within group (order by value) as p75,
193
- percentile_cont(0.95) within group (order by value) as p95
194
- from public.rum_samples
195
- where bucket_start >= %(from_time)s
196
- and bucket_start < %(to_time)s
197
- and device = %(device)s
198
- and (%(release)s = 'all' or release = %(release)s)
199
- group by metric, release, device
200
- order by metric, release
201
- """,
202
- {"from_time": from_time, "to_time": to_time, "device": device, "release": release.lower()},
203
- fetch=True,
204
- )
 
 
 
 
 
 
 
 
 
 
 
 
205
  for row in rows:
206
  if row["sample_count"] < 20:
207
  row["p50"] = row["p75"] = row["p95"] = None
 
11
 
12
  import asyncio
13
  import hashlib
14
+ import logging
15
  import math
16
  import os
17
  import re
 
38
  _RATE_WINDOW_SECONDS = 60
39
  _RATE_LIMIT = 120
40
  _rate_buckets: dict[str, tuple[float, int]] = {}
41
+ _logger = logging.getLogger("performance_rum")
42
 
43
 
44
  class MetricSample(BaseModel):
 
150
  if not _allow_rate(_rate_key(request, os.getenv("RUM_HASH_SALT", "rum"))):
151
  raise HTTPException(status_code=429, detail="rate limit exceeded")
152
 
153
+ try:
154
+ await asyncio.to_thread(
155
+ _execute,
156
+ """
157
+ insert into public.rum_samples
158
+ (metric, value, release, device, connection_type, navigation_type, bucket_start)
159
+ values (%(metric)s, %(value)s, %(release)s, %(device)s, %(connection_type)s,
160
+ %(navigation_type)s, %(bucket_start)s)
161
+ """,
162
+ {
163
+ "metric": sample.metric,
164
+ "value": sample.value,
165
+ "release": sample.release,
166
+ "device": sample.device,
167
+ "connection_type": sample.connection_type,
168
+ "navigation_type": sample.navigation_type,
169
+ "bucket_start": _bucket_start(datetime.now(timezone.utc)),
170
+ },
171
+ )
172
+ except HTTPException:
173
+ raise
174
+ except Exception as exc:
175
+ _logger.error(
176
+ "RUM database operation failed type=%s metric=%s device=%s",
177
+ type(exc).__name__, sample.metric, sample.device,
178
+ )
179
+ raise HTTPException(
180
+ status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
181
+ detail="RUM database temporaneamente non disponibile",
182
+ ) from exc
183
  return {"accepted": True}
184
 
185
 
 
197
  if release != "all" and not _RELEASE_RE.fullmatch(release.lower()):
198
  raise HTTPException(status_code=400, detail="invalid release")
199
 
200
+ try:
201
+ rows = await asyncio.to_thread(
202
+ _execute,
203
+ """
204
+ select metric, release, device,
205
+ count(*)::integer as sample_count,
206
+ percentile_cont(0.50) within group (order by value) as p50,
207
+ percentile_cont(0.75) within group (order by value) as p75,
208
+ percentile_cont(0.95) within group (order by value) as p95
209
+ from public.rum_samples
210
+ where bucket_start >= %(from_time)s
211
+ and bucket_start < %(to_time)s
212
+ and device = %(device)s
213
+ and (%(release)s = 'all' or release = %(release)s)
214
+ group by metric, release, device
215
+ order by metric, release
216
+ """,
217
+ {"from_time": from_time, "to_time": to_time, "device": device, "release": release.lower()},
218
+ fetch=True,
219
+ )
220
+ except HTTPException:
221
+ raise
222
+ except Exception as exc:
223
+ _logger.error(
224
+ "RUM summary database operation failed type=%s device=%s",
225
+ type(exc).__name__, device,
226
+ )
227
+ raise HTTPException(
228
+ status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
229
+ detail="RUM database temporaneamente non disponibile",
230
+ ) from exc
231
  for row in rows:
232
  if row["sample_count"] < 20:
233
  row["p50"] = row["p75"] = row["p95"] = None