rezabarkhordary commited on
Commit
472159c
·
verified ·
1 Parent(s): b34152a

Create sovereign_capacity_report.py

Browse files
Files changed (1) hide show
  1. sovereign_capacity_report.py +242 -0
sovereign_capacity_report.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # sovereign_capacity_report.py
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ from datetime import datetime, timezone
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ from sovereign_capacity_probe import run_capacity_probe
11
+
12
+
13
+ CAPACITY_OUTPUT_DIR = "sovereign_capacity_outputs"
14
+
15
+
16
+ def _utc_now() -> str:
17
+ return datetime.now(timezone.utc).isoformat()
18
+
19
+
20
+ def _ensure_dir(path: str) -> None:
21
+ os.makedirs(path, exist_ok=True)
22
+
23
+
24
+ def _safe(v: Any, default: Any = "") -> Any:
25
+ return v if v is not None else default
26
+
27
+
28
+ def _pct(v: Any) -> str:
29
+ try:
30
+ return f"{float(v):.2f}%"
31
+ except Exception:
32
+ return "0.00%"
33
+
34
+
35
+ def _ms(v: Any) -> str:
36
+ try:
37
+ return f"{float(v):.3f} ms"
38
+ except Exception:
39
+ return "0.000 ms"
40
+
41
+
42
+ def _rps(v: Any) -> str:
43
+ try:
44
+ return f"{float(v):.3f} rps"
45
+ except Exception:
46
+ return "0.000 rps"
47
+
48
+
49
+ def _render_summary(report: Dict[str, Any]) -> str:
50
+ summary = report.get("summary", {})
51
+ overall = summary.get("overall_latency", {})
52
+ counts = summary.get("decision_counts", {})
53
+ pcts = summary.get("decision_percentages", {})
54
+ cfg = report.get("config", {})
55
+
56
+ return f"""# Sovereign Capacity Report
57
+
58
+ Generated at: {_safe(report.get("generated_at"), _utc_now())}
59
+
60
+ ## 1. Probe Identity
61
+ - Probe Name: {_safe(report.get("probe_name"), "Sovereign Capacity Probe")}
62
+ - Case Count: {_safe(cfg.get("case_count"), 0)}
63
+ - Warmup Runs: {_safe(cfg.get("warmup_runs"), 0)}
64
+ - Iterations Per Case: {_safe(cfg.get("iterations_per_case"), 0)}
65
+ - Total Expected Requests: {_safe(cfg.get("total_expected_requests"), 0)}
66
+
67
+ ## 2. Executive Summary
68
+ - Successful Requests: {_safe(summary.get("successful_requests"), 0)}
69
+ - Failed Requests: {_safe(summary.get("failed_requests"), 0)}
70
+ - Total Wall Time: {_safe(summary.get("total_wall_seconds"), 0)} sec
71
+ - Approx Throughput: {_rps(summary.get("throughput_rps", 0))}
72
+ - Overall Min Latency: {_ms(overall.get("min_ms"))}
73
+ - Overall Avg Latency: {_ms(overall.get("avg_ms"))}
74
+ - Overall Median Latency: {_ms(overall.get("median_ms"))}
75
+ - Overall P95 Latency: {_ms(overall.get("p95_ms"))}
76
+ - Overall P99 Latency: {_ms(overall.get("p99_ms"))}
77
+ - Overall Max Latency: {_ms(overall.get("max_ms"))}
78
+ - Overall Standard Deviation: {_ms(overall.get("stdev_ms"))}
79
+
80
+ ## 3. Decision Distribution Under Load
81
+ - ALLOW Count: {_safe(counts.get("ALLOW"), 0)} ({_pct(pcts.get("ALLOW", 0))})
82
+ - FREEZE Count: {_safe(counts.get("FREEZE"), 0)} ({_pct(pcts.get("FREEZE", 0))})
83
+ - BLOCK Count: {_safe(counts.get("BLOCK"), 0)} ({_pct(pcts.get("BLOCK", 0))})
84
+ - UNKNOWN Count: {_safe(counts.get("UNKNOWN"), 0)} ({_pct(pcts.get("UNKNOWN", 0))})
85
+ """
86
+
87
+
88
+ def _render_case_latency(report: Dict[str, Any]) -> str:
89
+ blocks = ["## 4. Per-Scenario Latency Under Load"]
90
+ per_case = report.get("per_case_latency", {})
91
+
92
+ if not per_case:
93
+ blocks.append("- No per-case data available.")
94
+ return "\n".join(blocks)
95
+
96
+ for case_name, stats in per_case.items():
97
+ blocks.append(
98
+ f"""
99
+ ### {case_name}
100
+ - Count: {_safe(stats.get("count"), 0)}
101
+ - Min: {_ms(stats.get("min_ms"))}
102
+ - Avg: {_ms(stats.get("avg_ms"))}
103
+ - Median: {_ms(stats.get("median_ms"))}
104
+ - P95: {_ms(stats.get("p95_ms"))}
105
+ - P99: {_ms(stats.get("p99_ms"))}
106
+ - Max: {_ms(stats.get("max_ms"))}
107
+ - Stdev: {_ms(stats.get("stdev_ms"))}
108
+ """.rstrip()
109
+ )
110
+
111
+ return "\n\n".join(blocks)
112
+
113
+
114
+ def _render_failures(report: Dict[str, Any]) -> str:
115
+ failures = report.get("failures", [])
116
+ lines = ["## 5. Failures"]
117
+
118
+ if not failures:
119
+ lines.append("- No capacity-probe failures were recorded.")
120
+ return "\n".join(lines)
121
+
122
+ lines.append(f"- Failure Count: {len(failures)}")
123
+ for item in failures[:25]:
124
+ lines.append(
125
+ f"- Case: {item.get('case')} | Iteration: {item.get('iteration')} | Error: {item.get('error')}"
126
+ )
127
+ if len(failures) > 25:
128
+ lines.append(f"- Additional failures omitted: {len(failures) - 25}")
129
+
130
+ return "\n".join(lines)
131
+
132
+
133
+ def _render_samples(report: Dict[str, Any]) -> str:
134
+ sample_outputs = report.get("sample_outputs", {})
135
+ lines = ["## 6. Sample Outputs Under Load"]
136
+
137
+ if not sample_outputs:
138
+ lines.append("- No sample outputs available.")
139
+ return "\n".join(lines)
140
+
141
+ for case_name, sample in sample_outputs.items():
142
+ lines.append(f"### {case_name}")
143
+ lines.append(f"- Decision: {_safe(sample.get('decision'), 'UNKNOWN')}")
144
+ lines.append("```json")
145
+ lines.append(json.dumps(sample.get("sample_result", {}), ensure_ascii=False, indent=2))
146
+ lines.append("```")
147
+
148
+ return "\n".join(lines)
149
+
150
+
151
+ def _render_verdict(report: Dict[str, Any]) -> str:
152
+ summary = report.get("summary", {})
153
+ overall = summary.get("overall_latency", {})
154
+ failures = int(summary.get("failed_requests", 0) or 0)
155
+ p95 = float(overall.get("p95_ms", 0.0) or 0.0)
156
+ p99 = float(overall.get("p99_ms", 0.0) or 0.0)
157
+ throughput = float(summary.get("throughput_rps", 0.0) or 0.0)
158
+
159
+ if failures == 0 and p95 <= 100 and p99 <= 200:
160
+ verdict = "Capacity posture is stable for current probe volume, with acceptable runtime behavior under repeated load."
161
+ elif failures == 0:
162
+ verdict = "Capacity posture is operationally viable, but latency under load should be further optimized before strong bank-facing performance claims."
163
+ else:
164
+ verdict = "Capacity probe indicates additional hardening or stability work is required before bank-facing performance commitments."
165
+
166
+ return f"""## 7. Preliminary Capacity Verdict
167
+ {verdict}
168
+
169
+ ## 8. Notes
170
+ - This report reflects current repeated-request behavior, not final production-scale distributed load testing.
171
+ - Throughput in this report is an approximate runtime throughput for the current execution path.
172
+ - Bank-facing performance claims should be based on repeated probes, tuning iterations, and later higher-intensity validation.
173
+ - This report is suitable as a technical capacity artifact, not yet as a final production SLA statement.
174
+ """
175
+
176
+
177
+ def build_capacity_markdown(report: Dict[str, Any]) -> str:
178
+ parts = [
179
+ _render_summary(report),
180
+ _render_case_latency(report),
181
+ _render_failures(report),
182
+ _render_samples(report),
183
+ _render_verdict(report),
184
+ ]
185
+ return "\n\n".join(parts).strip() + "\n"
186
+
187
+
188
+ def save_capacity_report(
189
+ report: Dict[str, Any],
190
+ output_dir: str = CAPACITY_OUTPUT_DIR,
191
+ base_name: Optional[str] = None,
192
+ ) -> Dict[str, str]:
193
+ _ensure_dir(output_dir)
194
+
195
+ ts = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
196
+ base = base_name or f"sovereign_capacity_report_{ts}"
197
+
198
+ json_path = os.path.join(output_dir, f"{base}.json")
199
+ md_path = os.path.join(output_dir, f"{base}.md")
200
+
201
+ with open(json_path, "w", encoding="utf-8") as f:
202
+ json.dump(report, f, ensure_ascii=False, indent=2)
203
+
204
+ markdown = build_capacity_markdown(report)
205
+ with open(md_path, "w", encoding="utf-8") as f:
206
+ f.write(markdown)
207
+
208
+ return {
209
+ "json_report": json_path,
210
+ "markdown_report": md_path,
211
+ }
212
+
213
+
214
+ def generate_capacity_report(
215
+ iterations_per_case: int = 25,
216
+ warmup_runs: int = 2,
217
+ output_dir: str = CAPACITY_OUTPUT_DIR,
218
+ base_name: Optional[str] = None,
219
+ ) -> Dict[str, Any]:
220
+ report = run_capacity_probe(
221
+ iterations_per_case=iterations_per_case,
222
+ warmup_runs=warmup_runs,
223
+ )
224
+
225
+ files = save_capacity_report(
226
+ report=report,
227
+ output_dir=output_dir,
228
+ base_name=base_name,
229
+ )
230
+
231
+ return {
232
+ "ok": True,
233
+ "generated_at": _utc_now(),
234
+ "report": report,
235
+ "files": files,
236
+ }
237
+
238
+
239
+ if __name__ == "__main__":
240
+ out = generate_capacity_report(iterations_per_case=10, warmup_runs=1)
241
+ print(json.dumps(out, indent=2, ensure_ascii=False))
242
+