Skip to content

Commit

Permalink
feat: add Collection mode to Monitor (#26)
Browse files Browse the repository at this point in the history
Co-authored-by: yaojiping <[email protected]>
  • Loading branch information
yaojp123 and yaojiping authored Dec 13, 2024
1 parent 85879c5 commit 020c8aa
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 32 deletions.
114 changes: 114 additions & 0 deletions web/src/components/CollectStatus/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import request from "@/utils/request"
import { firstUpperCase, formatToUniversalTime } from "@/utils/utils";
import { Descriptions, Icon, Tooltip } from "antd";
import moment from "moment";
import { useEffect, useMemo, useRef, useState } from "react";
import styles from "./index.less";
import { formatMessage } from "umi/locale";

const STATUS_ICONS = {
'ok': (
<div
style={{
background: "#00bb1b",
height: 12,
width: 12,
borderRadius: 12,
display: "inline-block",
verticalAlign: "text-bottom",
}}
/>
),
'warning': (
<Icon
type="warning"
theme="filled"
style={{ color: "#ff3030", fontSize: 14 }}
/>
),
'unknown': (
<div
style={{
background: "#bbbbbb",
height: 12,
width: 12,
borderRadius: 12,
display: "inline-block",
verticalAlign: "text-bottom",
}}
/>
)
}

export default (props) => {

const { fetchUrl } = props;

const [loading, setLoading] = useState(false);
const [data, setData] = useState();
const intervalRef = useRef()

const fetchData = async (fetchUrl) => {
if (!fetchUrl) return
setLoading(true)
const res = await request(fetchUrl)
if (res && !res?.error) {
setData(res)
}
setLoading(false)
}

useEffect(() => {
fetchData(fetchUrl)
if (intervalRef.current) {
clearInterval(intervalRef.current)
}
intervalRef.current = setInterval(() => {
fetchData(fetchUrl)
}, 300000)
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current)
}
}
}, [fetchUrl])

const stats = useMemo(() => {
return ['cluster_health', 'cluster_stats', 'node_stats', data?.metric_collection_mode === 'agent' ? 'shard_stats' : 'index_stats']
}, [data?.metric_collection_mode])

const renderIcon = () => {
if (!data) {
return STATUS_ICONS['unknown']
} else if (stats.every((key) => data?.[key]?.status === 'ok')) {
return STATUS_ICONS['ok']
} else {
return STATUS_ICONS['warning']
}
}

return (
<Tooltip
placement="bottomRight"
title={(
<Descriptions className={styles.content} title={formatMessage({ id: 'cluster.collect.last_active_at'})} column={1}>
{
stats.map((key) => (
<Descriptions.Item key={key} label={formatMessage({ id: `cluster.manage.monitor_configs.${key}`})}>
<div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
{STATUS_ICONS[data?.[key]?.status || 'unknown']}{formatToUniversalTime(data?.[key]?.last_active_at)}
</div>
</Descriptions.Item>
))
}
</Descriptions>
)}
overlayStyle={{ maxWidth: 360 }}
>
<div style={{ display: "flex", alignItems: "center", gap: 6 }}>
{renderIcon()}
{firstUpperCase(data?.metric_collection_mode) || "Unknown"}
</div>
</Tooltip>
);
}
21 changes: 21 additions & 0 deletions web/src/components/CollectStatus/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.content {
:global {
.ant-descriptions-item-label {
width: 110px;
}
.ant-descriptions-title, .ant-descriptions-item-label, .ant-descriptions-item-content {
color: #fff;
}
.ant-descriptions-title {
margin-bottom: 12px;
}
.ant-descriptions-item {
padding-bottom: 12px;
}
.ant-descriptions-row:last-child {
.ant-descriptions-item {
padding-bottom: 6px;
}
}
}
}
61 changes: 31 additions & 30 deletions web/src/components/Overview/Monitor/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import DatePicker from "@/common/src/DatePicker";
import { getLocale } from "umi/locale";
import { getTimezone } from "@/utils/utils";
import { getContext } from "@/pages/DataManagement/context";
import { ESPrefix } from "@/services/common";
import CollectStatus from "@/components/CollectStatus";

const { TabPane } = Tabs;

Expand Down Expand Up @@ -122,36 +124,35 @@ const Monitor = (props) => {
selectedCluster ? (
<>
<div style={{ marginBottom: 5 }}>
<div style={{ display: 'flex', gap: 8 }}>
<div style={{ flexGrow: 0 }}>
<DatePicker
locale={getLocale()}
start={state.timeRange.min}
end={state.timeRange.max}
onRangeChange={({ start, end }) => {
handleTimeChange({ start, end })
}}
{...refresh}
onRefreshChange={setRefresh}
onRefresh={handleTimeChange}
showTimeSetting={true}
showTimeInterval={true}
timeInterval={state.timeInterval}
showTimeout={true}
timeout={state.timeout}
onTimeSettingChange={(timeSetting) => {
localStorage.setItem(TIMEOUT_CACHE_KEY, timeSetting.timeout)
setState({
...state,
timeInterval: timeSetting.timeInterval,
timeout: timeSetting.timeout
});
}}
timeZone={timeZone}
onTimeZoneChange={setTimeZone}
recentlyUsedRangesKey={'monitor'}
/>
</div>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<DatePicker
locale={getLocale()}
start={state.timeRange.min}
end={state.timeRange.max}
onRangeChange={({ start, end }) => {
handleTimeChange({ start, end })
}}
{...refresh}
onRefreshChange={setRefresh}
onRefresh={handleTimeChange}
showTimeSetting={true}
showTimeInterval={true}
timeInterval={state.timeInterval}
showTimeout={true}
timeout={state.timeout}
onTimeSettingChange={(timeSetting) => {
localStorage.setItem(TIMEOUT_CACHE_KEY, timeSetting.timeout)
setState({
...state,
timeInterval: timeSetting.timeInterval,
timeout: timeSetting.timeout
});
}}
timeZone={timeZone}
onTimeZoneChange={setTimeZone}
recentlyUsedRangesKey={'monitor'}
/>
<CollectStatus fetchUrl={`${ESPrefix}/${selectedCluster?.id}/_collection_stats`}/>
</div>
</div>

Expand Down
6 changes: 5 additions & 1 deletion web/src/locales/en-US/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default {
"cluster.manage.monitor_configs.cluster_stats": "Cluster stats",
"cluster.manage.monitor_configs.node_stats": "Node stats",
"cluster.manage.monitor_configs.index_stats": "Index stats",
"cluster.manage.monitor_configs.shard_stats": "Shard stats",
"cluster.manage.metadata_configs.health_check": "Health check",
"cluster.manage.metadata_configs.node_availability_check":
"Node availability check",
Expand Down Expand Up @@ -349,5 +350,8 @@ export default {
"cluster.providers.ecloud": "Ecloud",

"cluster.metrics.request.copy": "Copy request",
"cluster.metrics.request.copy.success": "Copy request successfully"
"cluster.metrics.request.copy.success": "Copy request successfully",

"cluster.collect.last_active_at": "Last Active At",

};
6 changes: 5 additions & 1 deletion web/src/locales/zh-CN/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default {
"cluster.manage.monitor_configs.cluster_stats": "集群指标",
"cluster.manage.monitor_configs.node_stats": "节点指标",
"cluster.manage.monitor_configs.index_stats": "索引指标",
"cluster.manage.monitor_configs.shard_stats": "分片指标",
"cluster.manage.metadata_configs.health_check": "健康检查",
"cluster.manage.metadata_configs.node_availability_check": "节点可用性检查",
"cluster.manage.metadata_configs.metadata_refresh": "元数据同步",
Expand Down Expand Up @@ -334,5 +335,8 @@ export default {
"cluster.providers.ecloud": "移动云",

"cluster.metrics.request.copy": "复制请求",
"cluster.metrics.request.copy.success": "复制请求成功"
"cluster.metrics.request.copy.success": "复制请求成功",

"cluster.collect.last_active_at": "最后活动时间",

};
1 change: 1 addition & 0 deletions web/src/pages/Platform/Overview/Indices/Monitor/shards.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { formatter } from "@/utils/format";
import { filterSearchValue, sorter, formatUtcTimeToLocal } from "@/utils/utils";
import { formatTimeRange } from "@/lib/elasticsearch/util";
import IconText from "@/components/infini/IconText";
import AutoTextEllipsis from "@/components/AutoTextEllipsis";

const { Search } = Input;

Expand Down
1 change: 1 addition & 0 deletions web/src/pages/Platform/Overview/Node/Monitor/shards.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { formatter } from "@/utils/format";
import { filterSearchValue, sorter, formatUtcTimeToLocal } from "@/utils/utils";
import { formatTimeRange } from "@/lib/elasticsearch/util";
import IconText from "@/components/infini/IconText";
import AutoTextEllipsis from "@/components/AutoTextEllipsis";

const { Search } = Input;

Expand Down
5 changes: 5 additions & 0 deletions web/src/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,8 @@ export const firstUpperCase = (val) => {
}
return val;
};

export const formatToUniversalTime = (time, format, timezone) => {
if (!time) return '-';
return moment(time).tz(timezone || getTimezone()).format(format || "YYYY-MM-DD HH:mm:ss (G[M]TZ)")
}

0 comments on commit 020c8aa

Please sign in to comment.