Merge remote-tracking branch 'songquanpeng/main'

# Conflicts:
#	controller/log.go
#	model/log.go
#	web/src/components/LogsTable.js
This commit is contained in:
quzard 2023-06-24 19:42:33 +08:00
commit 75b4e9d3b5
4 changed files with 55 additions and 29 deletions

View File

@ -16,9 +16,10 @@ func GetAllLogs(c *gin.Context) {
startTimestamp, _ := strconv.ParseInt(c.Query("start_timestamp"), 10, 64)
endTimestamp, _ := strconv.ParseInt(c.Query("end_timestamp"), 10, 64)
username := c.Query("username")
tokenName := c.Query("token_name")
modelName := c.Query("model_name")
channelName := c.Query("channel_name")
logs, err := model.GetAllLogs(logType, startTimestamp, endTimestamp, modelName, username, p*common.ItemsPerPage, common.ItemsPerPage, channelName)
logs, err := model.GetAllLogs(logType, startTimestamp, endTimestamp, modelName, username, tokenName, p*common.ItemsPerPage, common.ItemsPerPage, channelName)
if err != nil {
c.JSON(200, gin.H{
"success": false,
@ -99,10 +100,11 @@ func GetLogsStat(c *gin.Context) {
logType, _ := strconv.Atoi(c.Query("type"))
startTimestamp, _ := strconv.ParseInt(c.Query("start_timestamp"), 10, 64)
endTimestamp, _ := strconv.ParseInt(c.Query("end_timestamp"), 10, 64)
tokenName := c.Query("token_name")
username := c.Query("username")
modelName := c.Query("model_name")
channelName := c.Query("channel_name")
quotaNum := model.SumUsedQuota(logType, startTimestamp, endTimestamp, modelName, username, "", channelName)
quotaNum := model.SumUsedQuota(logType, startTimestamp, endTimestamp, modelName, username, tokenName, channelName)
//tokenNum := model.SumUsedToken(logType, startTimestamp, endTimestamp, modelName, username, "")
c.JSON(200, gin.H{
"success": true,

View File

@ -454,7 +454,8 @@
"起始时间": "Start Time",
"结束时间": "End Time",
"查询": "Query",
"提示令牌": "Prompt Token",
"补全令牌": "Completion Token",
"消耗额度": "Used Quota"
"提示": "Prompt",
"补全": "Completion",
"消耗额度": "Used Quota",
"可选值": "Optional Values"
}

View File

@ -68,7 +68,7 @@ func RecordConsumeLog(userId int, promptTokens int, completionTokens int, modelN
}
}
func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName string, username string, startIdx int, num int, channelName string) (logs []*Log, err error) {
func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName string, username string, tokenName string, startIdx int, num int, channelName string) (logs []*Log, err error) {
var tx *gorm.DB
if logType == LogTypeUnknown {
tx = DB
@ -81,6 +81,9 @@ func GetAllLogs(logType int, startTimestamp int64, endTimestamp int64, modelName
if username != "" {
tx = tx.Where("username = ?", username)
}
if tokenName != "" {
tx = tx.Where("token_name = ?", tokenName)
}
if startTimestamp != 0 {
tx = tx.Where("created_at >= ?", startTimestamp)
}

View File

@ -51,13 +51,14 @@ const LogsTable = () => {
const isAdminUser = isAdmin();
let now = new Date();
const [inputs, setInputs] = useState({
name: '',
username: '',
token_name: '',
model_name: '',
channel_name: '',
start_timestamp: timestamp2string(0),
end_timestamp: timestamp2string(now.getTime() / 1000 + 3600)
});
const { name, model_name,channel_name, start_timestamp, end_timestamp } = inputs;
const { channel_name, username, token_name, model_name, start_timestamp, end_timestamp } = inputs;
const [stat, setStat] = useState({
quota: 0,
@ -71,7 +72,7 @@ const LogsTable = () => {
const getLogSelfStat = async () => {
let localStartTimestamp = Date.parse(start_timestamp) / 1000;
let localEndTimestamp = Date.parse(end_timestamp) / 1000;
let res = await API.get(`/api/log/self/stat?type=${logType}&token_name=${name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`);
let res = await API.get(`/api/log/self/stat?type=${logType}&token_name=${token_name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`);
const { success, message, data } = res.data;
if (success) {
setStat(data);
@ -83,7 +84,7 @@ const LogsTable = () => {
const getLogStat = async () => {
let localStartTimestamp = Date.parse(start_timestamp) / 1000;
let localEndTimestamp = Date.parse(end_timestamp) / 1000;
let res = await API.get(`/api/log/stat?type=${logType}&username=${name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`);
let res = await API.get(`/api/log/stat?type=${logType}&username=${username}&token_name=${token_name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`);
const { success, message, data } = res.data;
if (success) {
setStat(data);
@ -97,9 +98,9 @@ const LogsTable = () => {
let localStartTimestamp = Date.parse(start_timestamp) / 1000;
let localEndTimestamp = Date.parse(end_timestamp) / 1000;
if (isAdminUser) {
url = `/api/log/?p=${startIdx}&type=${logType}&username=${name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`;
url = `/api/log/?p=${startIdx}&type=${logType}&username=${username}&token_name=${token_name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`;
} else {
url = `/api/log/self/?p=${startIdx}&type=${logType}&token_name=${name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`;
url = `/api/log/self/?p=${startIdx}&type=${logType}&token_name=${token_name}&model_name=${model_name}&channel_name=${channel_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`;
}
const res = await API.get(url);
const { success, message, data } = res.data;
@ -129,6 +130,7 @@ const LogsTable = () => {
const refresh = async () => {
setLoading(true);
setActivePage(1)
await loadLogs(0);
if (isAdminUser) {
getLogStat().then();
@ -184,12 +186,20 @@ const LogsTable = () => {
<Header as='h3'>使用明细总消耗额度{renderQuota(stat.quota)}</Header>
<Form>
<Form.Group>
<Form.Input fluid label={isAdminUser ? '用户名称' : '令牌名称'} width={3} value={name}
placeholder={isAdminUser ? '留空则查询全部用户' : '留空则查询全部令牌'} name='name'
{
isAdminUser && (
<Form.Input fluid label={'用户名称'} width={2} value={username}
placeholder={'可选值'} name='username'
onChange={handleInputChange} />
)
}
<Form.Input fluid label={'令牌名称'} width={isAdminUser ? 2 : 3} value={token_name}
placeholder={'可选值'} name='token_name' onChange={handleInputChange} />
<Form.Input fluid label='模型名称' width={isAdminUser ? 2 : 3} value={model_name} placeholder='可选值'
name='model_name'
onChange={handleInputChange} />
<Form.Input fluid label='模型名称' width={3} value={model_name} placeholder='留空则查询全部模型' name='model_name'
onChange={handleInputChange} />
<Form.Input fluid label='渠道名称' width={3} value={channel_name} placeholder='留空则查询全部模型' name='channel_name'
<Form.Input fluid label='渠道名称' width={isAdminUser ? 2 : 3} value={channel_name} placeholder='可选值'
name='channel_name'
onChange={handleInputChange} />
<Form.Input fluid label='起始时间' width={4} value={start_timestamp} type='datetime-local'
name='start_timestamp'
@ -212,11 +222,25 @@ const LogsTable = () => {
>
时间
</Table.HeaderCell>
{
isAdminUser && <Table.HeaderCell
style={{ cursor: 'pointer' }}
onClick={() => {
sortLog('username');
}}
width={1}
>
用户
</Table.HeaderCell>
}
<Table.HeaderCell
style={{ cursor: 'pointer' }}
onClick={() => {
sortLog('token_name');
}}
width={1}
>
{isAdminUser ? '用户' : '令牌'}
令牌
</Table.HeaderCell>
<Table.HeaderCell
style={{ cursor: 'pointer' }}
@ -252,7 +276,7 @@ const LogsTable = () => {
}}
width={1}
>
提示令牌
提示
</Table.HeaderCell>
<Table.HeaderCell
style={{ cursor: 'pointer' }}
@ -261,7 +285,7 @@ const LogsTable = () => {
}}
width={1}
>
补全令牌
补全
</Table.HeaderCell>
<Table.HeaderCell
style={{ cursor: 'pointer' }}
@ -277,7 +301,7 @@ const LogsTable = () => {
onClick={() => {
sortLog('content');
}}
width={5}
width={isAdminUser ? 4 : 5}
>
详情
</Table.HeaderCell>
@ -300,16 +324,12 @@ const LogsTable = () => {
<Table.Cell>{log.username ? <Label>{log.username}</Label> : ''}</Table.Cell>
)
}
{
!isAdminUser && (
<Table.Cell>{log.token_name ? <Label>{log.token_name}</Label> : ''}</Table.Cell>
)
}
<Table.Cell>{log.token_name ? <Label basic>{log.token_name}</Label> : ''}</Table.Cell>
<Table.Cell>{renderType(log.type)}</Table.Cell>
<Table.Cell>{log.model_name ? <Label basic>{log.model_name}</Label> : ''}</Table.Cell>
<Table.Cell>{log.channel_name ? <Label basic>{log.channel_name}</Label> : ''}</Table.Cell>
<Table.Cell>{log.prompt_tokens ? log.prompt_tokens: ''}</Table.Cell>
<Table.Cell>{log.completion_tokens ? log.completion_tokens: ''}</Table.Cell>
<Table.Cell>{log.prompt_tokens ? log.prompt_tokens : ''}</Table.Cell>
<Table.Cell>{log.completion_tokens ? log.completion_tokens : ''}</Table.Cell>
<Table.Cell>{log.quota ? renderQuota(log.quota, 6) : ''}</Table.Cell>
<Table.Cell>{log.content}</Table.Cell>
</Table.Row>
@ -319,7 +339,7 @@ const LogsTable = () => {
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan={'8'}>
<Table.HeaderCell colSpan={'10'}>
<Select
placeholder='选择明细分类'
options={LOG_OPTIONS}