diff --git a/Common/Types/Infrastrucutre/BasicMetrics.ts b/Common/Types/Infrastrucutre/BasicMetrics.ts index 73ada33fde..964cfc9e24 100644 --- a/Common/Types/Infrastrucutre/BasicMetrics.ts +++ b/Common/Types/Infrastrucutre/BasicMetrics.ts @@ -2,6 +2,8 @@ export interface MemoryMetrics { total: number; free: number; used: number; + percentUsed: number; + percentFree: number; } export interface CPUMetrics { @@ -12,8 +14,9 @@ export interface BasicDiskMetrics { total: number; free: number; used: number; - available: number; diskPath: string; + percentUsed: number; + percentFree: number; } export default interface BasicInfrastructureMetrics { diff --git a/Common/Types/Monitor/ServerMonitor/ServerMonitorRequest.ts b/Common/Types/Monitor/ServerMonitor/ServerMonitorRequest.ts deleted file mode 100644 index 75694e0e38..0000000000 --- a/Common/Types/Monitor/ServerMonitor/ServerMonitorRequest.ts +++ /dev/null @@ -1,6 +0,0 @@ -import ObjectID from '../../ObjectID'; - -export default interface ServerMonitorRequest { - monitorId: ObjectID; - secretKey: ObjectID; -} diff --git a/Common/Types/Monitor/ServerMonitor/ServerMonitorResponse.ts b/Common/Types/Monitor/ServerMonitor/ServerMonitorResponse.ts index 7ee7379584..15db769334 100644 --- a/Common/Types/Monitor/ServerMonitor/ServerMonitorResponse.ts +++ b/Common/Types/Monitor/ServerMonitor/ServerMonitorResponse.ts @@ -1,8 +1,8 @@ import BasicInfrastructureMetrics from '../../Infrastrucutre/BasicMetrics'; import ObjectID from '../../ObjectID'; -export interface ServerMonitorResponse { +export default interface ServerMonitorResponse { monitorId: ObjectID; - secretKey: ObjectID; basicInfrastructureMetrics: BasicInfrastructureMetrics; + metricsCollectedAt: Date; } diff --git a/CommonServer/Utils/Probe/ProbeMonitorResponse.ts b/CommonServer/Utils/Probe/ProbeMonitorResponse.ts index 6fc77f9925..cb0a418f94 100644 --- a/CommonServer/Utils/Probe/ProbeMonitorResponse.ts +++ b/CommonServer/Utils/Probe/ProbeMonitorResponse.ts @@ -35,11 +35,15 @@ import OnCallDutyPolicy from 'Model/Models/OnCallDutyPolicy'; import IncomingMonitorRequest from 'Common/Types/Monitor/IncomingMonitor/IncomingMonitorRequest'; import MonitorType from 'Common/Types/Monitor/MonitorType'; import VMUtil from '../VM'; +import ServerMonitorResponse from 'Common/Types/Monitor/ServerMonitor/ServerMonitorResponse'; + +type DataToProcess = ProbeMonitorResponse | IncomingMonitorRequest | ServerMonitorResponse; export default class ProbeMonitorResponseService { public static async processProbeResponse( - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest + dataToProcess: DataToProcess ): Promise { + let response: ProbeApiIngestResponse = { monitorId: dataToProcess.monitorId, criteriaMetId: undefined, @@ -105,8 +109,7 @@ export default class ProbeMonitorResponseService { // get last log. We do this because there are many monitoring steps and we need to store those. logger.info( - `${dataToProcess.monitorId.toString()} - monitor type ${ - monitor.monitorType + `${dataToProcess.monitorId.toString()} - monitor type ${monitor.monitorType }` ); @@ -180,6 +183,23 @@ export default class ProbeMonitorResponseService { }); } + if ( + monitor.monitorType === MonitorType.Server && + (dataToProcess as ServerMonitorResponse).metricsCollectedAt + ) { + await MonitorService.updateOneById({ + id: monitor.id!, + data: { + serverMonitorRequestReceivedAt: ( + dataToProcess as ServerMonitorResponse + ).metricsCollectedAt!, + }, + props: { + isRoot: true, + }, + }); + } + // TODO: save data to Clickhouse. const monitorSteps: MonitorSteps = monitor.monitorSteps!; @@ -229,7 +249,7 @@ export default class ProbeMonitorResponseService { if (incidentTemplate.autoResolveIncident) { if ( !autoResolveCriteriaInstanceIdIncidentIdsDictionary[ - criteriaInstance.data.id.toString() + criteriaInstance.data.id.toString() ] ) { autoResolveCriteriaInstanceIdIncidentIdsDictionary[ @@ -294,13 +314,11 @@ export default class ProbeMonitorResponseService { if (response.criteriaMetId && response.rootCause) { logger.info( - `${dataToProcess.monitorId.toString()} - Criteria met: ${ - response.criteriaMetId + `${dataToProcess.monitorId.toString()} - Criteria met: ${response.criteriaMetId }` ); logger.info( - `${dataToProcess.monitorId.toString()} - Root cause: ${ - response.rootCause + `${dataToProcess.monitorId.toString()} - Root cause: ${response.rootCause }` ); @@ -315,7 +333,7 @@ export default class ProbeMonitorResponseService { !response.criteriaMetId && monitorSteps.data.defaultMonitorStatusId && monitor.currentMonitorStatusId?.toString() !== - monitorSteps.data.defaultMonitorStatusId.toString() + monitorSteps.data.defaultMonitorStatusId.toString() ) { logger.info( `${dataToProcess.monitorId.toString()} - No criteria met. Change to default status.` @@ -360,7 +378,7 @@ export default class ProbeMonitorResponseService { >; rootCause: string; criteriaInstance: MonitorCriteriaInstance | null; - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest; + dataToProcess: DataToProcess; }): Promise> { // check active incidents and if there are open incidents, do not cretae anothr incident. const openIncidents: Array = await IncidentService.findBy({ @@ -410,7 +428,7 @@ export default class ProbeMonitorResponseService { private static async criteriaMetCreateIncidentsAndUpdateMonitorStatus(input: { criteriaInstance: MonitorCriteriaInstance; monitor: Monitor; - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest; + dataToProcess: DataToProcess; rootCause: string; autoResolveCriteriaInstanceIdIncidentIdsDictionary: Dictionary< Array @@ -422,7 +440,7 @@ export default class ProbeMonitorResponseService { input.criteriaInstance.data?.changeMonitorStatus && input.criteriaInstance.data?.monitorStatusId && input.criteriaInstance.data?.monitorStatusId.toString() !== - input.monitor.currentMonitorStatusId?.toString() + input.monitor.currentMonitorStatusId?.toString() ) { logger.info( `${input.monitor.id?.toString()} - Change monitor status to ${input.criteriaInstance.data?.monitorStatusId.toString()}` @@ -476,9 +494,9 @@ export default class ProbeMonitorResponseService { openIncidents.find((incident: Incident) => { return ( incident.createdCriteriaId === - input.criteriaInstance.data?.id.toString() && + input.criteriaInstance.data?.id.toString() && incident.createdIncidentTemplateId === - criteriaIncident.id.toString() + criteriaIncident.id.toString() ); }); @@ -584,7 +602,7 @@ export default class ProbeMonitorResponseService { private static async resolveOpenIncident(input: { openIncident: Incident; rootCause: string; - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest; + dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest | DataToProcess; }): Promise { const resolvedStateId: ObjectID = await IncidentStateTimelineService.getResolvedStateIdForProject( @@ -644,7 +662,7 @@ export default class ProbeMonitorResponseService { if ( input.autoResolveCriteriaInstanceIdIncidentIdsDictionary[ - input.openIncident.createdCriteriaId?.toString() + input.openIncident.createdCriteriaId?.toString() ] ) { if ( @@ -662,7 +680,7 @@ export default class ProbeMonitorResponseService { } private static async processMonitorStep(input: { - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest; + dataToProcess: DataToProcess; monitorStep: MonitorStep; monitor: Monitor; probeApiIngestResponse: ProbeApiIngestResponse; @@ -708,7 +726,7 @@ export default class ProbeMonitorResponseService { } private static async processMonitorCriteiaInstance(input: { - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest; + dataToProcess: DataToProcess; monitorStep: MonitorStep; monitor: Monitor; probeApiIngestResponse: ProbeApiIngestResponse; @@ -733,7 +751,7 @@ export default class ProbeMonitorResponseService { } private static async isMonitorInstanceCriteriaFiltersMet(input: { - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest; + dataToProcess: DataToProcess; monitorStep: MonitorStep; monitor: Monitor; probeApiIngestResponse: ProbeApiIngestResponse; @@ -766,7 +784,7 @@ export default class ProbeMonitorResponseService { if ( FilterCondition.Any === - input.criteriaInstance.data?.filterCondition && + input.criteriaInstance.data?.filterCondition && didMeetCriteria === true ) { finalResult = rootCause; @@ -774,7 +792,7 @@ export default class ProbeMonitorResponseService { if ( FilterCondition.All === - input.criteriaInstance.data?.filterCondition && + input.criteriaInstance.data?.filterCondition && didMeetCriteria === false ) { finalResult = null; @@ -783,7 +801,7 @@ export default class ProbeMonitorResponseService { if ( FilterCondition.All === - input.criteriaInstance.data?.filterCondition && + input.criteriaInstance.data?.filterCondition && didMeetCriteria && rootCause ) { @@ -795,7 +813,7 @@ export default class ProbeMonitorResponseService { } private static async isMonitorInstanceCriteriaFilterMet(input: { - dataToProcess: ProbeMonitorResponse | IncomingMonitorRequest; + dataToProcess: DataToProcess; monitorStep: MonitorStep; monitor: Monitor; probeApiIngestResponse: ProbeApiIngestResponse; @@ -936,10 +954,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseTimeInMs! > (value as number) ) { - return `Response time is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseTimeInMs - } ms which is greater than the criteria value of ${value} ms.`; + return `Response time is ${(input.dataToProcess as ProbeMonitorResponse) + .responseTimeInMs + } ms which is greater than the criteria value of ${value} ms.`; } return null; } @@ -951,10 +968,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseTimeInMs! < (value as number) ) { - return `Response time is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseTimeInMs - } ms which is less than the criteria value of ${value} ms.`; + return `Response time is ${(input.dataToProcess as ProbeMonitorResponse) + .responseTimeInMs + } ms which is less than the criteria value of ${value} ms.`; } return null; } @@ -966,10 +982,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseTimeInMs === (value as number) ) { - return `Response time is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseTimeInMs - } ms.`; + return `Response time is ${(input.dataToProcess as ProbeMonitorResponse) + .responseTimeInMs + } ms.`; } return null; } @@ -981,10 +996,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseTimeInMs !== (value as number) ) { - return `Response time is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseTimeInMs - } ms which is not equal to the criteria value of ${value} ms.`; + return `Response time is ${(input.dataToProcess as ProbeMonitorResponse) + .responseTimeInMs + } ms which is not equal to the criteria value of ${value} ms.`; } return null; } @@ -999,10 +1013,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseTimeInMs! >= (value as number) ) { - return `Response time is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseTimeInMs - } ms which is greater than or equal to the criteria value of ${value} ms.`; + return `Response time is ${(input.dataToProcess as ProbeMonitorResponse) + .responseTimeInMs + } ms which is greater than or equal to the criteria value of ${value} ms.`; } return null; } @@ -1016,10 +1029,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseTimeInMs! <= (value as number) ) { - return `Response time is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseTimeInMs - } ms which is less than or equal to the criteria value of ${value} ms.`; + return `Response time is ${(input.dataToProcess as ProbeMonitorResponse) + .responseTimeInMs + } ms which is less than or equal to the criteria value of ${value} ms.`; } return null; } @@ -1051,10 +1063,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseCode! > (value as number) ) { - return `Response status code is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseCode - } which is greater than the criteria value of ${value}.`; + return `Response status code is ${(input.dataToProcess as ProbeMonitorResponse) + .responseCode + } which is greater than the criteria value of ${value}.`; } return null; } @@ -1066,10 +1077,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseCode! < (value as number) ) { - return `Response status code is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseCode - } which is less than the criteria value of ${value}.`; + return `Response status code is ${(input.dataToProcess as ProbeMonitorResponse) + .responseCode + } which is less than the criteria value of ${value}.`; } return null; } @@ -1081,10 +1091,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseCode === (value as number) ) { - return `Response status code is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseCode - }.`; + return `Response status code is ${(input.dataToProcess as ProbeMonitorResponse) + .responseCode + }.`; } return null; } @@ -1096,10 +1105,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseCode !== (value as number) ) { - return `Response status code is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseCode - } which is not equal to the criteria value of ${value}.`; + return `Response status code is ${(input.dataToProcess as ProbeMonitorResponse) + .responseCode + } which is not equal to the criteria value of ${value}.`; } return null; } @@ -1114,10 +1122,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseCode! >= (value as number) ) { - return `Response status code is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseCode - } which is greater than or equal to the criteria value of ${value}.`; + return `Response status code is ${(input.dataToProcess as ProbeMonitorResponse) + .responseCode + } which is greater than or equal to the criteria value of ${value}.`; } return null; } @@ -1131,10 +1138,9 @@ export default class ProbeMonitorResponseService { (input.dataToProcess as ProbeMonitorResponse) .responseCode! <= (value as number) ) { - return `Response status code is ${ - (input.dataToProcess as ProbeMonitorResponse) - .responseCode - } which is less than or equal to the criteria value of ${value}.`; + return `Response status code is ${(input.dataToProcess as ProbeMonitorResponse) + .responseCode + } which is less than or equal to the criteria value of ${value}.`; } return null; } @@ -1180,7 +1186,7 @@ export default class ProbeMonitorResponseService { if (input.criteriaFilter.checkOn === CheckOn.ResponseHeader) { const headerKeys: Array = Object.keys( (input.dataToProcess as ProbeMonitorResponse).responseHeaders || - {} + {} ).map((key: string) => { return key.toLowerCase(); }); @@ -1212,7 +1218,7 @@ export default class ProbeMonitorResponseService { if (input.criteriaFilter.checkOn === CheckOn.ResponseHeaderValue) { const headerValues: Array = Object.values( (input.dataToProcess as ProbeMonitorResponse).responseHeaders || - {} + {} ).map((key: string) => { return key.toLowerCase(); }); @@ -1241,12 +1247,17 @@ export default class ProbeMonitorResponseService { } } + + + // All incoming request related checks if (input.criteriaFilter.checkOn === CheckOn.IncomingRequest) { + const lastCheckTime: Date = ( input.dataToProcess as IncomingMonitorRequest ).incomingRequestReceivedAt; + const differenceInMinutes: number = OneUptimeDate.getDifferenceInMinutes( lastCheckTime, @@ -1403,6 +1414,296 @@ export default class ProbeMonitorResponseService { } } + + + // Server Monitoring Checks + + if (input.criteriaFilter.checkOn === CheckOn.CPUUsagePercent) { + if (!value) { + return null; + } + + if (typeof value === Typeof.String) { + try { + value = parseInt(value as string); + } catch (err) { + logger.error(err); + return null; + } + } + + if (typeof value !== Typeof.Number) { + return null; + } + + const currentCpuPercent: number = (input.dataToProcess as ServerMonitorResponse) + .basicInfrastructureMetrics.cpuMetrics.percentUsage || 0 + + if (input.criteriaFilter.filterType === FilterType.GreaterThan) { + + if ( + (currentCpuPercent > (value as number)) + ) { + return `CPU Percent is ${currentCpuPercent + }% which is greater than the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.LessThan) { + if ( + (currentCpuPercent < (value as number)) + ) { + return `CPU Percent is ${currentCpuPercent + }% which is less than than the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.EqualTo) { + if ( + (currentCpuPercent === (value as number)) + ) { + return `CPU Percent is ${currentCpuPercent + }% which is equal to the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.NotEqualTo) { + if ( + (currentCpuPercent !== (value as number)) + ) { + return `CPU Percent is ${currentCpuPercent + }% which is not equal to the criteria value of ${value}%.`; + } + + return null; + } + + if ( + input.criteriaFilter.filterType === + FilterType.GreaterThanOrEqualTo + ) { + if ( + (currentCpuPercent >= (value as number)) + ) { + return `CPU Percent is ${currentCpuPercent + }% which is greater than or equal to the criteria value of ${value}%.`; + } + + return null; + } + + if ( + input.criteriaFilter.filterType === FilterType.LessThanOrEqualTo + ) { + if ( + (currentCpuPercent <= (value as number)) + ) { + return `CPU Percent is ${currentCpuPercent + }% which is less than or equal to the criteria value of ${value}%.`; + } + + return null; + } + } + + if (input.criteriaFilter.checkOn === CheckOn.MemoryUsagePercent) { + if (!value) { + return null; + } + + if (typeof value === Typeof.String) { + try { + value = parseInt(value as string); + } catch (err) { + logger.error(err); + return null; + } + } + + if (typeof value !== Typeof.Number) { + return null; + } + + const memoryPercent: number = (input.dataToProcess as ServerMonitorResponse) + .basicInfrastructureMetrics.memoryMetrics.percentFree || 0 + + if (input.criteriaFilter.filterType === FilterType.GreaterThan) { + + if ( + (memoryPercent > (value as number)) + ) { + return `Memory Percent is ${memoryPercent + }% which is greater than the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.LessThan) { + if ( + (memoryPercent < (value as number)) + ) { + return `Memory Percent is ${memoryPercent + }% which is less than than the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.EqualTo) { + if ( + (memoryPercent === (value as number)) + ) { + return `Memory Percent is ${memoryPercent + }% which is equal to the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.NotEqualTo) { + if ( + (memoryPercent !== (value as number)) + ) { + return `Memory Percent is ${memoryPercent + }% which is not equal to the criteria value of ${value}%.`; + } + + return null; + } + + if ( + input.criteriaFilter.filterType === + FilterType.GreaterThanOrEqualTo + ) { + if ( + (memoryPercent >= (value as number)) + ) { + return `Memory Percent is ${memoryPercent + }% which is greater than or equal to the criteria value of ${value}%.`; + } + + return null; + } + + if ( + input.criteriaFilter.filterType === FilterType.LessThanOrEqualTo + ) { + if ( + (memoryPercent <= (value as number)) + ) { + return `Memory Percent is ${memoryPercent + }% which is less than or equal to the criteria value of ${value}%.`; + } + + return null; + } + } + + if (input.criteriaFilter.checkOn === CheckOn.DiskUsagePercent) { + if (!value) { + return null; + } + + if (typeof value === Typeof.String) { + try { + value = parseInt(value as string); + } catch (err) { + logger.error(err); + return null; + } + } + + if (typeof value !== Typeof.Number) { + return null; + } + + const diskPath: string = input.criteriaFilter.serverMonitorOptions?.diskPath || '/'; + + const diskPercent: number = (input.dataToProcess as ServerMonitorResponse) + .basicInfrastructureMetrics.diskMetrics.filter((item)=>{ + return item.diskPath.trim().toLowerCase() === diskPath.trim().toLowerCase(); + })[0]?.percentFree || 0 + + if (input.criteriaFilter.filterType === FilterType.GreaterThan) { + + if ( + (diskPercent > (value as number)) + ) { + return `Disk Percent for ${diskPath} is ${diskPercent + }% which is greater than the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.LessThan) { + if ( + (diskPercent < (value as number)) + ) { + return `Disk Percent for ${diskPath} is ${diskPercent + }% which is less than than the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.EqualTo) { + if ( + (diskPercent === (value as number)) + ) { + return `Disk Percent for ${diskPath} is ${diskPercent + }% which is equal to the criteria value of ${value}%.`; + } + + return null; + } + + if (input.criteriaFilter.filterType === FilterType.NotEqualTo) { + if ( + (diskPercent !== (value as number)) + ) { + return `Disk Percent for ${diskPath} is ${diskPercent + }% which is not equal to the criteria value of ${value}%.`; + } + + return null; + } + + if ( + input.criteriaFilter.filterType === + FilterType.GreaterThanOrEqualTo + ) { + if ( + (diskPercent >= (value as number)) + ) { + return `Disk Percent for ${diskPath} is ${diskPercent + }% which is greater than or equal to the criteria value of ${value}%.`; + } + + return null; + } + + if ( + input.criteriaFilter.filterType === FilterType.LessThanOrEqualTo + ) { + if ( + (diskPercent <= (value as number)) + ) { + return `Disk Percent for ${diskPath} is ${diskPercent + }% which is less than or equal to the criteria value of ${value}%.`; + } + + return null; + } + } + return null; } } diff --git a/Ingestor/API/IncomingRequest.ts b/Ingestor/API/IncomingRequest.ts index 00f03e6854..f6411275cc 100644 --- a/Ingestor/API/IncomingRequest.ts +++ b/Ingestor/API/IncomingRequest.ts @@ -13,6 +13,9 @@ import { JSONObject } from 'Common/Types/JSON'; import ObjectID from 'Common/Types/ObjectID'; import IncomingMonitorRequest from 'Common/Types/Monitor/IncomingMonitor/IncomingMonitorRequest'; import OneUptimeDate from 'Common/Types/Date'; +import MonitorService from 'CommonServer/Services/MonitorService'; +import MonitorType from 'Common/Types/Monitor/MonitorType'; +import Monitor from 'Model/Models/Monitor'; const router: ExpressRouter = Express.getRouter(); @@ -28,16 +31,35 @@ const processIncomingRequest: RequestHandler = async ( | string | JSONObject; - const monitorIdAsString: string | undefined = req.params['id']; + const monitorSecretKeyAsString: string | undefined = + req.params['secretkey']; - if (!monitorIdAsString) { - throw new BadDataException('Monitor Id is required'); + + if (!monitorSecretKeyAsString) { + throw new BadDataException('Invalid Secret Key'); + } + + + const monitor: Monitor | null = await MonitorService.findOneBy({ + query: { + incomingRequestSecretKey: new ObjectID(monitorSecretKeyAsString), + monitorType: MonitorType.Server + }, + select: { + _id: true + }, + props: { + isRoot: true + } + }); + + if (!monitor || !monitor._id) { + throw new BadDataException('Monitor not found'); } - const monitorId: ObjectID = ObjectID.fromString(monitorIdAsString); const incomingRequest: IncomingMonitorRequest = { - monitorId: monitorId, + monitorId: new ObjectID(monitor._id), requestHeaders: requestHeaders, requestBody: requestBody, incomingRequestReceivedAt: OneUptimeDate.getCurrentDate(), @@ -54,7 +76,7 @@ const processIncomingRequest: RequestHandler = async ( }; router.post( - '/incoming-request/:id', + '/incoming-request/:secretkey', async ( req: ExpressRequest, res: ExpressResponse, @@ -65,7 +87,7 @@ router.post( ); router.get( - '/incoming-request/:id', + '/incoming-request/:secretkey', async ( req: ExpressRequest, res: ExpressResponse, diff --git a/Ingestor/API/Probe.ts b/Ingestor/API/Probe.ts index bc52f214f9..518af020fb 100644 --- a/Ingestor/API/Probe.ts +++ b/Ingestor/API/Probe.ts @@ -52,6 +52,7 @@ router.post( return Response.sendJsonObjectResponse(req, res, { probeApiIngestResponse: probeApiIngestResponse, } as any); + } catch (err) { return next(err); } diff --git a/Ingestor/API/ServerMonitor.ts b/Ingestor/API/ServerMonitor.ts index 0e726928db..bac1879e49 100644 --- a/Ingestor/API/ServerMonitor.ts +++ b/Ingestor/API/ServerMonitor.ts @@ -3,57 +3,19 @@ import Express, { ExpressResponse, ExpressRouter, NextFunction, - RequestHandler, } from 'CommonServer/Utils/Express'; import Response from 'CommonServer/Utils/Response'; import BadDataException from 'Common/Types/Exception/BadDataException'; -import ProbeMonitorResponseService from 'CommonServer/Utils/Probe/ProbeMonitorResponse'; -import Dictionary from 'Common/Types/Dictionary'; -import { JSONObject } from 'Common/Types/JSON'; import ObjectID from 'Common/Types/ObjectID'; -import OneUptimeDate from 'Common/Types/Date'; +import Monitor from 'Model/Models/Monitor'; +import MonitorService from 'CommonServer/Services/MonitorService'; +import MonitorType from 'Common/Types/Monitor/MonitorType'; +import ServerMonitorResponse from 'Common/Types/Monitor/ServerMonitor/ServerMonitorResponse'; +import ProbeApiIngestResponse from 'Common/Types/Probe/ProbeApiIngestResponse'; +import ProbeMonitorResponseService from 'CommonServer/Utils/Probe/ProbeMonitorResponse'; const router: ExpressRouter = Express.getRouter(); -const processServerMonitor: RequestHandler = async ( - req: ExpressRequest, - res: ExpressResponse, - next: NextFunction -): Promise => { - try { - const requestHeaders: Dictionary = - req.headers as Dictionary; - const requestBody: string | JSONObject = req.body as - | string - | JSONObject; - - const monitorSecretKeyAsString: string | undefined = - req.params['secretkey']; - - if (!monitorSecretKeyAsString) { - throw new BadDataException('Monitor Secret Key is required'); - } - - const monitorId: ObjectID = ObjectID.fromString( - monitorSecretKeyAsString - ); - - const serverMonitorRequest: ServerMonitorRequest = { - monitorId: monitorId, - requestHeaders: requestHeaders, - requestBody: requestBody, - incomingRequestReceivedAt: OneUptimeDate.getCurrentDate(), - onlyCheckForIncomingRequestReceivedAt: false, - }; - - // process probe response here. - await ProbeMonitorResponseService.processProbeResponse(incomingRequest); - - return Response.sendEmptyResponse(req, res); - } catch (err) { - return next(err); - } -}; router.get( '/server-monitor/:secretkey', @@ -62,18 +24,96 @@ router.get( res: ExpressResponse, next: NextFunction ): Promise => { - processServerMonitor(req, res, next); + try { + + const monitorSecretKeyAsString: string | undefined = + req.params['secretkey']; + + + if (!monitorSecretKeyAsString) { + throw new BadDataException('Invalid Secret Key'); + } + + + const monitor: Monitor | null = await MonitorService.findOneBy({ + query: { + serverMonitorSecretKey: new ObjectID(monitorSecretKeyAsString), + monitorType: MonitorType.Server + }, + select: { + monitorSteps: true + }, + props: { + isRoot: true + } + }); + + if (!monitor) { + throw new BadDataException('Monitor not found'); + } + + return Response.sendEntityResponse(req, res, monitor, Monitor); + + } catch (err) { + return next(err); + } } ); router.post( - '/server-monitor/response/ingest', + '/server-monitor/response/ingest/:secretkey', async ( req: ExpressRequest, res: ExpressResponse, next: NextFunction ): Promise => { - processServerMonitor(req, res, next); + try { + const monitorSecretKeyAsString: string | undefined = + req.params['secretkey']; + + + if (!monitorSecretKeyAsString) { + throw new BadDataException('Invalid Secret Key'); + } + + + const monitor: Monitor | null = await MonitorService.findOneBy({ + query: { + serverMonitorSecretKey: new ObjectID(monitorSecretKeyAsString), + monitorType: MonitorType.Server + }, + select: { + _id: true + }, + props: { + isRoot: true + } + }); + + if (!monitor) { + throw new BadDataException('Monitor not found'); + } + + // now process this request. + + const serverMonitorResponse = req.body['serverMonitorResponse'] as ServerMonitorResponse; + + if (!serverMonitorResponse) { + throw new BadDataException('Invalid Server Monitor Response'); + } + + // process probe response here. + const probeApiIngestResponse: ProbeApiIngestResponse = + await ProbeMonitorResponseService.processProbeResponse( + serverMonitorResponse + ); + + return Response.sendJsonObjectResponse(req, res, { + probeApiIngestResponse: probeApiIngestResponse, + } as any); + } catch (err) { + return next(err); + } } );