ForcePilot/backend/server/routers/channels/analytics_router.py

260 lines
11 KiB
Python
Raw Normal View History

"""聚合视图域 analytics 子域 Router。
实现 9 GET 端点统一采用模板 A控制面端口路由通过
``use_cases.analytics_view.<method>(...)`` 调用类型化方法经控制面管道
五阶段鉴权 权限 限流 dispatch 审计处理
端点清单
- ANL-01: GET /analytics/messages 消息深度分析
- ANL-02: GET /analytics/messages/distribution 消息类型分布
- ANL-04: GET /analytics/sessions 会话分析
- ANL-05: GET /analytics/delivery 投递链路分析
- ANL-06: GET /analytics/delivery/latency 投递延迟分布
- ANL-07: GET /analytics/delivery/funnel 投递漏斗分析
- ANL-ACCOUNTS: GET /analytics/accounts 账户活跃度分析
- ANL-PEERS: GET /analytics/peers 对端活跃度分析
- ANL-CR: GET /analytics/content-review 内容审核分析
设计依据18-聚合视图域-analytics-router-设计方案.mdv1.2 6 端点
ANL-ACCOUNTS/PEERS/CR 为后续扩展端点
"""
from __future__ import annotations
from typing import Any
from fastapi import APIRouter, Depends, Query, Request
from yuxi.channels.contract.dtos.channel import ChannelType
from yuxi.storage.postgres.models_business import User
from server.routers.channels import (
Granularity,
build_operator,
get_channel_use_cases,
parse_datetime,
raiseOnControlFailure,
serialize_control_data,
)
from server.utils.auth_middleware import get_admin_user
analytics_router = APIRouter(tags=["channels-analytics"])
@analytics_router.get("/analytics/messages", response_model=dict)
async def analyze_messages(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
granularity: Granularity = Query(default="day", description="时间粒度"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""消息深度分析ANL-01"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.analyzeMessages(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
granularity=granularity,
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/messages/distribution", response_model=dict)
async def get_message_distribution(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""消息类型分布分析ANL-02"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.getMessageDistribution(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/sessions", response_model=dict)
async def analyze_sessions(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
granularity: Granularity = Query(default="day", description="时间粒度"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""会话分析ANL-04"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.analyzeSessions(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
granularity=granularity,
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/delivery", response_model=dict)
async def analyze_delivery(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""投递链路分析ANL-05"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.analyzeDelivery(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/delivery/latency", response_model=dict)
async def get_delivery_latency_distribution(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""投递延迟分布ANL-06"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.getDeliveryLatencyDistribution(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/delivery/funnel", response_model=dict)
async def get_delivery_funnel(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""投递漏斗分析ANL-07"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.getDeliveryFunnel(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/accounts", response_model=dict)
async def analyze_accounts(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
granularity: Granularity = Query(default="day", description="时间粒度"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""账户活跃度分析ANL-ACCOUNTS"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.analyzeAccounts(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
granularity=granularity,
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/peers", response_model=dict)
async def analyze_peers(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
account_id: str | None = Query(default=None, description="账户 ID 过滤"),
limit: int = Query(default=100, ge=1, le=500, description="Top N 上限1-500"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""对端活跃度分析ANL-PEERS"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.analyzePeers(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
operator=operator,
account_id=account_id,
limit=limit,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}
@analytics_router.get("/analytics/content-review", response_model=dict)
async def analyze_content_review(
request: Request,
start_time: str = Query(..., description="开始时间ISO 8601"),
end_time: str = Query(..., description="结束时间ISO 8601"),
granularity: Granularity = Query(default="day", description="时间粒度"),
channel_type: ChannelType | None = Query(default=None, description="渠道类型过滤"),
use_cases=Depends(get_channel_use_cases),
current_user: User = Depends(get_admin_user),
) -> dict[str, Any]:
"""内容审核分析ANL-CR"""
operator = build_operator(current_user, request)
start_time_dt = parse_datetime("start_time", start_time)
end_time_dt = parse_datetime("end_time", end_time)
result = await use_cases.analytics_view.analyzeContentReview(
channel_type=channel_type,
start_time=start_time_dt.isoformat(),
end_time=end_time_dt.isoformat(),
granularity=granularity,
operator=operator,
)
raiseOnControlFailure(result)
return {"success": True, "data": serialize_control_data(result.data)}