feat: add tencent cloud integration

This commit is contained in:
moonrailgun 2024-07-24 00:34:47 +08:00
parent 9a7afed08c
commit 8585ea4196
5 changed files with 178 additions and 7 deletions

View File

@ -0,0 +1,86 @@
import { z } from 'zod';
const tencentCloudAlarmEventSchema = z.object({
sessionId: z.string(),
alarmStatus: z.union([z.literal('0'), z.literal('1')]),
alarmType: z.literal('event'),
alarmObjInfo: z.object({
region: z.string().optional(),
appId: z.string(),
uin: z.string(),
dimensions: z.object({
unInstanceId: z.string(),
}),
}),
alarmPolicyInfo: z.object({
policyName: z.string(),
conditions: z.object({
productName: z.string(),
productShowName: z.string(),
eventName: z.string(),
eventShowName: z.string(),
}),
}),
firstOccurTime: z.string(),
durationTime: z.number(),
recoverTime: z.string(),
});
// 定义 metric 类型
const tencentCloudAlarmMetricSchema = z.object({
sessionId: z.string(),
alarmStatus: z.union([z.literal('0'), z.literal('1')]),
alarmType: z.literal('metric'),
alarmLevel: z.string(),
alarmObjInfo: z.object({
region: z.string().optional(),
namespace: z.string(),
appId: z.string(),
uin: z.string(),
dimensions: z.object({
deviceName: z.string(),
objId: z.string(),
objName: z.string(),
unInstanceId: z.string(),
}),
}),
alarmPolicyInfo: z.object({
policyId: z.string(),
policyType: z.string(),
policyName: z.string(),
policyTypeCName: z.string(),
policyTypeEname: z.string().optional(),
conditions: z.object({
metricName: z.string(),
metricShowName: z.string(),
calcType: z.string().optional(),
calcValue: z.string().optional(),
currentValue: z.string().optional(),
historyValue: z.string().optional(),
unit: z.string().optional(),
calcUnit: z.string().optional(),
period: z.string().optional(),
periodNum: z.string().optional(),
alarmNotifyType: z.string().optional(),
alarmNotifyPeriod: z.number().optional(),
}),
tag: z.array(z.unknown()).optional(),
policyTags: z
.array(
z.object({
key: z.string(),
value: z.string(),
})
)
.optional(),
}),
firstOccurTime: z.string(),
durationTime: z.number(),
recoverTime: z.string(),
policyDetailURL: z.string().optional(),
});
export const tencentCloudAlarmSchema = z.union([
tencentCloudAlarmEventSchema,
tencentCloudAlarmMetricSchema,
]);

View File

@ -5,7 +5,7 @@ export type MonitorInfoWithNotificationIds = MonitorInfo & {
notifications: { id: string }[];
};
export const MonitorPublicInfoSchema = MonitorModelSchema.pick({
export const monitorPublicInfoSchema = MonitorModelSchema.pick({
id: true,
name: true,
type: true,

View File

@ -1,5 +1,5 @@
import { prisma } from '../_client';
import { MonitorPublicInfoSchema } from '../_schema/monitor';
import { monitorPublicInfoSchema } from '../_schema/monitor';
import { MonitorManager } from './manager';
export const monitorManager = new MonitorManager();
@ -13,7 +13,7 @@ export async function getMonitorPublicInfos(monitorIds: string[]) {
},
});
return res.map((item) => MonitorPublicInfoSchema.parse(item));
return res.map((item) => monitorPublicInfoSchema.parse(item));
}
export function getMonitorData(

View File

@ -5,6 +5,7 @@ import _ from 'lodash';
import { OpenApiMeta } from 'trpc-openapi';
import { OPENAPI_TAG } from '../../../utils/const';
import { createFeedEvent } from '../../../model/feed/event';
import { tencentCloudAlarmSchema } from '../../../model/_schema/feed';
export const feedIntegrationRouter = router({
github: publicProcedure
@ -39,7 +40,7 @@ export const feedIntegrationRouter = router({
.then((res) => res?.workspaceId);
if (!workspaceId) {
return 'Not found';
throw new Error('Not found Workspace');
}
if (eventType === 'push') {
@ -127,7 +128,91 @@ export const feedIntegrationRouter = router({
}
}
return 'not supported';
return 'Not supported yet';
}),
tencentCloudAlarm: publicProcedure
.meta(
buildFeedPublicOpenapi({
method: 'POST',
path: '/{channelId}/tencent-cloud/alarm',
summary: 'integrate with tencent-cloud webhook',
})
)
.input(
z
.object({
channelId: z.string(),
})
.passthrough()
)
.output(z.string())
.mutation(async ({ input, ctx }) => {
const { channelId, ...data } = input;
const workspaceId = await prisma.feedChannel
.findFirst({
where: {
id: channelId,
},
select: {
workspaceId: true,
},
})
.then((res) => res?.workspaceId);
if (!workspaceId) {
throw new Error('Not found Workspace');
}
const res = tencentCloudAlarmSchema.safeParse(data);
if (!res.success) {
throw new Error('Input not valid');
}
const alarm = res.data;
if (alarm.alarmType === 'event') {
const conditions = alarm.alarmPolicyInfo.conditions;
await createFeedEvent(workspaceId, {
channelId: channelId,
eventName: alarm.alarmType,
eventContent: `[${alarm.alarmStatus === '1' ? 'Trigger' : 'Recover'}] **${alarm.alarmObjInfo.dimensions.unInstanceId}** ${alarm.alarmPolicyInfo.policyName} ${conditions.productShowName} ${conditions.eventShowName}.`,
tags: [
alarm.alarmObjInfo.appId,
alarm.alarmObjInfo.dimensions.unInstanceId,
],
source: 'tencent-cloud',
senderId: alarm.alarmObjInfo.appId,
senderName: alarm.alarmPolicyInfo.policyName,
important: alarm.alarmStatus === '1',
});
return 'ok';
}
if (alarm.alarmType === 'metric') {
const conditions = alarm.alarmPolicyInfo.conditions;
await createFeedEvent(workspaceId, {
channelId: channelId,
eventName: alarm.alarmType,
eventContent: `[${alarm.alarmStatus === '1' ? 'Trigger' : 'Recover'}] **${alarm.alarmObjInfo.dimensions.unInstanceId}** ${alarm.alarmPolicyInfo.policyName} ${conditions.metricShowName} ${conditions.calcType} ${conditions.calcValue}${conditions.calcUnit} (current: ${conditions.currentValue}${conditions.unit}) [${alarm.firstOccurTime} - ${alarm.durationTime}](keep: ${alarm.durationTime}s).`,
tags: [
alarm.alarmObjInfo.appId,
alarm.alarmObjInfo.dimensions.unInstanceId,
...(alarm.alarmPolicyInfo.tag ?? []).map(String),
],
source: 'tencent-cloud',
senderId: alarm.alarmObjInfo.appId,
senderName: alarm.alarmPolicyInfo.policyName,
important: alarm.alarmStatus === '1',
});
return 'ok';
}
return 'Not supported yet';
}),
});

View File

@ -29,7 +29,7 @@ import { runCodeInVM } from '../../model/monitor/provider/custom';
import { createAuditLog } from '../../model/auditLog';
import {
MonitorInfoWithNotificationIds,
MonitorPublicInfoSchema,
monitorPublicInfoSchema,
} from '../../model/_schema/monitor';
import { monitorPageManager } from '../../model/monitor/page/manager';
@ -107,7 +107,7 @@ export const monitorRouter = router({
monitorIds: z.array(z.string()),
})
)
.output(z.array(MonitorPublicInfoSchema))
.output(z.array(monitorPublicInfoSchema))
.query(async ({ input }) => {
const { monitorIds } = input;