fastapi-alertengine 1.0.3__tar.gz → 1.0.4__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.
Files changed (17) hide show
  1. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/PKG-INFO +1 -1
  2. fastapi_alertengine-1.0.4/fastapi_alertengine/engine.py +114 -0
  3. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine.egg-info/PKG-INFO +1 -1
  4. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/pyproject.toml +1 -1
  5. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/setup.cfg +1 -1
  6. fastapi_alertengine-1.0.3/fastapi_alertengine/engine.py +0 -0
  7. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/README.md +0 -0
  8. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine/__init__.py +0 -0
  9. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine/app_main.py +0 -0
  10. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine/client.py +0 -0
  11. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine/config.py +0 -0
  12. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine/middleware.py +0 -0
  13. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine/storage.py.py +0 -0
  14. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine.egg-info/SOURCES.txt +0 -0
  15. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine.egg-info/dependency_links.txt +0 -0
  16. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine.egg-info/requires.txt +0 -0
  17. {fastapi_alertengine-1.0.3 → fastapi_alertengine-1.0.4}/fastapi_alertengine.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-alertengine
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: FastAPI AlertEngine: fintech-grade request monitoring (p95 latency + error rate) without Prometheus.
5
5
  Author: Tandem Media
6
6
  Project-URL: Homepage, https://github.com/Tandem-Media/fastapi-alertengine
@@ -0,0 +1,114 @@
1
+ # fastapi_alertengine/engine.py
2
+
3
+ import time
4
+ from typing import Dict, Any
5
+
6
+
7
+ STREAM_KEY = "anchorflow:request_metrics"
8
+
9
+
10
+ class AlertEngine:
11
+ """
12
+ Real-time SLO / latency alert engine.
13
+
14
+ Uses rolling window analysis over Redis Stream data.
15
+ """
16
+
17
+ def __init__(self, redis):
18
+ self.redis = redis
19
+
20
+ def _fetch_recent(self, last_n: int = 200):
21
+ raw = self.redis.xrevrange(STREAM_KEY, count=last_n)
22
+
23
+ events = []
24
+ for _, fields in raw:
25
+ try:
26
+ events.append({
27
+ "latency_ms": float(fields.get("latency_ms", 0)),
28
+ "type": fields.get("type", "api"),
29
+ "status_code": int(fields.get("status_code", 0)),
30
+ "timestamp": int(fields.get("timestamp", 0)),
31
+ })
32
+ except Exception:
33
+ continue
34
+
35
+ return events
36
+
37
+ def _p95(self, values):
38
+ if not values:
39
+ return 0.0
40
+
41
+ values.sort()
42
+ idx = int(len(values) * 0.95)
43
+ return values[min(idx, len(values) - 1)]
44
+
45
+ def _anomaly_score(self, current, baseline):
46
+ if baseline == 0:
47
+ return 0
48
+
49
+ return abs(current - baseline) / baseline
50
+
51
+ def evaluate(self, window_size: int = 200) -> Dict[str, Any]:
52
+ events = self._fetch_recent(window_size)
53
+
54
+ if not events:
55
+ return {
56
+ "status": "ok",
57
+ "reason": "no_data"
58
+ }
59
+
60
+ all_lat = [e["latency_ms"] for e in events]
61
+ webhook_lat = [e["latency_ms"] for e in events if e["type"] == "webhook"]
62
+ api_lat = [e["latency_ms"] for e in events if e["type"] == "api"]
63
+
64
+ def p95(values):
65
+ if not values:
66
+ return 0.0
67
+ values.sort()
68
+ idx = int(len(values) * 0.95)
69
+ return values[min(idx, len(values) - 1)]
70
+
71
+ overall_p95 = p95(all_lat)
72
+ webhook_p95 = p95(webhook_lat)
73
+ api_p95 = p95(api_lat)
74
+
75
+ # Baseline (simple rolling heuristic)
76
+ baseline = sum(all_lat) / len(all_lat)
77
+
78
+ anomaly = self._anomaly_score(overall_p95, baseline)
79
+
80
+ # Alert thresholds
81
+ status = "ok"
82
+
83
+ if overall_p95 > 3000 or anomaly > 2.0:
84
+ status = "critical"
85
+ elif overall_p95 > 1000 or anomaly > 1.0:
86
+ status = "warning"
87
+
88
+ # Failure pressure signal
89
+ error_rate = sum(1 for e in events if e["status_code"] >= 500) / len(events)
90
+
91
+ if error_rate > 0.2:
92
+ status = "critical"
93
+ elif error_rate > 0.1 and status != "critical":
94
+ status = "warning"
95
+
96
+ return {
97
+ "status": status,
98
+ "metrics": {
99
+ "overall_p95_ms": overall_p95,
100
+ "webhook_p95_ms": webhook_p95,
101
+ "api_p95_ms": api_p95,
102
+ "error_rate": error_rate,
103
+ "anomaly_score": anomaly,
104
+ "sample_size": len(events),
105
+ },
106
+ "thresholds": {
107
+ "p95_warning": 1000,
108
+ "p95_critical": 3000,
109
+ "anomaly_warning": 1.0,
110
+ "anomaly_critical": 2.0,
111
+ "error_rate_critical": 0.2,
112
+ },
113
+ "timestamp": int(time.time()),
114
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-alertengine
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: FastAPI AlertEngine: fintech-grade request monitoring (p95 latency + error rate) without Prometheus.
5
5
  Author: Tandem Media
6
6
  Project-URL: Homepage, https://github.com/Tandem-Media/fastapi-alertengine
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fastapi-alertengine"
7
- version = "1.0.3"
7
+ version = "1.0.4"
8
8
  description = "FastAPI AlertEngine: fintech-grade request monitoring (p95 latency + error rate) without Prometheus."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = fastapi-alertengine
3
- version = 1.0.3
3
+ version = "1.0.4"
4
4
 
5
5
  [options]
6
6
  packages = find:
File without changes