更新日志展示
This commit is contained in:
@@ -67,6 +67,13 @@ func (h *AdminReadHandler) Logs(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"detail": "failed to load logs"})
|
||||
return
|
||||
}
|
||||
// Resolve account_id -> account label (email) so the log table can show which
|
||||
// provider account fulfilled each generation under the user.
|
||||
accountByID, err := h.admin.AccountNameMap(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"detail": "failed to load logs"})
|
||||
return
|
||||
}
|
||||
out := make([]gin.H, 0, len(items))
|
||||
for _, item := range items {
|
||||
var userName any
|
||||
@@ -77,6 +84,14 @@ func (h *AdminReadHandler) Logs(c *gin.Context) {
|
||||
} else {
|
||||
userName = item.UserID
|
||||
}
|
||||
var accountName any
|
||||
if item.AccountID != "" {
|
||||
if label, ok := accountByID[item.AccountID]; ok {
|
||||
accountName = label
|
||||
} else {
|
||||
accountName = item.AccountID
|
||||
}
|
||||
}
|
||||
out = append(out, gin.H{
|
||||
"id": item.ID,
|
||||
"ts": item.TS.Unix(),
|
||||
@@ -92,6 +107,8 @@ func (h *AdminReadHandler) Logs(c *gin.Context) {
|
||||
"source": item.Source,
|
||||
"user_id": emptyStringNil(item.UserID),
|
||||
"user_name": userName,
|
||||
"account_id": emptyStringNil(item.AccountID),
|
||||
"account": accountName,
|
||||
"cost": item.Cost,
|
||||
"elapsed_ms": item.ElapsedMS,
|
||||
"file": emptyStringNil(item.File),
|
||||
|
||||
@@ -218,6 +218,13 @@ func (h *UserGenerationHandler) Logs(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"detail": "failed to load logs"})
|
||||
return
|
||||
}
|
||||
// Resolve account_id -> account label so the log table can show which
|
||||
// provider account fulfilled each generation under the user.
|
||||
accountByID, err := h.admin.AccountNameMap(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"detail": "failed to load logs"})
|
||||
return
|
||||
}
|
||||
|
||||
out := make([]gin.H, 0, len(items))
|
||||
for _, item := range items {
|
||||
@@ -229,6 +236,14 @@ func (h *UserGenerationHandler) Logs(c *gin.Context) {
|
||||
} else {
|
||||
userName = item.UserID
|
||||
}
|
||||
var accountName any
|
||||
if item.AccountID != "" {
|
||||
if label, ok := accountByID[item.AccountID]; ok {
|
||||
accountName = label
|
||||
} else {
|
||||
accountName = item.AccountID
|
||||
}
|
||||
}
|
||||
out = append(out, gin.H{
|
||||
"id": item.ID,
|
||||
"ts": item.TS.Unix(),
|
||||
@@ -244,6 +259,8 @@ func (h *UserGenerationHandler) Logs(c *gin.Context) {
|
||||
"source": emptyStringNil(item.Source),
|
||||
"user_id": emptyStringNil(item.UserID),
|
||||
"user_name": userName,
|
||||
"account_id": emptyStringNil(item.AccountID),
|
||||
"account": accountName,
|
||||
"cost": item.Cost,
|
||||
"elapsed_ms": item.ElapsedMS,
|
||||
"file": emptyStringNil(item.File),
|
||||
|
||||
@@ -136,6 +136,28 @@ func (s *AdminReadService) UserNameMap(ctx context.Context) (map[string]string,
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// AccountNameMap builds a token-account id -> display label lookup (account
|
||||
// email, else display name, else id) used to annotate log rows with which
|
||||
// provider account fulfilled each generation (event_logs.account_id).
|
||||
func (s *AdminReadService) AccountNameMap(ctx context.Context) (map[string]string, error) {
|
||||
accounts, err := s.tokens.List(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make(map[string]string, len(accounts))
|
||||
for _, a := range accounts {
|
||||
label := strings.TrimSpace(a.AccountEmail)
|
||||
if label == "" {
|
||||
label = strings.TrimSpace(a.AccountDisplayName)
|
||||
}
|
||||
if label == "" {
|
||||
label = a.ID
|
||||
}
|
||||
out[a.ID] = label
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *AdminReadService) Stats(ctx context.Context) (map[string]any, error) {
|
||||
stats, err := s.events.Stats(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -237,7 +237,7 @@ const sourcePill = (s) => ({
|
||||
<th class="text-center px-4 py-3 font-medium">预览</th>
|
||||
<th class="text-left px-4 py-3 font-medium">时间</th>
|
||||
<th class="text-left px-3 py-3 font-medium">状态</th>
|
||||
<th class="text-left px-3 py-3 font-medium">用户</th>
|
||||
<th class="text-left px-3 py-3 font-medium">用户 / 账号</th>
|
||||
<th class="text-left px-3 py-3 font-medium">模型</th>
|
||||
<th class="text-left px-3 py-3 font-medium">提示词 / 错误</th>
|
||||
<th class="text-left px-3 py-3 font-medium">参数</th>
|
||||
@@ -280,6 +280,7 @@ const sourcePill = (s) => ({
|
||||
</td>
|
||||
<td class="px-3 py-3.5 align-middle min-w-0">
|
||||
<div class="text-xs text-white/80 truncate" :title="e.user_name || '匿名'">{{ e.user_name || '匿名' }}</div>
|
||||
<div v-if="e.account" class="mt-0.5 text-[11px] text-white/45 truncate" :title="e.account">{{ e.account }}</div>
|
||||
</td>
|
||||
<td class="px-3 py-3.5 align-middle min-w-0">
|
||||
<div class="font-mono text-xs text-white/90 truncate" :title="e.model">{{ e.model }}</div>
|
||||
|
||||
@@ -194,6 +194,7 @@ const params = (e) => {
|
||||
<col class="w-16" /> <!-- preview -->
|
||||
<col class="w-28" /> <!-- time -->
|
||||
<col class="w-24" /> <!-- status -->
|
||||
<col class="w-28" /> <!-- user/account -->
|
||||
<col class="w-36" /> <!-- model -->
|
||||
<col /> <!-- prompt/error -->
|
||||
<col class="w-40" /> <!-- params -->
|
||||
@@ -205,6 +206,7 @@ const params = (e) => {
|
||||
<th class="text-center px-3 py-3 font-medium">预览</th>
|
||||
<th class="text-left px-3 py-3 font-medium">时间</th>
|
||||
<th class="text-left px-3 py-3 font-medium">状态</th>
|
||||
<th class="text-left px-3 py-3 font-medium">用户 / 账号</th>
|
||||
<th class="text-left px-3 py-3 font-medium">模型</th>
|
||||
<th class="text-left px-3 py-3 font-medium">提示词 / 错误</th>
|
||||
<th class="text-left px-3 py-3 font-medium">参数</th>
|
||||
@@ -236,6 +238,10 @@ const params = (e) => {
|
||||
<span class="w-1.5 h-1.5 rounded-full" :class="statusDot(e.status)"></span>{{ statusLabel(e.status) }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-3 py-3 align-middle min-w-0">
|
||||
<div class="text-xs text-slate-700 truncate" :title="e.user_name || '匿名'">{{ e.user_name || '匿名' }}</div>
|
||||
<div v-if="e.account" class="mt-0.5 text-[11px] text-slate-400 truncate" :title="e.account">{{ e.account }}</div>
|
||||
</td>
|
||||
<td class="px-3 py-3 align-middle min-w-0">
|
||||
<div class="font-mono text-xs text-slate-800 truncate" :title="e.model">{{ e.model }}</div>
|
||||
<div class="mt-0.5 flex items-center gap-1.5">
|
||||
|
||||
Reference in New Issue
Block a user