Skip to content

Commit 066adca

Browse files
Expose perf cache counts by bounded policy
1 parent 8e94bf6 commit 066adca

4 files changed

Lines changed: 29 additions & 1 deletion

File tree

config/dw-bounded-growth.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,17 @@
219219
'suppression' => 'No labels are exposed.',
220220
],
221221

222+
'dw_perf_redis_server_keys_by_policy' => [
223+
'owner' => 'scripts/perf/server_soak.py',
224+
'surface' => 'Perf harness /metrics scrape; optional remote_write.',
225+
'dimensions' => [
226+
'policy' => 'finite_cache_policy_inventory',
227+
],
228+
'cardinality' => 'policy series are fixed to the cache_keys inventory in this bounded-growth policy file.',
229+
'selection' => 'latest sampled Redis keys for each declared server-owned cache policy.',
230+
'suppression' => 'No suppression path is needed because the cache policy inventory is finite and reviewed.',
231+
],
232+
222233
'dw_perf_redis_db_keys' => [
223234
'owner' => 'scripts/perf/server_soak.py',
224235
'surface' => 'Perf harness /metrics scrape; optional remote_write.',

docs/bounded-growth.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ added without a TTL, admission, or cardinality contract.
5353
| `dw_perf_redis_memory_bytes` | Perf harness `/metrics`; optional remote_write | No labels; single gauge series per soak run. |
5454
| `dw_perf_redis_polling_keys` | Perf harness `/metrics`; optional remote_write | No labels; single gauge series per soak run. |
5555
| `dw_perf_redis_server_keys` | Perf harness `/metrics`; optional remote_write | No labels; single gauge series per soak run. Counts all Redis keys in the server-owned `server:*` cache namespace, not only the workflow-task polling subset. |
56+
| `dw_perf_redis_server_keys_by_policy` | Perf harness `/metrics`; optional remote_write | The only label is `policy`, fixed to the reviewed `cache_keys` inventory in `config/dw-bounded-growth.php`. |
5657
| `dw_perf_redis_db_keys` | Perf harness `/metrics`; optional remote_write | No labels; single gauge series per soak run. |
5758
| `dw_perf_assertion_failed` | Perf harness `/metrics`; optional remote_write | No labels; single gauge series per soak run. |
5859

@@ -101,7 +102,9 @@ evidence.
101102
`max_server_cache_keys_by_policy` / `final_server_cache_keys_by_policy`. Those
102103
per-policy maps mirror the `cache_keys` inventory so a long soak can show which
103104
bounded cache family produced growth instead of only reporting a total
104-
`server:*` count.
105+
`server:*` count. The same finite per-policy inventory is exposed as
106+
`dw_perf_redis_server_keys_by_policy{policy="..."}` for optional remote-write
107+
alerting.
105108

106109
Per-policy limits can be enforced with JSON maps keyed by policy ID:
107110
`DW_PERF_MAX_SERVER_CACHE_KEYS_BY_POLICY` for maximum observed keys and

scripts/perf/server_soak.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def __init__(self) -> None:
5151
"redis_db_keys": 0,
5252
"redis_polling_keys": 0,
5353
"redis_server_keys": 0,
54+
"redis_server_keys_by_policy": {policy_id: 0 for policy_id in SERVER_CACHE_KEY_PATTERNS},
5455
"assertion_failed": 0,
5556
}
5657

@@ -71,6 +72,12 @@ def update_sample(self, sample: dict[str, Any]) -> None:
7172
self.latest["redis_db_keys"] = int(sample.get("redis_db_keys") or 0)
7273
self.latest["redis_polling_keys"] = int(sample.get("redis_polling_keys") or 0)
7374
self.latest["redis_server_keys"] = int(sample.get("redis_server_keys") or 0)
75+
by_policy = sample.get("redis_server_keys_by_policy")
76+
if isinstance(by_policy, dict):
77+
self.latest["redis_server_keys_by_policy"] = {
78+
policy_id: int(by_policy.get(policy_id) or 0)
79+
for policy_id in SERVER_CACHE_KEY_PATTERNS
80+
}
7481

7582
def mark_assertion_failed(self) -> None:
7683
with self.lock:
@@ -106,6 +113,12 @@ def prometheus(self) -> str:
106113
"# HELP dw_perf_redis_server_keys Redis keys owned by the Durable Workflow server cache namespace.",
107114
"# TYPE dw_perf_redis_server_keys gauge",
108115
f"dw_perf_redis_server_keys {self.latest['redis_server_keys']}",
116+
"# HELP dw_perf_redis_server_keys_by_policy Redis keys owned by the Durable Workflow server cache namespace by bounded-growth policy.",
117+
"# TYPE dw_perf_redis_server_keys_by_policy gauge",
118+
*[
119+
f'dw_perf_redis_server_keys_by_policy{{policy="{policy_id}"}} {count}'
120+
for policy_id, count in sorted(self.latest["redis_server_keys_by_policy"].items())
121+
],
109122
"# HELP dw_perf_redis_db_keys Redis DBSIZE count.",
110123
"# TYPE dw_perf_redis_db_keys gauge",
111124
f"dw_perf_redis_db_keys {self.latest['redis_db_keys']}",

tests/Unit/ServerPerfHarnessContractTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public function test_soak_summary_records_trusted_evidence_fields(): void
2525
'final_server_cache_keys',
2626
'max_server_cache_keys_by_policy',
2727
'final_server_cache_keys_by_policy',
28+
'dw_perf_redis_server_keys_by_policy',
2829
'DW_PERF_MAX_SERVER_CACHE_KEYS_BY_POLICY',
2930
'DW_PERF_MAX_FINAL_SERVER_CACHE_KEYS_BY_POLICY',
3031
'parse_policy_thresholds',

0 commit comments

Comments
 (0)