feat: add monitor start or stop

This commit is contained in:
moonrailgun 2023-10-28 16:01:11 +08:00
parent 0a3479d06c
commit 1631521321
3 changed files with 136 additions and 18 deletions

View File

@ -1,7 +1,11 @@
import { Button, Card, Select, Space, Spin } from 'antd';
import dayjs, { Dayjs } from 'dayjs';
import React, { useMemo, useState } from 'react';
import { trpc } from '../../api/trpc';
import {
defaultErrorHandler,
defaultSuccessHandler,
trpc,
} from '../../api/trpc';
import { useCurrentWorkspaceId } from '../../store/user';
import { Loading } from '../Loading';
import { getMonitorLink, getMonitorProvider } from '../modals/monitor/provider';
@ -16,6 +20,7 @@ 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;
@ -34,6 +39,46 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
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 <Loading />;
@ -46,10 +91,17 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
return (
<div className="w-full h-full overflow-auto">
<Spin spinning={isLoading}>
<Space direction="vertical">
<Space className="w-full" direction="vertical">
<div className="flex justify-between">
<Space direction="vertical">
<div className="text-2xl">{monitorInfo.name}</div>
<div className="text-2xl flex items-center gap-2">
<span>{monitorInfo.name}</span>
{monitorInfo.active === false && (
<div className="bg-red-500 rounded-full px-2 py-0.5 text-white text-xs">
Stoped
</div>
)}
</div>
<div>
<ColorTag label={monitorInfo.type} />
@ -65,7 +117,7 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
</div>
</div>
<div>
<div className="flex gap-2">
<Button
type="primary"
onClick={() => {
@ -74,6 +126,22 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
>
Edit
</Button>
{monitorInfo.active ? (
<Button
loading={changeActiveMutation.isLoading}
onClick={handleStop}
>
Stop
</Button>
) : (
<Button
loading={changeActiveMutation.isLoading}
onClick={handleStart}
>
Start
</Button>
)}
</div>
<Card>

View File

@ -108,6 +108,10 @@ class MonitorManager {
console.log('All monitor has been begin.');
});
}
getRunner(monitorId: string): MonitorRunner | undefined {
return this.monitorRunner[monitorId];
}
}
/**
@ -154,13 +158,10 @@ class MonitorRunner {
// check event update
if (value < 0 && currentStatus === 'UP') {
await prisma.monitorEvent.create({
data: {
message: `Monitor [${monitor.name}] has been down`,
monitorId: monitor.id,
type: 'DOWN',
},
});
await this.createEvent(
'DOWN',
`Monitor [${monitor.name}] has been down`
);
await this.notify(
`[${monitor.name}] 🔴 Down`,
`[${monitor.name}] 🔴 Down\nTime: ${dayjs().format(
@ -168,13 +169,7 @@ class MonitorRunner {
)}`
);
} else if (value > 0 && currentStatus === 'DOWN') {
await prisma.monitorEvent.create({
data: {
message: `Monitor [${monitor.name}] has been up`,
monitorId: monitor.id,
type: 'UP',
},
});
await this.createEvent('UP', `Monitor [${monitor.name}] has been up`);
await this.notify(
`[${monitor.name}] ✅ Up`,
`[${monitor.name}] ✅ Up\nTime: ${dayjs().format(
@ -219,6 +214,16 @@ class MonitorRunner {
this.startMonitor();
}
async createEvent(type: 'UP' | 'DOWN', message: string) {
return await prisma.monitorEvent.create({
data: {
message,
monitorId: this.monitor.id,
type,
},
});
}
async notify(title: string, message: string) {
const notifications = this.monitor.notifications;
await Promise.all(

View File

@ -161,6 +161,51 @@ export const monitorRouter = router({
},
});
}),
changeActive: workspaceOwnerProcedure
.meta(
buildMonitorOpenapi({
method: 'PATCH',
path: '/{monitorId}/changeActive',
})
)
.input(
z.object({
monitorId: z.string(),
active: z.boolean(),
})
)
.output(monitorInfoSchema)
.mutation(async ({ input, ctx }) => {
const { workspaceId, monitorId, active } = input;
const monitor = await prisma.monitor.update({
where: {
workspaceId,
id: monitorId,
},
data: {
active,
},
});
const runner = monitorManager.getRunner(monitorId);
if (runner) {
if (active === true) {
runner.startMonitor();
runner.createEvent(
'UP',
`Monitor [${monitor.name}] has been manual start`
);
} else {
runner.stopMonitor();
runner.createEvent(
'DOWN',
`Monitor [${monitor.name}] has been manual stop`
);
}
}
return monitor;
}),
recentData: workspaceProcedure
.meta(
buildMonitorOpenapi({