Skip to content

Commit 85670d7

Browse files
committed
[#12240] Heatmap apply getHeatmapAppData api
1 parent 976ae62 commit 85670d7

File tree

3 files changed

+115
-75
lines changed

3 files changed

+115
-75
lines changed

web-frontend/src/main/v3/packages/ui/src/components/Heatmap/HeatmapChartCore.tsx

Lines changed: 114 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from 'echarts/components';
1212
import { ECharts, EChartsOption } from 'echarts';
1313
import { colors, GetHeatmapAppData } from '@pinpoint-fe/ui/src/constants';
14-
import { capitalize, debounce } from 'lodash';
14+
import { capitalize, debounce, max } from 'lodash';
1515
import { defaultTickFormatter } from '@pinpoint-fe/ui/src/components/ReChart';
1616
import { HeatmapSettingType } from './HeatmapSetting';
1717

@@ -26,10 +26,15 @@ echarts.use([
2626

2727
echarts.use([HeatmapChartEcharts, CanvasRenderer]);
2828

29+
const colorSteps = 10;
2930
export const HeatmapColor = {
30-
success: '#34b994',
31-
failed: '#eb4748',
32-
selected: 'blue',
31+
success: Array.from({ length: colorSteps }, (_, i) => {
32+
return colors.green[(i + 1) * 100 === 1000 ? 950 : (i + 1) * 100];
33+
}),
34+
fail: Array.from({ length: colorSteps }, (_, i) => {
35+
return colors.red[(i + 1) * 100 === 1000 ? 950 : (i + 1) * 100];
36+
}),
37+
selected: colors.yellow[200],
3338
};
3439

3540
type HeatmapChartCoreProps = {
@@ -38,6 +43,14 @@ type HeatmapChartCoreProps = {
3843
setting: HeatmapSettingType;
3944
};
4045

46+
type DataForRender = {
47+
value: [string, string, number];
48+
itemStyle?: {
49+
color: string;
50+
opacity: number;
51+
};
52+
};
53+
4154
const HeatmapChartCore = React.forwardRef(
4255
({ data, setting }: HeatmapChartCoreProps, ref: React.Ref<ReactEChartsCore>) => {
4356
const containerRef = React.useRef<HTMLDivElement>(null);
@@ -88,39 +101,54 @@ const HeatmapChartCore = React.forwardRef(
88101
[startCell, endCell],
89102
);
90103

104+
const maxCount = React.useMemo(() => {
105+
let success = 0;
106+
let fail = 0;
107+
108+
const { heatmapData } = data || {};
109+
110+
if (heatmapData) {
111+
for (const data of heatmapData) {
112+
for (const cell of data.cellDataList) {
113+
success = Math.max(success, cell.successCount);
114+
fail = Math.max(fail, cell.failCount);
115+
}
116+
}
117+
}
118+
119+
return { success, fail };
120+
}, [data]);
121+
91122
const dataForRender = React.useMemo(() => {
92-
const successData: [string, string, number][] = [];
93-
const failData: {
94-
value: [string, string, number];
95-
itemStyle?: {
96-
color: string;
97-
opacity: number;
98-
};
99-
}[] = [];
100-
let maxFailCount = 0;
101-
let maxSuccessCount = 0;
123+
const successData: DataForRender['value'][] = [];
124+
const failData: DataForRender['value'][] = [];
125+
const coverData: DataForRender[] = []; // 가장 위에 덮어져서 tooltip, select 이벤트를 받기 위한 것
102126

103127
const { heatmapData } = data || {};
104128
heatmapData?.forEach((row) => {
105129
row?.cellDataList?.forEach((cell) => {
106-
successData.push([String(row.timestamp), String(cell.elapsedTime), cell.successCount]);
107-
failData.push({
108-
value: [String(row.timestamp), String(cell.elapsedTime), cell.failCount],
109-
itemStyle: isSelectedCell(row.timestamp, cell.elapsedTime)
110-
? {
111-
color: HeatmapColor.selected,
112-
opacity: 0.8,
113-
}
114-
: undefined,
130+
coverData.push({
131+
value: [String(row.timestamp), String(cell.elapsedTime), 0],
132+
itemStyle: {
133+
color: isSelectedCell(row.timestamp, cell.elapsedTime)
134+
? HeatmapColor.selected
135+
: 'transparent',
136+
opacity: 1,
137+
},
115138
});
116139

117-
maxSuccessCount = Math.max(maxSuccessCount, cell.successCount);
118-
maxFailCount = Math.max(maxFailCount, cell.failCount);
140+
if (cell?.successCount) {
141+
successData.push([String(row.timestamp), String(cell.elapsedTime), cell.successCount]);
142+
}
143+
144+
if (cell?.failCount) {
145+
failData.push([String(row.timestamp), String(cell.elapsedTime), cell.failCount]);
146+
}
119147
});
120148
});
121149

122-
return { successData, failData, maxFailCount, maxSuccessCount };
123-
}, [data, startCell, endCell]);
150+
return { successData, failData, coverData };
151+
}, [data, startCell, endCell, maxCount]);
124152

125153
const xAxisData = React.useMemo(() => {
126154
return data?.heatmapData?.map((row) => String(row.timestamp)) || [];
@@ -146,24 +174,30 @@ const HeatmapChartCore = React.forwardRef(
146174
},
147175
formatter: (params: any) => {
148176
const { data } = params;
149-
const [timestamp, elapsedTime, failedCount] = data?.value;
177+
const [timestamp, elapsedTime] = data?.value;
178+
179+
const failedCount = dataForRender?.failData.find((item: [string, string, number]) => {
180+
return item[0] === timestamp && item[1] === elapsedTime;
181+
})?.[2];
182+
150183
const successCount = dataForRender?.successData.find((item: [string, string, number]) => {
151184
return item[0] === timestamp && item[1] === elapsedTime;
152185
})?.[2];
186+
153187
return `
154188
<div style="display: flex; flex-direction: column; gap: 5px; padding: 2px;">
155189
<div style="margin-bottom: 5px;"><strong>${defaultTickFormatter(Number(timestamp))}</strong></div>
156-
${['success', 'failed']
190+
${['success', 'fail']
157191
.map((type) => {
158192
const count = type === 'success' ? successCount : failedCount;
159-
const color = type === 'success' ? HeatmapColor.success : HeatmapColor.failed;
193+
const color = HeatmapColor[type as 'success' | 'fail'][5];
160194
161195
return `
162196
<div style="display: flex; justify-content: space-between; gap: 5px;">
163197
<div style="display: flex; gap: 6px; align-items: center;">
164-
<div style="width: 8px; height: 8px; background: ${color}"></div>${capitalize(type)}
198+
<div style="width: 8px; height: 8px; background: ${color}; border: ${count === 0 ? '1px solid black' : 'none'};"></div>${capitalize(type)}
165199
</div>
166-
<div>${count === undefined ? 'N/A' : Number(count).toLocaleString()}</div>
200+
<div>${count === undefined ? 0 : Number(count).toLocaleString()}</div>
167201
</div>
168202
`;
169203
})
@@ -195,6 +229,7 @@ const HeatmapChartCore = React.forwardRef(
195229
data: yAxisData.filter(
196230
(yValue) => Number(yValue) >= setting.yMin && Number(yValue) <= setting.yMax,
197231
),
232+
offset: 1,
198233
axisLabel: {
199234
interval: (index: number, value: string) => {
200235
if (yAxisData.length <= 5) {
@@ -223,7 +258,7 @@ const HeatmapChartCore = React.forwardRef(
223258
{
224259
id: 'success',
225260
min: 0,
226-
max: dataForRender?.maxSuccessCount,
261+
max: maxCount.success,
227262
calculable: true,
228263
seriesIndex: 0,
229264
orient: 'horizontal',
@@ -239,14 +274,14 @@ const HeatmapChartCore = React.forwardRef(
239274
return Math.floor(Number(value)).toLocaleString();
240275
},
241276
inRange: {
242-
color: ['#ffffff', dataForRender?.maxFailCount ? HeatmapColor.success : '#ffffff'],
277+
color: HeatmapColor.success,
243278
},
244279
range: successRange,
245280
},
246281
{
247282
id: 'fail',
248283
min: 0,
249-
max: dataForRender?.maxFailCount,
284+
max: maxCount.fail,
250285
calculable: true,
251286
seriesIndex: 1,
252287
orient: 'horizontal',
@@ -259,10 +294,15 @@ const HeatmapChartCore = React.forwardRef(
259294
return Math.floor(Number(value)).toLocaleString();
260295
},
261296
inRange: {
262-
color: ['#ffffff', dataForRender?.maxFailCount ? HeatmapColor.failed : '#ffffff'],
297+
color: HeatmapColor.fail,
263298
},
264299
range: failRange,
265300
},
301+
{
302+
id: 'cover',
303+
show: false,
304+
seriesIndex: 2,
305+
},
266306
],
267307
graphic: [
268308
{
@@ -276,11 +316,11 @@ const HeatmapChartCore = React.forwardRef(
276316
rich: {
277317
boldSuccess: {
278318
fontWeight: 'bold',
279-
fill: HeatmapColor.success,
319+
fill: HeatmapColor.success[5],
280320
},
281321
boldFailed: {
282322
fontWeight: 'bold',
283-
fill: HeatmapColor.failed,
323+
fill: HeatmapColor.fail[5],
284324
},
285325
},
286326
},
@@ -293,12 +333,14 @@ const HeatmapChartCore = React.forwardRef(
293333
data: dataForRender?.successData,
294334
},
295335
{
296-
name: 'failed',
336+
name: 'fail',
297337
type: 'heatmap',
298338
data: dataForRender?.failData,
299-
itemStyle: {
300-
opacity: 0.5,
301-
},
339+
},
340+
{
341+
name: 'cover',
342+
type: 'heatmap',
343+
data: dataForRender?.coverData,
302344
emphasis: {
303345
itemStyle: {
304346
borderColor: '#333',
@@ -316,36 +358,36 @@ const HeatmapChartCore = React.forwardRef(
316358
echarts={echarts}
317359
option={option}
318360
style={{ height: '100%', width: '100%' }}
319-
onEvents={{
320-
mousedown: (params: any, echartsInstance: ECharts) => {
321-
console.log('mousedown', params);
322-
setStartCell(`${params.value[0]}-${params.value[1]}`);
323-
setEndCell(`${params.value[0]}-${params.value[1]}`);
324-
},
325-
mousemove: (params: any) => {
326-
if (!startCell) {
327-
return;
328-
}
329-
setEndCell(`${params.value[0]}-${params.value[1]}`);
330-
},
331-
mouseup: (params: any) => {
332-
console.log('mouseup', params, startCell, endCell);
333-
setStartCell('');
334-
setEndCell('');
335-
},
336-
datarangeselected: debounce((params: any) => {
337-
if (params.visualMapId === 'success') {
338-
setSuccessRange(params.selected);
339-
} else if (params.visualMapId === 'fail') {
340-
setFailRange(params.selected);
341-
}
342-
}, 300),
343-
// click: (params: any, echartsInstance: ECharts) => {
344-
// console.log('click', params);
345-
// setStartCell(`${params.value[0]}-${params.value[1]}`);
346-
// // setRange([1000, 3000]);
347-
// },
348-
}}
361+
// onEvents={{
362+
// mousedown: (params: any, echartsInstance: ECharts) => {
363+
// console.log('mousedown', params);
364+
// setStartCell(`${params.value[0]}-${params.value[1]}`);
365+
// setEndCell(`${params.value[0]}-${params.value[1]}`);
366+
// },
367+
// mousemove: (params: any) => {
368+
// if (!startCell) {
369+
// return;
370+
// }
371+
// setEndCell(`${params.value[0]}-${params.value[1]}`);
372+
// },
373+
// mouseup: (params: any) => {
374+
// console.log('mouseup', params, startCell, endCell);
375+
// setStartCell('');
376+
// setEndCell('');
377+
// },
378+
// datarangeselected: debounce((params: any) => {
379+
// if (params.visualMapId === 'success') {
380+
// setSuccessRange(params.selected);
381+
// } else if (params.visualMapId === 'fail') {
382+
// setFailRange(params.selected);
383+
// }
384+
// }, 300),
385+
// // click: (params: any, echartsInstance: ECharts) => {
386+
// // console.log('click', params);
387+
// // setStartCell(`${params.value[0]}-${params.value[1]}`);
388+
// // // setRange([1000, 3000]);
389+
// // },
390+
// }}
349391
/>
350392
</div>
351393
);

web-frontend/src/main/v3/packages/ui/src/components/Heatmap/HeatmapFetcher.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
ApplicationType,
1313
GetHeatmapAppData,
1414
} from '@pinpoint-fe/ui/src/constants';
15-
import { mockData } from './mockData';
1615

1716
export interface HeatmapFetcherHandle {
1817
handleCaptureImage: () => Promise<void>;
@@ -43,7 +42,7 @@ export const HeatmapFetcher = React.forwardRef(
4342
const { data, isLoading } = useGetHeatmapAppData(parameters);
4443

4544
// console.log('search', searchParameters, 'parameters', parameters);
46-
console.log('data', data);
45+
// console.log('data', data);
4746

4847
React.useEffect(() => {
4948
setParameters({

web-frontend/src/main/v3/packages/ui/src/pages/ServerMap.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,6 @@ export const ServerMapPage = ({
436436
onClick={() => {
437437
setChartType('heatmap');
438438
}}
439-
disabled={true}
440439
>
441440
<AiOutlineTable />
442441
</Button>

0 commit comments

Comments
 (0)