项目文件夹

文件
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

145 行
10 KiB
Markdown

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# Synthetic RDS PostgreSQL Suite
This suite benchmarks RDS PostgreSQL root-cause analysis against bundled telemetry fixtures instead of live AWS infrastructure. Each scenario is a static evidence snapshot served through a `FixtureGrafanaBackend`, which drives the same agentic pipeline (`plan → investigate → diagnose`) used in production.
## Scenario table
### Axis 1 — Efficiency (marker: `synthetic`)
| ID | Name | Difficulty | True root cause | Adversarial element | Forbidden |
| --- | --------------------------------- | ---------- | ------------------- | ----------------------------------------------- | ----------------------------- |
| 000 | healthy | 1 | healthy | none | resource_exhaustion |
| 001 | replication-lag | 1 | replication_lag | none | — |
| 002 | connection-exhaustion | 1 | connection_exhaustion | none | — |
| 003 | storage-full | 1 | storage_exhaustion | none | — |
| 004 | cpu-saturation-bad-query | 1 | cpu_saturation | none | — |
| 005 | failover | 1 | multi_az_failover_health_check | none | — |
| 006 | replication-lag-cpu-redherring | 2 | replication_lag | CPUUtilization elevated (analytics job) | category: cpu_saturation |
| 007 | connection-pressure-noisy-healthy | 2 | healthy | CPU/connections oscillating near-threshold | category: connection_exhaustion |
| 008 | storage-full-missing-metric | 3 | storage_exhaustion | FreeStorageSpace absent from fixture | — |
| 009 | dual-fault-connection-cpu | 4 | connection_exhaustion | connections + CPU both failing, causally linked | keywords: storage, replication |
| 010 | replication-lag-missing-metric | 3 | replication_lag | ReplicaLag metric absent from fixture | — |
### Axis 2 — Reasoning (marker: `axis2`)
Axis 2 scenarios use `SelectiveGrafanaBackend`. The agent must ask for the right metrics and explicitly rule out alternative hypotheses. Each scenario has `ruling_out_keywords` that must appear in the agent's output.
| ID | Name | Difficulty | True root cause | Red herring / adversarial element | Must rule out |
| --- | ---------------------------------- | ---------- | ------------------- | -------------------------------------------------------------------- | ----------------------------------------- |
| 011 | cpu-storage-compositional | 4 | dual_resource_exhaustion | ReplicaLag elevation and connection spike as side effects | connection_exhaustion, replication |
| 012 | replication-lag-misleading-events | 3 | replication_lag | Three historical infra events in event stream (none are root cause) | infrastructure (failover as root cause) |
| 013 | storage-recovery-false-alert | 3 | healthy | FreeStorageSpace spike + WriteLatency brief elevation | resource_exhaustion (already recovered) |
| 014 | checkpoint-storm-cpu-saturation | 4 | checkpoint_io_storm | CPU at 92% — alert fires on CPU but cause is VACUUM checkpoint storm | cpu_saturation (CPU is symptom, not root) |
## Difficulty levels
| Level | Description |
| ----- | ----------- |
| 1 | Single dominant signal — all evidence consistent, root cause identifiable in one step |
| 2 | One confounder present — second evidence source needed to rule it out |
| 3 | Absent or indirect evidence — key metric missing, or misleading signals require timeline reasoning |
| 4 | Compositional fault — two failure modes active; agent must identify both and correctly characterise causally-linked side effects |
## MECE basis
Uniqueness is on `(primary_signal × rate × corroborating_presence × event_presence)`, not on primary signal alone.
003 and 008 both map to `storage_full` but have distinct fingerprints:
- **003**: `FreeStorageSpace` present and trending to 0 with elevated `WriteIOPS`
- **008**: `FreeStorageSpace` absent from the fixture entirely — agent must infer from events + PI write latency
## Scoring
### Axis 1 (all scenarios — `test_suite.py`)
Each scenario passes when all of the following are true:
1. The model returns a non-empty root cause
2. The predicted `ROOT_CAUSE_CATEGORY` matches `answer.yml`
3. Every required keyword from `answer.yml:required_keywords` appears in the output
4. The actual category is not in `answer.yml:forbidden_categories` (level 2+ scenarios)
5. No forbidden keyword from `answer.yml:forbidden_keywords` appears in the output (level 4 scenario)
6. Every source listed in `answer.yml:required_evidence_sources` is non-empty in `final_state["evidence"]` — proves the agent consulted the right evidence, not just keyword-matched the alert title
Additionally, a `TrajectoryScore` is computed for each scenario with an `optimal_trajectory`:
- `sequencing_ok`: all expected action types appear in the agent's executed action log (set membership; parallel execution order is non-deterministic)
- `calibration_ok`: number of investigation loops ≤ `max_investigation_loops`
- `efficiency_score`: mean(sequencing_ok, calibration_ok); 1.0 = full pass
### Axis 2 (adversarial scenarios — `test_suite_axis2.py`, marker: `axis2`)
Axis 2 runs through `SelectiveGrafanaBackend`, which:
- Returns only the metric series matching the agent's `metric_name` query (case-insensitive substring)
- Records every metric name the agent requested in `queried_metrics` (audit log)
On top of all Axis 1 checks, Axis 2 asserts a `ReasoningScore`:
- `ruling_out_ok`: every token in `answer.yml:ruling_out_keywords` appears in agent output (proves the agent addressed and dismissed alternative hypotheses)
- `queries_ok`: every entry in `answer.yml:required_queries` was requested by the agent via `query_timeseries`**not yet testable**: the current action registry hardcodes `metric_name="pipeline_runs_total"` for all `query_grafana_metrics` calls; `required_queries` is reserved for when the agent supports per-metric querying
- `reasoning_score`: mean(ruling_out_ok, queries_ok); 1.0 = full pass
### Gap metric
The gap between Axis 1 and Axis 2 pass rates is the primary health indicator for adversarial robustness. A large gap means the agent can find answers when handed all data but cannot reason when it must choose what to look at. Track it per difficulty level:
```bash
python -m tests.synthetic.rds_postgres.run_suite --mock-grafana --axis2
```
## Each scenario folder contains
- `scenario.yml`: scenario metadata (engine, difficulty, adversarial_signals, depends_on)
- `alert.json`: synthetic alert payload
- `aws_cloudwatch_metrics.json`: CloudWatch metric evidence (may omit metrics to simulate collection gaps)
- `aws_rds_events.json`: RDS event stream for the incident window
- `aws_performance_insights.json`: top SQL and wait-event evidence
- `answer.yml`: expected category, required keywords, optional forbidden constraints, required evidence sources
## Running
Via the interactive CLI (recommended):
```bash
opensre tests synthetic
```
Run the whole Axis 1 suite directly:
```bash
python -m tests.synthetic.rds_postgres.run_suite --mock-grafana
```
Run Axis 2 adversarial scenarios via pytest:
```bash
pytest -m axis2 tests/synthetic/rds_postgres/test_suite_axis2.py -v
```
Run a single scenario:
```bash
python -m tests.synthetic.rds_postgres.run_suite --scenario 006-replication-lag-cpu-redherring --mock-grafana
```
Print JSON results:
```bash
python -m tests.synthetic.rds_postgres.run_suite --mock-grafana --json
```
## CI tier strategy
- **Axis 1, Levels 1–2** (scenarios 000–007): run on every commit (`@synthetic`)
- **Axis 1, Levels 3–4** (scenarios 008–010): deferred to nightly — require indirect inference
- **Axis 2** (scenarios 011–013, `@axis2`): run nightly alongside Axis 1 levels 3–4; gap is reported each run
## Known gaps
- **Temporal ordering**: all scenarios deliver evidence as a static snapshot. Production delivers evidence incrementally (alert fires → query metrics → query events → …). Testing temporal ordering requires architectural changes to the fixture backend and is out of scope.
- **Level 4 coverage**: two compositional fault scenarios (009, 011). A fuller curriculum would include 3–4 dual-fault combinations across different failure mode pairs.
- **Slack/markdown renderer for multi-fault**: the renderer displays a single `root_cause` string. Compositional faults may eventually need a `root_causes: list` field in the schema.
- **Axis 2 `required_queries` not yet enforced**: The agent action registry hardcodes `metric_name="pipeline_runs_total"` for all `query_grafana_metrics` calls. `SelectiveGrafanaBackend` records all queried metric names as an audit log but does not filter results. When the agent is updated to pass dynamic CloudWatch metric names (e.g. `metric_name="CPUUtilization"`), re-enable filtering in `SelectiveGrafanaBackend.query_timeseries` and set `required_queries` in `answer.yml`.
## Dependency: healthy_rca_state
Scenario 007 depends on `HEALTHY_SHORT_CIRCUIT=true` (the default) and the `healthy` category being wired into the LLM prompt. If you run with `HEALTHY_SHORT_CIRCUIT=false`, scenario 007 will fall through to the LLM path, which should still classify as `healthy` — but the test is most deterministic with the short-circuit enabled.