Commit 75f0cb8e by jasonzeng

feat: add error logging functionality to relay and update logs table for error type display

parent f970a039
...@@ -39,6 +39,26 @@ func relayHandler(c *gin.Context, relayMode int) *dto.OpenAIErrorWithStatusCode ...@@ -39,6 +39,26 @@ func relayHandler(c *gin.Context, relayMode int) *dto.OpenAIErrorWithStatusCode
default: default:
err = relay.TextHelper(c) err = relay.TextHelper(c)
} }
if err != nil {
// 保存错误日志到mysql中
userId := c.GetInt("id")
tokenName := c.GetString("token_name")
modelName := c.GetString("original_model")
tokenId := c.GetInt("token_id")
userGroup := c.GetString("group")
channelId := c.GetInt("channel_id")
other := make(map[string]interface{})
other["error_type"] = err.Error.Type
other["error_code"] = err.Error.Code
other["status_code"] = err.StatusCode
other["channel_id"] = channelId
other["channel_name"] = c.GetString("channel_name")
other["channel_type"] = c.GetInt("channel_type")
model.RecordErrorLog(c, userId, channelId, modelName, tokenName, err.Error.Message, tokenId, 0, false, userGroup, other)
}
return err return err
} }
......
...@@ -40,6 +40,7 @@ const ( ...@@ -40,6 +40,7 @@ const (
LogTypeConsume LogTypeConsume
LogTypeManage LogTypeManage
LogTypeSystem LogTypeSystem
LogTypeError
) )
func formatUserLogs(logs []*Log) { func formatUserLogs(logs []*Log) {
...@@ -88,6 +89,35 @@ func RecordLog(userId int, logType int, content string) { ...@@ -88,6 +89,35 @@ func RecordLog(userId int, logType int, content string) {
} }
} }
func RecordErrorLog(c *gin.Context, userId int, channelId int, modelName string, tokenName string, content string, tokenId int, useTimeSeconds int,
isStream bool, group string, other map[string]interface{}) {
common.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")
otherStr := common.MapToJsonStr(other)
log := &Log{
UserId: userId,
Username: username,
CreatedAt: common.GetTimestamp(),
Type: LogTypeError,
Content: content,
PromptTokens: 0,
CompletionTokens: 0,
TokenName: tokenName,
ModelName: modelName,
Quota: 0,
ChannelId: channelId,
TokenId: tokenId,
UseTime: useTimeSeconds,
IsStream: isStream,
Group: group,
Other: otherStr,
}
err := LOG_DB.Create(log).Error
if err != nil {
common.LogError(c, "failed to record log: "+err.Error())
}
}
func RecordConsumeLog(c *gin.Context, userId int, channelId int, promptTokens int, completionTokens int, func RecordConsumeLog(c *gin.Context, userId int, channelId int, promptTokens int, completionTokens int,
modelName string, tokenName string, quota int, content string, tokenId int, userQuota int, useTimeSeconds int, modelName string, tokenName string, quota int, content string, tokenId int, userQuota int, useTimeSeconds int,
isStream bool, group string, other map[string]interface{}) { isStream bool, group string, other map[string]interface{}) {
......
...@@ -85,8 +85,10 @@ const LogsTable = () => { ...@@ -85,8 +85,10 @@ const LogsTable = () => {
return <Tag color='orange' size='large'>{t('管理')}</Tag>; return <Tag color='orange' size='large'>{t('管理')}</Tag>;
case 4: case 4:
return <Tag color='purple' size='large'>{t('系统')}</Tag>; return <Tag color='purple' size='large'>{t('系统')}</Tag>;
case 5:
return <Tag color='red' size='large'>{t('错误')}</Tag>;
default: default:
return <Tag color='black' size='large'>{t('未知')}</Tag>; return <Tag color='grey' size='large'>{t('未知')}</Tag>;
} }
} }
...@@ -160,7 +162,7 @@ const LogsTable = () => { ...@@ -160,7 +162,7 @@ const LogsTable = () => {
color={stringToColor(record.model_name)} color={stringToColor(record.model_name)}
size='large' size='large'
onClick={(event) => { onClick={(event) => {
copyText(event, record.model_name).then(r => {}); copyText(event, record.model_name).then(r => { });
}} }}
> >
{' '}{record.model_name}{' '} {' '}{record.model_name}{' '}
...@@ -170,13 +172,13 @@ const LogsTable = () => { ...@@ -170,13 +172,13 @@ const LogsTable = () => {
<> <>
<Space vertical align={'start'}> <Space vertical align={'start'}>
<Popover content={ <Popover content={
<div style={{padding: 10}}> <div style={{ padding: 10 }}>
<Space vertical align={'start'}> <Space vertical align={'start'}>
<Tag <Tag
color={stringToColor(record.model_name)} color={stringToColor(record.model_name)}
size='large' size='large'
onClick={(event) => { onClick={(event) => {
copyText(event, record.model_name).then(r => {}); copyText(event, record.model_name).then(r => { });
}} }}
> >
{t('请求并计费模型')}{' '}{record.model_name}{' '} {t('请求并计费模型')}{' '}{record.model_name}{' '}
...@@ -185,7 +187,7 @@ const LogsTable = () => { ...@@ -185,7 +187,7 @@ const LogsTable = () => {
color={stringToColor(other.upstream_model_name)} color={stringToColor(other.upstream_model_name)}
size='large' size='large'
onClick={(event) => { onClick={(event) => {
copyText(event, other.upstream_model_name).then(r => {}); copyText(event, other.upstream_model_name).then(r => { });
}} }}
> >
{t('实际模型')}{' '}{other.upstream_model_name}{' '} {t('实际模型')}{' '}{other.upstream_model_name}{' '}
...@@ -197,9 +199,9 @@ const LogsTable = () => { ...@@ -197,9 +199,9 @@ const LogsTable = () => {
color={stringToColor(record.model_name)} color={stringToColor(record.model_name)}
size='large' size='large'
onClick={(event) => { onClick={(event) => {
copyText(event, record.model_name).then(r => {}); copyText(event, record.model_name).then(r => { });
}} }}
suffixIcon={<IconRefresh style={{width: '0.8em', height: '0.8em', opacity: 0.6}} />} suffixIcon={<IconRefresh style={{ width: '0.8em', height: '0.8em', opacity: 0.6 }} />}
> >
{' '}{record.model_name}{' '} {' '}{record.model_name}{' '}
</Tag> </Tag>
...@@ -325,7 +327,7 @@ const LogsTable = () => { ...@@ -325,7 +327,7 @@ const LogsTable = () => {
className: isAdmin() ? 'tableShow' : 'tableHiddle', className: isAdmin() ? 'tableShow' : 'tableHiddle',
render: (text, record, index) => { render: (text, record, index) => {
return isAdminUser ? ( return isAdminUser ? (
record.type === 0 || record.type === 2 ? ( (record.type === 0 || record.type === 2 || record.type === 5) ? (
<div> <div>
{ {
<Tooltip content={record.channel_name || '[未知]'}> <Tooltip content={record.channel_name || '[未知]'}>
...@@ -378,7 +380,7 @@ const LogsTable = () => { ...@@ -378,7 +380,7 @@ const LogsTable = () => {
title: t('令牌'), title: t('令牌'),
dataIndex: 'token_name', dataIndex: 'token_name',
render: (text, record, index) => { render: (text, record, index) => {
return record.type === 0 || record.type === 2 ? ( return (record.type === 0 || record.type === 2 || record.type === 5) ? (
<div> <div>
<Tag <Tag
color='grey' color='grey'
...@@ -402,7 +404,7 @@ const LogsTable = () => { ...@@ -402,7 +404,7 @@ const LogsTable = () => {
title: t('分组'), title: t('分组'),
dataIndex: 'group', dataIndex: 'group',
render: (text, record, index) => { render: (text, record, index) => {
if (record.type === 0 || record.type === 2) { if (record.type === 0 || record.type === 2 || record.type === 5) {
if (record.group) { if (record.group) {
return ( return (
<> <>
...@@ -447,7 +449,7 @@ const LogsTable = () => { ...@@ -447,7 +449,7 @@ const LogsTable = () => {
title: t('模型'), title: t('模型'),
dataIndex: 'model_name', dataIndex: 'model_name',
render: (text, record, index) => { render: (text, record, index) => {
return record.type === 0 || record.type === 2 ? ( return (record.type === 0 || record.type === 2 || record.type === 5) ? (
<>{renderModelName(record)}</> <>{renderModelName(record)}</>
) : ( ) : (
<></> <></>
...@@ -487,7 +489,7 @@ const LogsTable = () => { ...@@ -487,7 +489,7 @@ const LogsTable = () => {
title: t('提示'), title: t('提示'),
dataIndex: 'prompt_tokens', dataIndex: 'prompt_tokens',
render: (text, record, index) => { render: (text, record, index) => {
return record.type === 0 || record.type === 2 ? ( return (record.type === 0 || record.type === 2 || record.type === 5) ? (
<>{<span> {text} </span>}</> <>{<span> {text} </span>}</>
) : ( ) : (
<></> <></>
...@@ -500,7 +502,7 @@ const LogsTable = () => { ...@@ -500,7 +502,7 @@ const LogsTable = () => {
dataIndex: 'completion_tokens', dataIndex: 'completion_tokens',
render: (text, record, index) => { render: (text, record, index) => {
return parseInt(text) > 0 && return parseInt(text) > 0 &&
(record.type === 0 || record.type === 2) ? ( (record.type === 0 || record.type === 2 || record.type === 5) ? (
<>{<span> {text} </span>}</> <>{<span> {text} </span>}</>
) : ( ) : (
<></> <></>
...@@ -512,7 +514,7 @@ const LogsTable = () => { ...@@ -512,7 +514,7 @@ const LogsTable = () => {
title: t('花费'), title: t('花费'),
dataIndex: 'quota', dataIndex: 'quota',
render: (text, record, index) => { render: (text, record, index) => {
return record.type === 0 || record.type === 2 ? ( return (record.type === 0 || record.type === 2 || record.type === 5) ? (
<>{renderQuota(text, 6)}</> <>{renderQuota(text, 6)}</>
) : ( ) : (
<></> <></>
...@@ -962,7 +964,7 @@ const LogsTable = () => { ...@@ -962,7 +964,7 @@ const LogsTable = () => {
const handlePageChange = (page) => { const handlePageChange = (page) => {
setActivePage(page); setActivePage(page);
loadLogs(page, pageSize, logType).then((r) => {}); loadLogs(page, pageSize, logType).then((r) => { });
}; };
const handlePageSizeChange = async (size) => { const handlePageSizeChange = async (size) => {
...@@ -1146,7 +1148,7 @@ const LogsTable = () => { ...@@ -1146,7 +1148,7 @@ const LogsTable = () => {
<Form.Section></Form.Section> <Form.Section></Form.Section>
</> </>
</Form> </Form>
<div style={{marginTop:10}}> <div style={{ marginTop: 10 }}>
<Select <Select
defaultValue='0' defaultValue='0'
style={{ width: 120 }} style={{ width: 120 }}
...@@ -1160,6 +1162,7 @@ const LogsTable = () => { ...@@ -1160,6 +1162,7 @@ const LogsTable = () => {
<Select.Option value='2'>{t('消费')}</Select.Option> <Select.Option value='2'>{t('消费')}</Select.Option>
<Select.Option value='3'>{t('管理')}</Select.Option> <Select.Option value='3'>{t('管理')}</Select.Option>
<Select.Option value='4'>{t('系统')}</Select.Option> <Select.Option value='4'>{t('系统')}</Select.Option>
<Select.Option value='5'>{t('错误')}</Select.Option>
</Select> </Select>
<Button <Button
theme='light' theme='light'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment