feat(p3.1-t2): Tier-2 三服務感知強化 — Sentry 簽章 + DiagnosisAggregator + Solver actions test
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

Wave 8 P3.1-T2 三項感知強化(多 engineer 補完):

Sentry Webhook 簽章驗證:
- sentry_webhook.py: 接入 SentryWebhookService.verify_sentry_signature()
- 拒絕無效 sentry-hook-signature → 401 → 防偽造攻擊

DiagnosisAggregator Pod 深診斷整合:
- pre_decision_investigator.py: 新增 _collect_diagnosis_aggregator()
- ENABLE_DIAGNOSIS_AGGREGATOR feature flag 守衛(default=False)
- evidence_snapshot.py: extra_diagnosis 欄位 + build_summary 顯示
- timeout=3.0s + try/except 隔離(fail-soft)
- Conservative 策略:待重疊分析確認 vs PreDecisionInvestigator 不重複

config.py:
- 新增 ENABLE_DIAGNOSIS_AGGREGATOR Field(default=False,K8s ConfigMap 動態啟用)

Solver B1 補測(commit 7c726ebc 對應):
- test_solver_recommended_actions.py — 20 tests + 3 skipped
- 驗證結構化 recommended_actions(北極星 §1.1 修復多樣性 ≥ 40%)
- LLM 失敗 graceful degraded(candidates=[], degraded=True)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Multiple Engineers (Wave 8 P3.1-T2) <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-04-27 08:24:15 +08:00
parent 6de10cb073
commit 3a2cd15144
5 changed files with 693 additions and 0 deletions

View File

@@ -92,6 +92,8 @@ class EvidenceSnapshot:
# Phase 4 ADR-084: 動態異常感官DynamicBaseline + LogAnomaly + TrendPredictor
# 2026-04-15 ogt + Claude Sonnet 4.6(亞太): Phase 4 8D 升級
anomaly_context: dict[str, Any] | None = None # Phase 4 動態異常上下文
# 2026-04-27 P3.1-T2 by Claude — DiagnosisAggregator Pod 深診斷補充in-memory only不持久化
extra_diagnosis: str | None = None
# 感官品質
mcp_health: dict[str, bool] = field(default_factory=dict)
@@ -162,6 +164,9 @@ class EvidenceSnapshot:
parts.append(f"[依賴拓撲] {self.dependency_topology}")
if self.anomaly_context:
parts.append(f"[動態異常偵測]\n{self.anomaly_context}")
# 2026-04-27 P3.1-T2 by Claude — DiagnosisAggregator Pod 深診斷ENABLE_DIAGNOSIS_AGGREGATOR=true 時填入)
if self.extra_diagnosis:
parts.append(f"[Pod深診斷]\n{self.extra_diagnosis}")
# 感官品質報告
failed_tools = [t for t, ok in self.mcp_health.items() if not ok]

View File

@@ -149,6 +149,21 @@ class PreDecisionInvestigator:
except Exception:
logger.exception("phase4_anomaly_collect_error", incident_id=incident_id)
# 4.6 P3.1-T2 by Claude 2026-04-27 — DiagnosisAggregator Pod 深診斷守門ENABLE_DIAGNOSIS_AGGREGATOR
# Conservative 策略:預設關閉,避免與 MCP sensor 重複收集 K8s+SignOz 資料。
# 待重疊分析完成確認互補性後,由統帥設定 ENABLE_DIAGNOSIS_AGGREGATOR=true 啟用。
try:
from src.core.config import settings as _settings
if _settings.ENABLE_DIAGNOSIS_AGGREGATOR:
await asyncio.wait_for(
self._collect_diagnosis_aggregator(snapshot, incident),
timeout=3.0,
)
except asyncio.TimeoutError:
logger.warning("diagnosis_aggregator_collect_timeout", incident_id=incident_id)
except Exception:
logger.warning("diagnosis_aggregator_collect_failed", incident_id=incident_id)
# 5. 組裝 summary
snapshot.evidence_summary = snapshot.build_summary()
@@ -171,6 +186,48 @@ class PreDecisionInvestigator:
)
return snapshot
async def _collect_diagnosis_aggregator(
self,
snapshot: EvidenceSnapshot,
incident: "Incident",
) -> None:
"""
P3.1-T2 by Claude 2026-04-27 — DiagnosisAggregator Pod 深診斷整合
僅在 ENABLE_DIAGNOSIS_AGGREGATOR=true 時呼叫(外層已守門)。
從 incident labels 取 pod_name + namespace呼叫 DiagnosisAggregator
收集 K8s events + SignOz metrics結果存入 snapshot.extra_diagnosis。
Conservative 策略說明:
DiagnosisAggregator 與 MCP sensorsD1_K8S_STATE / D3_METRICS存在資料重疊
本方法透過 feature flag 隔離,不影響主路徑。資料僅作補充,不覆蓋 MCP 結果。
"""
from src.services.diagnosis_aggregator import get_diagnosis_aggregator
labels = _get_labels(incident)
pod_name = labels.get("pod", labels.get("name", ""))
namespace = labels.get("namespace", "awoooi-prod")
if not pod_name:
logger.debug("diagnosis_aggregator_skip_no_pod", incident_id=snapshot.incident_id)
return
aggregator = get_diagnosis_aggregator()
ctx = await aggregator.collect_pod_diagnosis(
pod_name=pod_name,
namespace=namespace,
)
prompt_ctx = ctx.get_llm_prompt_context()
if prompt_ctx:
snapshot.extra_diagnosis = prompt_ctx[:4000] # 限 4K chars不壓縮主 evidence_summary
logger.debug(
"diagnosis_aggregator_collected",
incident_id=snapshot.incident_id,
pod=pod_name,
signals=len(ctx.signals),
highest_severity=ctx.highest_severity.value,
)
async def _collect_phase4_anomalies(self, snapshot: EvidenceSnapshot) -> None:
"""
Phase 4 8D 感官增強:從 ProactiveInspector 快取 + LogAnomalyDetector