diff --git a/Common/Types/Monitor/CriteriaFilter.ts b/Common/Types/Monitor/CriteriaFilter.ts index 1c21437bae..2a6c1df9f8 100644 --- a/Common/Types/Monitor/CriteriaFilter.ts +++ b/Common/Types/Monitor/CriteriaFilter.ts @@ -34,6 +34,9 @@ export enum CheckOn { ScreenSizeType = "Screen Size", BrowserType = "Browser Type", + + // Log monitors. + LogCount = "Log Count", } export interface ServerMonitorOptions { diff --git a/Common/Types/Monitor/MonitorCriteriaInstance.ts b/Common/Types/Monitor/MonitorCriteriaInstance.ts index 2aad09e65b..1fcffe56d9 100644 --- a/Common/Types/Monitor/MonitorCriteriaInstance.ts +++ b/Common/Types/Monitor/MonitorCriteriaInstance.ts @@ -80,6 +80,31 @@ export default class MonitorCriteriaInstance extends DatabaseProperty { return monitorCriteriaInstance; } + if (arg.monitorType === MonitorType.Logs) { + const monitorCriteriaInstance: MonitorCriteriaInstance = + new MonitorCriteriaInstance(); + + monitorCriteriaInstance.data = { + id: ObjectID.generate().toString(), + monitorStatusId: arg.monitorStatusId, + filterCondition: FilterCondition.Any, + filters: [ + { + checkOn: CheckOn.LogCount, + filterType: FilterType.GreaterThan, + value: 0, // if there are some logs then monitor is online. + }, + ], + incidents: [], + changeMonitorStatus: true, + createIncidents: false, + name: `Check if ${arg.monitorName} is online`, + description: `This criteria checks if the ${arg.monitorName} is online`, + }; + + return monitorCriteriaInstance; + } + if (arg.monitorType === MonitorType.SSLCertificate) { const monitorCriteriaInstance: MonitorCriteriaInstance = new MonitorCriteriaInstance(); @@ -283,6 +308,35 @@ export default class MonitorCriteriaInstance extends DatabaseProperty { }; } + if (arg.monitorType === MonitorType.Logs) { + monitorCriteriaInstance.data = { + id: ObjectID.generate().toString(), + monitorStatusId: arg.monitorStatusId, + filterCondition: FilterCondition.Any, + filters: [ + { + checkOn: CheckOn.LogCount, + filterType: FilterType.EqualTo, + value: 0, // if there are no logs then the monitor is offline + }, + ], + incidents: [ + { + title: `${arg.monitorName} is offline`, + description: `${arg.monitorName} is currently offline.`, + incidentSeverityId: arg.incidentSeverityId, + autoResolveIncident: true, + id: ObjectID.generate().toString(), + onCallPolicyIds: [], + }, + ], + changeMonitorStatus: true, + createIncidents: true, + name: `Check if ${arg.monitorName} is offline`, + description: `This criteria checks if the ${arg.monitorName} is offline`, + }; + } + if (arg.monitorType === MonitorType.IncomingRequest) { monitorCriteriaInstance.data = { id: ObjectID.generate().toString(), diff --git a/Common/Types/Monitor/MonitorStep.ts b/Common/Types/Monitor/MonitorStep.ts index f4e6b78f68..86358f4472 100644 --- a/Common/Types/Monitor/MonitorStep.ts +++ b/Common/Types/Monitor/MonitorStep.ts @@ -10,7 +10,9 @@ import JSONFunctions from "../JSONFunctions"; import ObjectID from "../ObjectID"; import Port from "../Port"; import MonitorCriteria from "./MonitorCriteria"; -import MonitorStepLogMonitor, { MonitorStepLogMonitorUtil } from "./MonitorStepLogMonitor"; +import MonitorStepLogMonitor, { + MonitorStepLogMonitorUtil, +} from "./MonitorStepLogMonitor"; import MonitorType from "./MonitorType"; import BrowserType from "./SyntheticMonitors//BrowserType"; import ScreenSizeType from "./SyntheticMonitors/ScreenSizeType"; @@ -194,6 +196,16 @@ export default class MonitorStep extends DatabaseProperty { return "Monitor Destination is required."; } + if (monitorType === MonitorType.Logs) { + if (!value.data.logMonitor) { + return "Log Monitor is required"; + } + + if (!value.data.logMonitor.lastXSecondsOfLogs) { + return "Monitor Last Minutes of Logs is required."; + } + } + if ( !value.data.customCode && (monitorType === MonitorType.CustomJavaScriptCode || @@ -252,7 +264,9 @@ export default class MonitorStep extends DatabaseProperty { customCode: this.data.customCode || undefined, screenSizeTypes: this.data.screenSizeTypes || undefined, browserTypes: this.data.browserTypes || undefined, - logMonitor: this.data.logMonitor ? MonitorStepLogMonitorUtil.toJSON(this.data.logMonitor) : undefined, + logMonitor: this.data.logMonitor + ? MonitorStepLogMonitorUtil.toJSON(this.data.logMonitor) + : undefined, }, }); } diff --git a/Common/Types/Monitor/MonitorStepLogMonitor.ts b/Common/Types/Monitor/MonitorStepLogMonitor.ts index 63242cdfce..eccdec0cf4 100644 --- a/Common/Types/Monitor/MonitorStepLogMonitor.ts +++ b/Common/Types/Monitor/MonitorStepLogMonitor.ts @@ -12,7 +12,6 @@ export default interface MonitorStepLogMonitor { } export class MonitorStepLogMonitorUtil { - public static getDefault(): MonitorStepLogMonitor { return { attributes: {}, diff --git a/Common/Types/Monitor/MonitorType.ts b/Common/Types/Monitor/MonitorType.ts index 0b6060c44e..54b12b061f 100644 --- a/Common/Types/Monitor/MonitorType.ts +++ b/Common/Types/Monitor/MonitorType.ts @@ -181,6 +181,9 @@ export class MonitorTypeHelper { MonitorType.CustomJavaScriptCode, MonitorType.IncomingRequest, MonitorType.Server, + MonitorType.Logs, + MonitorType.Metrics, + MonitorType.Traces, ]; } diff --git a/Common/Types/ObjectID.ts b/Common/Types/ObjectID.ts index 49aa32beb6..95192d53ee 100644 --- a/Common/Types/ObjectID.ts +++ b/Common/Types/ObjectID.ts @@ -49,6 +49,9 @@ export default class ObjectID extends DatabaseProperty { public static toJSONArray(ids: Array): Array { return ids.map((id: ObjectID) => { + if (typeof id === "string") { + id = new ObjectID(id); + } return id.toJSON(); }); } diff --git a/Dashboard/src/Components/Form/Monitor/LogMonitor/LogMonitorStepFrom.tsx b/Dashboard/src/Components/Form/Monitor/LogMonitor/LogMonitorStepFrom.tsx index 8f42e83003..1086fe04df 100644 --- a/Dashboard/src/Components/Form/Monitor/LogMonitor/LogMonitorStepFrom.tsx +++ b/Dashboard/src/Components/Form/Monitor/LogMonitor/LogMonitorStepFrom.tsx @@ -84,7 +84,7 @@ const LogMonitorStepForm: FunctionComponent = ( value: 86400, }, ], - title: "Check Last X Seconds of Logs", + title: "Monitor Last X Time of Logs", isAdvancedFilter: true, }, { diff --git a/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx b/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx index 40afb39c3a..eb2e9918fc 100644 --- a/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx +++ b/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx @@ -8,7 +8,9 @@ import Exception from "Common/Types/Exception/Exception"; import IP from "Common/Types/IP/IP"; import MonitorCriteria from "Common/Types/Monitor/MonitorCriteria"; import MonitorStep from "Common/Types/Monitor/MonitorStep"; -import MonitorStepLogMonitor, { MonitorStepLogMonitorUtil } from "Common/Types/Monitor/MonitorStepLogMonitor"; +import MonitorStepLogMonitor, { + MonitorStepLogMonitorUtil, +} from "Common/Types/Monitor/MonitorStepLogMonitor"; import MonitorType from "Common/Types/Monitor/MonitorType"; import BrowserType from "Common/Types/Monitor/SyntheticMonitors/BrowserType"; import Port from "Common/Types/Port"; @@ -367,29 +369,6 @@ const MonitorStepElement: FunctionComponent = ( )} - {props.monitorType === MonitorType.Logs && ( -
- - { - monitorStep.setLogMonitor(value); - setMonitorStep(MonitorStep.clone(monitorStep)); - }} - attributeKeys={attributeKeys} - telemetryServices={telemetryServices} - /> -
- )} - {props.monitorType === MonitorType.API && (
= (
)} + {props.monitorType === MonitorType.Logs && ( +
+ + { + monitorStep.setLogMonitor(value); + setMonitorStep(MonitorStep.clone(monitorStep)); + }} + attributeKeys={attributeKeys} + telemetryServices={telemetryServices} + /> +
+ )} + {isCodeMonitor && (
{ + return i.value === CheckOn.LogCount; + }); + } + return options; } @@ -249,6 +255,17 @@ export default class CriteriaFilterUtil { }); } + if (checkOn === CheckOn.LogCount) { + options = options.filter((i: DropdownOption) => { + return ( + i.value === FilterType.GreaterThan || + i.value === FilterType.LessThan || + i.value === FilterType.LessThanOrEqualTo || + i.value === FilterType.GreaterThanOrEqualTo + ); + }); + } + if ( checkOn === CheckOn.CPUUsagePercent || checkOn === CheckOn.DiskUsagePercent || @@ -469,6 +486,10 @@ export default class CriteriaFilterUtil { return "1234"; } + if (checkOn === CheckOn.LogCount) { + return "1"; + } + if (checkOn === CheckOn.ServerProcessCommand) { return "node index.js"; } diff --git a/Ingestor/API/OTelIngest.ts b/Ingestor/API/OTelIngest.ts index ba84a98101..d2d905bd77 100644 --- a/Ingestor/API/OTelIngest.ts +++ b/Ingestor/API/OTelIngest.ts @@ -24,12 +24,13 @@ import Express, { } from "CommonServer/Utils/Express"; import logger from "CommonServer/Utils/Logger"; import Response from "CommonServer/Utils/Response"; -import Log, rity } from "Model/AnalyticsModels/Log"; +import Log from "Model/AnalyticsModels/Log"; import Metric, { MetricPointType } from "Model/AnalyticsModels/Metric"; import Span, { SpanKind, SpanStatus } from "Model/AnalyticsModels/Span"; import protobuf from "protobufjs"; import Dictionary from "Common/Types/Dictionary"; import ObjectID from "Common/Types/ObjectID"; +import LogSeverity from "Common/Types/Log/LogSeverity"; // Load proto file for OTel