feat(aiot): 告警生成时异步上报运维平台
- 边缘告警入库后异步 POST 到运维平台 /admin-api/ops/alarm/receive - 提前提取 ORM 字段避免异步执行时 session 关闭导致属性为空 - event_time 转为 ISO 字符串格式,修复时间显示为 1970 的问题 - 请求参数含 alarmId、alarmType、deviceId、eventTime、alarmLevel、notifyUserIds、tenantId Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,12 +15,15 @@ API 路径规范:
|
|||||||
from fastapi import APIRouter, Query, Depends, HTTPException
|
from fastapi import APIRouter, Query, Depends, HTTPException
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import httpx
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from app.yudao_compat import YudaoResponse, get_current_user
|
from app.yudao_compat import YudaoResponse, get_current_user
|
||||||
from app.services.alarm_event_service import get_alarm_event_service, AlarmEventService
|
from app.services.alarm_event_service import get_alarm_event_service, AlarmEventService
|
||||||
from app.services.notification_service import get_notification_service
|
from app.services.notification_service import get_notification_service
|
||||||
from app.services.oss_storage import get_oss_storage
|
from app.services.oss_storage import get_oss_storage
|
||||||
from app.schemas import EdgeAlarmReport
|
from app.schemas import EdgeAlarmReport
|
||||||
|
from app.utils.logger import logger
|
||||||
|
|
||||||
router = APIRouter(prefix="/admin-api/aiot/alarm", tags=["AIoT-告警"])
|
router = APIRouter(prefix="/admin-api/aiot/alarm", tags=["AIoT-告警"])
|
||||||
|
|
||||||
@@ -285,6 +288,16 @@ async def edge_alarm_report(
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass # WebSocket 通知失败不影响主流程
|
pass # WebSocket 通知失败不影响主流程
|
||||||
|
|
||||||
|
# 异步上报运维平台(提前提取字段,避免 ORM session 关闭后无法访问)
|
||||||
|
ops_data = {
|
||||||
|
"alarm_id": alarm.alarm_id,
|
||||||
|
"alarm_type": alarm.alarm_type,
|
||||||
|
"device_id": alarm.device_id,
|
||||||
|
"event_time": alarm.event_time.strftime("%Y-%m-%dT%H:%M:%S") if isinstance(alarm.event_time, datetime) else str(alarm.event_time or ""),
|
||||||
|
"alarm_level": alarm.alarm_level or 2,
|
||||||
|
}
|
||||||
|
asyncio.create_task(_notify_ops_platform(ops_data))
|
||||||
|
|
||||||
return YudaoResponse.success({
|
return YudaoResponse.success({
|
||||||
"alarmId": alarm.alarm_id,
|
"alarmId": alarm.alarm_id,
|
||||||
"created": True,
|
"created": True,
|
||||||
@@ -293,6 +306,31 @@ async def edge_alarm_report(
|
|||||||
|
|
||||||
# ==================== 辅助函数 ====================
|
# ==================== 辅助函数 ====================
|
||||||
|
|
||||||
|
OPS_ALARM_URL = "http://192.168.0.104:48080/admin-api/ops/alarm/receive"
|
||||||
|
|
||||||
|
|
||||||
|
async def _notify_ops_platform(data: dict):
|
||||||
|
"""异步上报告警到运维平台(失败不影响主流程)"""
|
||||||
|
payload = {
|
||||||
|
"alarmId": data["alarm_id"],
|
||||||
|
"alarmType": data["alarm_type"],
|
||||||
|
"deviceId": data["device_id"],
|
||||||
|
"eventTime": data["event_time"],
|
||||||
|
"alarmLevel": data["alarm_level"],
|
||||||
|
"notifyUserIds": [1],
|
||||||
|
"tenantId": 1,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient(timeout=10) as client:
|
||||||
|
resp = await client.post(OPS_ALARM_URL, json=payload)
|
||||||
|
if resp.status_code == 200:
|
||||||
|
logger.info(f"运维平台上报成功: {data['alarm_id']}, resp={resp.text[:200]}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"运维平台上报失败: status={resp.status_code}, body={resp.text[:200]}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"运维平台上报异常: {e}")
|
||||||
|
|
||||||
|
|
||||||
def _get_alarm_type_name(alarm_type: Optional[str]) -> str:
|
def _get_alarm_type_name(alarm_type: Optional[str]) -> str:
|
||||||
"""获取告警类型名称"""
|
"""获取告警类型名称"""
|
||||||
type_names = {
|
type_names = {
|
||||||
|
|||||||
Reference in New Issue
Block a user