mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-04 10:13:53 +08:00
Merge branch 'feature/1.8-cx' into 'main'
feature/1.8-Improve system observability See merge request apipark/APIPark!348
This commit is contained in:
@@ -599,7 +599,7 @@ export const AI_SERVICE_LOG_LIST: PageProColumns<LogItem>[] = [
|
||||
},
|
||||
{
|
||||
title: '消费者',
|
||||
dataIndex: ['consumers', 'name'],
|
||||
dataIndex: ['consumer', 'name'],
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
|
||||
@@ -260,46 +260,11 @@ const LogDetail = ({ selectedRow, serviceType, serviceId, teamId }: LogDetailPro
|
||||
fetchData<BasicResponse<{ log: AIServiceDetailType }>>('service/log/ai', {
|
||||
method: 'GET',
|
||||
eoParams: { log: selectedRow?.id, service: serviceId, team: teamId },
|
||||
eoTransformKeys: ['is_system_consumer', 'log_time'],
|
||||
eoApiPrefix: 'http://uat.apikit.com:11204/mockApi/aoplatform/api/v1/'
|
||||
eoTransformKeys: ['is_system_consumer', 'log_time']
|
||||
}).then((response) => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
// const result = data.log
|
||||
const result = {
|
||||
id: '123',
|
||||
api: {
|
||||
id: '222',
|
||||
name: 'api222'
|
||||
},
|
||||
logTime: '2023-01-01 00:00:00',
|
||||
consumer: {
|
||||
id: '333',
|
||||
name: 'consumers333'
|
||||
},
|
||||
isSystemConsumer: false,
|
||||
status: '200',
|
||||
provider: {
|
||||
id: '444',
|
||||
name: 'provider444'
|
||||
},
|
||||
model: 'model1',
|
||||
ip: '1.1.1.1',
|
||||
request: {
|
||||
header:
|
||||
'{\n "mcpServers": {\n "APIPark/test1234": {\n "url": "http://swagger-demo.apinto.com/openapi/v1/mcp/service/c8bc25ca-8855-45cd-8bcc-239195b6c346/sse?apikey={your_api_key}"\n }\n }\n}',
|
||||
body: '{\n "mcpServers": {\n "APIPark/44444": {\n "url": "http://swagger-demo.apinto.com/openapi/v1/mcp/service/c8bc25ca-8855-45cd-8bcc-239195b6c346/sse?apikey={your_api_key}"\n }\n }\n}',
|
||||
origin: '123',
|
||||
token: 0
|
||||
},
|
||||
response: {
|
||||
header:
|
||||
'{\n "mcpServers": {\n "APIPark/44444": {\n "url": "http://swagger-demo.apinto.com/openapi/v1/mcp/service/c8bc25ca-8855-45cd-8bcc-239195b6c346/sse?apikey={your_api_key}"\n }\n }\n}',
|
||||
body: '{\n "mcpServers": {\n "APIPark/44444": {\n "url": "http://swagger-demo.apinto.com/openapi/v1/mcp/service/c8bc25ca-8855-45cd-8bcc-239195b6c346/sse?apikey={your_api_key}"\n }\n }\n}',
|
||||
origin: '312',
|
||||
token: '333'
|
||||
}
|
||||
}
|
||||
const result = data.log
|
||||
getAIServiceDescriptionItemsList({
|
||||
time: result.logTime,
|
||||
api: result.api.name,
|
||||
@@ -329,36 +294,11 @@ const LogDetail = ({ selectedRow, serviceType, serviceId, teamId }: LogDetailPro
|
||||
fetchData<BasicResponse<{ log: RestServiceDetailType }>>('service/log/rest', {
|
||||
method: 'GET',
|
||||
eoParams: { log: selectedRow?.id, service: serviceId, team: teamId },
|
||||
eoTransformKeys: ['is_system_consumer', 'log_time'],
|
||||
eoApiPrefix: 'http://uat.apikit.com:11204/mockApi/aoplatform/api/v1/'
|
||||
eoTransformKeys: ['is_system_consumer', 'log_time']
|
||||
}).then((response) => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
const result = {
|
||||
id: '123',
|
||||
api: {
|
||||
id: '222',
|
||||
name: 'api222'
|
||||
},
|
||||
logTime: '2023-01-01 00:00:00',
|
||||
consumer: {
|
||||
id: '333',
|
||||
name: 'consumers333'
|
||||
},
|
||||
isSystemConsumer: true,
|
||||
status: '200',
|
||||
ip: '1.1.1.1',
|
||||
request: {
|
||||
header:
|
||||
'{\n "mcpServers": {\n "APIPark/test1234": {\n "url": "http://swagger-demo.apinto.com/openapi/v1/mcp/service/c8bc25ca-8855-45cd-8bcc-239195b6c346/sse?apikey={your_api_key}"\n }\n }\n}',
|
||||
origin: '123'
|
||||
},
|
||||
response: {
|
||||
header:
|
||||
'{\n "mcpServers": {\n "APIPark/44444": {\n "url": "http://swagger-demo.apinto.com/openapi/v1/mcp/service/c8bc25ca-8855-45cd-8bcc-239195b6c346/sse?apikey={your_api_key}"\n }\n }\n}',
|
||||
origin: '312'
|
||||
}
|
||||
}
|
||||
const result = data.log
|
||||
getRestServiceDescriptionItemsList({
|
||||
time: result.logTime,
|
||||
api: result.api.name,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
|
||||
import { useFetch } from '@common/hooks/http'
|
||||
import LogDetail, { HttpStatusColor } from './LogDetail'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { ActionType } from '@ant-design/pro-components'
|
||||
import { ActionType, ParamsType } from '@ant-design/pro-components'
|
||||
import { getTime } from '@dashboard/utils/dashboard'
|
||||
|
||||
export type LogItem = {
|
||||
@@ -66,9 +66,7 @@ const ServiceLogs = ({ serviceType }: { serviceType: 'aiService' | 'restService'
|
||||
if (x.dataIndex === 'status') {
|
||||
x.render = (text: any, record: any) => (
|
||||
<>
|
||||
<div className="w-full">
|
||||
{renderStatusWithColor(record.status)}
|
||||
</div>
|
||||
<div className="w-full">{renderStatusWithColor(record.status)}</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -79,73 +77,62 @@ const ServiceLogs = ({ serviceType }: { serviceType: 'aiService' | 'restService'
|
||||
})
|
||||
}, [state.language])
|
||||
|
||||
/**
|
||||
* 根据状态码返回对应颜色的文本
|
||||
* @param status 状态
|
||||
* @returns
|
||||
*/
|
||||
const renderStatusWithColor = (status: string | number) => {
|
||||
// 获取状态码首位数字
|
||||
const firstDigit = status.toString().charAt(0)
|
||||
let color = ''
|
||||
switch (firstDigit) {
|
||||
case '2':
|
||||
color = HttpStatusColor.SUCCESS
|
||||
break
|
||||
case '4':
|
||||
color = HttpStatusColor.CLIENT_ERROR
|
||||
break
|
||||
case '5':
|
||||
color = HttpStatusColor.SERVER_ERROR
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
return color ? <span style={{ color }}>{status}</span> : status
|
||||
/**
|
||||
* 根据状态码返回对应颜色的文本
|
||||
* @param status 状态
|
||||
* @returns
|
||||
*/
|
||||
const renderStatusWithColor = (status: string | number) => {
|
||||
// 获取状态码首位数字
|
||||
const firstDigit = status.toString().charAt(0)
|
||||
let color = ''
|
||||
switch (firstDigit) {
|
||||
case '2':
|
||||
color = HttpStatusColor.SUCCESS
|
||||
break
|
||||
case '4':
|
||||
color = HttpStatusColor.CLIENT_ERROR
|
||||
break
|
||||
case '5':
|
||||
color = HttpStatusColor.SERVER_ERROR
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
return color ? <span style={{ color }}>{status}</span> : status
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 AI 列表数据
|
||||
* @param dataType
|
||||
* @returns
|
||||
*/
|
||||
const getAiServiceLogList = () => {
|
||||
const getAiServiceLogList = (
|
||||
params: ParamsType & {
|
||||
pageSize?: number | undefined
|
||||
current?: number | undefined
|
||||
keyword?: string | undefined
|
||||
}
|
||||
) => {
|
||||
return fetchData<BasicResponse<{ log: LogItem[] }>>(`service/logs/ai`, {
|
||||
method: 'GET',
|
||||
eoParams: {
|
||||
service: serviceId,
|
||||
team: teamId,
|
||||
start: timeRange?.start,
|
||||
end: timeRange?.end
|
||||
end: timeRange?.end,
|
||||
page: params?.current,
|
||||
page_size:params?.pageSize
|
||||
},
|
||||
eoTransformKeys: ['log_time', 'response_time', 'token_per_second'],
|
||||
eoApiPrefix: 'http://uat.apikit.com:11204/mockApi/aoplatform/api/v1/'
|
||||
eoTransformKeys: ['log_time', 'response_time', 'token_per_second']
|
||||
})
|
||||
.then((response) => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
// 保存数据
|
||||
return {
|
||||
data: [
|
||||
{
|
||||
id: '123123',
|
||||
api: {
|
||||
id: '444',
|
||||
name: 'api1'
|
||||
},
|
||||
ip: '127.0.0.1',
|
||||
status: 200,
|
||||
logTime: '2023-01-01 00:00:00',
|
||||
token: 123,
|
||||
consumers: {
|
||||
id: '333',
|
||||
name: 'consumers333'
|
||||
},
|
||||
model: 'GPT444',
|
||||
tokenPerSecond: '123m/s'
|
||||
}
|
||||
],
|
||||
total: 1,
|
||||
data: data.logs,
|
||||
total: data.total,
|
||||
success: true
|
||||
}
|
||||
} else {
|
||||
@@ -162,44 +149,33 @@ const ServiceLogs = ({ serviceType }: { serviceType: 'aiService' | 'restService'
|
||||
* @param dataType
|
||||
* @returns
|
||||
*/
|
||||
const getRestServiceLogList = () => {
|
||||
const getRestServiceLogList = (
|
||||
params: ParamsType & {
|
||||
pageSize?: number | undefined
|
||||
current?: number | undefined
|
||||
keyword?: string | undefined
|
||||
}
|
||||
) => {
|
||||
console.log('params===', params)
|
||||
return fetchData<BasicResponse<{ log: LogItem[] }>>(`service/logs/rest`, {
|
||||
method: 'GET',
|
||||
eoParams: {
|
||||
service: serviceId,
|
||||
team: teamId,
|
||||
start: timeRange?.start,
|
||||
end: timeRange?.end
|
||||
end: timeRange?.end,
|
||||
page: params?.current,
|
||||
page_size:params?.pageSize
|
||||
},
|
||||
eoTransformKeys: ['log_time', 'response_time', 'token_per_second'],
|
||||
eoApiPrefix: 'http://uat.apikit.com:11204/mockApi/aoplatform/api/v1/'
|
||||
eoTransformKeys: ['log_time', 'response_time', 'token_per_second']
|
||||
})
|
||||
.then((response) => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
const data = []
|
||||
for (let i = 0; i < 100; i++) {
|
||||
data.push({
|
||||
id: '123123' + i,
|
||||
api: {
|
||||
id: '444' + i,
|
||||
name: 'api1' + i
|
||||
},
|
||||
ip: '127.0.0.1',
|
||||
status: 200,
|
||||
logTime: '2023-01-01 00:00:00',
|
||||
responseTime: '1111-01-01 00:00:00',
|
||||
traffic: '123',
|
||||
consumers: {
|
||||
id: '123' + i,
|
||||
name: 'consumers222' + i
|
||||
}
|
||||
})
|
||||
}
|
||||
// 保存数据
|
||||
return {
|
||||
data: data,
|
||||
total: data.length,
|
||||
data: data.logs,
|
||||
total: data.total,
|
||||
success: true
|
||||
}
|
||||
} else {
|
||||
@@ -260,7 +236,13 @@ const ServiceLogs = ({ serviceType }: { serviceType: 'aiService' | 'restService'
|
||||
id={`${serviceType}_logs`}
|
||||
columns={[...columns]}
|
||||
minVirtualHeight={430}
|
||||
request={async () => (serviceType === 'aiService' ? getAiServiceLogList() : getRestServiceLogList())}
|
||||
request={async (
|
||||
params: ParamsType & {
|
||||
pageSize?: number | undefined
|
||||
current?: number | undefined
|
||||
keyword?: string | undefined
|
||||
}
|
||||
) => (serviceType === 'aiService' ? getAiServiceLogList(params) : getRestServiceLogList(params))}
|
||||
onRowClick={(row: LogItem) => handleRowClick(row)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -190,6 +190,25 @@ const ServiceAreaChart = ({ customClassNames, dataInfo, height }: ServiceAreaCha
|
||||
setChartOption(dataInfo)
|
||||
}
|
||||
}, [dataInfo, JSON.stringify(dataInfo)])
|
||||
|
||||
// 添加窗口大小变化监听,实现自适应
|
||||
useEffect(() => {
|
||||
// 定义resize处理函数
|
||||
const handleResize = () => {
|
||||
const echartsInstance = chartRef.current?.getEchartsInstance()
|
||||
if (echartsInstance) {
|
||||
echartsInstance.resize()
|
||||
}
|
||||
}
|
||||
|
||||
// 添加监听
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
// 组件卸载时移除监听
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<div className={`w-full ${customClassNames}`}>
|
||||
<div className="absolute top-[10px] left-[10px] w-full">
|
||||
|
||||
@@ -231,6 +231,25 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height }: ServiceBarCharPr
|
||||
setChartOption(dataInfo)
|
||||
}
|
||||
}, [dataInfo, JSON.stringify(dataInfo)])
|
||||
|
||||
// 添加窗口大小变化监听,实现自适应
|
||||
useEffect(() => {
|
||||
// 定义resize处理函数
|
||||
const handleResize = () => {
|
||||
const echartsInstance = chartRef.current?.getEchartsInstance()
|
||||
if (echartsInstance) {
|
||||
echartsInstance.resize()
|
||||
}
|
||||
}
|
||||
|
||||
// 添加监听
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
// 组件卸载时移除监听
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
return (
|
||||
<div className={`w-full ${customClassNames}`}>
|
||||
<ECharts ref={chartRef} option={option} style={{ height: height || 400 }} opts={{ renderer: 'svg' }} />
|
||||
|
||||
@@ -59,11 +59,11 @@ const RankingList = ({ topRankingList, serviceType }: { topRankingList: RankingL
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div className="flex w-full pb-[10px]">
|
||||
<div className="flex flex-wrap w-full pb-[10px]">
|
||||
{Object.keys(topRankingList)?.map((item: any, index: number) => (
|
||||
<Card
|
||||
key={index}
|
||||
className={`flex-1 h-fit rounded-[10px] ${index > 0 ? 'ml-[10px]' : ''}`}
|
||||
className={`flex-1 min-w-[300px] h-fit rounded-[10px] ${index > 0 ? 'ml-[10px] md:ml-[10px] sm:ml-0 sm:mt-[10px]' : ''}`}
|
||||
classNames={{
|
||||
body: 'p-[15px]'
|
||||
}}
|
||||
@@ -75,7 +75,7 @@ const RankingList = ({ topRankingList, serviceType }: { topRankingList: RankingL
|
||||
id={item}
|
||||
columns={[...columns]}
|
||||
minVirtualHeight={430}
|
||||
noScroll
|
||||
noScroll={true}
|
||||
request={() => getTableData(item)}
|
||||
showPagination={false}
|
||||
tableClass="ranking-list"
|
||||
|
||||
Reference in New Issue
Block a user