mirror of
https://github.com/fawney19/Aether.git
synced 2026-01-02 15:52:26 +08:00
@@ -41,7 +41,7 @@ const props = withDefaults(defineProps<{
|
|||||||
isAdmin: boolean
|
isAdmin: boolean
|
||||||
hours?: number
|
hours?: number
|
||||||
}>(), {
|
}>(), {
|
||||||
hours: 168 // 默认7天
|
hours: 24 // 默认当天
|
||||||
})
|
})
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@@ -174,17 +174,17 @@ async function loadData() {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
if (props.isAdmin) {
|
if (props.isAdmin) {
|
||||||
// 管理员:获取所有用户数据
|
// 管理员:获取所有用户数据(按比例采样)
|
||||||
timelineData.value = await cacheAnalysisApi.getIntervalTimeline({
|
timelineData.value = await cacheAnalysisApi.getIntervalTimeline({
|
||||||
hours: props.hours,
|
hours: props.hours,
|
||||||
include_user_info: true,
|
include_user_info: true,
|
||||||
limit: 2000,
|
limit: 10000,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 普通用户:获取自己的数据
|
// 普通用户:获取自己的数据
|
||||||
timelineData.value = await meApi.getIntervalTimeline({
|
timelineData.value = await meApi.getIntervalTimeline({
|
||||||
hours: props.hours,
|
hours: props.hours,
|
||||||
limit: 1000,
|
limit: 5000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -920,8 +920,8 @@ class CacheHitAnalysisAdapter(AdminApiAdapter):
|
|||||||
@router.get("/cache-affinity/interval-timeline")
|
@router.get("/cache-affinity/interval-timeline")
|
||||||
async def get_interval_timeline(
|
async def get_interval_timeline(
|
||||||
request: Request,
|
request: Request,
|
||||||
hours: int = Query(168, ge=1, le=720, description="分析最近多少小时的数据"),
|
hours: int = Query(24, ge=1, le=720, description="分析最近多少小时的数据"),
|
||||||
limit: int = Query(1000, ge=100, le=5000, description="最大返回数据点数量"),
|
limit: int = Query(10000, ge=100, le=50000, description="最大返回数据点数量"),
|
||||||
user_id: Optional[str] = Query(None, description="指定用户 ID"),
|
user_id: Optional[str] = Query(None, description="指定用户 ID"),
|
||||||
include_user_info: bool = Query(False, description="是否包含用户信息(用于管理员多用户视图)"),
|
include_user_info: bool = Query(False, description="是否包含用户信息(用于管理员多用户视图)"),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ async def get_my_active_requests(
|
|||||||
@router.get("/usage/interval-timeline")
|
@router.get("/usage/interval-timeline")
|
||||||
async def get_my_interval_timeline(
|
async def get_my_interval_timeline(
|
||||||
request: Request,
|
request: Request,
|
||||||
hours: int = Query(168, ge=1, le=720, description="分析最近多少小时的数据"),
|
hours: int = Query(24, ge=1, le=720, description="分析最近多少小时的数据"),
|
||||||
limit: int = Query(1000, ge=100, le=5000, description="最大返回数据点数量"),
|
limit: int = Query(5000, ge=100, le=20000, description="最大返回数据点数量"),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
"""获取当前用户的请求间隔时间线数据,用于散点图展示"""
|
"""获取当前用户的请求间隔时间线数据,用于散点图展示"""
|
||||||
|
|||||||
@@ -1730,8 +1730,8 @@ class UsageService:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_interval_timeline(
|
def get_interval_timeline(
|
||||||
db: Session,
|
db: Session,
|
||||||
hours: int = 168,
|
hours: int = 24,
|
||||||
limit: int = 1000,
|
limit: int = 10000,
|
||||||
user_id: Optional[str] = None,
|
user_id: Optional[str] = None,
|
||||||
include_user_info: bool = False,
|
include_user_info: bool = False,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
@@ -1740,8 +1740,8 @@ class UsageService:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
db: 数据库会话
|
db: 数据库会话
|
||||||
hours: 分析最近多少小时的数据
|
hours: 分析最近多少小时的数据(默认24小时)
|
||||||
limit: 最大返回数据点数量
|
limit: 最大返回数据点数量(默认10000)
|
||||||
user_id: 指定用户 ID(可选,为空则返回所有用户)
|
user_id: 指定用户 ID(可选,为空则返回所有用户)
|
||||||
include_user_info: 是否包含用户信息(用于管理员多用户视图)
|
include_user_info: 是否包含用户信息(用于管理员多用户视图)
|
||||||
|
|
||||||
@@ -1758,6 +1758,7 @@ class UsageService:
|
|||||||
# 根据是否需要用户信息选择不同的查询
|
# 根据是否需要用户信息选择不同的查询
|
||||||
if include_user_info and not user_id:
|
if include_user_info and not user_id:
|
||||||
# 管理员视图:返回带用户信息的数据点
|
# 管理员视图:返回带用户信息的数据点
|
||||||
|
# 使用按比例采样,保持每个用户的数据量比例不变
|
||||||
sql = text(f"""
|
sql = text(f"""
|
||||||
WITH request_intervals AS (
|
WITH request_intervals AS (
|
||||||
SELECT
|
SELECT
|
||||||
@@ -1774,17 +1775,41 @@ class UsageService:
|
|||||||
AND u.created_at > :start_date
|
AND u.created_at > :start_date
|
||||||
AND u.user_id IS NOT NULL
|
AND u.user_id IS NOT NULL
|
||||||
{user_filter}
|
{user_filter}
|
||||||
|
),
|
||||||
|
filtered_intervals AS (
|
||||||
|
SELECT
|
||||||
|
created_at,
|
||||||
|
user_id,
|
||||||
|
username,
|
||||||
|
EXTRACT(EPOCH FROM (created_at - prev_request_at)) / 60.0 as interval_minutes,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at) as rn
|
||||||
|
FROM request_intervals
|
||||||
|
WHERE prev_request_at IS NOT NULL
|
||||||
|
AND EXTRACT(EPOCH FROM (created_at - prev_request_at)) / 60.0 <= 120
|
||||||
|
),
|
||||||
|
total_count AS (
|
||||||
|
SELECT COUNT(*) as cnt FROM filtered_intervals
|
||||||
|
),
|
||||||
|
user_totals AS (
|
||||||
|
SELECT user_id, COUNT(*) as user_cnt FROM filtered_intervals GROUP BY user_id
|
||||||
|
),
|
||||||
|
user_limits AS (
|
||||||
|
SELECT
|
||||||
|
ut.user_id,
|
||||||
|
CASE WHEN tc.cnt <= :limit THEN ut.user_cnt
|
||||||
|
ELSE GREATEST(CEIL(ut.user_cnt::float * :limit / tc.cnt), 1)::int
|
||||||
|
END as user_limit
|
||||||
|
FROM user_totals ut, total_count tc
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
created_at,
|
fi.created_at,
|
||||||
user_id,
|
fi.user_id,
|
||||||
username,
|
fi.username,
|
||||||
EXTRACT(EPOCH FROM (created_at - prev_request_at)) / 60.0 as interval_minutes
|
fi.interval_minutes
|
||||||
FROM request_intervals
|
FROM filtered_intervals fi
|
||||||
WHERE prev_request_at IS NOT NULL
|
JOIN user_limits ul ON fi.user_id = ul.user_id
|
||||||
AND EXTRACT(EPOCH FROM (created_at - prev_request_at)) / 60.0 <= 120
|
WHERE fi.rn <= ul.user_limit
|
||||||
ORDER BY created_at
|
ORDER BY fi.created_at
|
||||||
LIMIT :limit
|
|
||||||
""")
|
""")
|
||||||
else:
|
else:
|
||||||
# 普通视图:只返回时间和间隔
|
# 普通视图:只返回时间和间隔
|
||||||
|
|||||||
Reference in New Issue
Block a user