perf: do not handle ansi sequence for parsing logs
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@@ -53,7 +53,7 @@ const BarChart: React.FC<ChartProps & { maxItems?: number }> = (props) => {
|
||||
axisLabel: {
|
||||
...yAxis.axisLabel,
|
||||
overflow: 'truncate',
|
||||
width: 60,
|
||||
width: 75,
|
||||
ellipsis: '...'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -101,6 +101,7 @@ const MixLineBarChart: React.FC<
|
||||
stack: 'total',
|
||||
yAxisIndex: 0,
|
||||
itemStyle: {
|
||||
...item.itemStyle,
|
||||
color: item.color
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,6 +30,8 @@ class AnsiParser {
|
||||
private percent: number = 0;
|
||||
private isComplete: boolean = false;
|
||||
private chunked: boolean = true; // true: send data in chunks, false: send all data at once
|
||||
private reminder: string = '';
|
||||
private lines: string[] = [];
|
||||
private pageSize: number = 500;
|
||||
private colorMap = {
|
||||
'30': 'black',
|
||||
@@ -52,6 +54,8 @@ class AnsiParser {
|
||||
this.screen = [['']];
|
||||
this.rawDataRows = 0;
|
||||
this.uid = this.uid + 1;
|
||||
this.lines = [];
|
||||
this.reminder = '';
|
||||
this.page = 1;
|
||||
}
|
||||
|
||||
@@ -109,7 +113,6 @@ class AnsiParser {
|
||||
const n = parseInt(match[1] || '1', 10);
|
||||
const m = parseInt(match[2] || '1', 10);
|
||||
const command = match[3];
|
||||
|
||||
switch (command) {
|
||||
case 'A':
|
||||
this.cursorRow = Math.max(0, this.cursorRow - n);
|
||||
@@ -183,6 +186,28 @@ class AnsiParser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private processInputByLine(input: string): {
|
||||
data: string[];
|
||||
lines: number;
|
||||
remainder: string;
|
||||
} {
|
||||
const lines = input?.split(/\r?\n/) || [];
|
||||
const remainder = lines.pop() || '';
|
||||
|
||||
// const data = lines.join('\n');
|
||||
this.rawDataRows += lines.length;
|
||||
this.lines.push(...lines);
|
||||
return {
|
||||
data: this.lines,
|
||||
lines: this.rawDataRows,
|
||||
remainder
|
||||
};
|
||||
}
|
||||
|
||||
private getAllLines() {
|
||||
return this.lines.join('\n');
|
||||
}
|
||||
|
||||
private async processQueue(): Promise<void> {
|
||||
if (this.isProcessing) {
|
||||
return;
|
||||
@@ -191,11 +216,12 @@ class AnsiParser {
|
||||
this.isProcessing = true;
|
||||
|
||||
while (this.taskQueue.length > 0) {
|
||||
const input = this.taskQueue.shift();
|
||||
const input = this.reminder + this.taskQueue.shift();
|
||||
|
||||
if (input) {
|
||||
try {
|
||||
const result = this.processInput(input);
|
||||
const result = this.processInputByLine(input);
|
||||
this.reminder = result.remainder;
|
||||
if (this.chunked) {
|
||||
self.postMessage({ result: result.data, lines: result.lines });
|
||||
} else if (!this.isComplete) {
|
||||
@@ -220,7 +246,7 @@ class AnsiParser {
|
||||
this.processQueue();
|
||||
} else if (this.isComplete && !this.chunked) {
|
||||
self.postMessage({
|
||||
result: this.getScreenText(),
|
||||
result: this.getAllLines(),
|
||||
percent: this.percent,
|
||||
isComplete: true
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
|
||||
const pageRef = useRef<any>(page);
|
||||
const totalPageRef = useRef<any>(totalPage);
|
||||
const isLoadingMoreRef = useRef(false);
|
||||
const [currentData, setCurrentData] = useState<any[]>([]);
|
||||
const [currentData, setCurrentPageData] = useState<any[]>([]);
|
||||
const scrollPosRef = useRef<any>({
|
||||
pos: 'bottom',
|
||||
page: 1
|
||||
@@ -59,6 +59,21 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
|
||||
}
|
||||
}));
|
||||
|
||||
const removeBracketsFromLine = (row: string) => {
|
||||
return row.startsWith('(…)') ? row.slice(3) : row;
|
||||
};
|
||||
|
||||
const setCurrentData = (lines: string[]) => {
|
||||
const dataList = lines.map((line, index) => {
|
||||
return {
|
||||
content: removeBracketsFromLine(line),
|
||||
uid: `${pageRef.current}-${index}`
|
||||
};
|
||||
});
|
||||
|
||||
setCurrentPageData(dataList);
|
||||
};
|
||||
|
||||
const debounceLoading = _.debounce(() => {
|
||||
setLoading(false);
|
||||
isLoadingMoreRef.current = false;
|
||||
|
||||
@@ -119,7 +119,7 @@ const ExportData: React.FC<{
|
||||
init();
|
||||
} else {
|
||||
setQuery({
|
||||
start_date: dayjs().subtract(30, 'days').format('YYYY-MM-DD'),
|
||||
start_date: dayjs().subtract(29, 'days').format('YYYY-MM-DD'),
|
||||
end_date: dayjs().format('YYYY-MM-DD'),
|
||||
model_ids: [],
|
||||
user_ids: []
|
||||
|
||||
@@ -50,11 +50,19 @@ const UsageInner: FC<{ maxWidth: number }> = ({ maxWidth }) => {
|
||||
const topUserNames = topUsers.map((item: any) => {
|
||||
topUserPrompt.data.push({
|
||||
name: item.username,
|
||||
value: item.prompt_token_count
|
||||
value: item.prompt_token_count,
|
||||
itemStyle: {
|
||||
borderRadius: !item.completion_token_count
|
||||
? [2, 2, 2, 2]
|
||||
: [0, 2, 2, 0]
|
||||
}
|
||||
});
|
||||
topUserCompletion.data.push({
|
||||
name: item.username,
|
||||
value: item.completion_token_count
|
||||
value: item.completion_token_count,
|
||||
itemStyle: {
|
||||
borderRadius: !item.prompt_token_count ? [2, 2, 2, 2] : [2, 0, 0, 2]
|
||||
}
|
||||
});
|
||||
return item.username;
|
||||
});
|
||||
|
||||
@@ -85,7 +85,7 @@ const generateValueMap = (list: { timestamp: number; value: number }[]) => {
|
||||
};
|
||||
|
||||
const generateData = (dateRage: string[], valueMap: Map<string, number>) => {
|
||||
return dateRage.map((date) => {
|
||||
return dateRage.map((date, index) => {
|
||||
const value = valueMap.get(date) || 0;
|
||||
return {
|
||||
time: date,
|
||||
@@ -201,15 +201,40 @@ export default function useUseageData<T>(config: {
|
||||
};
|
||||
|
||||
// =========== token usage data ==============
|
||||
const completionDataList = generateData(
|
||||
dateRange,
|
||||
generateValueMap(completionTokenHistory)
|
||||
);
|
||||
const promptDataList = generateData(
|
||||
dateRange,
|
||||
generateValueMap(promptTokenHistory)
|
||||
);
|
||||
|
||||
const completionData: any = {
|
||||
name: 'Completion tokens',
|
||||
color: baseColorMap.base,
|
||||
data: generateData(dateRange, generateValueMap(completionTokenHistory))
|
||||
data: completionDataList.map((item, index) => {
|
||||
return {
|
||||
...item,
|
||||
itemStyle: {
|
||||
borderRadius: !promptDataList[index].value
|
||||
? [2, 2, 0, 0]
|
||||
: [0, 0, 0, 0]
|
||||
}
|
||||
};
|
||||
})
|
||||
};
|
||||
const promptData: any = {
|
||||
name: 'Prompt tokens',
|
||||
color: baseColorMap.baseR3,
|
||||
data: generateData(dateRange, generateValueMap(promptTokenHistory))
|
||||
data: promptDataList.map((item, index) => {
|
||||
return {
|
||||
...item,
|
||||
itemStyle: {
|
||||
borderRadius: [2, 2, 0, 0]
|
||||
}
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user