feat: add cronjob for send https certificate expired notification
This commit is contained in:
parent
18f3073e94
commit
7b95c55a70
@ -1,7 +1,9 @@
|
||||
import React from 'react';
|
||||
import { TipIcon } from '../TipIcon';
|
||||
|
||||
interface MonitorStatsBlockProps {
|
||||
title: string;
|
||||
tooltip?: string;
|
||||
desc: string;
|
||||
text: string;
|
||||
}
|
||||
@ -9,7 +11,12 @@ export const MonitorStatsBlock: React.FC<MonitorStatsBlockProps> = React.memo(
|
||||
(props) => {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-0.5 font-bold">{props.title}</div>
|
||||
<div className="mb-0.5 font-bold">
|
||||
{props.title}
|
||||
{props.tooltip && (
|
||||
<TipIcon className="ml-1" content={props.tooltip} />
|
||||
)}
|
||||
</div>
|
||||
<div className="text-gray-500">{props.desc}</div>
|
||||
<div>{props.text}</div>
|
||||
</div>
|
||||
|
@ -30,9 +30,13 @@ const MonitorHttp: React.FC = React.memo(() => {
|
||||
},
|
||||
},
|
||||
]}
|
||||
tooltip={t(
|
||||
'For HTTPS monitoring, if any notification method is assigned, notifications will be sent at 1, 3, 7 and 14 days before expiration.'
|
||||
)}
|
||||
>
|
||||
<Input placeholder="https://example.com" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Method"
|
||||
name={['payload', 'method']}
|
||||
@ -161,6 +165,9 @@ export const MonitorHttpOverview: MonitorOverviewComponent = React.memo(
|
||||
return (
|
||||
<MonitorStatsBlock
|
||||
title={t('Cert Exp.')}
|
||||
tooltip={t(
|
||||
'For HTTPS monitoring, if any notification method is assigned, notifications will be sent at 1, 3, 7 and 14 days before expiration.'
|
||||
)}
|
||||
desc={dayjs(payload.certInfo?.validTo).format('YYYY-MM-DD')}
|
||||
text={t('{{num}} days', {
|
||||
num: payload.certInfo?.daysRemaining,
|
||||
|
@ -5,7 +5,9 @@ const config = {
|
||||
namespaces: ['translation'],
|
||||
translator: {
|
||||
type: 'openai',
|
||||
model: 'gpt-4',
|
||||
openai: {
|
||||
modelName: 'gpt-4',
|
||||
},
|
||||
},
|
||||
scanner: {
|
||||
autoImport: false,
|
||||
|
@ -87,6 +87,7 @@
|
||||
"k593cf342": "Sind Sie sicher, diesen Monitor zu löschen?",
|
||||
"k5a839f71": "Betriebszeit",
|
||||
"k5eb87a8b": "Start",
|
||||
"k5ec0de4": "Für die HTTPS-Überwachung werden bei Zuweisung einer Benachrichtigungsmethode Benachrichtigungen 1, 3, 7 und 14 Tage vor Ablauf gesendet.",
|
||||
"k5ecf04b0": "Ansicht",
|
||||
"k6067f0ff": "TLS/SSL-Fehler ignorieren",
|
||||
"k621317b5": "Neue Seite",
|
||||
|
@ -87,6 +87,7 @@
|
||||
"k593cf342": "Did you sure delete this monitor?",
|
||||
"k5a839f71": "Uptime",
|
||||
"k5eb87a8b": "Start",
|
||||
"k5ec0de4": "For HTTPS monitoring, if any notification method is assigned, notifications will be sent at 1, 3, 7 and 14 days before expiration.",
|
||||
"k5ecf04b0": "View",
|
||||
"k6067f0ff": "Ignore TLS/SSL error",
|
||||
"k621317b5": "New page",
|
||||
|
@ -87,6 +87,7 @@
|
||||
"k593cf342": "Êtes-vous sûr de vouloir supprimer ce moniteur ?",
|
||||
"k5a839f71": "Disponibilité",
|
||||
"k5eb87a8b": "Démarrer",
|
||||
"k5ec0de4": "Pour la surveillance HTTPS, si une méthode de notification est assignée, des notifications seront envoyées à 1, 3, 7 et 14 jours avant l'expiration.",
|
||||
"k5ecf04b0": "Vue",
|
||||
"k6067f0ff": "Ignorer l'erreur TLS/SSL",
|
||||
"k621317b5": "Nouvelle page",
|
||||
|
@ -87,12 +87,13 @@
|
||||
"k593cf342": "このモニターを削除してもよろしいですか?",
|
||||
"k5a839f71": "アップタイム",
|
||||
"k5eb87a8b": "開始",
|
||||
"k5ec0de4": "HTTPSモニタリングの場合、通知方法が割り当てられている場合、有効期限の1、3、7、14日前に通知が送信されます。",
|
||||
"k5ecf04b0": "ビュー",
|
||||
"k6067f0ff": "TLS/SSLエラーを無視",
|
||||
"k621317b5": "新しいページ",
|
||||
"k62e19375": "最終更新:{{date}}",
|
||||
"k646a3a80": "{{monitorName}}のメトリック",
|
||||
"k659b065": "For example: https://open.feishu.cn/open-apis/bot/v2/hook/00000000-0000-0000-0000-000000000000",
|
||||
"k659b065": "例:https://open.feishu.cn/open-apis/bot/v2/hook/00000000-0000-0000-0000-000000000000",
|
||||
"k67c5a895": "昨日",
|
||||
"k683be220": "実行",
|
||||
"k691b7170": "停止済み",
|
||||
|
@ -87,6 +87,7 @@
|
||||
"k593cf342": "Czy na pewno chcesz usunąć ten monitor?",
|
||||
"k5a839f71": "Czas działania",
|
||||
"k5eb87a8b": "Wznów",
|
||||
"k5ec0de4": "Dla monitorowania HTTPS, jeśli przypisana jest jakakolwiek metoda powiadamiania, powiadomienia zostaną wysłane 1, 3, 7 i 14 dni przed wygaśnięciem.",
|
||||
"k5ecf04b0": "Widok",
|
||||
"k6067f0ff": "Ignoruj błąd TLS/SSL",
|
||||
"k621317b5": "Nowa strona",
|
||||
|
@ -87,6 +87,7 @@
|
||||
"k593cf342": "De certeza que eliminou este monitor?",
|
||||
"k5a839f71": "Tempo de atividade",
|
||||
"k5eb87a8b": "Início",
|
||||
"k5ec0de4": "Para monitoramento HTTPS, se algum método de notificação estiver atribuído, notificações serão enviadas com 1, 3, 7 e 14 dias antes do vencimento.",
|
||||
"k5ecf04b0": "Ver",
|
||||
"k6067f0ff": "Ignorar erro TLS/SSL",
|
||||
"k621317b5": "Nova página",
|
||||
|
@ -87,6 +87,7 @@
|
||||
"k593cf342": "Вы уверены, что хотите удалить этот монитор?",
|
||||
"k5a839f71": "Время работы",
|
||||
"k5eb87a8b": "Старт",
|
||||
"k5ec0de4": "Для мониторинга HTTPS, если назначен любой метод уведомления, уведомления будут отправлены за 1, 3, 7 и 14 дней до истечения срока действия.",
|
||||
"k5ecf04b0": "Просмотр",
|
||||
"k6067f0ff": "Игнорировать ошибку TLS/SSL",
|
||||
"k621317b5": "Новая страница",
|
||||
|
@ -87,6 +87,7 @@
|
||||
"k593cf342": "您确定要删除这个监控器吗?",
|
||||
"k5a839f71": "正常运行时间",
|
||||
"k5eb87a8b": "开始",
|
||||
"k5ec0de4": "对于 HTTPS 监控,如果分配了任何通知方法,则将在到期前 1、3、7 和 14 天发送通知。",
|
||||
"k5ecf04b0": "查看",
|
||||
"k6067f0ff": "忽略 TLS/SSL 错误",
|
||||
"k621317b5": "新页面",
|
||||
|
@ -4,6 +4,9 @@ import { prisma } from '../model/_client';
|
||||
import dayjs from 'dayjs';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { env } from '../utils/env';
|
||||
import { sendNotification } from '../model/notification';
|
||||
import { token } from '../model/notification/token';
|
||||
import _ from 'lodash';
|
||||
|
||||
type WebsiteEventCountSqlReturn = {
|
||||
workspace_id: string;
|
||||
@ -15,8 +18,11 @@ export function initCronjob() {
|
||||
logger.info('Start daily cronjob');
|
||||
|
||||
try {
|
||||
await statDailyUsage();
|
||||
await clearMonitorDataDaily();
|
||||
await Promise.all([
|
||||
statDailyUsage().catch(logger.error),
|
||||
clearMonitorDataDaily().catch(logger.error),
|
||||
dailyHTTPCertCheckNotify().catch(logger.error),
|
||||
]);
|
||||
|
||||
logger.info('Daily cronjob completed');
|
||||
} catch (err) {
|
||||
@ -30,7 +36,7 @@ export function initCronjob() {
|
||||
}
|
||||
|
||||
async function statDailyUsage() {
|
||||
logger.info('Statistics Workspace Daily Usage Start');
|
||||
logger.info('[statDailyUsage] Statistics Workspace Daily Usage Start');
|
||||
const start = dayjs().subtract(1, 'day').startOf('day').toDate();
|
||||
const end = dayjs().startOf('day').toDate();
|
||||
const date = dayjs().subtract(1, 'day').toDate();
|
||||
@ -133,7 +139,7 @@ async function statDailyUsage() {
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
logger.info('Statistics Workspace Daily Usage Completed');
|
||||
logger.info('[statDailyUsage] Statistics Workspace Daily Usage Completed');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,7 +151,10 @@ async function clearMonitorDataDaily() {
|
||||
}
|
||||
|
||||
const date = dayjs().subtract(2, 'weeks').toDate();
|
||||
logger.info('Start clear monitor data before:', date.toISOString());
|
||||
logger.info(
|
||||
'[clearMonitorDataDaily] Start clear monitor data before:',
|
||||
date.toISOString()
|
||||
);
|
||||
const res = await prisma.monitorData.deleteMany({
|
||||
where: {
|
||||
createdAt: {
|
||||
@ -154,5 +163,72 @@ async function clearMonitorDataDaily() {
|
||||
},
|
||||
});
|
||||
|
||||
logger.info('Clear monitor completed, delete record:', res.count);
|
||||
logger.info(
|
||||
'[clearMonitorDataDaily] Clear monitor completed, delete record:',
|
||||
res.count
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Https notify
|
||||
*/
|
||||
|
||||
async function dailyHTTPCertCheckNotify() {
|
||||
logger.info('[dailyHTTPCertCheckNotify] Start run dailyHTTPCertCheckNotify');
|
||||
const start = Date.now();
|
||||
|
||||
const res = await prisma.$queryRaw<
|
||||
{ monitorId: string; daysRemaining: number }[]
|
||||
>`
|
||||
SELECT "monitorId", (payload -> 'certInfo' ->> 'daysRemaining')::int as "daysRemaining"
|
||||
FROM "MonitorStatus"
|
||||
WHERE "statusName" = 'tls'
|
||||
AND "updatedAt" >= now() - interval '1 day'
|
||||
AND (payload -> 'certInfo' ->> 'daysRemaining')::int in (1, 3, 7, 14);
|
||||
`;
|
||||
|
||||
logger.info(`[dailyHTTPCertCheckNotify] find ${res.length} records`);
|
||||
|
||||
const monitors = await prisma.monitor.findMany({
|
||||
where: {
|
||||
id: {
|
||||
in: res.map((r) => r.monitorId),
|
||||
},
|
||||
},
|
||||
include: {
|
||||
notifications: true,
|
||||
},
|
||||
});
|
||||
|
||||
let sendCount = 0;
|
||||
|
||||
for (const m of monitors) {
|
||||
if (m.active === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const n of m.notifications) {
|
||||
const daysRemaining = res.find(
|
||||
(item) => item.monitorId === m.id
|
||||
)?.daysRemaining;
|
||||
if (!daysRemaining) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = `[${m.name}][${_.get(m.payload, 'url')}] Certificate will be expired in ${daysRemaining} days`;
|
||||
|
||||
try {
|
||||
await sendNotification(n, content, [token.text(content)]).catch(
|
||||
logger.error
|
||||
);
|
||||
sendCount++;
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`[dailyHTTPCertCheckNotify] run completed, send ${sendCount} notifications, time usage: ${Date.now() - start}ms`
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user