Merge pull request #2825 from seefs001/feature/request-id-log-column

feat: log search field request_id && conversion_path display
This commit is contained in:
Calcium-Ion
2026-02-04 15:13:06 +08:00
committed by GitHub
4 changed files with 39 additions and 9 deletions

View File

@@ -20,7 +20,8 @@ func GetAllLogs(c *gin.Context) {
modelName := c.Query("model_name") modelName := c.Query("model_name")
channel, _ := strconv.Atoi(c.Query("channel")) channel, _ := strconv.Atoi(c.Query("channel"))
group := c.Query("group") group := c.Query("group")
logs, total, err := model.GetAllLogs(logType, startTimestamp, endTimestamp, modelName, username, tokenName, pageInfo.GetStartIdx(), pageInfo.GetPageSize(), channel, group) requestId := c.Query("request_id")
logs, total, err := model.GetAllLogs(logType, startTimestamp, endTimestamp, modelName, username, tokenName, pageInfo.GetStartIdx(), pageInfo.GetPageSize(), channel, group, requestId)
if err != nil { if err != nil {
common.ApiError(c, err) common.ApiError(c, err)
return return
@@ -40,7 +41,8 @@ func GetUserLogs(c *gin.Context) {
tokenName := c.Query("token_name") tokenName := c.Query("token_name")
modelName := c.Query("model_name") modelName := c.Query("model_name")
group := c.Query("group") group := c.Query("group")
logs, total, err := model.GetUserLogs(userId, logType, startTimestamp, endTimestamp, modelName, tokenName, pageInfo.GetStartIdx(), pageInfo.GetPageSize(), group) requestId := c.Query("request_id")
logs, total, err := model.GetUserLogs(userId, logType, startTimestamp, endTimestamp, modelName, tokenName, pageInfo.GetStartIdx(), pageInfo.GetPageSize(), group, requestId)
if err != nil { if err != nil {
common.ApiError(c, err) common.ApiError(c, err)
return return

View File

@@ -36,6 +36,7 @@ type Log struct {
TokenId int `json:"token_id" gorm:"default:0;index"` TokenId int `json:"token_id" gorm:"default:0;index"`
Group string `json:"group" gorm:"index"` Group string `json:"group" gorm:"index"`
Ip string `json:"ip" gorm:"index;default:''"` Ip string `json:"ip" gorm:"index;default:''"`
RequestId string `json:"request_id,omitempty" gorm:"type:varchar(64);index:idx_logs_request_id;default:''"`
Other string `json:"other"` Other string `json:"other"`
} }
@@ -58,7 +59,6 @@ func formatUserLogs(logs []*Log) {
if otherMap != nil { if otherMap != nil {
// Remove admin-only debug fields. // Remove admin-only debug fields.
delete(otherMap, "admin_info") delete(otherMap, "admin_info")
delete(otherMap, "request_conversion")
delete(otherMap, "reject_reason") delete(otherMap, "reject_reason")
} }
logs[i].Other = common.MapToJsonStr(otherMap) logs[i].Other = common.MapToJsonStr(otherMap)
@@ -102,6 +102,7 @@ func RecordErrorLog(c *gin.Context, userId int, channelId int, modelName string,
isStream bool, group string, other map[string]interface{}) { isStream bool, group string, other map[string]interface{}) {
logger.LogInfo(c, fmt.Sprintf("record error log: userId=%d, channelId=%d, modelName=%s, tokenName=%s, content=%s", userId, channelId, modelName, tokenName, content)) logger.LogInfo(c, fmt.Sprintf("record error log: userId=%d, channelId=%d, modelName=%s, tokenName=%s, content=%s", userId, channelId, modelName, tokenName, content))
username := c.GetString("username") username := c.GetString("username")
requestId := c.GetString(common.RequestIdKey)
otherStr := common.MapToJsonStr(other) otherStr := common.MapToJsonStr(other)
// 判断是否需要记录 IP // 判断是否需要记录 IP
needRecordIp := false needRecordIp := false
@@ -132,7 +133,8 @@ func RecordErrorLog(c *gin.Context, userId int, channelId int, modelName string,
} }
return "" return ""
}(), }(),
Other: otherStr, RequestId: requestId,
Other: otherStr,
} }
err := LOG_DB.Create(log).Error err := LOG_DB.Create(log).Error
if err != nil { if err != nil {
@@ -161,6 +163,7 @@ func RecordConsumeLog(c *gin.Context, userId int, params RecordConsumeLogParams)
} }
logger.LogInfo(c, fmt.Sprintf("record consume log: userId=%d, params=%s", userId, common.GetJsonString(params))) logger.LogInfo(c, fmt.Sprintf("record consume log: userId=%d, params=%s", userId, common.GetJsonString(params)))
username := c.GetString("username") username := c.GetString("username")
requestId := c.GetString(common.RequestIdKey)
otherStr := common.MapToJsonStr(params.Other) otherStr := common.MapToJsonStr(params.Other)
// 判断是否需要记录 IP // 判断是否需要记录 IP
needRecordIp := false needRecordIp := false
@@ -191,7 +194,8 @@ func RecordConsumeLog(c *gin.Context, userId int, params RecordConsumeLogParams)
} }
return "" return ""
}(), }(),
Other: otherStr, RequestId: requestId,
Other: otherStr,
} }
err := LOG_DB.Create(log).Error err := LOG_DB.Create(log).Error
if err != nil { if err != nil {
@@ -204,7 +208,7 @@ func RecordConsumeLog(c *gin.Context, userId int, params RecordConsumeLogParams)
} }
} }
func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName string, username string, tokenName string, startIdx int, num int, channel int, group string) (logs []*Log, total int64, err error) { func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName string, username string, tokenName string, startIdx int, num int, channel int, group string, requestId string) (logs []*Log, total int64, err error) {
var tx *gorm.DB var tx *gorm.DB
if logType == LogTypeUnknown { if logType == LogTypeUnknown {
tx = LOG_DB tx = LOG_DB
@@ -221,6 +225,9 @@ func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName
if tokenName != "" { if tokenName != "" {
tx = tx.Where("logs.token_name = ?", tokenName) tx = tx.Where("logs.token_name = ?", tokenName)
} }
if requestId != "" {
tx = tx.Where("logs.request_id = ?", requestId)
}
if startTimestamp != 0 { if startTimestamp != 0 {
tx = tx.Where("logs.created_at >= ?", startTimestamp) tx = tx.Where("logs.created_at >= ?", startTimestamp)
} }
@@ -269,7 +276,7 @@ func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName
return logs, total, err return logs, total, err
} }
func GetUserLogs(userId int, logType int, startTimestamp int64, endTimestamp int64, modelName string, tokenName string, startIdx int, num int, group string) (logs []*Log, total int64, err error) { func GetUserLogs(userId int, logType int, startTimestamp int64, endTimestamp int64, modelName string, tokenName string, startIdx int, num int, group string, requestId string) (logs []*Log, total int64, err error) {
var tx *gorm.DB var tx *gorm.DB
if logType == LogTypeUnknown { if logType == LogTypeUnknown {
tx = LOG_DB.Where("logs.user_id = ?", userId) tx = LOG_DB.Where("logs.user_id = ?", userId)
@@ -283,6 +290,9 @@ func GetUserLogs(userId int, logType int, startTimestamp int64, endTimestamp int
if tokenName != "" { if tokenName != "" {
tx = tx.Where("logs.token_name = ?", tokenName) tx = tx.Where("logs.token_name = ?", tokenName)
} }
if requestId != "" {
tx = tx.Where("logs.request_id = ?", requestId)
}
if startTimestamp != 0 { if startTimestamp != 0 {
tx = tx.Where("logs.created_at >= ?", startTimestamp) tx = tx.Where("logs.created_at >= ?", startTimestamp)
} }

View File

@@ -93,6 +93,15 @@ const LogsFilters = ({
size='small' size='small'
/> />
<Form.Input
field='request_id'
prefix={<IconSearch />}
placeholder={t('Request ID')}
showClear
pure
size='small'
/>
{isAdminUser && ( {isAdminUser && (
<> <>
<Form.Input <Form.Input

View File

@@ -94,6 +94,7 @@ export const useLogsData = () => {
model_name: '', model_name: '',
channel: '', channel: '',
group: '', group: '',
request_id: '',
dateRange: [ dateRange: [
timestamp2string(getTodayStartTimestamp()), timestamp2string(getTodayStartTimestamp()),
timestamp2string(now.getTime() / 1000 + 3600), timestamp2string(now.getTime() / 1000 + 3600),
@@ -230,6 +231,7 @@ export const useLogsData = () => {
end_timestamp, end_timestamp,
channel: formValues.channel || '', channel: formValues.channel || '',
group: formValues.group || '', group: formValues.group || '',
request_id: formValues.request_id || '',
logType: formValues.logType ? parseInt(formValues.logType) : 0, logType: formValues.logType ? parseInt(formValues.logType) : 0,
}; };
}; };
@@ -348,6 +350,12 @@ export const useLogsData = () => {
value: `${logs[i].channel} - ${logs[i].channel_name || '[未知]'}`, value: `${logs[i].channel} - ${logs[i].channel_name || '[未知]'}`,
}); });
} }
if (logs[i].request_id) {
expandDataLocal.push({
key: t('Request ID'),
value: logs[i].request_id,
});
}
if (other?.ws || other?.audio) { if (other?.ws || other?.audio) {
expandDataLocal.push({ expandDataLocal.push({
key: t('语音输入'), key: t('语音输入'),
@@ -620,6 +628,7 @@ export const useLogsData = () => {
end_timestamp, end_timestamp,
channel, channel,
group, group,
request_id,
logType: formLogType, logType: formLogType,
} = getFormValues(); } = getFormValues();
@@ -633,9 +642,9 @@ export const useLogsData = () => {
let localStartTimestamp = Date.parse(start_timestamp) / 1000; let localStartTimestamp = Date.parse(start_timestamp) / 1000;
let localEndTimestamp = Date.parse(end_timestamp) / 1000; let localEndTimestamp = Date.parse(end_timestamp) / 1000;
if (isAdminUser) { if (isAdminUser) {
url = `/api/log/?p=${startIdx}&page_size=${pageSize}&type=${currentLogType}&username=${username}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}&channel=${channel}&group=${group}`; url = `/api/log/?p=${startIdx}&page_size=${pageSize}&type=${currentLogType}&username=${username}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}&channel=${channel}&group=${group}&request_id=${request_id}`;
} else { } else {
url = `/api/log/self/?p=${startIdx}&page_size=${pageSize}&type=${currentLogType}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}&group=${group}`; url = `/api/log/self/?p=${startIdx}&page_size=${pageSize}&type=${currentLogType}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}&group=${group}&request_id=${request_id}`;
} }
url = encodeURI(url); url = encodeURI(url);
const res = await API.get(url); const res = await API.get(url);