import { Button, Card, Select, Space, Spin } from 'antd'; import dayjs, { Dayjs } from 'dayjs'; import React, { useMemo, useState } from 'react'; import { defaultErrorHandler, defaultSuccessHandler, trpc, } from '../../api/trpc'; import { useCurrentWorkspaceId } from '../../store/user'; import { Loading } from '../Loading'; import { getMonitorLink, getMonitorProvider } from '../modals/monitor/provider'; import { NotFoundTip } from '../NotFoundTip'; import { MonitorInfo as MonitorInfoType } from '../../../types'; import { Area, AreaConfig } from '@ant-design/charts'; import { MonitorHealthBar } from './MonitorHealthBar'; import { useSocketSubscribeList } from '../../api/socketio'; import { last, uniqBy } from 'lodash-es'; import { ErrorTip } from '../ErrorTip'; import { ColorTag } from '../ColorTag'; import { useNavigate } from 'react-router'; import { MonitorStatsBlock } from './MonitorStatsBlock'; import { MonitorEventList } from './MonitorEventList'; import { useEvent } from '../../hooks/useEvent'; interface MonitorInfoProps { monitorId: string; } export const MonitorInfo: React.FC = React.memo((props) => { const workspaceId = useCurrentWorkspaceId(); const { monitorId } = props; const [currectResponse, setCurrentResponse] = useState(0); const navigate = useNavigate(); const { data: monitorInfo, isInitialLoading, isLoading, } = trpc.monitor.get.useQuery({ workspaceId, monitorId, }); const changeActiveMutation = trpc.monitor.changeActive.useMutation({ onSuccess: defaultSuccessHandler, onError: defaultErrorHandler, }); const trpcUtils = trpc.useContext(); const handleStart = useEvent(async () => { await changeActiveMutation.mutateAsync({ workspaceId, monitorId, active: true, }); trpcUtils.monitor.get.refetch({ workspaceId, monitorId, }); trpcUtils.monitor.events.refetch({ workspaceId, monitorId, }); }); const handleStop = useEvent(async () => { await changeActiveMutation.mutateAsync({ workspaceId, monitorId, active: false, }); trpcUtils.monitor.get.refetch({ workspaceId, monitorId, }); trpcUtils.monitor.events.refetch({ workspaceId, monitorId, }); }); if (isInitialLoading) { return ; } if (!monitorInfo) { return ; } return (
{monitorInfo.name} {monitorInfo.active === false && (
Stoped
)}
{getMonitorLink(monitorInfo as any as MonitorInfoType)}
Monitored for {dayjs().diff(dayjs(monitorInfo.createdAt), 'days')}{' '} days
{monitorInfo.active ? ( ) : ( )}
{ setCurrentResponse(last(items)?.value ?? 0); }} />
); }); MonitorInfo.displayName = 'MonitorInfo'; export const MonitorDataMetrics: React.FC<{ monitorId: string; monitorType: string; currectResponse: number; }> = React.memo((props) => { const workspaceId = useCurrentWorkspaceId(); const { monitorId, monitorType, currectResponse } = props; const { data, isLoading } = trpc.monitor.dataMetrics.useQuery({ workspaceId, monitorId, }); const providerOverview = useMemo(() => { const provider = getMonitorProvider(monitorType); if (!provider || !provider.overview) { return null; } return ( <> {provider.overview.map((Component) => ( ))} ); }, [monitorId, monitorType]); if (isLoading) { return ; } if (!data) { return ; } return (
{providerOverview}
); }); MonitorDataMetrics.displayName = 'MonitorDataMetrics'; const MonitorDataChart: React.FC<{ monitorId: string }> = React.memo( (props) => { const workspaceId = useCurrentWorkspaceId(); const { monitorId } = props; const [rangeType, setRangeType] = useState('recent'); const subscribedDataList = useSocketSubscribeList( 'onMonitorReceiveNewData', { filter: (data) => { return data.monitorId === props.monitorId; }, } ); const range = useMemo((): [Dayjs, Dayjs] => { if (rangeType === '3h') { return [dayjs().subtract(3, 'hour'), dayjs()]; } if (rangeType === '6h') { return [dayjs().subtract(6, 'hour'), dayjs()]; } if (rangeType === '24h') { return [dayjs().subtract(24, 'hour'), dayjs()]; } if (rangeType === '1w') { return [dayjs().subtract(1, 'week'), dayjs()]; } return [dayjs().subtract(0.5, 'hour'), dayjs()]; }, [rangeType]); const { data: _recentData = [] } = trpc.monitor.recentData.useQuery({ workspaceId, monitorId, take: 40, }); const { data: _data = [] } = trpc.monitor.data.useQuery({ workspaceId, monitorId, startAt: range[0].valueOf(), endAt: range[1].valueOf(), }); const { data, annotations } = useMemo(() => { const annotations: AreaConfig['annotations'] = []; let start: number | null = null; let fetchedData = rangeType === 'recent' ? _recentData : _data; const data = uniqBy( [...fetchedData, ...subscribedDataList], 'createdAt' ).map((d, i, arr) => { const value = d.value > 0 ? d.value : null; const time = dayjs(d.createdAt).valueOf(); if (!value && !start && arr[i - 1]) { start = dayjs(arr[i - 1]['createdAt']).valueOf(); } else if (value && start) { annotations.push({ type: 'region', start: [start, 'min'], end: [time, 'max'], style: { fill: 'red', fillOpacity: 0.25, }, }); start = null; } return { value, time, }; }); return { data, annotations }; }, [_recentData, _data, subscribedDataList]); const config = useMemo(() => { return { data, height: 200, xField: 'time', yField: 'value', smooth: true, meta: { time: { formatter(value) { return dayjs(value).format( rangeType === '1w' ? 'MM-DD HH:mm' : 'HH:mm' ); }, }, }, color: 'rgb(34 197 94 / 0.8)', areaStyle: () => { return { fill: 'l(270) 0:rgb(34 197 94 / 0.2) 0.5:rgb(34 197 94 / 0.5) 1:rgb(34 197 94 / 0.8)', }; }, annotations, tooltip: { title: (title, datum) => { return dayjs(datum.time).format('YYYY-MM-DD HH:mm'); }, formatter(datum) { return { name: 'usage', value: datum.value ? datum.value + 'ms' : 'null', }; }, }, }; }, [data, rangeType]); return (
); } ); MonitorDataChart.displayName = 'MonitorDataChart';