refactor: Update import statements for ProbeMonitor and ServerMonitor to use ProbeMonitorResponse and ServerMonitorResponse

This commit is contained in:
Simon Larsen
2024-08-06 11:26:13 -06:00
parent 3f7cfa3110
commit 5fc95eb02e
6 changed files with 320 additions and 161 deletions

View File

@@ -11,9 +11,9 @@ const reviews: Review[] = [
title: "OneUptime is fantastic!",
},
{
name: "Bob",
text: "The incident management feature is top-notch. It has streamlined our response process significantly.",
title: "Top-notch incident management",
name: "Reg, Skillable",
text: "We use OneUptime to reliably monitor endpoint availability globally, and it delivers.",
title: "OneUptime delivers!",
},
{
name: "Charlie",

View File

@@ -186,8 +186,10 @@ const monitorLogs: MonitorLogsFunction = async (data: {
query.body = new Search(logQuery.body);
}
if (logQuery.severityText) {
query.severityText = logQuery.severityText;
if (logQuery.severityTexts && logQuery.severityTexts.length > 0) {
query.severityText = QueryHelper.any(
logQuery.severityTexts as Array<string>,
);
}
if (logQuery.telemetryServiceIds && logQuery.telemetryServiceIds.length > 0) {

View File

@@ -6,7 +6,7 @@ import ObjectID from "../ObjectID";
export default interface MonitorStepLogMonitor {
attributes: Dictionary<string | number | boolean>;
body: string;
severityText: Array<LogSeverity>;
severityTexts: Array<LogSeverity>;
telemetryServiceIds: Array<ObjectID>;
lastXSecondsOfLogs: number;
}
@@ -16,7 +16,7 @@ export class MonitorStepLogMonitorUtil {
return {
attributes: {},
body: "",
severityText: [],
severityTexts: [],
telemetryServiceIds: [],
lastXSecondsOfLogs: 60,
};
@@ -27,7 +27,7 @@ export class MonitorStepLogMonitorUtil {
attributes:
(json["attributes"] as Dictionary<string | number | boolean>) || {},
body: json["body"] as string,
severityText: json["severityText"] as Array<LogSeverity>,
severityTexts: json["severityTexts"] as Array<LogSeverity>,
telemetryServiceIds: ObjectID.fromJSONArray(
json["telemetryServiceIds"] as Array<JSONObject>,
),
@@ -39,7 +39,7 @@ export class MonitorStepLogMonitorUtil {
return {
attributes: monitor.attributes,
body: monitor.body,
severityText: monitor.severityText,
severityTexts: monitor.severityTexts,
telemetryServiceId: ObjectID.toJSONArray(monitor.telemetryServiceIds),
lastXSecondsOfLogs: monitor.lastXSecondsOfLogs,
};

View File

@@ -48,7 +48,7 @@ export const DefaultValidateFunction: DefaultValidateFunctionType = (
return {};
};
export interface BaseComponentProps<T extends GenericObject> {
export interface BaseComponentProps<T> {
submitButtonStyleType?: ButtonStyleType | undefined;
initialValues?: FormValues<T> | undefined;
onValidate?: undefined | ((values: FormValues<T>) => JSONObject);

View File

@@ -1,11 +1,10 @@
import LogSeverity from "Common/Types/Log/LogSeverity";
import MonitorStepLogMonitor from "Common/Types/Monitor/MonitorStepLogMonitor";
import FiltersForm from "CommonUI/src/Components/Filters/FiltersForm";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import Query from "CommonUI/src/Utils/BaseDatabase/Query";
import DropdownUtil from "CommonUI/src/Utils/Dropdown";
import TelemetryService from "Common/Models/DatabaseModels/TelemetryService";
import React, { FunctionComponent, ReactElement } from "react";
import BasicForm from "CommonUI/src/Components/Forms/BasicForm";
import LogSeverity from "Common/Types/Log/LogSeverity";
import DropdownUtil from "CommonUI/src/Utils/Dropdown";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
export interface ComponentProps {
monitorStepLogMonitor: MonitorStepLogMonitor;
@@ -20,24 +19,24 @@ const LogMonitorStepForm: FunctionComponent<ComponentProps> = (
props: ComponentProps,
): ReactElement => {
return (
<FiltersForm<MonitorStepLogMonitor>
<BasicForm
id="logs-filter"
showFilter={true}
filterData={props.monitorStepLogMonitor}
onFilterChanged={(filterData: Query<MonitorStepLogMonitor>) => {
props.onMonitorStepLogMonitorChanged(
filterData as MonitorStepLogMonitor,
);
}}
filters={[
hideSubmitButton={true}
initialValue={props.monitorStepLogMonitor}
onChange={props.onMonitorStepLogMonitorChanged}
fields={[
{
key: "body",
type: FieldType.Text,
field: {
body: true,
},
type: FormFieldSchemaType.Text,
title: "Search Log Body",
},
{
key: "lastXSecondsOfLogs",
type: FieldType.Dropdown,
field: {
lastXSecondsOfLogs: true,
},
type: FormFieldSchemaType.Dropdown,
filterDropdownOptions: [
{
label: "Last 5 seconds",
@@ -88,16 +87,20 @@ const LogMonitorStepForm: FunctionComponent<ComponentProps> = (
isAdvancedFilter: true,
},
{
key: "severityText",
field: {
severityTexts: true,
},
filterDropdownOptions:
DropdownUtil.getDropdownOptionsFromEnum(LogSeverity),
type: FieldType.MultiSelectDropdown,
type: FormFieldSchemaType.MultiSelectDropdown,
title: "Log Severity",
isAdvancedFilter: true,
},
{
key: "telemetryServiceIds",
type: FieldType.MultiSelectDropdown,
field: {
telemetryServiceIds: true,
},
type: FormFieldSchemaType.MultiSelectDropdown,
filterDropdownOptions: props.telemetryServices.map(
(telemetryService: TelemetryService) => {
return {
@@ -110,8 +113,10 @@ const LogMonitorStepForm: FunctionComponent<ComponentProps> = (
isAdvancedFilter: true,
},
{
key: "attributes",
type: FieldType.JSON,
field: {
attributes: true,
},
type: FormFieldSchemaType.JSON,
title: "Filter by Attributes",
jsonKeys: props.attributeKeys,
isAdvancedFilter: true,

View File

@@ -16,6 +16,19 @@ import React, {
useEffect,
useState,
} from "react";
import ComponentLoader from "CommonUI/src/Components/ComponentLoader/ComponentLoader";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import TelemetryService from "Common/Models/DatabaseModels/TelemetryService";
import { JSONObject } from "Common/Types/JSON";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import ListResult from "CommonUI/src/Utils/BaseDatabase/ListResult";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import DashboardNavigation from "../../../Utils/Navigation";
import { LIMIT_PER_PROJECT } from "Common/Types/Database/LimitMax";
import SortOrder from "Common/Types/BaseDatabase/SortOrder";
import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse";
import API from "CommonUI/src/Utils/API/API";
import Includes from "Common/Types/BaseDatabase/Includes";
export interface ComponentProps {
monitorStatusOptions: Array<MonitorStatus>;
@@ -25,138 +38,268 @@ export interface ComponentProps {
onCallPolicyOptions: Array<OnCallDutyPolicy>;
}
export interface LogMonitorStepView {
body: string | undefined;
severityTexts: Array<string> | undefined;
attributes: JSONObject | undefined;
telemetryServices: Array<TelemetryService> | undefined;
}
const MonitorStepElement: FunctionComponent<ComponentProps> = (
props: ComponentProps,
): ReactElement => {
const [requestDetailsFields, setRequestDetailsFields] = useState<
Array<Field<MonitorStepType>>
>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [error, setError] = useState<string | undefined>(undefined);
const [telemetryServices, setTelemetryServices] = useState<
Array<TelemetryService> | undefined
>(undefined);
// this field is used for most monitor types
let fields: Array<Field<MonitorStepType>> = [];
let logFields: Array<Field<LogMonitorStepView>> = [];
const logMonitorDetailView: LogMonitorStepView = {
body: undefined,
severityTexts: undefined,
attributes: undefined,
telemetryServices: undefined,
};
const fetchTelemetryServices: PromiseVoidFunction =
async (): Promise<void> => {
const telemetryServicesResult: ListResult<TelemetryService> =
await ModelAPI.getList<TelemetryService>({
modelType: TelemetryService,
query: {
projectId: DashboardNavigation.getProjectId(),
_id: new Includes(
props.monitorStep.data?.logMonitor?.telemetryServiceIds || [],
),
},
limit: LIMIT_PER_PROJECT,
skip: 0,
select: {
_id: true,
name: true,
serviceColor: true,
},
sort: {
name: SortOrder.Ascending,
},
});
if (telemetryServicesResult instanceof HTTPErrorResponse) {
throw telemetryServicesResult;
}
setTelemetryServices(telemetryServicesResult.data);
};
const loadComponent: PromiseVoidFunction = async (): Promise<void> => {
setIsLoading(true);
try {
if (props.monitorType === MonitorType.Logs) {
await fetchTelemetryServices();
}
} catch (err) {
setError(API.getFriendlyErrorMessage(err as Error));
}
setIsLoading(false);
};
useEffect(() => {
let fields: Array<Field<MonitorStepType>> = [];
if (props.monitorType === MonitorType.API) {
fields = [
{
key: "monitorDestination",
title: "API URL",
description: "URL of the API you want to monitor.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
{
key: "requestType",
title: "Request Type",
description: "Whats the type of the API request?",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
{
key: "requestBody",
title: "Request Body",
description: "Request Body to send, if any.",
fieldType: FieldType.JSON,
placeholder: "No data entered",
},
{
key: "requestHeaders",
title: "Request Headers",
description: "Request Headers to send, if any.",
fieldType: FieldType.DictionaryOfStrings,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.Website) {
fields = [
{
key: "monitorDestination",
title: "Website URL",
description: "URL of the website you want to monitor.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.Ping) {
fields = [
{
key: "monitorDestination",
title: "Ping Hostname or IP Address",
description:
"Hostname or IP Address of the resource you would like us to ping.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.Port) {
fields = [
{
key: "monitorDestination",
title: "Ping Hostname or IP Address",
description:
"Hostname or IP Address of the resource you would like us to ping.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
{
key: "monitorDestinationPort",
title: "Port",
description: "Port of the resource you would like us to ping.",
fieldType: FieldType.Port,
placeholder: "No port entered",
},
];
} else if (props.monitorType === MonitorType.IP) {
fields = [
{
key: "monitorDestination",
title: "IP Address",
description: "IP Address of the resource you would like us to ping.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.CustomJavaScriptCode) {
fields = [
{
key: "customCode",
title: "JavaScript Code",
description: "JavaScript code to run.",
fieldType: FieldType.JavaScript,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.SyntheticMonitor) {
fields = [
{
key: "customCode",
title: "JavaScript Code",
description: "JavaScript code to run.",
fieldType: FieldType.JavaScript,
placeholder: "No data entered",
},
{
key: "browserTypes",
title: "Browser Types",
description: "Browser types to run the synthetic monitor on.",
fieldType: FieldType.ArrayOfText,
placeholder: "No data entered",
},
{
key: "screenSizeTypes",
title: "Screen Size Types",
description: "Screen size types to run the synthetic monitor on.",
fieldType: FieldType.ArrayOfText,
placeholder: "No data entered",
},
];
}
setRequestDetailsFields(fields);
loadComponent();
}, [props.monitorType]);
if (isLoading) {
return <ComponentLoader />;
}
if (error) {
return <ErrorMessage error={error} />;
}
if (props.monitorType === MonitorType.API) {
fields = [
{
key: "monitorDestination",
title: "API URL",
description: "URL of the API you want to monitor.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
{
key: "requestType",
title: "Request Type",
description: "Whats the type of the API request?",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
{
key: "requestBody",
title: "Request Body",
description: "Request Body to send, if any.",
fieldType: FieldType.JSON,
placeholder: "No data entered",
},
{
key: "requestHeaders",
title: "Request Headers",
description: "Request Headers to send, if any.",
fieldType: FieldType.DictionaryOfStrings,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.Website) {
fields = [
{
key: "monitorDestination",
title: "Website URL",
description: "URL of the website you want to monitor.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.Ping) {
fields = [
{
key: "monitorDestination",
title: "Ping Hostname or IP Address",
description:
"Hostname or IP Address of the resource you would like us to ping.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.Port) {
fields = [
{
key: "monitorDestination",
title: "Ping Hostname or IP Address",
description:
"Hostname or IP Address of the resource you would like us to ping.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
{
key: "monitorDestinationPort",
title: "Port",
description: "Port of the resource you would like us to ping.",
fieldType: FieldType.Port,
placeholder: "No port entered",
},
];
} else if (props.monitorType === MonitorType.IP) {
fields = [
{
key: "monitorDestination",
title: "IP Address",
description: "IP Address of the resource you would like us to ping.",
fieldType: FieldType.Text,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.CustomJavaScriptCode) {
fields = [
{
key: "customCode",
title: "JavaScript Code",
description: "JavaScript code to run.",
fieldType: FieldType.JavaScript,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.SyntheticMonitor) {
fields = [
{
key: "customCode",
title: "JavaScript Code",
description: "JavaScript code to run.",
fieldType: FieldType.JavaScript,
placeholder: "No data entered",
},
{
key: "browserTypes",
title: "Browser Types",
description: "Browser types to run the synthetic monitor on.",
fieldType: FieldType.ArrayOfText,
placeholder: "No data entered",
},
{
key: "screenSizeTypes",
title: "Screen Size Types",
description: "Screen size types to run the synthetic monitor on.",
fieldType: FieldType.ArrayOfText,
placeholder: "No data entered",
},
];
} else if (props.monitorType === MonitorType.Logs) {
logFields = [];
if (props.monitorStep.data?.logMonitor?.body) {
logMonitorDetailView.body = props.monitorStep.data?.logMonitor?.body;
logFields.push({
key: "body",
title: "Filter Log Message",
description: "Filter by log message with this text:",
fieldType: FieldType.Text,
placeholder: "No log message entered",
});
}
if (props.monitorStep.data?.logMonitor?.severityTexts) {
logMonitorDetailView.severityTexts =
props.monitorStep.data?.logMonitor?.severityTexts;
logFields.push({
key: "severityTexts",
title: "Log Severity",
description: "Severity of the logs to monitor.",
fieldType: FieldType.ArrayOfText,
placeholder: "No severity entered",
});
}
if (
props.monitorStep.data?.logMonitor?.attributes &&
Object.keys(props.monitorStep.data?.logMonitor?.attributes).length > 0
) {
logMonitorDetailView.attributes =
props.monitorStep.data?.logMonitor?.attributes;
logFields.push({
key: "attributes",
title: "Log Attributes",
description: "Attributes of the logs to monitor.",
fieldType: FieldType.JSON,
placeholder: "No attributes entered",
});
}
if (
props.monitorStep.data?.logMonitor?.telemetryServiceIds &&
props.monitorStep.data?.logMonitor?.telemetryServiceIds.length > 0 &&
telemetryServices &&
telemetryServices.length > 0
) {
logMonitorDetailView.telemetryServices = telemetryServices; // set the telemetry services
logFields.push({
key: "telemetryServices",
title: "Telemetry Services",
description: "Telemetry services to monitor.",
fieldType: FieldType.Element,
placeholder: "No telemetry services entered",
});
}
}
return (
<div className="mt-5">
<FieldLabelElement
title={"Request Details"}
title={"Monitor Details"}
description={
"Here are the details of the request we will send to monitor your resource status."
}
@@ -164,11 +307,20 @@ const MonitorStepElement: FunctionComponent<ComponentProps> = (
isHeading={true}
/>
<div className="mt-5">
<Detail
id={"monitor-step"}
item={props.monitorStep.data as any}
fields={requestDetailsFields}
/>
{fields && fields.length && (
<Detail<MonitorStepType>
id={"monitor-step"}
item={props.monitorStep.data!}
fields={fields}
/>
)}
{logFields && logFields.length && (
<Detail<LogMonitorStepView>
id={"monitor-logs"}
item={logMonitorDetailView}
fields={logFields}
/>
)}
</div>
<HorizontalRule />