chore: adjust the date range for usage
This commit is contained in:
@@ -32,7 +32,7 @@ const LogsPagination: React.FC<LogsPaginationProps> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pagination">
|
<div className="pagination">
|
||||||
{page > 1 && (
|
{
|
||||||
<>
|
<>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({ id: 'models.logs.pagination.first' })}
|
title={intl.formatMessage({ id: 'models.logs.pagination.first' })}
|
||||||
@@ -64,7 +64,7 @@ const LogsPagination: React.FC<LogsPaginationProps> = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</>
|
</>
|
||||||
)}
|
}
|
||||||
<span className="pages">
|
<span className="pages">
|
||||||
<span className="curr">{page}</span> /{' '}
|
<span className="curr">{page}</span> /{' '}
|
||||||
<span className="total">{total}</span>
|
<span className="total">{total}</span>
|
||||||
|
|||||||
@@ -1,191 +1,18 @@
|
|||||||
import PageTools from '@/components/page-tools';
|
import PageTools from '@/components/page-tools';
|
||||||
|
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Col, Row } from 'antd';
|
import { Col, Row } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import { FC, memo, useContext } from 'react';
|
||||||
import _ from 'lodash';
|
|
||||||
import { FC, memo, useCallback, useContext, useEffect, useState } from 'react';
|
|
||||||
import { DashboardContext } from '../../config/dashboard-context';
|
import { DashboardContext } from '../../config/dashboard-context';
|
||||||
import RequestTokenInner from './request-token-inner';
|
import RequestTokenInner from './request-token-inner';
|
||||||
import TopUser from './top-user';
|
import TopUser from './top-user';
|
||||||
|
import useUsageData from './use-usage-data';
|
||||||
const baseColorMap = {
|
|
||||||
baseL2: 'rgba(13,171,219,0.8)',
|
|
||||||
baseL1: 'rgba(0,34,255,0.8)',
|
|
||||||
base: 'rgba(0,85,255,0.8)',
|
|
||||||
baseR1: 'rgba(0,255,233,0.8)',
|
|
||||||
baseR2: 'rgba(48,0,255,0.8)',
|
|
||||||
baseR3: 'rgba(85,167,255,0.8)'
|
|
||||||
};
|
|
||||||
|
|
||||||
const getCurrentMonthDays = () => {
|
|
||||||
const now = dayjs();
|
|
||||||
const daysInMonth = now.daysInMonth();
|
|
||||||
const year = dayjs().year();
|
|
||||||
const month = dayjs().month() + 1;
|
|
||||||
|
|
||||||
const dates = [];
|
|
||||||
for (let day = 1; day <= daysInMonth; day++) {
|
|
||||||
dates.push(dayjs(`${year}-${month}-${day}`).format('YYYY-MM-DD'));
|
|
||||||
}
|
|
||||||
return dates;
|
|
||||||
};
|
|
||||||
|
|
||||||
const UsageInner: FC<{ paddingRight: string }> = ({ paddingRight }) => {
|
const UsageInner: FC<{ paddingRight: string }> = ({ paddingRight }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const [topUserData, setTopUserData] = useState<{
|
|
||||||
userData: { name: string; value: number }[];
|
|
||||||
topUserList: string[];
|
|
||||||
}>({
|
|
||||||
userData: [],
|
|
||||||
topUserList: []
|
|
||||||
});
|
|
||||||
|
|
||||||
const [requestTokenData, setRequestTokenData] = useState<{
|
|
||||||
requestData: {
|
|
||||||
name: string;
|
|
||||||
color: string;
|
|
||||||
areaStyle: any;
|
|
||||||
data: { time: string; value: number }[];
|
|
||||||
}[];
|
|
||||||
tokenData: { time: string; value: number }[];
|
|
||||||
xAxisData: string[];
|
|
||||||
}>({
|
|
||||||
requestData: [],
|
|
||||||
tokenData: [],
|
|
||||||
xAxisData: []
|
|
||||||
});
|
|
||||||
|
|
||||||
const { model_usage } = useContext(DashboardContext);
|
const { model_usage } = useContext(DashboardContext);
|
||||||
const data = model_usage || {};
|
|
||||||
|
|
||||||
const handleSelectDate = (date: any) => {
|
const { requestTokenData, topUserData } = useUsageData(model_usage || {});
|
||||||
// fetchData?.();
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateData = useCallback(() => {
|
|
||||||
const currentMonthDays = getCurrentMonthDays();
|
|
||||||
const requestList: {
|
|
||||||
name: string;
|
|
||||||
color: string;
|
|
||||||
areaStyle: any;
|
|
||||||
data: { time: string; value: number }[];
|
|
||||||
} = {
|
|
||||||
name: 'API requests',
|
|
||||||
areaStyle: {},
|
|
||||||
color: baseColorMap.base,
|
|
||||||
data: []
|
|
||||||
};
|
|
||||||
|
|
||||||
const completionData: any = {
|
|
||||||
name: 'Completion tokens',
|
|
||||||
color: baseColorMap.base,
|
|
||||||
data: []
|
|
||||||
};
|
|
||||||
const prompData: any = {
|
|
||||||
name: 'Prompt tokens',
|
|
||||||
color: baseColorMap.baseR3,
|
|
||||||
data: []
|
|
||||||
};
|
|
||||||
|
|
||||||
const topUserPrompt: any = {
|
|
||||||
name: 'Prompt tokens',
|
|
||||||
color: baseColorMap.baseR3,
|
|
||||||
data: []
|
|
||||||
};
|
|
||||||
const topUserCompletion: any = {
|
|
||||||
name: 'Completion tokens',
|
|
||||||
color: baseColorMap.base,
|
|
||||||
data: []
|
|
||||||
};
|
|
||||||
|
|
||||||
_.each(currentMonthDays, (date: string) => {
|
|
||||||
// tokens data
|
|
||||||
const item = _.find(data.completion_token_history, (item: any) => {
|
|
||||||
return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date;
|
|
||||||
});
|
|
||||||
if (!item) {
|
|
||||||
completionData.data.push({
|
|
||||||
titme: date,
|
|
||||||
value: 0
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
completionData.data.push({
|
|
||||||
value: item.value,
|
|
||||||
time: dayjs(item.timestamp * 1000).format('YYYY-MM-DD')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const promptItem = _.find(data.prompt_token_history, (item: any) => {
|
|
||||||
return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date;
|
|
||||||
});
|
|
||||||
if (!promptItem) {
|
|
||||||
prompData.data.push({
|
|
||||||
value: 0,
|
|
||||||
time: date
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
prompData.data.push({
|
|
||||||
value: promptItem.value,
|
|
||||||
time: dayjs(promptItem.timestamp * 1000).format('YYYY-MM-DD')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============== api request data =================
|
|
||||||
const requestItem = _.find(data.api_request_history, (item: any) => {
|
|
||||||
return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!requestItem) {
|
|
||||||
requestList.data.push({
|
|
||||||
time: date,
|
|
||||||
value: 0
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
requestList.data.push({
|
|
||||||
time: dayjs(requestItem.timestamp * 1000).format('YYYY-MM-DD'),
|
|
||||||
value: requestItem.value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// ========== top users ============
|
|
||||||
if (!data.top_users?.length) {
|
|
||||||
setTopUserData({
|
|
||||||
userData: [],
|
|
||||||
topUserList: []
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const users: string[] = [];
|
|
||||||
_.each(data.top_users, (item: any) => {
|
|
||||||
users.push(item.username);
|
|
||||||
topUserPrompt.data.push({
|
|
||||||
name: item.username,
|
|
||||||
value: item.prompt_token_count
|
|
||||||
});
|
|
||||||
topUserCompletion.data.push({
|
|
||||||
name: item.username,
|
|
||||||
value: item.completion_token_count
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
setTopUserData({
|
|
||||||
userData: [topUserCompletion, topUserPrompt],
|
|
||||||
topUserList: _.uniq(users)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setRequestTokenData({
|
|
||||||
requestData: [requestList],
|
|
||||||
tokenData: [completionData, prompData],
|
|
||||||
xAxisData: currentMonthDays
|
|
||||||
});
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
generateData();
|
|
||||||
}, [generateData]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
import dayjs from 'dayjs';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
const baseColorMap = {
|
||||||
|
baseL2: 'rgba(13,171,219,0.8)',
|
||||||
|
baseL1: 'rgba(0,34,255,0.8)',
|
||||||
|
base: 'rgba(0,85,255,0.8)',
|
||||||
|
baseR1: 'rgba(0,255,233,0.8)',
|
||||||
|
baseR2: 'rgba(48,0,255,0.8)',
|
||||||
|
baseR3: 'rgba(85,167,255,0.8)'
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrentMonthDays = () => {
|
||||||
|
const now = dayjs();
|
||||||
|
const daysInMonth = now.daysInMonth();
|
||||||
|
const year = dayjs().year();
|
||||||
|
const month = dayjs().month() + 1;
|
||||||
|
|
||||||
|
const dates = [];
|
||||||
|
for (let day = 1; day <= daysInMonth; day++) {
|
||||||
|
dates.push(dayjs(`${year}-${month}-${day}`).format('YYYY-MM-DD'));
|
||||||
|
}
|
||||||
|
return dates;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getLast30Days = () => {
|
||||||
|
const dates: string[] = [];
|
||||||
|
|
||||||
|
for (let i = 29; i >= 0; i--) {
|
||||||
|
const date = dayjs().subtract(i, 'day').format('YYYY-MM-DD');
|
||||||
|
dates.push(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dates;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAdjustedDateRange = (startDate: number, endDate: number): string[] => {
|
||||||
|
const start = dayjs(startDate);
|
||||||
|
const end = dayjs(endDate);
|
||||||
|
const diff = end.diff(start, 'day') + 1;
|
||||||
|
|
||||||
|
const targetRange = 30;
|
||||||
|
const diffDays = targetRange - diff;
|
||||||
|
|
||||||
|
let preDays = Math.ceil(diffDays / 2);
|
||||||
|
let postDays = Math.floor(diffDays / 2);
|
||||||
|
|
||||||
|
// if the difference is less than 30 days, adjust the start and end dates
|
||||||
|
if (diff >= targetRange) {
|
||||||
|
return Array.from({ length: targetRange }, (_, i) =>
|
||||||
|
start.add(i, 'day').format('YYYY-MM-DD')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const adjustedStart = start.subtract(preDays, 'day');
|
||||||
|
const adjustedEnd = end.add(postDays, 'day');
|
||||||
|
|
||||||
|
const totalDays = adjustedEnd.diff(adjustedStart, 'day') + 1;
|
||||||
|
|
||||||
|
const dateRange: string[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < totalDays; i++) {
|
||||||
|
dateRange.push(adjustedStart.add(i, 'day').format('YYYY-MM-DD'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return dateRange;
|
||||||
|
};
|
||||||
|
|
||||||
|
const findByDate = (list: any[], date: string) => {
|
||||||
|
return list.find(
|
||||||
|
(item) => dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function useUseageData(data: any) {
|
||||||
|
const usageData = useMemo(() => {
|
||||||
|
let topUserData: {
|
||||||
|
userData: { name: string; value: number }[];
|
||||||
|
topUserList: string[];
|
||||||
|
} = {
|
||||||
|
userData: [],
|
||||||
|
topUserList: []
|
||||||
|
};
|
||||||
|
|
||||||
|
let requestTokenData: {
|
||||||
|
requestData: {
|
||||||
|
name: string;
|
||||||
|
color: string;
|
||||||
|
areaStyle: any;
|
||||||
|
data: { time: string; value: number }[];
|
||||||
|
}[];
|
||||||
|
tokenData: { time: string; value: number }[];
|
||||||
|
xAxisData: string[];
|
||||||
|
} = {
|
||||||
|
requestData: [],
|
||||||
|
tokenData: [],
|
||||||
|
xAxisData: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const startDate = _.get(data?.api_request_history, '0.timestamp', 0);
|
||||||
|
const endDate = _.get(
|
||||||
|
data?.api_request_history || [],
|
||||||
|
data?.api_request_history?.length - 1,
|
||||||
|
0
|
||||||
|
).timestamp;
|
||||||
|
|
||||||
|
const currentMonthDays = getAdjustedDateRange(
|
||||||
|
startDate * 1000,
|
||||||
|
endDate * 1000
|
||||||
|
);
|
||||||
|
const requestList: {
|
||||||
|
name: string;
|
||||||
|
color: string;
|
||||||
|
areaStyle: any;
|
||||||
|
data: { time: string; value: number }[];
|
||||||
|
} = {
|
||||||
|
name: 'API requests',
|
||||||
|
areaStyle: {},
|
||||||
|
color: baseColorMap.base,
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const completionData: any = {
|
||||||
|
name: 'Completion tokens',
|
||||||
|
color: baseColorMap.base,
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
const promptData: any = {
|
||||||
|
name: 'Prompt tokens',
|
||||||
|
color: baseColorMap.baseR3,
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const topUserPrompt: any = {
|
||||||
|
name: 'Prompt tokens',
|
||||||
|
color: baseColorMap.baseR3,
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
const topUserCompletion: any = {
|
||||||
|
name: 'Completion tokens',
|
||||||
|
color: baseColorMap.base,
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
|
||||||
|
_.each(currentMonthDays, (date: string) => {
|
||||||
|
// tokens data
|
||||||
|
|
||||||
|
const item = findByDate(data.completion_token_history || [], date);
|
||||||
|
if (!item) {
|
||||||
|
completionData.data.push({
|
||||||
|
time: date,
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
completionData.data.push({
|
||||||
|
value: item.value,
|
||||||
|
time: dayjs(item.timestamp * 1000).format('YYYY-MM-DD')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const promptItem = findByDate(data.prompt_token_history || [], date);
|
||||||
|
if (!promptItem) {
|
||||||
|
promptData.data.push({
|
||||||
|
value: 0,
|
||||||
|
time: date
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
promptData.data.push({
|
||||||
|
value: promptItem.value,
|
||||||
|
time: dayjs(promptItem.timestamp * 1000).format('YYYY-MM-DD')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============== api request data =================
|
||||||
|
|
||||||
|
const requestItem = findByDate(data.api_request_history || [], date);
|
||||||
|
|
||||||
|
if (!requestItem) {
|
||||||
|
requestList.data.push({
|
||||||
|
time: date,
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
requestList.data.push({
|
||||||
|
time: dayjs(requestItem.timestamp * 1000).format('YYYY-MM-DD'),
|
||||||
|
value: requestItem.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ========== top users ============
|
||||||
|
if (!data.top_users?.length) {
|
||||||
|
topUserData = {
|
||||||
|
userData: [],
|
||||||
|
topUserList: []
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const users: string[] = [];
|
||||||
|
_.each(data.top_users, (item: any) => {
|
||||||
|
users.push(item.username);
|
||||||
|
topUserPrompt.data.push({
|
||||||
|
name: item.username,
|
||||||
|
value: item.prompt_token_count
|
||||||
|
});
|
||||||
|
topUserCompletion.data.push({
|
||||||
|
name: item.username,
|
||||||
|
value: item.completion_token_count
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
topUserData = {
|
||||||
|
userData: [topUserCompletion, topUserPrompt],
|
||||||
|
topUserList: _.uniq(users)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
requestTokenData = {
|
||||||
|
requestData: [requestList],
|
||||||
|
tokenData: [completionData, promptData],
|
||||||
|
xAxisData: currentMonthDays
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
requestTokenData,
|
||||||
|
topUserData
|
||||||
|
};
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return usageData;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user