refactor(monitor): tidy formatting, consolidate imports and add type annotations

- Normalize whitespace/indentation and reformat several monitor utilities and message builders
- Consolidate and reorder imports (including MonitorEvaluationSummary) across evaluator/data-extractor modules
- Add explicit types (MonitorStatus, BasicDiskMetrics) and tighten type annotations in observation/resource code
- Minor cleanups to conditional formatting in dashboard components (EvaluationLogList, SummaryInfo)
This commit is contained in:
Nawaz Dhandala 2025-11-05 09:33:29 +00:00
parent 3837208023
commit 775b8846c7
No known key found for this signature in database
GPG key ID: 96C5DCA24769DBCA
11 changed files with 2075 additions and 2079 deletions

View file

@ -174,8 +174,7 @@ export default class ServerMonitorCriteria {
).basicInfrastructureMetrics?.diskMetrics.find(
(item: BasicDiskMetrics) => {
return (
item.diskPath.trim().toLowerCase() ===
diskPath.trim().toLowerCase()
item.diskPath.trim().toLowerCase() === diskPath.trim().toLowerCase()
);
},
);

View file

@ -16,192 +16,193 @@ import MetricQueryConfigData from "../../../Types/Metrics/MetricQueryConfigData"
import MetricFormulaConfigData from "../../../Types/Metrics/MetricFormulaConfigData";
export default class MonitorCriteriaDataExtractor {
public static getProbeMonitorResponse(
dataToProcess: DataToProcess,
): ProbeMonitorResponse | null {
if ((dataToProcess as ProbeMonitorResponse).monitorStepId) {
return dataToProcess as ProbeMonitorResponse;
}
public static getProbeMonitorResponse(
dataToProcess: DataToProcess,
): ProbeMonitorResponse | null {
if ((dataToProcess as ProbeMonitorResponse).monitorStepId) {
return dataToProcess as ProbeMonitorResponse;
}
return null;
}
return null;
}
public static getServerMonitorResponse(
dataToProcess: DataToProcess,
): ServerMonitorResponse | null {
if ((dataToProcess as ServerMonitorResponse).hostname) {
return dataToProcess as ServerMonitorResponse;
}
public static getServerMonitorResponse(
dataToProcess: DataToProcess,
): ServerMonitorResponse | null {
if ((dataToProcess as ServerMonitorResponse).hostname) {
return dataToProcess as ServerMonitorResponse;
}
return null;
}
return null;
}
public static getIncomingMonitorRequest(
dataToProcess: DataToProcess,
): IncomingMonitorRequest | null {
if (
(dataToProcess as IncomingMonitorRequest).incomingRequestReceivedAt !==
undefined
) {
return dataToProcess as IncomingMonitorRequest;
}
public static getIncomingMonitorRequest(
dataToProcess: DataToProcess,
): IncomingMonitorRequest | null {
if (
(dataToProcess as IncomingMonitorRequest).incomingRequestReceivedAt !==
undefined
) {
return dataToProcess as IncomingMonitorRequest;
}
return null;
}
return null;
}
public static getLogMonitorResponse(
dataToProcess: DataToProcess,
): LogMonitorResponse | null {
if ((dataToProcess as LogMonitorResponse).logCount !== undefined) {
return dataToProcess as LogMonitorResponse;
}
public static getLogMonitorResponse(
dataToProcess: DataToProcess,
): LogMonitorResponse | null {
if ((dataToProcess as LogMonitorResponse).logCount !== undefined) {
return dataToProcess as LogMonitorResponse;
}
return null;
}
return null;
}
public static getTraceMonitorResponse(
dataToProcess: DataToProcess,
): TraceMonitorResponse | null {
if ((dataToProcess as TraceMonitorResponse).spanCount !== undefined) {
return dataToProcess as TraceMonitorResponse;
}
public static getTraceMonitorResponse(
dataToProcess: DataToProcess,
): TraceMonitorResponse | null {
if ((dataToProcess as TraceMonitorResponse).spanCount !== undefined) {
return dataToProcess as TraceMonitorResponse;
}
return null;
}
return null;
}
public static getMetricMonitorResponse(
dataToProcess: DataToProcess,
): MetricMonitorResponse | null {
if ((dataToProcess as MetricMonitorResponse).metricResult !== undefined) {
return dataToProcess as MetricMonitorResponse;
}
public static getMetricMonitorResponse(
dataToProcess: DataToProcess,
): MetricMonitorResponse | null {
if ((dataToProcess as MetricMonitorResponse).metricResult !== undefined) {
return dataToProcess as MetricMonitorResponse;
}
return null;
}
return null;
}
public static getCustomCodeMonitorResponse(
dataToProcess: DataToProcess,
): CustomCodeMonitorResponse | null {
const probeResponse: ProbeMonitorResponse | null =
MonitorCriteriaDataExtractor.getProbeMonitorResponse(dataToProcess);
public static getCustomCodeMonitorResponse(
dataToProcess: DataToProcess,
): CustomCodeMonitorResponse | null {
const probeResponse: ProbeMonitorResponse | null =
MonitorCriteriaDataExtractor.getProbeMonitorResponse(dataToProcess);
if (probeResponse?.customCodeMonitorResponse) {
return probeResponse.customCodeMonitorResponse;
}
if (probeResponse?.customCodeMonitorResponse) {
return probeResponse.customCodeMonitorResponse;
}
return null;
}
return null;
}
public static getSyntheticMonitorResponses(
dataToProcess: DataToProcess,
): Array<SyntheticMonitorResponse> {
const probeResponse: ProbeMonitorResponse | null =
MonitorCriteriaDataExtractor.getProbeMonitorResponse(dataToProcess);
public static getSyntheticMonitorResponses(
dataToProcess: DataToProcess,
): Array<SyntheticMonitorResponse> {
const probeResponse: ProbeMonitorResponse | null =
MonitorCriteriaDataExtractor.getProbeMonitorResponse(dataToProcess);
return probeResponse?.syntheticMonitorResponse || [];
}
return probeResponse?.syntheticMonitorResponse || [];
}
public static getSslResponse(
dataToProcess: DataToProcess,
): SslMonitorResponse | null {
const probeResponse: ProbeMonitorResponse | null =
MonitorCriteriaDataExtractor.getProbeMonitorResponse(dataToProcess);
public static getSslResponse(
dataToProcess: DataToProcess,
): SslMonitorResponse | null {
const probeResponse: ProbeMonitorResponse | null =
MonitorCriteriaDataExtractor.getProbeMonitorResponse(dataToProcess);
if (probeResponse?.sslResponse) {
return probeResponse.sslResponse;
}
if (probeResponse?.sslResponse) {
return probeResponse.sslResponse;
}
return null;
}
return null;
}
public static extractMetricValues(input: {
criteriaFilter: CriteriaFilter;
dataToProcess: DataToProcess;
monitorStep: MonitorStep;
}): { alias: string | null; values: Array<number> } | null {
const metricResponse: MetricMonitorResponse | null =
MonitorCriteriaDataExtractor.getMetricMonitorResponse(
input.dataToProcess,
);
public static extractMetricValues(input: {
criteriaFilter: CriteriaFilter;
dataToProcess: DataToProcess;
monitorStep: MonitorStep;
}): { alias: string | null; values: Array<number> } | null {
const metricResponse: MetricMonitorResponse | null =
MonitorCriteriaDataExtractor.getMetricMonitorResponse(
input.dataToProcess,
);
if (!metricResponse) {
return null;
}
if (!metricResponse) {
return null;
}
const aggregatedResults: Array<AggregatedResult> =
metricResponse.metricResult || [];
const aggregatedResults: Array<AggregatedResult> =
metricResponse.metricResult || [];
if (!aggregatedResults.length) {
return {
alias: input.criteriaFilter.metricMonitorOptions?.metricAlias || null,
values: [],
};
}
if (!aggregatedResults.length) {
return {
alias: input.criteriaFilter.metricMonitorOptions?.metricAlias || null,
values: [],
};
}
let alias: string | null =
input.criteriaFilter.metricMonitorOptions?.metricAlias || null;
let alias: string | null =
input.criteriaFilter.metricMonitorOptions?.metricAlias || null;
let result: AggregatedResult | undefined;
let result: AggregatedResult | undefined;
if (alias) {
const queryConfigs: Array<MetricQueryConfigData> =
input.monitorStep.data?.metricMonitor?.metricViewConfig?.queryConfigs ||
[];
if (alias) {
const queryConfigs: Array<MetricQueryConfigData> =
input.monitorStep.data?.metricMonitor?.metricViewConfig?.queryConfigs ||
[];
let aliasIndex: number = queryConfigs.findIndex(
(queryConfig: MetricQueryConfigData) => {
return queryConfig.metricAliasData?.metricVariable === alias;
},
);
let aliasIndex: number = queryConfigs.findIndex(
(queryConfig: MetricQueryConfigData) => {
return queryConfig.metricAliasData?.metricVariable === alias;
},
);
if (aliasIndex < 0) {
const formulaConfigs: Array<MetricFormulaConfigData> =
input.monitorStep.data?.metricMonitor?.metricViewConfig
?.formulaConfigs || [];
if (aliasIndex < 0) {
const formulaConfigs: Array<MetricFormulaConfigData> =
input.monitorStep.data?.metricMonitor?.metricViewConfig
?.formulaConfigs || [];
const formulaIndex: number = formulaConfigs.findIndex(
(formulaConfig: MetricFormulaConfigData) => {
return formulaConfig.metricAliasData?.metricVariable === alias;
},
);
const formulaIndex: number = formulaConfigs.findIndex(
(formulaConfig: MetricFormulaConfigData) => {
return formulaConfig.metricAliasData?.metricVariable === alias;
},
);
if (formulaIndex >= 0) {
aliasIndex = queryConfigs.length + formulaIndex;
}
}
if (formulaIndex >= 0) {
aliasIndex = queryConfigs.length + formulaIndex;
}
}
if (aliasIndex >= 0 && aliasIndex < aggregatedResults.length) {
result = aggregatedResults[aliasIndex];
}
}
if (aliasIndex >= 0 && aliasIndex < aggregatedResults.length) {
result = aggregatedResults[aliasIndex];
}
}
if (!result) {
result = aggregatedResults[0];
if (!alias) {
const defaultAlias: string | undefined =
input.monitorStep.data?.metricMonitor?.metricViewConfig?.queryConfigs?.[0]?.metricAliasData?.metricVariable;
alias = defaultAlias || null;
}
}
if (!result) {
result = aggregatedResults[0];
if (!alias) {
const defaultAlias: string | undefined =
input.monitorStep.data?.metricMonitor?.metricViewConfig
?.queryConfigs?.[0]?.metricAliasData?.metricVariable;
alias = defaultAlias || null;
}
}
if (!result) {
return {
alias: alias,
values: [],
};
}
if (!result) {
return {
alias: alias,
values: [],
};
}
const values: Array<number> = result.data
.map((entry: AggregateModel) => {
return entry.value;
})
.filter((value: number) => {
return typeof value === "number" && !isNaN(value);
});
const values: Array<number> = result.data
.map((entry: AggregateModel) => {
return entry.value;
})
.filter((value: number) => {
return typeof value === "number" && !isNaN(value);
});
return {
alias: alias,
values: values,
};
}
return {
alias: alias,
values: values,
};
}
}

View file

@ -16,7 +16,7 @@ import MonitorCriteria from "../../../Types/Monitor/MonitorCriteria";
import MonitorCriteriaInstance from "../../../Types/Monitor/MonitorCriteriaInstance";
import MonitorStep from "../../../Types/Monitor/MonitorStep";
import FilterCondition from "../../../Types/Filter/FilterCondition";
import {
import MonitorEvaluationSummary, {
MonitorEvaluationCriteriaResult,
MonitorEvaluationEvent,
MonitorEvaluationFilterResult,
@ -30,7 +30,6 @@ import OneUptimeDate from "../../../Types/Date";
import { JSONObject } from "../../../Types/JSON";
import Typeof from "../../../Types/Typeof";
import ReturnResult from "../../../Types/IsolatedVM/ReturnResult";
import MonitorEvaluationSummary from "../../../Types/Monitor/MonitorEvaluationSummary";
export default class MonitorCriteriaEvaluator {
public static async processMonitorStep(input: {

View file

@ -1,141 +1,141 @@
import {
CriteriaFilter,
FilterType,
CriteriaFilter,
FilterType,
} from "../../../Types/Monitor/CriteriaFilter";
export default class MonitorCriteriaExpectationBuilder {
public static getCriteriaFilterDescription(
criteriaFilter: CriteriaFilter,
): string {
const parts: Array<string> = [criteriaFilter.checkOn];
public static getCriteriaFilterDescription(
criteriaFilter: CriteriaFilter,
): string {
const parts: Array<string> = [criteriaFilter.checkOn];
if (criteriaFilter.filterType) {
parts.push(criteriaFilter.filterType);
}
if (criteriaFilter.filterType) {
parts.push(criteriaFilter.filterType);
}
if (criteriaFilter.value !== undefined && criteriaFilter.value !== null) {
parts.push(String(criteriaFilter.value));
}
if (criteriaFilter.value !== undefined && criteriaFilter.value !== null) {
parts.push(String(criteriaFilter.value));
}
return parts.join(" ").trim();
}
return parts.join(" ").trim();
}
public static describeCriteriaExpectation(
criteriaFilter: CriteriaFilter,
): string | null {
if (!criteriaFilter.filterType) {
return null;
}
public static describeCriteriaExpectation(
criteriaFilter: CriteriaFilter,
): string | null {
if (!criteriaFilter.filterType) {
return null;
}
let expectation: string;
let expectation: string;
const value: string | number | undefined = criteriaFilter.value;
const value: string | number | undefined = criteriaFilter.value;
switch (criteriaFilter.filterType) {
case FilterType.GreaterThan:
expectation = `to be greater than ${value}`;
break;
case FilterType.GreaterThanOrEqualTo:
expectation = `to be greater than or equal to ${value}`;
break;
case FilterType.LessThan:
expectation = `to be less than ${value}`;
break;
case FilterType.LessThanOrEqualTo:
expectation = `to be less than or equal to ${value}`;
break;
case FilterType.EqualTo:
expectation = `to equal ${value}`;
break;
case FilterType.NotEqualTo:
expectation = `to not equal ${value}`;
break;
case FilterType.Contains:
expectation = `to contain ${value}`;
break;
case FilterType.NotContains:
expectation = `to not contain ${value}`;
break;
case FilterType.StartsWith:
expectation = `to start with ${value}`;
break;
case FilterType.EndsWith:
expectation = `to end with ${value}`;
break;
case FilterType.IsEmpty:
expectation = "to be empty";
break;
case FilterType.IsNotEmpty:
expectation = "to not be empty";
break;
case FilterType.True:
expectation = "to be true";
break;
case FilterType.False:
expectation = "to be false";
break;
case FilterType.IsExecuting:
expectation = "to be executing";
break;
case FilterType.IsNotExecuting:
expectation = "to not be executing";
break;
case FilterType.RecievedInMinutes:
expectation = value
? `to receive a heartbeat within ${value} minutes`
: "to receive a heartbeat within the configured window";
break;
case FilterType.NotRecievedInMinutes:
expectation = value
? `to miss a heartbeat for at least ${value} minutes`
: "to miss a heartbeat within the configured window";
break;
case FilterType.EvaluatesToTrue:
expectation = "to evaluate to true";
break;
default:
expectation = `${criteriaFilter.filterType}${value ? ` ${value}` : ""}`;
break;
}
switch (criteriaFilter.filterType) {
case FilterType.GreaterThan:
expectation = `to be greater than ${value}`;
break;
case FilterType.GreaterThanOrEqualTo:
expectation = `to be greater than or equal to ${value}`;
break;
case FilterType.LessThan:
expectation = `to be less than ${value}`;
break;
case FilterType.LessThanOrEqualTo:
expectation = `to be less than or equal to ${value}`;
break;
case FilterType.EqualTo:
expectation = `to equal ${value}`;
break;
case FilterType.NotEqualTo:
expectation = `to not equal ${value}`;
break;
case FilterType.Contains:
expectation = `to contain ${value}`;
break;
case FilterType.NotContains:
expectation = `to not contain ${value}`;
break;
case FilterType.StartsWith:
expectation = `to start with ${value}`;
break;
case FilterType.EndsWith:
expectation = `to end with ${value}`;
break;
case FilterType.IsEmpty:
expectation = "to be empty";
break;
case FilterType.IsNotEmpty:
expectation = "to not be empty";
break;
case FilterType.True:
expectation = "to be true";
break;
case FilterType.False:
expectation = "to be false";
break;
case FilterType.IsExecuting:
expectation = "to be executing";
break;
case FilterType.IsNotExecuting:
expectation = "to not be executing";
break;
case FilterType.RecievedInMinutes:
expectation = value
? `to receive a heartbeat within ${value} minutes`
: "to receive a heartbeat within the configured window";
break;
case FilterType.NotRecievedInMinutes:
expectation = value
? `to miss a heartbeat for at least ${value} minutes`
: "to miss a heartbeat within the configured window";
break;
case FilterType.EvaluatesToTrue:
expectation = "to evaluate to true";
break;
default:
expectation = `${criteriaFilter.filterType}${value ? ` ${value}` : ""}`;
break;
}
const evaluationWindow: string | null =
MonitorCriteriaExpectationBuilder.getEvaluationWindowDescription(
criteriaFilter,
);
const evaluationWindow: string | null =
MonitorCriteriaExpectationBuilder.getEvaluationWindowDescription(
criteriaFilter,
);
if (evaluationWindow) {
expectation += ` ${evaluationWindow}`;
}
if (evaluationWindow) {
expectation += ` ${evaluationWindow}`;
}
return expectation.trim();
}
return expectation.trim();
}
public static getEvaluationWindowDescription(
criteriaFilter: CriteriaFilter,
): string | null {
const parts: Array<string> = [];
public static getEvaluationWindowDescription(
criteriaFilter: CriteriaFilter,
): string | null {
const parts: Array<string> = [];
if (
criteriaFilter.eveluateOverTime &&
criteriaFilter.evaluateOverTimeOptions?.timeValueInMinutes
) {
parts.push(
`over the last ${criteriaFilter.evaluateOverTimeOptions.timeValueInMinutes} minutes`,
);
}
if (
criteriaFilter.eveluateOverTime &&
criteriaFilter.evaluateOverTimeOptions?.timeValueInMinutes
) {
parts.push(
`over the last ${criteriaFilter.evaluateOverTimeOptions.timeValueInMinutes} minutes`,
);
}
const aggregation: string | undefined =
criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
criteriaFilter.metricMonitorOptions?.metricAggregationType;
const aggregation: string | undefined =
criteriaFilter.evaluateOverTimeOptions?.evaluateOverTimeType ||
criteriaFilter.metricMonitorOptions?.metricAggregationType;
if (aggregation) {
parts.push(`using ${aggregation.toLowerCase()}`);
}
if (aggregation) {
parts.push(`using ${aggregation.toLowerCase()}`);
}
if (!parts.length) {
return null;
}
if (!parts.length) {
return null;
}
return parts.join(" ");
}
return parts.join(" ");
}
}

View file

@ -6,83 +6,83 @@ import MonitorCriteriaExpectationBuilder from "./MonitorCriteriaExpectationBuild
import MonitorCriteriaObservationBuilder from "./MonitorCriteriaObservationBuilder";
export default class MonitorCriteriaMessageBuilder {
public static buildCriteriaFilterMessage(input: {
monitor: Monitor;
criteriaFilter: CriteriaFilter;
dataToProcess: DataToProcess;
monitorStep: MonitorStep;
didMeetCriteria: boolean;
matchMessage: string | null;
}): string {
if (input.matchMessage) {
return input.matchMessage;
}
public static buildCriteriaFilterMessage(input: {
monitor: Monitor;
criteriaFilter: CriteriaFilter;
dataToProcess: DataToProcess;
monitorStep: MonitorStep;
didMeetCriteria: boolean;
matchMessage: string | null;
}): string {
if (input.matchMessage) {
return input.matchMessage;
}
if (input.didMeetCriteria) {
const description: string =
MonitorCriteriaExpectationBuilder.getCriteriaFilterDescription(
input.criteriaFilter,
);
if (input.didMeetCriteria) {
const description: string =
MonitorCriteriaExpectationBuilder.getCriteriaFilterDescription(
input.criteriaFilter,
);
return `${description} condition met.`;
}
return `${description} condition met.`;
}
const failureMessage: string | null =
MonitorCriteriaMessageBuilder.buildCriteriaFilterFailureMessage({
monitor: input.monitor,
criteriaFilter: input.criteriaFilter,
dataToProcess: input.dataToProcess,
monitorStep: input.monitorStep,
});
const failureMessage: string | null =
MonitorCriteriaMessageBuilder.buildCriteriaFilterFailureMessage({
monitor: input.monitor,
criteriaFilter: input.criteriaFilter,
dataToProcess: input.dataToProcess,
monitorStep: input.monitorStep,
});
if (failureMessage) {
return failureMessage;
}
if (failureMessage) {
return failureMessage;
}
const description: string =
MonitorCriteriaExpectationBuilder.getCriteriaFilterDescription(
input.criteriaFilter,
);
const description: string =
MonitorCriteriaExpectationBuilder.getCriteriaFilterDescription(
input.criteriaFilter,
);
return `${description} condition was not met.`;
}
return `${description} condition was not met.`;
}
private static buildCriteriaFilterFailureMessage(input: {
monitor: Monitor;
criteriaFilter: CriteriaFilter;
dataToProcess: DataToProcess;
monitorStep: MonitorStep;
}): string | null {
const expectation: string | null =
MonitorCriteriaExpectationBuilder.describeCriteriaExpectation(
input.criteriaFilter,
);
private static buildCriteriaFilterFailureMessage(input: {
monitor: Monitor;
criteriaFilter: CriteriaFilter;
dataToProcess: DataToProcess;
monitorStep: MonitorStep;
}): string | null {
const expectation: string | null =
MonitorCriteriaExpectationBuilder.describeCriteriaExpectation(
input.criteriaFilter,
);
const observation: string | null =
MonitorCriteriaObservationBuilder.describeFilterObservation({
monitor: input.monitor,
criteriaFilter: input.criteriaFilter,
dataToProcess: input.dataToProcess,
monitorStep: input.monitorStep,
});
const observation: string | null =
MonitorCriteriaObservationBuilder.describeFilterObservation({
monitor: input.monitor,
criteriaFilter: input.criteriaFilter,
dataToProcess: input.dataToProcess,
monitorStep: input.monitorStep,
});
if (observation) {
if (expectation) {
return `${observation} (expected ${expectation}).`;
}
if (observation) {
if (expectation) {
return `${observation} (expected ${expectation}).`;
}
return `${observation}; configured filter was not met.`;
}
return `${observation}; configured filter was not met.`;
}
if (expectation) {
const description: string =
MonitorCriteriaExpectationBuilder.getCriteriaFilterDescription(
input.criteriaFilter,
);
if (expectation) {
const description: string =
MonitorCriteriaExpectationBuilder.getCriteriaFilterDescription(
input.criteriaFilter,
);
return `${description} did not satisfy the configured condition (${expectation}).`;
}
return `${description} did not satisfy the configured condition (${expectation}).`;
}
return null;
}
return null;
}
}

View file

@ -4,200 +4,193 @@ import Typeof from "../../../Types/Typeof";
import { ServerProcess } from "../../../Types/Monitor/ServerMonitor/ServerMonitorResponse";
export default class MonitorCriteriaMessageFormatter {
public static formatNumber(
value: number | null | undefined,
options?: { maximumFractionDigits?: number },
): string | null {
if (value === null || value === undefined || isNaN(value)) {
return null;
}
public static formatNumber(
value: number | null | undefined,
options?: { maximumFractionDigits?: number },
): string | null {
if (value === null || value === undefined || isNaN(value)) {
return null;
}
const fractionDigits: number =
options?.maximumFractionDigits !== undefined
? options.maximumFractionDigits
: Math.abs(value) < 10
? 2
: Math.abs(value) < 100
? 1
: 0;
const fractionDigits: number =
options?.maximumFractionDigits !== undefined
? options.maximumFractionDigits
: Math.abs(value) < 10
? 2
: Math.abs(value) < 100
? 1
: 0;
return value.toFixed(fractionDigits);
}
return value.toFixed(fractionDigits);
}
public static formatPercentage(
value: number | null | undefined,
): string | null {
const formatted: string | null = MonitorCriteriaMessageFormatter.formatNumber(
value,
{
maximumFractionDigits:
value !== null && value !== undefined && Math.abs(value) < 100 ? 1 : 0,
},
);
public static formatPercentage(
value: number | null | undefined,
): string | null {
const formatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(value, {
maximumFractionDigits:
value !== null && value !== undefined && Math.abs(value) < 100
? 1
: 0,
});
if (!formatted) {
return null;
}
if (!formatted) {
return null;
}
return `${formatted}%`;
}
return `${formatted}%`;
}
public static formatBytes(
bytes: number | null | undefined,
): string | null {
if (bytes === null || bytes === undefined || isNaN(bytes)) {
return null;
}
public static formatBytes(bytes: number | null | undefined): string | null {
if (bytes === null || bytes === undefined || isNaN(bytes)) {
return null;
}
const units: Array<string> = ["B", "KB", "MB", "GB", "TB", "PB"];
let value: number = bytes;
let index: number = 0;
const units: Array<string> = ["B", "KB", "MB", "GB", "TB", "PB"];
let value: number = bytes;
let index: number = 0;
while (value >= 1024 && index < units.length - 1) {
value = value / 1024;
index++;
}
while (value >= 1024 && index < units.length - 1) {
value = value / 1024;
index++;
}
const formatted: string | null = MonitorCriteriaMessageFormatter.formatNumber(
value,
{
maximumFractionDigits: value >= 100 ? 0 : value >= 10 ? 1 : 2,
},
);
const formatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(value, {
maximumFractionDigits: value >= 100 ? 0 : value >= 10 ? 1 : 2,
});
if (!formatted) {
return null;
}
if (!formatted) {
return null;
}
return `${formatted} ${units[index]}`;
}
return `${formatted} ${units[index]}`;
}
public static formatList(
items: Array<string>,
maxItems: number = 5,
): string {
if (!items.length) {
return "";
}
public static formatList(items: Array<string>, maxItems: number = 5): string {
if (!items.length) {
return "";
}
const trimmedItems: Array<string> = items.slice(0, maxItems);
const suffix: string =
items.length > maxItems ? `, +${items.length - maxItems} more` : "";
const trimmedItems: Array<string> = items.slice(0, maxItems);
const suffix: string =
items.length > maxItems ? `, +${items.length - maxItems} more` : "";
return `${trimmedItems.join(", ")} ${suffix}`.trim();
}
return `${trimmedItems.join(", ")} ${suffix}`.trim();
}
public static formatSnippet(text: string, maxLength: number = 120): string {
const sanitized: string = text.replace(/\s+/g, " ").trim();
public static formatSnippet(text: string, maxLength: number = 120): string {
const sanitized: string = text.replace(/\s+/g, " ").trim();
if (sanitized.length <= maxLength) {
return sanitized;
}
if (sanitized.length <= maxLength) {
return sanitized;
}
return `${sanitized.slice(0, maxLength)}`;
}
return `${sanitized.slice(0, maxLength)}`;
}
public static describeProcesses(
processes: Array<ServerProcess>,
): string | null {
if (!processes.length) {
return null;
}
public static describeProcesses(
processes: Array<ServerProcess>,
): string | null {
if (!processes.length) {
return null;
}
const processSummaries: Array<string> = processes.map(
(process: ServerProcess) => {
return `${process.name} (pid ${process.pid})`;
},
);
const processSummaries: Array<string> = processes.map(
(process: ServerProcess) => {
return `${process.name} (pid ${process.pid})`;
},
);
return MonitorCriteriaMessageFormatter.formatList(processSummaries);
}
return MonitorCriteriaMessageFormatter.formatList(processSummaries);
}
public static computeDiskUsagePercent(
diskMetric: BasicInfrastructureMetrics["diskMetrics"][number],
): number | null {
if (!diskMetric) {
return null;
}
public static computeDiskUsagePercent(
diskMetric: BasicInfrastructureMetrics["diskMetrics"][number],
): number | null {
if (!diskMetric) {
return null;
}
if (
diskMetric.percentUsed !== undefined &&
diskMetric.percentUsed !== null &&
!isNaN(diskMetric.percentUsed)
) {
return diskMetric.percentUsed;
}
if (
diskMetric.percentUsed !== undefined &&
diskMetric.percentUsed !== null &&
!isNaN(diskMetric.percentUsed)
) {
return diskMetric.percentUsed;
}
if (
diskMetric.percentFree !== undefined &&
diskMetric.percentFree !== null &&
!isNaN(diskMetric.percentFree)
) {
return 100 - diskMetric.percentFree;
}
if (
diskMetric.percentFree !== undefined &&
diskMetric.percentFree !== null &&
!isNaN(diskMetric.percentFree)
) {
return 100 - diskMetric.percentFree;
}
if (diskMetric.total && diskMetric.used && diskMetric.total > 0) {
return (diskMetric.used / diskMetric.total) * 100;
}
if (diskMetric.total && diskMetric.used && diskMetric.total > 0) {
return (diskMetric.used / diskMetric.total) * 100;
}
return null;
}
return null;
}
public static summarizeNumericSeries(values: Array<number>): string | null {
if (!values.length) {
return null;
}
public static summarizeNumericSeries(values: Array<number>): string | null {
if (!values.length) {
return null;
}
const latest: number | undefined = values[values.length - 1];
const latest: number | undefined = values[values.length - 1];
if (latest === undefined) {
return null;
}
if (latest === undefined) {
return null;
}
const latestFormatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(latest, {
maximumFractionDigits: 2,
});
const latestFormatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(latest, {
maximumFractionDigits: 2,
});
let summary: string = `latest ${latestFormatted ?? latest}`;
let summary: string = `latest ${latestFormatted ?? latest}`;
if (values.length > 1) {
const min: number = Math.min(...values);
const max: number = Math.max(...values);
if (values.length > 1) {
const min: number = Math.min(...values);
const max: number = Math.max(...values);
const minFormatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(min, {
maximumFractionDigits: 2,
});
const maxFormatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(max, {
maximumFractionDigits: 2,
});
const minFormatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(min, {
maximumFractionDigits: 2,
});
const maxFormatted: string | null =
MonitorCriteriaMessageFormatter.formatNumber(max, {
maximumFractionDigits: 2,
});
summary += ` (min ${minFormatted ?? min}, max ${maxFormatted ?? max})`;
}
summary += ` (min ${minFormatted ?? min}, max ${maxFormatted ?? max})`;
}
summary += ` across ${values.length} data point${
values.length === 1 ? "" : "s"
}`;
summary += ` across ${values.length} data point${
values.length === 1 ? "" : "s"
}`;
return summary;
}
return summary;
}
public static formatResultValue(value: unknown): string {
if (value === null || value === undefined) {
return "undefined";
}
public static formatResultValue(value: unknown): string {
if (value === null || value === undefined) {
return "undefined";
}
if (typeof value === Typeof.Object) {
try {
return JSON.stringify(value);
} catch (err) {
logger.error(err);
return "[object]";
}
}
if (typeof value === Typeof.Object) {
try {
return JSON.stringify(value);
} catch (err) {
logger.error(err);
return "[object]";
}
}
return value.toString();
}
return value.toString();
}
}

View file

@ -3,7 +3,10 @@ import CaptureSpan from "../Telemetry/CaptureSpan";
import TelemetryUtil from "../Telemetry/Telemetry";
import MetricService from "../../Services/MetricService";
import DataToProcess from "./DataToProcess";
import { MetricPointType, ServiceType } from "../../../Models/AnalyticsModels/Metric";
import {
MetricPointType,
ServiceType,
} from "../../../Models/AnalyticsModels/Metric";
import MetricType from "../../../Models/DatabaseModels/MetricType";
import BasicInfrastructureMetrics from "../../../Types/Infrastructure/BasicMetrics";
import Dictionary from "../../../Types/Dictionary";
@ -17,464 +20,463 @@ import ObjectID from "../../../Types/ObjectID";
import OneUptimeDate from "../../../Types/Date";
export default class MonitorMetricUtil {
private static buildMonitorMetricAttributes(data: {
monitorId: ObjectID;
projectId: ObjectID;
monitorName?: string | undefined;
probeName?: string | undefined;
extraAttributes?: JSONObject;
}): JSONObject {
const attributes: JSONObject = {
monitorId: data.monitorId.toString(),
projectId: data.projectId.toString(),
};
if (data.extraAttributes) {
Object.assign(attributes, data.extraAttributes);
}
if (data.monitorName) {
attributes["monitorName"] = data.monitorName;
}
if (data.probeName) {
attributes["probeName"] = data.probeName;
}
return attributes;
}
private static buildMonitorMetricRow(data: {
projectId: ObjectID;
monitorId: ObjectID;
metricName: string;
value: number | null | undefined;
attributes: JSONObject;
metricPointType?: MetricPointType;
}): JSONObject {
const ingestionDate: Date = OneUptimeDate.getCurrentDate();
const ingestionTimestamp: string =
OneUptimeDate.toClickhouseDateTime(ingestionDate);
const timeUnixNano: string =
OneUptimeDate.toUnixNano(ingestionDate).toString();
const attributes: JSONObject = { ...data.attributes };
const attributeKeys: Array<string> =
TelemetryUtil.getAttributeKeys(attributes);
return {
_id: ObjectID.generate().toString(),
createdAt: ingestionTimestamp,
updatedAt: ingestionTimestamp,
projectId: data.projectId.toString(),
serviceId: data.monitorId.toString(),
serviceType: ServiceType.Monitor,
name: data.metricName,
aggregationTemporality: null,
metricPointType: data.metricPointType || MetricPointType.Sum,
time: ingestionTimestamp,
startTime: null,
timeUnixNano: timeUnixNano,
startTimeUnixNano: null,
attributes: attributes,
attributeKeys: attributeKeys,
isMonotonic: null,
count: null,
sum: null,
min: null,
max: null,
bucketCounts: [],
explicitBounds: [],
value: data.value ?? null,
} as JSONObject;
}
@CaptureSpan()
public static async saveMonitorMetrics(data: {
monitorId: ObjectID;
projectId: ObjectID;
dataToProcess: DataToProcess;
probeName: string | undefined;
monitorName: string | undefined;
}): Promise<void> {
if (!data.monitorId) {
return;
}
if (!data.projectId) {
return;
}
if (!data.dataToProcess) {
return;
}
const metricRows: Array<JSONObject> = [];
/*
* Metric name to serviceId map
* example: "cpu.usage" -> [serviceId1, serviceId2]
* since these are monitor metrics. They dont belong to any service so we can keep the array empty.
*/
const metricNameServiceNameMap: Dictionary<MetricType> = {};
if (
(data.dataToProcess as ServerMonitorResponse).basicInfrastructureMetrics
) {
// store cpu, memory, disk metrics.
if ((data.dataToProcess as ServerMonitorResponse).requestReceivedAt) {
let isOnline: boolean = true;
const differenceInMinutes: number =
OneUptimeDate.getDifferenceInMinutes(
(data.dataToProcess as ServerMonitorResponse).requestReceivedAt,
OneUptimeDate.getCurrentDate(),
);
if (differenceInMinutes > 2) {
isOnline = false;
}
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.IsOnline,
value: isOnline ? 1 : 0,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
// add MetricType
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.IsOnline;
metricType.description = CheckOn.IsOnline + " status for monitor";
metricType.unit = "";
// add to map
metricNameServiceNameMap[MonitorMetricType.IsOnline] = metricType;
}
const basicMetrics: BasicInfrastructureMetrics | undefined = (
data.dataToProcess as ServerMonitorResponse
).basicInfrastructureMetrics;
if (!basicMetrics) {
return;
}
if (basicMetrics.cpuMetrics) {
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.CPUUsagePercent,
value: basicMetrics.cpuMetrics.percentUsed ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.CPUUsagePercent;
metricType.description = CheckOn.CPUUsagePercent + " of Server/VM";
metricType.unit = "%";
metricNameServiceNameMap[MonitorMetricType.CPUUsagePercent] =
metricType;
}
if (basicMetrics.memoryMetrics) {
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.MemoryUsagePercent,
value: basicMetrics.memoryMetrics.percentUsed ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.MemoryUsagePercent;
metricType.description = CheckOn.MemoryUsagePercent + " of Server/VM";
metricType.unit = "%";
metricNameServiceNameMap[MonitorMetricType.MemoryUsagePercent] =
metricType;
}
if (basicMetrics.diskMetrics && basicMetrics.diskMetrics.length > 0) {
for (const diskMetric of basicMetrics.diskMetrics) {
const extraAttributes: JSONObject = {};
if (diskMetric.diskPath) {
extraAttributes["diskPath"] = diskMetric.diskPath;
}
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.DiskUsagePercent,
value: diskMetric.percentUsed ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.DiskUsagePercent;
metricType.description = CheckOn.DiskUsagePercent + " of Server/VM";
metricType.unit = "%";
metricNameServiceNameMap[MonitorMetricType.DiskUsagePercent] =
metricType;
}
}
}
if (
(data.dataToProcess as ProbeMonitorResponse).customCodeMonitorResponse
?.executionTimeInMS
) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ExecutionTime,
value:
(data.dataToProcess as ProbeMonitorResponse).customCodeMonitorResponse
?.executionTimeInMS ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ExecutionTime;
metricType.description = CheckOn.ExecutionTime + " of this monitor";
metricType.unit = "ms";
metricNameServiceNameMap[MonitorMetricType.ExecutionTime] = metricType;
}
if (
(data.dataToProcess as ProbeMonitorResponse) &&
(data.dataToProcess as ProbeMonitorResponse).syntheticMonitorResponse &&
(
(data.dataToProcess as ProbeMonitorResponse).syntheticMonitorResponse ||
[]
).length > 0
) {
const syntheticResponses: Array<SyntheticMonitorResponse> =
(data.dataToProcess as ProbeMonitorResponse).syntheticMonitorResponse ||
[];
for (const syntheticMonitorResponse of syntheticResponses) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
if (syntheticMonitorResponse.browserType) {
extraAttributes["browserType"] = syntheticMonitorResponse.browserType;
}
if (syntheticMonitorResponse.screenSizeType) {
extraAttributes["screenSizeType"] =
syntheticMonitorResponse.screenSizeType;
}
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ExecutionTime,
value: syntheticMonitorResponse.executionTimeInMS ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ExecutionTime;
metricType.description = CheckOn.ExecutionTime + " of this monitor";
metricType.unit = "ms";
metricNameServiceNameMap[MonitorMetricType.ExecutionTime] = metricType;
}
}
if ((data.dataToProcess as ProbeMonitorResponse).responseTimeInMs) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ResponseTime,
value:
(data.dataToProcess as ProbeMonitorResponse).responseTimeInMs ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ResponseTime;
metricType.description = CheckOn.ResponseTime + " of this monitor";
metricType.unit = "ms";
metricNameServiceNameMap[MonitorMetricType.ResponseTime] = metricType;
}
if ((data.dataToProcess as ProbeMonitorResponse).isOnline !== undefined) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.IsOnline,
value: (data.dataToProcess as ProbeMonitorResponse).isOnline ? 1 : 0,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.IsOnline;
metricType.description = CheckOn.IsOnline + " status for monitor";
metricType.unit = "";
metricNameServiceNameMap[MonitorMetricType.IsOnline] = metricType;
}
if ((data.dataToProcess as ProbeMonitorResponse).responseCode) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ResponseStatusCode,
value:
(data.dataToProcess as ProbeMonitorResponse).responseCode ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ResponseStatusCode;
metricType.description = CheckOn.ResponseStatusCode +
" for this monitor";
metricType.unit = "Status Code";
metricNameServiceNameMap[MonitorMetricType.ResponseStatusCode] =
metricType;
}
if (metricRows.length > 0) {
await MetricService.insertJsonRows(metricRows);
}
// index metrics
TelemetryUtil.indexMetricNameServiceNameMap({
projectId: data.projectId,
metricNameServiceNameMap: metricNameServiceNameMap,
}).catch((err: Error) => {
logger.error(err);
});
}
private static buildMonitorMetricAttributes(data: {
monitorId: ObjectID;
projectId: ObjectID;
monitorName?: string | undefined;
probeName?: string | undefined;
extraAttributes?: JSONObject;
}): JSONObject {
const attributes: JSONObject = {
monitorId: data.monitorId.toString(),
projectId: data.projectId.toString(),
};
if (data.extraAttributes) {
Object.assign(attributes, data.extraAttributes);
}
if (data.monitorName) {
attributes["monitorName"] = data.monitorName;
}
if (data.probeName) {
attributes["probeName"] = data.probeName;
}
return attributes;
}
private static buildMonitorMetricRow(data: {
projectId: ObjectID;
monitorId: ObjectID;
metricName: string;
value: number | null | undefined;
attributes: JSONObject;
metricPointType?: MetricPointType;
}): JSONObject {
const ingestionDate: Date = OneUptimeDate.getCurrentDate();
const ingestionTimestamp: string =
OneUptimeDate.toClickhouseDateTime(ingestionDate);
const timeUnixNano: string =
OneUptimeDate.toUnixNano(ingestionDate).toString();
const attributes: JSONObject = { ...data.attributes };
const attributeKeys: Array<string> =
TelemetryUtil.getAttributeKeys(attributes);
return {
_id: ObjectID.generate().toString(),
createdAt: ingestionTimestamp,
updatedAt: ingestionTimestamp,
projectId: data.projectId.toString(),
serviceId: data.monitorId.toString(),
serviceType: ServiceType.Monitor,
name: data.metricName,
aggregationTemporality: null,
metricPointType: data.metricPointType || MetricPointType.Sum,
time: ingestionTimestamp,
startTime: null,
timeUnixNano: timeUnixNano,
startTimeUnixNano: null,
attributes: attributes,
attributeKeys: attributeKeys,
isMonotonic: null,
count: null,
sum: null,
min: null,
max: null,
bucketCounts: [],
explicitBounds: [],
value: data.value ?? null,
} as JSONObject;
}
@CaptureSpan()
public static async saveMonitorMetrics(data: {
monitorId: ObjectID;
projectId: ObjectID;
dataToProcess: DataToProcess;
probeName: string | undefined;
monitorName: string | undefined;
}): Promise<void> {
if (!data.monitorId) {
return;
}
if (!data.projectId) {
return;
}
if (!data.dataToProcess) {
return;
}
const metricRows: Array<JSONObject> = [];
/*
* Metric name to serviceId map
* example: "cpu.usage" -> [serviceId1, serviceId2]
* since these are monitor metrics. They dont belong to any service so we can keep the array empty.
*/
const metricNameServiceNameMap: Dictionary<MetricType> = {};
if (
(data.dataToProcess as ServerMonitorResponse).basicInfrastructureMetrics
) {
// store cpu, memory, disk metrics.
if ((data.dataToProcess as ServerMonitorResponse).requestReceivedAt) {
let isOnline: boolean = true;
const differenceInMinutes: number =
OneUptimeDate.getDifferenceInMinutes(
(data.dataToProcess as ServerMonitorResponse).requestReceivedAt,
OneUptimeDate.getCurrentDate(),
);
if (differenceInMinutes > 2) {
isOnline = false;
}
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.IsOnline,
value: isOnline ? 1 : 0,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
// add MetricType
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.IsOnline;
metricType.description = CheckOn.IsOnline + " status for monitor";
metricType.unit = "";
// add to map
metricNameServiceNameMap[MonitorMetricType.IsOnline] = metricType;
}
const basicMetrics: BasicInfrastructureMetrics | undefined = (
data.dataToProcess as ServerMonitorResponse
).basicInfrastructureMetrics;
if (!basicMetrics) {
return;
}
if (basicMetrics.cpuMetrics) {
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.CPUUsagePercent,
value: basicMetrics.cpuMetrics.percentUsed ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.CPUUsagePercent;
metricType.description = CheckOn.CPUUsagePercent + " of Server/VM";
metricType.unit = "%";
metricNameServiceNameMap[MonitorMetricType.CPUUsagePercent] =
metricType;
}
if (basicMetrics.memoryMetrics) {
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.MemoryUsagePercent,
value: basicMetrics.memoryMetrics.percentUsed ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.MemoryUsagePercent;
metricType.description = CheckOn.MemoryUsagePercent + " of Server/VM";
metricType.unit = "%";
metricNameServiceNameMap[MonitorMetricType.MemoryUsagePercent] =
metricType;
}
if (basicMetrics.diskMetrics && basicMetrics.diskMetrics.length > 0) {
for (const diskMetric of basicMetrics.diskMetrics) {
const extraAttributes: JSONObject = {};
if (diskMetric.diskPath) {
extraAttributes["diskPath"] = diskMetric.diskPath;
}
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.DiskUsagePercent,
value: diskMetric.percentUsed ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.DiskUsagePercent;
metricType.description = CheckOn.DiskUsagePercent + " of Server/VM";
metricType.unit = "%";
metricNameServiceNameMap[MonitorMetricType.DiskUsagePercent] =
metricType;
}
}
}
if (
(data.dataToProcess as ProbeMonitorResponse).customCodeMonitorResponse
?.executionTimeInMS
) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ExecutionTime,
value:
(data.dataToProcess as ProbeMonitorResponse).customCodeMonitorResponse
?.executionTimeInMS ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ExecutionTime;
metricType.description = CheckOn.ExecutionTime + " of this monitor";
metricType.unit = "ms";
metricNameServiceNameMap[MonitorMetricType.ExecutionTime] = metricType;
}
if (
(data.dataToProcess as ProbeMonitorResponse) &&
(data.dataToProcess as ProbeMonitorResponse).syntheticMonitorResponse &&
(
(data.dataToProcess as ProbeMonitorResponse).syntheticMonitorResponse ||
[]
).length > 0
) {
const syntheticResponses: Array<SyntheticMonitorResponse> =
(data.dataToProcess as ProbeMonitorResponse).syntheticMonitorResponse ||
[];
for (const syntheticMonitorResponse of syntheticResponses) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
if (syntheticMonitorResponse.browserType) {
extraAttributes["browserType"] = syntheticMonitorResponse.browserType;
}
if (syntheticMonitorResponse.screenSizeType) {
extraAttributes["screenSizeType"] =
syntheticMonitorResponse.screenSizeType;
}
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ExecutionTime,
value: syntheticMonitorResponse.executionTimeInMS ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ExecutionTime;
metricType.description = CheckOn.ExecutionTime + " of this monitor";
metricType.unit = "ms";
metricNameServiceNameMap[MonitorMetricType.ExecutionTime] = metricType;
}
}
if ((data.dataToProcess as ProbeMonitorResponse).responseTimeInMs) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ResponseTime,
value:
(data.dataToProcess as ProbeMonitorResponse).responseTimeInMs ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ResponseTime;
metricType.description = CheckOn.ResponseTime + " of this monitor";
metricType.unit = "ms";
metricNameServiceNameMap[MonitorMetricType.ResponseTime] = metricType;
}
if ((data.dataToProcess as ProbeMonitorResponse).isOnline !== undefined) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.IsOnline,
value: (data.dataToProcess as ProbeMonitorResponse).isOnline ? 1 : 0,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.IsOnline;
metricType.description = CheckOn.IsOnline + " status for monitor";
metricType.unit = "";
metricNameServiceNameMap[MonitorMetricType.IsOnline] = metricType;
}
if ((data.dataToProcess as ProbeMonitorResponse).responseCode) {
const extraAttributes: JSONObject = {
probeId: (
data.dataToProcess as ProbeMonitorResponse
).probeId.toString(),
};
const attributes: JSONObject = this.buildMonitorMetricAttributes({
monitorId: data.monitorId,
projectId: data.projectId,
monitorName: data.monitorName,
probeName: data.probeName,
extraAttributes: extraAttributes,
});
const metricRow: JSONObject = this.buildMonitorMetricRow({
projectId: data.projectId,
monitorId: data.monitorId,
metricName: MonitorMetricType.ResponseStatusCode,
value:
(data.dataToProcess as ProbeMonitorResponse).responseCode ?? null,
attributes: attributes,
metricPointType: MetricPointType.Sum,
});
metricRows.push(metricRow);
const metricType: MetricType = new MetricType();
metricType.name = MonitorMetricType.ResponseStatusCode;
metricType.description = CheckOn.ResponseStatusCode + " for this monitor";
metricType.unit = "Status Code";
metricNameServiceNameMap[MonitorMetricType.ResponseStatusCode] =
metricType;
}
if (metricRows.length > 0) {
await MetricService.insertJsonRows(metricRows);
}
// index metrics
TelemetryUtil.indexMetricNameServiceNameMap({
projectId: data.projectId,
metricNameServiceNameMap: metricNameServiceNameMap,
}).catch((err: Error) => {
logger.error(err);
});
}
}

View file

@ -24,6 +24,7 @@ import ProbeApiIngestResponse from "../../../Types/Probe/ProbeApiIngestResponse"
import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
import Monitor from "../../../Models/DatabaseModels/Monitor";
import MonitorProbe from "../../../Models/DatabaseModels/MonitorProbe";
import MonitorStatus from "../../../Models/DatabaseModels/MonitorStatus";
import MonitorStatusTimeline from "../../../Models/DatabaseModels/MonitorStatusTimeline";
import OneUptimeDate from "../../../Types/Date";
import LogMonitorResponse from "../../../Types/Monitor/LogMonitor/LogMonitorResponse";
@ -87,17 +88,18 @@ export default class MonitorResourceUtil {
return monitorStatusNameCache[cacheKey];
}
const monitorStatus = await MonitorStatusService.findOneBy({
query: {
_id: statusId,
},
select: {
name: true,
},
props: {
isRoot: true,
},
});
const monitorStatus: MonitorStatus | null =
await MonitorStatusService.findOneBy({
query: {
_id: statusId,
},
select: {
name: true,
},
props: {
isRoot: true,
},
});
const statusName: string | null = monitorStatus?.name || null;
monitorStatusNameCache[cacheKey] = statusName;

View file

@ -116,8 +116,7 @@ const EvaluationLogList: FunctionComponent<ComponentProps> = (
const renderEventAction: () => ReactElement | null = () => {
if (
event.relatedIncidentId &&
(event.type === "incident-created" ||
event.type === "incident-skipped")
(event.type === "incident-created" || event.type === "incident-skipped")
) {
const incidentRoute: Route = RouteUtil.populateRouteParams(
RouteMap[PageMap.INCIDENT_VIEW] as Route,
@ -140,8 +139,7 @@ const EvaluationLogList: FunctionComponent<ComponentProps> = (
if (
event.relatedAlertId &&
(event.type === "alert-created" ||
event.type === "alert-skipped")
(event.type === "alert-created" || event.type === "alert-skipped")
) {
const alertRoute: Route = RouteUtil.populateRouteParams(
RouteMap[PageMap.ALERT_VIEW] as Route,

View file

@ -118,11 +118,9 @@ const SummaryInfo: FunctionComponent<ComponentProps> = (
const probableMonitorEvaluationSummary: MonitorEvaluationSummary | undefined =
props.evaluationSummary ||
props.probeMonitorResponses?.find(
(response: ProbeMonitorResponse) => {
return Boolean(response.evaluationSummary);
},
)?.evaluationSummary;
props.probeMonitorResponses?.find((response: ProbeMonitorResponse) => {
return Boolean(response.evaluationSummary);
})?.evaluationSummary;
if (
MonitorTypeHelper.isProbableMonitor(props.monitorType) &&