Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f320088
upgrade vulnerable dependencies to fix known security issues
FU-design Jun 16, 2025
1ce02fe
upgrade vulnerable dependencies to fix known security issues
FU-design Jun 16, 2025
6635ae8
Replace vite-plugin-icons with unplugin-icons
FU-design Jun 18, 2025
56cfbe9
refactor svg-icon component
FU-design Jun 18, 2025
f4e2752
eslint bugfix
FU-design Jun 18, 2025
bc364a0
eslint bugfix
FU-design Jun 18, 2025
204a3ed
bugfix
FU-design Jun 18, 2025
4e92ba8
format bugfix
FU-design Jun 18, 2025
9a4f276
fix ci
FU-design Jun 19, 2025
3d31dfb
fix ci
FU-design Jun 19, 2025
b016e98
fix ci
FU-design Jun 19, 2025
8cc2e3f
add unit tests for filter-form
FU-design Jun 19, 2025
691c351
add lost license
FU-design Jun 19, 2025
30c598d
fix header menu not updating when navigating from AI Assistant to Sys…
FU-design Jun 19, 2025
f7d5b4a
bugfix
FU-design Jun 19, 2025
47135c5
disable Complete button until checkWorkflow is done
FU-design Jun 19, 2025
ec3a794
bugfix
FU-design Jun 19, 2025
d1fe4fb
merge code
FU-design Jun 24, 2025
b319f1e
add use-chart composable
FU-design Jun 24, 2025
5267180
change menu storage structure
FU-design Jun 26, 2025
c862169
merge code
FU-design Jun 26, 2025
df078f2
bugfix
FU-design Jun 26, 2025
aba8e8b
fix broken layout on login page
FU-design Jun 26, 2025
4a237dc
bugfix
FU-design Jun 26, 2025
55379b5
add hostname duplication check on host addition
FU-design Jul 2, 2025
92c6125
merge code
FU-design Jul 2, 2025
dbde7a2
change chart component data construct
FU-design Jul 10, 2025
7bfdac7
add charts for cluster and host metrics
FU-design Jul 11, 2025
5336430
Merge remote-tracking branch 'origin/main' into bigtop-ui-feature
FU-design Jul 11, 2025
059b0e1
format chart data with default two decimal places
FU-design Jul 11, 2025
c2562fb
merge code
FU-design Jul 12, 2025
abbf9a1
bugfix
FU-design Jul 12, 2025
eb1a72c
bugfix
FU-design Jul 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions bigtop-manager-ui/src/api/metrics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { get } from '@/api/request-util'
import type { MetricsData, TimeRangeType } from './types'

export const getClusterMetricsInfo = (paramsPath: { id: number }, params: { interval: TimeRangeType }) => {
return get<MetricsData>(`/metrics/clusters/${paramsPath.id}`, params)
}

export const getHostMetricsInfo = (paramsPath: { id: number }, params: { interval: TimeRangeType }) => {
return get<MetricsData>(`/metrics/hosts/${paramsPath.id}`, params)
}
36 changes: 36 additions & 0 deletions bigtop-manager-ui/src/api/metrics/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export type TimeRangeType = '1m' | '5m' | '15m' | '30m' | '1h' | '2h'
export type MetricsData = {
cpuUsageCur: string
memoryUsageCur: string
diskUsageCur: string
fileDescriptorUsage: string
diskReadCur: string
diskWriteCur: string
cpuUsage: string[]
systemLoad1: string[]
systemLoad5: string[]
systemLoad15: string[]
memoryUsage: string[]
diskRead: string[]
diskWrite: string[]
timestamps: string[]
}
144 changes: 95 additions & 49 deletions bigtop-manager-ui/src/components/charts/category-chart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,49 @@
<script setup lang="ts">
import dayjs from 'dayjs'
import { computed, onMounted, toRefs, watchEffect } from 'vue'
import { roundFixed } from '@/utils/storage'
import { type EChartsOption, useChart } from '@/composables/use-chart'

const props = defineProps<{
interface Props {
chartId: string
title: string
data?: any[]
timeDistance?: string
}>()
data?: any
legendMap?: [string, string][] | undefined
config?: EChartsOption
xAxisData?: string[]
formatter?: {
yAxis?: (value: unknown) => string
tooltip?: (value: unknown) => string
}
}

const props = withDefaults(defineProps<Props>(), {
legendMap: undefined,
xAxisData: () => {
return []
},
data: () => {
return {}
},
config: () => {
return {}
},
formatter: () => {
return {}
}
})

const { data, chartId, title, timeDistance } = toRefs(props)
const { data, chartId, title, config, legendMap, xAxisData, formatter } = toRefs(props)
const { initChart, setOptions } = useChart()
const baseConfig = { type: 'line' }

const option = computed(
(): EChartsOption => ({
grid: {
top: '20px',
top: '30px',
left: '40px',
right: '30px',
bottom: '20px'
bottom: '30px'
},
tooltip: {
trigger: 'axis',
Expand All @@ -47,16 +71,12 @@
textStyle: {
color: '#fff'
},
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
formatter: createTooltipFormatter(formatter.value.tooltip)
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: [],
axisPointer: {
type: 'line'
Expand All @@ -69,18 +89,11 @@
yAxis: [
{
type: 'value',
axisPointer: {
type: 'shadow',
label: {
formatter: '{value} %'
}
},
min: 0,
max: 100,
interval: 20,
axisLabel: {
width: 32,
fontSize: 8,
formatter: '{value} %'
overflow: 'truncate',
formatter: formatter.value.yAxis ?? '{value} %'
}
}
],
Expand All @@ -98,31 +111,50 @@
})
)

const intervalToMs = (interval: string): number => {
const unit = interval.replace(/\d+/g, '')
const value = parseInt(interval)

switch (unit) {
case 'm':
return value * 60 * 1000
case 'h':
return value * 60 * 60 * 1000
default:
throw new Error('Unsupported interval: ' + interval)
}
const defaultTooltipFormatter = (val: unknown) => {
const num = roundFixed(val)
return num ? `${num} %` : '--'
}

const getTimePoints = (interval: string = '15m'): string[] => {
const now = dayjs()
const gap = intervalToMs(interval)
const result: string[] = []
const tooltipHtml = (item: any) => {
return `
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; gap: 12px">
<div style="display: flex; align-items: center;">
<div>${item.marker}${item.seriesName}</div>
</div>
<div>${item.valueText}</div>
</div>
`
}

for (let i = 5; i >= 0; i--) {
const time = now.subtract(i * gap, 'millisecond')
result.push(time.format('HH:mm'))
const createTooltipFormatter = (formatValue?: (value: unknown) => string) => {
const format = formatValue ?? defaultTooltipFormatter
console.log('format :>> ', format)
return (params: any) => {
const title = params[0]?.axisValueLabel ?? ''
const lines = params
.map((item: any) => {
const valueText = format(item.value)
return tooltipHtml({ ...item, valueText })
})
.join('')
return `<div style="margin-bottom: 4px;">${title}</div>${lines}`
}
}

return result
/**
* Generates ECharts series config by mapping legend keys to data and formatting values.
*
* @param data - A partial object containing data arrays for each series key.
* @param legendMap - An array of [key, displayName] pairs.
* @returns An array of ECharts series config objects with populated and formatted data.
*/
const generateChartSeries = <T,>(data: Partial<T>, legendMap: [string, string][]) => {
return legendMap.map(([key, name]) => ({
name,
...baseConfig,
data: (data[key] || []).map((v: unknown) => roundFixed(v))
}))
}

onMounted(() => {
Expand All @@ -131,14 +163,28 @@
})

watchEffect(() => {
setOptions({
xAxis: [{ data: getTimePoints(timeDistance.value) || [] }]
})
})
let series = [] as any,
legend = [] as any

if (legendMap.value) {
legend = new Map(legendMap.value).values()
series = generateChartSeries(data.value, legendMap.value)
} else {
series = [
{
name: title.value.toLowerCase(),
data: data.value.map((v) => roundFixed(v))
}
]
}

watchEffect(() => {
setOptions({
series: [{ data: [{ value: data.value ?? [] }] }]
xAxis: xAxisData.value
? [{ data: xAxisData.value?.map((v) => dayjs(Number(v) * 1000).format('HH:mm')) || [] }]
: [],
...config.value,
legend,
series
})
})
</script>
Expand Down
16 changes: 8 additions & 8 deletions bigtop-manager-ui/src/components/charts/gauge-chart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@

<script setup lang="ts">
import { onMounted, shallowRef, toRefs, watchEffect } from 'vue'

import { type EChartsOption, useChart } from '@/composables/use-chart'
import { roundFixed } from '@/utils/storage'

interface GaugeChartProps {
chartId: string
title: string
percent?: number
percent?: string
}

const props = withDefaults(defineProps<GaugeChartProps>(), { percent: 0 })
const props = withDefaults(defineProps<GaugeChartProps>(), { percent: '0.00' })
const { percent, chartId, title } = toRefs(props)
const { initChart, setOptions } = useChart()

Expand Down Expand Up @@ -77,13 +79,13 @@
},
detail: {
valueAnimation: true,
formatter: '{value}%',
color: 'inherit',
fontSize: 18
fontSize: 18,
formatter: (val: number) => `${roundFixed(val, 2, '0.00', false)}%`
},
data: [
{
value: 0 * 100
value: 0.0
}
]
}
Expand All @@ -96,9 +98,7 @@
})

watchEffect(() => {
setOptions({
series: [{ data: [{ value: percent.value.toFixed(2) === 'NaN' ? 0 : percent.value.toFixed(2) }] }]
})
setOptions({ series: [{ data: [{ value: percent.value }] }] })
})
</script>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import { CommonStatus, CommonStatusTexts } from '@/enums/state'
import GaugeChart from '@/components/charts/gauge-chart.vue'
import CategoryChart from '@/components/charts/category-chart.vue'
import { Empty } from 'ant-design-vue'
import type { ServiceVO, ServiceStatusType } from '@/api/service/types'

type TimeRangeText = '1m' | '15m' | '30m' | '1h' | '6h' | '30h'
Expand Down Expand Up @@ -166,7 +167,7 @@
</div>
<template v-if="noChartData">
<div class="box-empty">
<a-empty />
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
</div>
</template>
<a-row v-else class="box-content">
Expand Down Expand Up @@ -213,7 +214,7 @@

&-content {
border-radius: 8px;
overflow: hidden;
overflow: visible;
box-sizing: border-box;
border: 1px solid $color-border;
}
Expand Down
16 changes: 13 additions & 3 deletions bigtop-manager-ui/src/composables/use-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,33 @@

import * as echarts from 'echarts/core'
import { GaugeChart, GaugeSeriesOption, LineChart, LineSeriesOption } from 'echarts/charts'
import { GridComponent, GridComponentOption, TooltipComponent, TooltipComponentOption } from 'echarts/components'
import {
TitleComponent,
GridComponent,
GridComponentOption,
TooltipComponent,
TooltipComponentOption,
LegendComponent,
LegendComponentOption
} from 'echarts/components'
import { UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import { onBeforeUnmount, onMounted, shallowRef } from 'vue'

export type EChartsOption = echarts.ComposeOption<
GaugeSeriesOption | GridComponentOption | TooltipComponentOption | LineSeriesOption
GaugeSeriesOption | GridComponentOption | TooltipComponentOption | LineSeriesOption | LegendComponentOption
>

echarts.use([
TitleComponent,
GaugeChart,
CanvasRenderer,
GridComponent,
LineChart,
TooltipComponent,
CanvasRenderer,
UniversalTransition
UniversalTransition,
LegendComponent
])

export const useChart = () => {
Expand Down
4 changes: 3 additions & 1 deletion bigtop-manager-ui/src/locales/en_US/overview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ export default {
service_name: 'Name',
service_version: 'Version',
metrics: 'Metrics',
kerberos: 'Kerberos'
kerberos: 'Kerberos',
system_load: 'System Load',
disk_io: 'Disk I/O'
}
4 changes: 3 additions & 1 deletion bigtop-manager-ui/src/locales/zh_CN/overview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ export default {
service_name: '服务名',
service_version: '服务版本',
metrics: '指标监控',
kerberos: 'Kerberos'
kerberos: 'Kerberos',
system_load: '系统负载',
disk_io: '磁盘 I/O'
}
Loading
Loading