feat: 实时卡片统一用get_realtime_stats一次查llmusage,消除数据矛盾
This commit is contained in:
parent
b129fc2ef2
commit
ef5644498e
@ -87,6 +87,36 @@ async def get_realtime_active_users(sor, today, scope=None, org_filter=None):
|
|||||||
return int(recs[0].cnt) if recs else 0
|
return int(recs[0].cnt) if recs else 0
|
||||||
|
|
||||||
|
|
||||||
|
async def get_realtime_stats(sor, today, scope=None, org_filter=None):
|
||||||
|
"""一次查llmusage返回全部实时指标,确保数据一致"""
|
||||||
|
w = _usage_where(scope, org_filter)
|
||||||
|
sql = ("SELECT "
|
||||||
|
"COUNT(*) as calls, "
|
||||||
|
"COALESCE(SUM(amount), 0) as amount, "
|
||||||
|
"COUNT(DISTINCT userid) as active_users, "
|
||||||
|
"SUM(CASE WHEN status='SUCCEEDED' THEN 1 ELSE 0 END) as success, "
|
||||||
|
"SUM(CASE WHEN status='FAILED' THEN 1 ELSE 0 END) as fail "
|
||||||
|
"FROM llmusage "
|
||||||
|
"WHERE use_date = ${today}$ AND " + w)
|
||||||
|
ns = {'today': today}
|
||||||
|
if org_filter:
|
||||||
|
ns['org'] = org_filter
|
||||||
|
recs = await sor.sqlExe(sql, ns)
|
||||||
|
if recs:
|
||||||
|
r = recs[0]
|
||||||
|
total = int(r.calls) if hasattr(r, 'calls') else r.get('calls', 0)
|
||||||
|
success = int(r.success) if hasattr(r, 'success') else r.get('success', 0)
|
||||||
|
fail = int(r.fail) if hasattr(r, 'fail') else r.get('fail', 0)
|
||||||
|
return {
|
||||||
|
'calls': total,
|
||||||
|
'amount': round(float(r.amount) if hasattr(r, 'amount') else r.get('amount', 0), 2),
|
||||||
|
'active_users': int(r.active_users) if hasattr(r, 'active_users') else r.get('active_users', 0),
|
||||||
|
'success_rate': round(success * 100.0 / total, 1) if total else 0,
|
||||||
|
'fail_count': fail,
|
||||||
|
}
|
||||||
|
return {'calls': 0, 'amount': 0, 'active_users': 0, 'success_rate': 0, 'fail_count': 0}
|
||||||
|
|
||||||
|
|
||||||
async def get_online_users(env, scope=None, org_filter=None):
|
async def get_online_users(env, scope=None, org_filter=None):
|
||||||
"""在线用户数 — 从 Redis session 中统计"""
|
"""在线用户数 — 从 Redis session 中统计"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -12,7 +12,7 @@ from .dashboards import (
|
|||||||
get_customer_user_today, get_daily_trend, get_hourly_concurrency,
|
get_customer_user_today, get_daily_trend, get_hourly_concurrency,
|
||||||
get_avg_ttft, get_currency_breakdown,
|
get_avg_ttft, get_currency_breakdown,
|
||||||
get_realtime_calls, get_realtime_amount, get_total_users_count,
|
get_realtime_calls, get_realtime_amount, get_total_users_count,
|
||||||
get_realtime_active_users, get_online_users,
|
get_realtime_active_users, get_online_users, get_realtime_stats,
|
||||||
get_distributor_customers_count, get_distributor_active_customers,
|
get_distributor_customers_count, get_distributor_active_customers,
|
||||||
get_distributor_top_customers,
|
get_distributor_top_customers,
|
||||||
get_scoped_today_usage, get_scoped_today_amount,
|
get_scoped_today_usage, get_scoped_today_amount,
|
||||||
@ -249,29 +249,30 @@ async def api_distributor_customers(request):
|
|||||||
|
|
||||||
# ── Jinja2 模板函数(实时,角色感知)──
|
# ── Jinja2 模板函数(实时,角色感知)──
|
||||||
|
|
||||||
|
async def _get_realtime_snapshot(request):
|
||||||
|
"""一次查询返回全部实时指标(含角色),各j2函数复用同一结果"""
|
||||||
|
env = request._run_ns
|
||||||
|
scope, org_filter = await _resolve_view(request)
|
||||||
|
today = env.curDateString()
|
||||||
|
async with get_sor_context(env, MODULE_NAME) as sor:
|
||||||
|
return await get_realtime_stats(sor, today, scope, org_filter)
|
||||||
|
|
||||||
|
|
||||||
async def j2_realtime_calls(request):
|
async def j2_realtime_calls(request):
|
||||||
try:
|
try:
|
||||||
env = request._run_ns
|
s = await _get_realtime_snapshot(request)
|
||||||
scope, org_filter = await _resolve_view(request)
|
return s.get('calls', 0)
|
||||||
today = env.curDateString()
|
|
||||||
async with get_sor_context(env, MODULE_NAME) as sor:
|
|
||||||
return await get_realtime_calls(sor, today, scope, org_filter)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug("sage_datamart API error: " + str(e))
|
debug("sage_datamart API error: " + str(e))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
async def j2_realtime_amount(request):
|
async def j2_realtime_amount(request):
|
||||||
try:
|
try:
|
||||||
env = request._run_ns
|
s = await _get_realtime_snapshot(request)
|
||||||
scope, org_filter = await _resolve_view(request)
|
return s.get('amount', 0)
|
||||||
today = env.curDateString()
|
|
||||||
async with get_sor_context(env, MODULE_NAME) as sor:
|
|
||||||
return await get_realtime_amount(sor, today, scope, org_filter)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug("sage_datamart API error: " + str(e))
|
debug("sage_datamart API error: " + str(e))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@ -285,22 +286,15 @@ async def j2_total_users(request):
|
|||||||
return await get_total_users_count(sor, scope, org_filter)
|
return await get_total_users_count(sor, scope, org_filter)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug("sage_datamart API error: " + str(e))
|
debug("sage_datamart API error: " + str(e))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
async def j2_active_today(request):
|
async def j2_active_today(request):
|
||||||
try:
|
try:
|
||||||
env = request._run_ns
|
s = await _get_realtime_snapshot(request)
|
||||||
scope, org_filter = await _resolve_view(request)
|
return s.get('active_users', 0)
|
||||||
today = env.curDateString()
|
|
||||||
async with get_sor_context(env, MODULE_NAME) as sor:
|
|
||||||
if scope == DISTRIBUTOR:
|
|
||||||
return await get_distributor_active_customers(sor, today, org_filter)
|
|
||||||
return await get_realtime_active_users(sor, today, scope, org_filter)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug("sage_datamart API error: " + str(e))
|
debug("sage_datamart API error: " + str(e))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
@ -310,33 +304,24 @@ async def j2_online_users(request):
|
|||||||
return await get_online_users(env)
|
return await get_online_users(env)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug("sage_datamart API error: " + str(e))
|
debug("sage_datamart API error: " + str(e))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
async def j2_scoped_success_rate(request):
|
async def j2_scoped_success_rate(request):
|
||||||
try:
|
try:
|
||||||
env = request._run_ns
|
s = await _get_realtime_snapshot(request)
|
||||||
scope, org_filter = await _resolve_view(request)
|
return s.get('success_rate', 0)
|
||||||
today = env.curDateString()
|
|
||||||
async with get_sor_context(env, MODULE_NAME) as sor:
|
|
||||||
return await get_scoped_success_rate(sor, today, scope, org_filter)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug("sage_datamart API error: " + str(e))
|
debug("sage_datamart API error: " + str(e))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
async def j2_scoped_fail_count(request):
|
async def j2_scoped_fail_count(request):
|
||||||
try:
|
try:
|
||||||
env = request._run_ns
|
s = await _get_realtime_snapshot(request)
|
||||||
scope, org_filter = await _resolve_view(request)
|
return s.get('fail_count', 0)
|
||||||
today = env.curDateString()
|
|
||||||
async with get_sor_context(env, MODULE_NAME) as sor:
|
|
||||||
return await get_scoped_fail_count(sor, today, scope, org_filter)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug("sage_datamart API error: " + str(e))
|
debug("sage_datamart API error: " + str(e))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user