diff --git a/sage_datamart/dashboards.py b/sage_datamart/dashboards.py index 0912ef6..4309f81 100644 --- a/sage_datamart/dashboards.py +++ b/sage_datamart/dashboards.py @@ -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 +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): """在线用户数 — 从 Redis session 中统计""" try: diff --git a/sage_datamart/init.py b/sage_datamart/init.py index 4258e56..f7ddbb3 100644 --- a/sage_datamart/init.py +++ b/sage_datamart/init.py @@ -12,7 +12,7 @@ from .dashboards import ( get_customer_user_today, get_daily_trend, get_hourly_concurrency, get_avg_ttft, get_currency_breakdown, 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_top_customers, get_scoped_today_usage, get_scoped_today_amount, @@ -249,29 +249,30 @@ async def api_distributor_customers(request): # ── 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): try: - 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_calls(sor, today, scope, org_filter) + s = await _get_realtime_snapshot(request) + return s.get('calls', 0) except Exception as e: debug("sage_datamart API error: " + str(e)) - return 0 async def j2_realtime_amount(request): try: - 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_amount(sor, today, scope, org_filter) + s = await _get_realtime_snapshot(request) + return s.get('amount', 0) except Exception as e: debug("sage_datamart API error: " + str(e)) - return 0 @@ -285,22 +286,15 @@ async def j2_total_users(request): return await get_total_users_count(sor, scope, org_filter) except Exception as e: debug("sage_datamart API error: " + str(e)) - return 0 async def j2_active_today(request): try: - env = request._run_ns - scope, org_filter = await _resolve_view(request) - 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) + s = await _get_realtime_snapshot(request) + return s.get('active_users', 0) except Exception as e: debug("sage_datamart API error: " + str(e)) - return 0 @@ -310,33 +304,24 @@ async def j2_online_users(request): return await get_online_users(env) except Exception as e: debug("sage_datamart API error: " + str(e)) - return 0 async def j2_scoped_success_rate(request): try: - 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_scoped_success_rate(sor, today, scope, org_filter) + s = await _get_realtime_snapshot(request) + return s.get('success_rate', 0) except Exception as e: debug("sage_datamart API error: " + str(e)) - return 0 async def j2_scoped_fail_count(request): try: - 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_scoped_fail_count(sor, today, scope, org_filter) + s = await _get_realtime_snapshot(request) + return s.get('fail_count', 0) except Exception as e: debug("sage_datamart API error: " + str(e)) - return 0