feat(api): Phase 13.2 #79 SignOz MCP Tool 整合
整合真實 SignOzClient 到 MCP Bridge: - gold_metrics: RPS + Error Rate + P99 Latency - trace_url: 動態 Trace URL 生成 - system_metrics: CPU/Disk 系統指標 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -200,16 +200,21 @@ class MCPBridge:
|
||||
self._tool_cache: dict[str, list[MCPTool]] = {}
|
||||
self._http_client = httpx.AsyncClient(timeout=30.0)
|
||||
|
||||
# 註冊 Mock Servers (Phase 3: 先驗證介面)
|
||||
self._register_mock_servers()
|
||||
# 註冊 MCP Servers (Phase 13.2: 整合真實服務)
|
||||
self._register_servers()
|
||||
|
||||
def _register_mock_servers(self) -> None:
|
||||
"""註冊 Mock MCP Servers (開發測試用)"""
|
||||
def _register_servers(self) -> None:
|
||||
"""註冊 MCP Servers"""
|
||||
self._servers["kubernetes"] = MCPServer(
|
||||
name="kubernetes",
|
||||
transport=MCPTransport.HTTP,
|
||||
endpoint="http://localhost:8081/mcp",
|
||||
)
|
||||
self._servers["signoz"] = MCPServer(
|
||||
name="signoz",
|
||||
transport=MCPTransport.HTTP,
|
||||
endpoint="http://192.168.0.188:3301", # SignOz Query Service
|
||||
)
|
||||
self._servers["filesystem"] = MCPServer(
|
||||
name="filesystem",
|
||||
transport=MCPTransport.STDIO,
|
||||
@@ -319,6 +324,47 @@ class MCPBridge:
|
||||
server_name=server.name,
|
||||
),
|
||||
],
|
||||
"signoz": [
|
||||
MCPTool(
|
||||
name="gold_metrics",
|
||||
description="Get Gold Metrics (RPS, Error Rate, P99 Latency) for a service",
|
||||
input_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service_name": {"type": "string", "description": "Service name (e.g., api-gateway)"},
|
||||
"namespace": {"type": "string", "description": "K8s namespace (default: awoooi-prod)"},
|
||||
"time_window_minutes": {"type": "integer", "description": "Time window in minutes (default: 10)"},
|
||||
},
|
||||
"required": ["service_name"],
|
||||
},
|
||||
server_name=server.name,
|
||||
),
|
||||
MCPTool(
|
||||
name="trace_url",
|
||||
description="Generate SignOz trace URL for debugging a service",
|
||||
input_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service_name": {"type": "string", "description": "Service name"},
|
||||
"window_minutes": {"type": "integer", "description": "Time window ± minutes (default: 5)"},
|
||||
},
|
||||
"required": ["service_name"],
|
||||
},
|
||||
server_name=server.name,
|
||||
),
|
||||
MCPTool(
|
||||
name="system_metrics",
|
||||
description="Get system metrics (CPU, Disk I/O) from SignOz",
|
||||
input_schema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"host": {"type": "string", "description": "Host IP (default: 192.168.0.188)"},
|
||||
"time_window_minutes": {"type": "integer", "description": "Time window in minutes (default: 5)"},
|
||||
},
|
||||
},
|
||||
server_name=server.name,
|
||||
),
|
||||
],
|
||||
"database": [
|
||||
MCPTool(
|
||||
name="query",
|
||||
@@ -568,6 +614,82 @@ class MCPBridge:
|
||||
else:
|
||||
return {"error": f"Unknown kubernetes tool: {tool_name}"}
|
||||
|
||||
# =============================================
|
||||
# SignOz: 監控指標查詢 (Phase 13.2 #79)
|
||||
# =============================================
|
||||
elif server.name == "signoz":
|
||||
from src.services.signoz_client import get_signoz_client
|
||||
|
||||
signoz = get_signoz_client()
|
||||
|
||||
if tool_name == "gold_metrics":
|
||||
# 取得 Gold Metrics (RPS, Error Rate, P99)
|
||||
service_name = parameters.get("service_name", "")
|
||||
if not service_name:
|
||||
return {"error": "Missing 'service_name' parameter"}
|
||||
|
||||
namespace = parameters.get("namespace", "awoooi-prod")
|
||||
time_window = parameters.get("time_window_minutes", 10)
|
||||
|
||||
metrics = await signoz.get_gold_metrics(
|
||||
service_name=service_name,
|
||||
namespace=namespace,
|
||||
time_window_minutes=time_window,
|
||||
)
|
||||
|
||||
return {
|
||||
"service_name": metrics.service_name,
|
||||
"namespace": metrics.namespace,
|
||||
"rps": round(metrics.rps, 2),
|
||||
"rps_trend": metrics.rps_trend,
|
||||
"error_rate": round(metrics.error_rate, 2),
|
||||
"error_count": metrics.error_count,
|
||||
"total_requests": metrics.total_requests,
|
||||
"p50_latency_ms": round(metrics.p50_latency_ms, 1),
|
||||
"p95_latency_ms": round(metrics.p95_latency_ms, 1),
|
||||
"p99_latency_ms": round(metrics.p99_latency_ms, 1),
|
||||
"latency_trend": metrics.latency_trend,
|
||||
"summary": metrics.to_summary(),
|
||||
}
|
||||
|
||||
elif tool_name == "trace_url":
|
||||
# 生成 SignOz Trace URL
|
||||
service_name = parameters.get("service_name", "")
|
||||
if not service_name:
|
||||
return {"error": "Missing 'service_name' parameter"}
|
||||
|
||||
window_minutes = parameters.get("window_minutes", 5)
|
||||
url = signoz.generate_trace_url(
|
||||
service_name=service_name,
|
||||
window_minutes=window_minutes,
|
||||
)
|
||||
|
||||
return {
|
||||
"service_name": service_name,
|
||||
"trace_url": url,
|
||||
"window_minutes": window_minutes,
|
||||
}
|
||||
|
||||
elif tool_name == "system_metrics":
|
||||
# 取得系統指標 (CPU/Disk)
|
||||
host = parameters.get("host", "192.168.0.188")
|
||||
time_window = parameters.get("time_window_minutes", 5)
|
||||
|
||||
metrics = await signoz.get_system_metrics(
|
||||
_host=host,
|
||||
time_window_minutes=time_window,
|
||||
)
|
||||
|
||||
return {
|
||||
"host": host,
|
||||
"cpu": metrics.get("cpu", {}),
|
||||
"disk": metrics.get("disk", {}),
|
||||
"time_range": metrics.get("time_range", {}),
|
||||
}
|
||||
|
||||
else:
|
||||
return {"error": f"Unknown signoz tool: {tool_name}"}
|
||||
|
||||
# =============================================
|
||||
# Database: 查詢 incident/approval 歷史 (Phase 13.2 #81)
|
||||
# =============================================
|
||||
|
||||
Reference in New Issue
Block a user