@oneuptime/common 12.0.14 → 12.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/GlobalOidc.ts +20 -0
- package/Models/DatabaseModels/GlobalSso.ts +20 -0
- package/Models/DatabaseModels/MarketingConversion.ts +19 -9
- package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +46 -0
- package/Models/DatabaseModels/StatusPage.ts +7 -4
- package/Server/API/StatusPageAPI.ts +29 -4
- package/Server/EnvironmentConfig.ts +7 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/SlackAuthorization.ts +43 -6
- package/Server/Middleware/UserAuthorization.ts +236 -26
- package/Server/Middleware/WhatsAppAuthorization.ts +43 -3
- package/Server/Services/GlobalOidcProjectService.ts +126 -1
- package/Server/Services/GlobalOidcService.ts +132 -0
- package/Server/Services/GlobalSsoProjectService.ts +126 -1
- package/Server/Services/GlobalSsoService.ts +132 -0
- package/Server/Services/UserEmailService.ts +4 -4
- package/Server/Utils/CronTab.ts +73 -0
- package/Server/Utils/GlobalSsoAuthorization.ts +175 -0
- package/Server/Utils/Marketing/ConversionUploadProvider.ts +35 -5
- package/Server/Utils/Marketing/Providers/GoogleAds.ts +1 -1
- package/Server/Utils/Marketing/Providers/LinkedIn.ts +1 -1
- package/Server/Utils/Marketing/Providers/Meta.ts +1 -1
- package/Server/Utils/Marketing/Providers/MicrosoftAds.ts +1 -1
- package/Server/Utils/Marketing/Providers/Reddit.ts +1 -1
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +48 -33
- package/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.ts +35 -30
- package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +33 -28
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +475 -47
- package/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.ts +35 -30
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +34 -28
- package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +33 -28
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +69 -40
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +35 -29
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +8 -0
- package/Server/Utils/Monitor/MonitorResource.ts +161 -21
- package/Server/Utils/StatusPageContentSecurityPolicy.ts +56 -0
- package/Server/Utils/StatusPageCustomizationAccess.ts +117 -0
- package/Tests/Server/API/StatusPageCustomizationOrigin.test.ts +348 -0
- package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +9 -59
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +227 -0
- package/Tests/Server/Middleware/SlackAuthorization.test.ts +149 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +27 -13
- package/Tests/Server/Middleware/UserAuthorizationGlobalSsoGovernance.test.ts +1455 -0
- package/Tests/Server/Middleware/UserAuthorizationSSOProvider.test.ts +91 -2
- package/Tests/Server/Middleware/WhatsAppAuthorization.test.ts +233 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +21 -8
- package/Tests/Server/Services/GlobalSsoProviderAuthorization.test.ts +1242 -0
- package/Tests/Server/Services/MonitorResourceProbeAgreementHydration.test.ts +459 -0
- package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +10 -0
- package/Tests/Server/Types/AnalyticsDatabase/AggregateUtilBucketTimestamp.test.ts +416 -0
- package/Tests/Server/Types/Database/QueryHelperManyToManyAndEmptyValues.test.ts +551 -0
- package/Tests/Server/Types/Database/SelectUtil.test.ts +348 -0
- package/Tests/Server/Utils/CronTab.test.ts +116 -0
- package/Tests/Server/Utils/GlobalSSOToken.test.ts +581 -0
- package/Tests/Server/Utils/GlobalSsoAuthorization.test.ts +1401 -0
- package/Tests/Server/Utils/Marketing/AdUploadableConversionTypes.test.ts +254 -0
- package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +1 -1
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaEvaluateOverTime.test.ts +508 -0
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +30 -9
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +987 -0
- package/Tests/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.test.ts +916 -0
- package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +382 -0
- package/Tests/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.test.ts +1219 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +86 -0
- package/Tests/Server/Utils/StatusPageContentSecurityPolicy.test.ts +136 -0
- package/Tests/Server/Utils/StatusPageCustomizationAccess.test.ts +223 -0
- package/Tests/Types/Monitor/MonitorStepConfigHelpers.test.ts +165 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceLinkRuleScope.test.ts +215 -0
- package/Tests/UI/Components/Forms/FormSubmitAnalytics.test.tsx +206 -0
- package/Tests/UI/Utils/AIChatExport/ConversationMarkdown.test.ts +774 -0
- package/Tests/UI/Utils/AIChatExport/MarkdownBlocks.test.ts +791 -0
- package/Tests/UI/Utils/AIChatExport/MarkdownSafety.test.ts +544 -0
- package/Tests/Utils/Analytics.test.ts +187 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +80 -0
- package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +1291 -0
- package/Tests/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.test.ts +214 -0
- package/Types/Marketing/MarketingConversion.ts +12 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/NetworkDevice/NetworkDeviceLinkRuleScope.ts +51 -0
- package/UI/Components/FormModal/BasicFormModal.tsx +12 -0
- package/UI/Components/Forms/BasicForm.tsx +13 -1
- package/UI/Components/Forms/BasicModelForm.tsx +2 -1
- package/UI/Components/Forms/ModelForm.tsx +10 -1
- package/UI/Components/Forms/Utils/FormAnalyticsName.ts +39 -0
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +6 -1
- package/Utils/Analytics.ts +55 -2
- package/Utils/Monitor/MonitorMetricType.ts +40 -0
- package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +587 -37
- package/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.ts +115 -0
- package/build/dist/Models/DatabaseModels/GlobalOidc.js +21 -0
- package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSso.js +21 -0
- package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MarketingConversion.js +20 -10
- package/build/dist/Models/DatabaseModels/MarketingConversion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +47 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +4 -4
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +25 -4
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +6 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js +29 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/SlackAuthorization.js +28 -4
- package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +197 -22
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/WhatsAppAuthorization.js +32 -2
- package/build/dist/Server/Middleware/WhatsAppAuthorization.js.map +1 -1
- package/build/dist/Server/Services/GlobalOidcProjectService.js +105 -0
- package/build/dist/Server/Services/GlobalOidcProjectService.js.map +1 -1
- package/build/dist/Server/Services/GlobalOidcService.js +127 -0
- package/build/dist/Server/Services/GlobalOidcService.js.map +1 -1
- package/build/dist/Server/Services/GlobalSsoProjectService.js +105 -0
- package/build/dist/Server/Services/GlobalSsoProjectService.js.map +1 -1
- package/build/dist/Server/Services/GlobalSsoService.js +127 -0
- package/build/dist/Server/Services/GlobalSsoService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +4 -4
- package/build/dist/Server/Utils/CronTab.js +66 -0
- package/build/dist/Server/Utils/CronTab.js.map +1 -1
- package/build/dist/Server/Utils/GlobalSsoAuthorization.js +112 -0
- package/build/dist/Server/Utils/GlobalSsoAuthorization.js.map +1 -0
- package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js +17 -1
- package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Meta.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Meta.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Reddit.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Reddit.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +37 -35
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +20 -22
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +370 -42
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +64 -52
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +25 -29
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +8 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +123 -23
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js +39 -0
- package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js.map +1 -0
- package/build/dist/Server/Utils/StatusPageCustomizationAccess.js +85 -0
- package/build/dist/Server/Utils/StatusPageCustomizationAccess.js.map +1 -0
- package/build/dist/Types/Marketing/MarketingConversion.js +10 -0
- package/build/dist/Types/Marketing/MarketingConversion.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js +46 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js.map +1 -0
- package/build/dist/UI/Components/FormModal/BasicFormModal.js +2 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +10 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js +2 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +4 -1
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js +33 -0
- package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js.map +1 -0
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js +2 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/Utils/Analytics.js +50 -2
- package/build/dist/Utils/Analytics.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +37 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +318 -37
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js +87 -0
- package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js.map +1 -0
- package/package.json +1 -1
|
@@ -4,87 +4,515 @@ import OneUptimeDate from "../../../../Types/Date";
|
|
|
4
4
|
import { JSONObject } from "../../../../Types/JSON";
|
|
5
5
|
import {
|
|
6
6
|
CheckOn,
|
|
7
|
+
CriteriaFilter,
|
|
7
8
|
EvaluateOverTimeOptions,
|
|
8
9
|
EvaluateOverTimeType,
|
|
10
|
+
NoDataPolicy,
|
|
9
11
|
} from "../../../../Types/Monitor/CriteriaFilter";
|
|
10
12
|
import ObjectID from "../../../../Types/ObjectID";
|
|
11
13
|
import Metric from "../../../../Models/AnalyticsModels/Metric";
|
|
12
14
|
import MonitorMetricTypeUtil from "../../../../Utils/Monitor/MonitorMetricType";
|
|
15
|
+
import MonitorMetricType from "../../../../Types/Monitor/MonitorMetricType";
|
|
13
16
|
import MetricService from "../../../Services/MetricService";
|
|
14
17
|
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
15
18
|
import InBetween from "../../../../Types/BaseDatabase/InBetween";
|
|
19
|
+
import CronTab from "../../CronTab";
|
|
20
|
+
import logger from "../../Logger";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Outcome of trying to turn an "evaluate over time" filter into a value the
|
|
24
|
+
* comparators can act on.
|
|
25
|
+
*/
|
|
26
|
+
export enum OverTimeEvaluationStatus {
|
|
27
|
+
/** The filter is not configured to evaluate over time at all. */
|
|
28
|
+
NotConfigured = "NotConfigured",
|
|
29
|
+
/**
|
|
30
|
+
* No metric series backs this CheckOn, so there is nothing to look back
|
|
31
|
+
* over. Callers keep their historical behaviour (compare the value that
|
|
32
|
+
* arrived with this check) rather than silently never firing.
|
|
33
|
+
*/
|
|
34
|
+
Unsupported = "Unsupported",
|
|
35
|
+
/**
|
|
36
|
+
* The window is usable and `value` holds every sample in it (for
|
|
37
|
+
* All Values / Any Value) or the aggregate (for Average / Sum / Min / Max).
|
|
38
|
+
*/
|
|
39
|
+
Evaluated = "Evaluated",
|
|
40
|
+
/**
|
|
41
|
+
* The window is empty, still filling up, or could not be read. The filter
|
|
42
|
+
* cannot be judged yet — what happens next is up to the no-data policy.
|
|
43
|
+
*/
|
|
44
|
+
InsufficientData = "InsufficientData",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface OverTimeEvaluation {
|
|
48
|
+
status: OverTimeEvaluationStatus;
|
|
49
|
+
value: Array<number | boolean> | number | boolean | undefined;
|
|
50
|
+
/** Number of samples the window returned. */
|
|
51
|
+
sampleCount: number;
|
|
52
|
+
/** Why the window was judged insufficient. Null otherwise. */
|
|
53
|
+
noDataReason: string | null;
|
|
54
|
+
/**
|
|
55
|
+
* True when InsufficientData was caused by the metric read failing rather
|
|
56
|
+
* than by a genuinely empty or partial window. A read failure must never
|
|
57
|
+
* be reported as a breach, whatever the no-data policy says.
|
|
58
|
+
*/
|
|
59
|
+
isReadError: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* What the calling criteria evaluator should do with an over-time filter.
|
|
64
|
+
*
|
|
65
|
+
* `earlyReturn` set means the filter has already been decided and the
|
|
66
|
+
* evaluator must return that result verbatim - crucially WITHOUT falling
|
|
67
|
+
* back to the value that arrived with this single check. That fallback was
|
|
68
|
+
* the reason "All values over the last 5 minutes" fired off one bad probe.
|
|
69
|
+
*/
|
|
70
|
+
export interface OverTimeCriteriaValue {
|
|
71
|
+
earlyReturn: { result: string | null } | null;
|
|
72
|
+
value: Array<number | boolean> | number | boolean | undefined;
|
|
73
|
+
}
|
|
16
74
|
|
|
17
75
|
export default class EvaluateOverTime {
|
|
18
|
-
|
|
19
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Multiple of the monitor's polling interval that either end of the window
|
|
78
|
+
* is allowed to sit away from the nearest sample before the window counts
|
|
79
|
+
* as "not covered yet".
|
|
80
|
+
*
|
|
81
|
+
* One whole interval is the theoretical minimum (a window that starts
|
|
82
|
+
* mid-cycle legitimately has its first sample up to one interval in). The
|
|
83
|
+
* extra half absorbs scheduling jitter - and the lag between a sample
|
|
84
|
+
* being written and being readable - so a monitor does not flip between
|
|
85
|
+
* "covered" and "not covered" on adjacent checks.
|
|
86
|
+
*/
|
|
87
|
+
private static readonly WINDOW_COVERAGE_TOLERANCE_FACTOR: number = 1.5;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolve an "evaluate over time" criteria filter into the value its
|
|
91
|
+
* comparator should use, applying the filter's no-data policy.
|
|
92
|
+
*
|
|
93
|
+
* This is the single entry point every monitor-type criteria evaluator
|
|
94
|
+
* uses. It exists so the "window has no usable data" decision is made in
|
|
95
|
+
* exactly one place: previously each evaluator did
|
|
96
|
+
* `overTimeValue || <value from this check>`, which quietly turned every
|
|
97
|
+
* over-time filter into an instantaneous one whenever the window came back
|
|
98
|
+
* empty.
|
|
99
|
+
*
|
|
100
|
+
* Deliberately not span-decorated: this runs for every criteria filter on
|
|
101
|
+
* every check and the vast majority return at the guard below without
|
|
102
|
+
* doing any work. evaluateOverTime, which issues the metric read, carries
|
|
103
|
+
* the span instead.
|
|
104
|
+
*/
|
|
105
|
+
public static async getOverTimeValueForCriteriaFilter(data: {
|
|
20
106
|
projectId: ObjectID;
|
|
21
107
|
monitorId: ObjectID;
|
|
22
|
-
|
|
23
|
-
metricType: CheckOn;
|
|
108
|
+
criteriaFilter: CriteriaFilter;
|
|
24
109
|
miscData?: JSONObject | undefined;
|
|
25
|
-
|
|
26
|
-
|
|
110
|
+
/** Monitor's monitoringInterval cron. Used to size the expected window. */
|
|
111
|
+
monitoringInterval?: string | undefined;
|
|
112
|
+
}): Promise<OverTimeCriteriaValue> {
|
|
113
|
+
/*
|
|
114
|
+
* Every criteria evaluator calls this for every filter, so the common
|
|
115
|
+
* case - a filter that does not evaluate over time - returns before any
|
|
116
|
+
* of the machinery below runs.
|
|
117
|
+
*/
|
|
118
|
+
if (
|
|
119
|
+
!data.criteriaFilter.evaluateOverTime ||
|
|
120
|
+
!data.criteriaFilter.evaluateOverTimeOptions
|
|
121
|
+
) {
|
|
122
|
+
return {
|
|
123
|
+
earlyReturn: null,
|
|
124
|
+
value: undefined,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const evaluation: OverTimeEvaluation = await this.evaluateOverTime({
|
|
129
|
+
projectId: data.projectId,
|
|
130
|
+
monitorId: data.monitorId,
|
|
131
|
+
criteriaFilter: data.criteriaFilter,
|
|
132
|
+
miscData: data.miscData,
|
|
133
|
+
monitoringInterval: data.monitoringInterval,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (
|
|
137
|
+
evaluation.status === OverTimeEvaluationStatus.NotConfigured ||
|
|
138
|
+
evaluation.status === OverTimeEvaluationStatus.Unsupported
|
|
139
|
+
) {
|
|
140
|
+
// Historical behaviour: the caller compares this check's own value.
|
|
141
|
+
return {
|
|
142
|
+
earlyReturn: null,
|
|
143
|
+
value: undefined,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (evaluation.status === OverTimeEvaluationStatus.Evaluated) {
|
|
148
|
+
return {
|
|
149
|
+
earlyReturn: null,
|
|
150
|
+
value: evaluation.value,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// InsufficientData - the no-data policy decides.
|
|
155
|
+
const policy: NoDataPolicy = evaluation.isReadError
|
|
156
|
+
? NoDataPolicy.Ignore
|
|
157
|
+
: data.criteriaFilter.evaluateOverTimeOptions?.onNoDataPolicy ||
|
|
158
|
+
NoDataPolicy.Ignore;
|
|
159
|
+
|
|
160
|
+
if (policy === NoDataPolicy.Trigger) {
|
|
161
|
+
return {
|
|
162
|
+
earlyReturn: {
|
|
163
|
+
result:
|
|
164
|
+
`${data.criteriaFilter.checkOn} has no data over the last ${data.criteriaFilter.evaluateOverTimeOptions?.timeValueInMinutes} minutes. ${evaluation.noDataReason || ""}`.trim(),
|
|
165
|
+
},
|
|
166
|
+
value: undefined,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (policy === NoDataPolicy.TreatAsZero) {
|
|
171
|
+
/*
|
|
172
|
+
* Zero for numeric series, and its boolean equivalent (false) for the
|
|
173
|
+
* online/timeout series, which EvaluateOverTime already maps 1 -> true.
|
|
174
|
+
*/
|
|
175
|
+
const isBooleanSeries: boolean =
|
|
176
|
+
data.criteriaFilter.checkOn === CheckOn.IsOnline ||
|
|
177
|
+
data.criteriaFilter.checkOn === CheckOn.IsRequestTimeout ||
|
|
178
|
+
data.criteriaFilter.checkOn === CheckOn.DnsIsOnline ||
|
|
179
|
+
data.criteriaFilter.checkOn === CheckOn.SnmpIsOnline ||
|
|
180
|
+
data.criteriaFilter.checkOn === CheckOn.ExternalStatusPageIsOnline;
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
earlyReturn: null,
|
|
184
|
+
value: isBooleanSeries ? [false] : [0],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
27
187
|
|
|
28
|
-
|
|
29
|
-
|
|
188
|
+
// NoDataPolicy.Ignore - the filter simply does not fire yet.
|
|
189
|
+
logger.debug(
|
|
190
|
+
`Over time filter for ${data.criteriaFilter.checkOn} not evaluated: ${evaluation.noDataReason}`,
|
|
30
191
|
);
|
|
31
192
|
|
|
32
|
-
|
|
193
|
+
return {
|
|
194
|
+
earlyReturn: { result: null },
|
|
195
|
+
value: undefined,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Read the evaluation window and decide whether it can back the filter.
|
|
201
|
+
*/
|
|
202
|
+
@CaptureSpan()
|
|
203
|
+
public static async evaluateOverTime(data: {
|
|
204
|
+
projectId: ObjectID;
|
|
205
|
+
monitorId: ObjectID;
|
|
206
|
+
criteriaFilter: CriteriaFilter;
|
|
207
|
+
miscData?: JSONObject | undefined;
|
|
208
|
+
monitoringInterval?: string | undefined;
|
|
209
|
+
}): Promise<OverTimeEvaluation> {
|
|
210
|
+
const evaluateOverTimeOptions: EvaluateOverTimeOptions | undefined =
|
|
211
|
+
data.criteriaFilter.evaluateOverTimeOptions;
|
|
212
|
+
|
|
213
|
+
if (!data.criteriaFilter.evaluateOverTime || !evaluateOverTimeOptions) {
|
|
214
|
+
return {
|
|
215
|
+
status: OverTimeEvaluationStatus.NotConfigured,
|
|
216
|
+
value: undefined,
|
|
217
|
+
sampleCount: 0,
|
|
218
|
+
noDataReason: null,
|
|
219
|
+
isReadError: false,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const metricName: MonitorMetricType | null =
|
|
224
|
+
MonitorMetricTypeUtil.getMonitorMetricTypeByCheckOnOrNull(
|
|
225
|
+
data.criteriaFilter.checkOn,
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
if (!metricName) {
|
|
229
|
+
/*
|
|
230
|
+
* Nothing writes a series for this CheckOn, so there is no history to
|
|
231
|
+
* look back over. Say so instead of throwing - the callers used to
|
|
232
|
+
* swallow that throw and silently compare the instantaneous value.
|
|
233
|
+
*/
|
|
234
|
+
return {
|
|
235
|
+
status: OverTimeEvaluationStatus.Unsupported,
|
|
236
|
+
value: undefined,
|
|
237
|
+
sampleCount: 0,
|
|
238
|
+
noDataReason: `${data.criteriaFilter.checkOn} is not recorded as a metric, so it cannot be evaluated over time.`,
|
|
239
|
+
isReadError: false,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/*
|
|
244
|
+
* The dashboard persists the dropdown's string value while Terraform and
|
|
245
|
+
* the API send a number, so coerce before doing arithmetic with it.
|
|
246
|
+
*/
|
|
247
|
+
const windowInMinutes: number =
|
|
248
|
+
Number(evaluateOverTimeOptions.timeValueInMinutes) || 0;
|
|
249
|
+
|
|
250
|
+
if (windowInMinutes <= 0) {
|
|
251
|
+
return {
|
|
252
|
+
status: OverTimeEvaluationStatus.InsufficientData,
|
|
253
|
+
value: undefined,
|
|
254
|
+
sampleCount: 0,
|
|
255
|
+
noDataReason: "No evaluation window configured.",
|
|
256
|
+
isReadError: false,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
33
259
|
|
|
34
260
|
const now: Date = OneUptimeDate.getCurrentDate();
|
|
261
|
+
const windowStart: Date = OneUptimeDate.getSomeMinutesAgo(windowInMinutes);
|
|
35
262
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
263
|
+
let metricItems: Array<Metric> = [];
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
const query: Query<Metric> = {
|
|
267
|
+
projectId: data.projectId,
|
|
268
|
+
time: new InBetween(windowStart, now),
|
|
269
|
+
primaryEntityId: data.monitorId,
|
|
270
|
+
name: metricName,
|
|
271
|
+
};
|
|
42
272
|
|
|
43
|
-
|
|
44
|
-
|
|
273
|
+
if (data.miscData) {
|
|
274
|
+
query.attributes = data.miscData;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
metricItems = await MetricService.findBy({
|
|
278
|
+
query: query,
|
|
279
|
+
limit: LIMIT_PER_PROJECT,
|
|
280
|
+
skip: 0,
|
|
281
|
+
props: {
|
|
282
|
+
isRoot: true,
|
|
283
|
+
},
|
|
284
|
+
select: {
|
|
285
|
+
value: true,
|
|
286
|
+
time: true,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
} catch (err) {
|
|
290
|
+
logger.error(
|
|
291
|
+
`Error in getting over time value for ${data.criteriaFilter.checkOn}`,
|
|
292
|
+
);
|
|
293
|
+
logger.error(err);
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
status: OverTimeEvaluationStatus.InsufficientData,
|
|
297
|
+
value: undefined,
|
|
298
|
+
sampleCount: 0,
|
|
299
|
+
noDataReason: "The metric store could not be read.",
|
|
300
|
+
isReadError: true,
|
|
301
|
+
};
|
|
45
302
|
}
|
|
46
303
|
|
|
47
|
-
const
|
|
48
|
-
query: query,
|
|
49
|
-
limit: LIMIT_PER_PROJECT,
|
|
50
|
-
skip: 0,
|
|
51
|
-
props: {
|
|
52
|
-
isRoot: true,
|
|
53
|
-
},
|
|
54
|
-
select: {
|
|
55
|
-
value: true,
|
|
56
|
-
},
|
|
57
|
-
});
|
|
304
|
+
const sampleTimes: Array<Date> = [];
|
|
58
305
|
|
|
59
|
-
const values: Array<number | boolean> =
|
|
60
|
-
.map((item: Metric) => {
|
|
61
|
-
if (
|
|
62
|
-
data.metricType === CheckOn.IsOnline ||
|
|
63
|
-
data.metricType === CheckOn.IsRequestTimeout
|
|
64
|
-
) {
|
|
65
|
-
return item.value === 1;
|
|
66
|
-
}
|
|
306
|
+
const values: Array<number | boolean> = [];
|
|
67
307
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
308
|
+
for (const item of metricItems) {
|
|
309
|
+
if (item.value === undefined || item.value === null) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (
|
|
314
|
+
data.criteriaFilter.checkOn === CheckOn.IsOnline ||
|
|
315
|
+
data.criteriaFilter.checkOn === CheckOn.IsRequestTimeout ||
|
|
316
|
+
data.criteriaFilter.checkOn === CheckOn.DnsIsOnline ||
|
|
317
|
+
data.criteriaFilter.checkOn === CheckOn.SnmpIsOnline ||
|
|
318
|
+
data.criteriaFilter.checkOn === CheckOn.ExternalStatusPageIsOnline
|
|
319
|
+
) {
|
|
320
|
+
values.push(item.value === 1);
|
|
321
|
+
} else {
|
|
322
|
+
values.push(item.value);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (item.time) {
|
|
326
|
+
sampleTimes.push(OneUptimeDate.fromString(item.time));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (values.length === 0) {
|
|
331
|
+
return {
|
|
332
|
+
status: OverTimeEvaluationStatus.InsufficientData,
|
|
333
|
+
value: undefined,
|
|
334
|
+
sampleCount: 0,
|
|
335
|
+
noDataReason: `No data was recorded for ${data.criteriaFilter.checkOn} in the last ${windowInMinutes} minutes.`,
|
|
336
|
+
isReadError: false,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/*
|
|
341
|
+
* "All Values" is the only evaluation type that claims something about
|
|
342
|
+
* the WHOLE window, so it is the only one that needs the whole window to
|
|
343
|
+
* be there. Array.every() is trivially true on a single sample, which is
|
|
344
|
+
* exactly how one bad probe used to satisfy
|
|
345
|
+
* "all values over the last 5 minutes".
|
|
346
|
+
*
|
|
347
|
+
* "Any Value" fires on a single breaching sample by design, and the
|
|
348
|
+
* aggregates (Average / Sum / Min / Max) are meaningful over a partial
|
|
349
|
+
* window, so they are left alone.
|
|
350
|
+
*/
|
|
351
|
+
if (
|
|
352
|
+
evaluateOverTimeOptions.evaluateOverTimeType ===
|
|
353
|
+
EvaluateOverTimeType.AllValues
|
|
354
|
+
) {
|
|
355
|
+
const isCovered: boolean = this.isWindowCovered({
|
|
356
|
+
windowStart: windowStart,
|
|
357
|
+
windowEnd: now,
|
|
358
|
+
sampleTimes: sampleTimes,
|
|
359
|
+
monitoringInterval: data.monitoringInterval,
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
if (!isCovered) {
|
|
363
|
+
return {
|
|
364
|
+
status: OverTimeEvaluationStatus.InsufficientData,
|
|
365
|
+
value: undefined,
|
|
366
|
+
sampleCount: values.length,
|
|
367
|
+
noDataReason: `Only ${values.length} data point(s) recorded so far - not enough to cover the last ${windowInMinutes} minutes.`,
|
|
368
|
+
isReadError: false,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
}
|
|
73
372
|
|
|
74
373
|
if (
|
|
75
|
-
|
|
374
|
+
evaluateOverTimeOptions.evaluateOverTimeType ===
|
|
76
375
|
EvaluateOverTimeType.AnyValue ||
|
|
77
|
-
|
|
376
|
+
evaluateOverTimeOptions.evaluateOverTimeType ===
|
|
78
377
|
EvaluateOverTimeType.AllValues
|
|
79
378
|
) {
|
|
80
379
|
// if its any or all then return the values. Otherwise compute the value based on the type
|
|
81
|
-
return
|
|
380
|
+
return {
|
|
381
|
+
status: OverTimeEvaluationStatus.Evaluated,
|
|
382
|
+
value: values,
|
|
383
|
+
sampleCount: values.length,
|
|
384
|
+
noDataReason: null,
|
|
385
|
+
isReadError: false,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
status: OverTimeEvaluationStatus.Evaluated,
|
|
391
|
+
value: this.getValueByEvaluationType({
|
|
392
|
+
values: values as Array<number>,
|
|
393
|
+
evaluateOverTimeType: evaluateOverTimeOptions.evaluateOverTimeType!,
|
|
394
|
+
}),
|
|
395
|
+
sampleCount: values.length,
|
|
396
|
+
noDataReason: null,
|
|
397
|
+
isReadError: false,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Whether the samples actually reach back to the start of the window.
|
|
403
|
+
*
|
|
404
|
+
* A monitor that has only been running for a minute has one sample in a
|
|
405
|
+
* five minute window. That sample says nothing about the other four
|
|
406
|
+
* minutes, so "all values over the last 5 minutes" must not be considered
|
|
407
|
+
* satisfied by it.
|
|
408
|
+
*
|
|
409
|
+
* The check is expressed in time rather than in sample count so it is
|
|
410
|
+
* immune to a probe skipping a beat, to several probes writing into the
|
|
411
|
+
* same series, and to a sample landing a fraction of a second outside the
|
|
412
|
+
* window.
|
|
413
|
+
*/
|
|
414
|
+
private static isWindowCovered(data: {
|
|
415
|
+
windowStart: Date;
|
|
416
|
+
windowEnd: Date;
|
|
417
|
+
sampleTimes: Array<Date>;
|
|
418
|
+
monitoringInterval?: string | undefined;
|
|
419
|
+
}): boolean {
|
|
420
|
+
if (data.sampleTimes.length === 0) {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const sortedTimes: Array<number> = data.sampleTimes
|
|
425
|
+
.map((time: Date) => {
|
|
426
|
+
return time.getTime();
|
|
427
|
+
})
|
|
428
|
+
.filter((time: number) => {
|
|
429
|
+
return !isNaN(time);
|
|
430
|
+
})
|
|
431
|
+
.sort((a: number, b: number) => {
|
|
432
|
+
return a - b;
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
if (sortedTimes.length === 0) {
|
|
436
|
+
/*
|
|
437
|
+
* Timestamps were unreadable. Fall back to requiring more than one
|
|
438
|
+
* sample so a brand new monitor still cannot satisfy the window off a
|
|
439
|
+
* single reading.
|
|
440
|
+
*/
|
|
441
|
+
return data.sampleTimes.length > 1;
|
|
82
442
|
}
|
|
83
443
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
444
|
+
const intervalInSeconds: number | null = this.getSamplingIntervalInSeconds({
|
|
445
|
+
monitoringInterval: data.monitoringInterval,
|
|
446
|
+
sortedSampleTimes: sortedTimes,
|
|
87
447
|
});
|
|
448
|
+
|
|
449
|
+
if (intervalInSeconds === null) {
|
|
450
|
+
/*
|
|
451
|
+
* A single sample and no configured interval - there is no way to tell
|
|
452
|
+
* whether the monitor is polled once an hour or once a second, so the
|
|
453
|
+
* window cannot be called covered.
|
|
454
|
+
*/
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const oldestSampleMs: number = sortedTimes[0]!;
|
|
459
|
+
const newestSampleMs: number = sortedTimes[sortedTimes.length - 1]!;
|
|
460
|
+
|
|
461
|
+
const allowedGapMs: number =
|
|
462
|
+
intervalInSeconds * 1000 * this.WINDOW_COVERAGE_TOLERANCE_FACTOR;
|
|
463
|
+
|
|
464
|
+
const leadingGapMs: number = oldestSampleMs - data.windowStart.getTime();
|
|
465
|
+
|
|
466
|
+
/*
|
|
467
|
+
* The trailing edge matters as much as the leading one: samples that
|
|
468
|
+
* stop part way through the window say nothing about the minutes since,
|
|
469
|
+
* so "all values over the last N minutes" must not be satisfied by
|
|
470
|
+
* stale data either.
|
|
471
|
+
*/
|
|
472
|
+
const trailingGapMs: number = data.windowEnd.getTime() - newestSampleMs;
|
|
473
|
+
|
|
474
|
+
return leadingGapMs <= allowedGapMs && trailingGapMs <= allowedGapMs;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* How far apart consecutive samples are expected to be, in seconds.
|
|
479
|
+
*
|
|
480
|
+
* The monitor's own schedule is authoritative when we have it. Otherwise
|
|
481
|
+
* infer it from the data: the widest gap actually observed between
|
|
482
|
+
* consecutive samples is the longest wait the window has demonstrated, so
|
|
483
|
+
* it is the safest estimate of the cadence.
|
|
484
|
+
*/
|
|
485
|
+
private static getSamplingIntervalInSeconds(data: {
|
|
486
|
+
monitoringInterval?: string | undefined;
|
|
487
|
+
sortedSampleTimes: Array<number>;
|
|
488
|
+
}): number | null {
|
|
489
|
+
const configuredIntervalInSeconds: number | null =
|
|
490
|
+
CronTab.getIntervalInSeconds(data.monitoringInterval);
|
|
491
|
+
|
|
492
|
+
if (configuredIntervalInSeconds !== null) {
|
|
493
|
+
return configuredIntervalInSeconds;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (data.sortedSampleTimes.length < 2) {
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
let widestGapInSeconds: number = 0;
|
|
501
|
+
|
|
502
|
+
for (let i: number = 1; i < data.sortedSampleTimes.length; i++) {
|
|
503
|
+
const gapInSeconds: number =
|
|
504
|
+
(data.sortedSampleTimes[i]! - data.sortedSampleTimes[i - 1]!) / 1000;
|
|
505
|
+
|
|
506
|
+
if (gapInSeconds > widestGapInSeconds) {
|
|
507
|
+
widestGapInSeconds = gapInSeconds;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (widestGapInSeconds <= 0) {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return widestGapInSeconds;
|
|
88
516
|
}
|
|
89
517
|
|
|
90
518
|
private static getValueByEvaluationType(data: {
|
|
@@ -6,15 +6,21 @@ import {
|
|
|
6
6
|
} from "../../../../Types/Monitor/CriteriaFilter";
|
|
7
7
|
import ExternalStatusPageMonitorResponse from "../../../../Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse";
|
|
8
8
|
import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
|
|
9
|
-
import EvaluateOverTime from "./EvaluateOverTime";
|
|
9
|
+
import EvaluateOverTime, { OverTimeCriteriaValue } from "./EvaluateOverTime";
|
|
10
10
|
import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
11
|
-
import logger from "../../Logger";
|
|
12
11
|
|
|
13
12
|
export default class ExternalStatusPageMonitorCriteria {
|
|
14
13
|
@CaptureSpan()
|
|
15
14
|
public static async isMonitorInstanceCriteriaFilterMet(input: {
|
|
16
15
|
dataToProcess: DataToProcess;
|
|
17
16
|
criteriaFilter: CriteriaFilter;
|
|
17
|
+
/*
|
|
18
|
+
* The monitor's monitoringInterval cron. Over-time filters use it to
|
|
19
|
+
* work out how many samples a fully covered window should hold, so a
|
|
20
|
+
* monitor that has only just started is not mistaken for one whose
|
|
21
|
+
* whole window is breaching.
|
|
22
|
+
*/
|
|
23
|
+
monitoringInterval?: string | undefined;
|
|
18
24
|
}): Promise<string | null> {
|
|
19
25
|
let threshold: number | string | undefined | null =
|
|
20
26
|
input.criteriaFilter.value;
|
|
@@ -26,37 +32,36 @@ export default class ExternalStatusPageMonitorCriteria {
|
|
|
26
32
|
| ExternalStatusPageMonitorResponse
|
|
27
33
|
| undefined = dataToProcess.externalStatusPageResponse;
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
overTimeValue = await EvaluateOverTime.getValueOverTime({
|
|
38
|
-
projectId: (input.dataToProcess as ProbeMonitorResponse).projectId,
|
|
39
|
-
monitorId: input.dataToProcess.monitorId!,
|
|
40
|
-
evaluateOverTimeOptions: input.criteriaFilter.evaluateOverTimeOptions,
|
|
41
|
-
metricType: input.criteriaFilter.checkOn,
|
|
42
|
-
});
|
|
35
|
+
const overTime: OverTimeCriteriaValue =
|
|
36
|
+
await EvaluateOverTime.getOverTimeValueForCriteriaFilter({
|
|
37
|
+
projectId: (input.dataToProcess as ProbeMonitorResponse).projectId,
|
|
38
|
+
monitorId: input.dataToProcess.monitorId!,
|
|
39
|
+
criteriaFilter: input.criteriaFilter,
|
|
40
|
+
monitoringInterval: input.monitoringInterval,
|
|
41
|
+
});
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
/*
|
|
44
|
+
* The window could not back this over-time filter (nothing recorded yet,
|
|
45
|
+
* or the monitor has not been running long enough to cover it). Return
|
|
46
|
+
* the decision the no-data policy already made instead of falling
|
|
47
|
+
* through to the value that arrived with this one check - that fallback
|
|
48
|
+
* is what let "all values over the last N minutes" fire off a single
|
|
49
|
+
* bad reading.
|
|
50
|
+
*/
|
|
51
|
+
if (overTime.earlyReturn) {
|
|
52
|
+
return overTime.earlyReturn.result;
|
|
54
53
|
}
|
|
55
54
|
|
|
55
|
+
const overTimeValue:
|
|
56
|
+
| Array<number | boolean>
|
|
57
|
+
| number
|
|
58
|
+
| boolean
|
|
59
|
+
| undefined = overTime.value;
|
|
60
|
+
|
|
56
61
|
// Check if external status page is online
|
|
57
62
|
if (input.criteriaFilter.checkOn === CheckOn.ExternalStatusPageIsOnline) {
|
|
58
63
|
const currentIsOnline: boolean | Array<boolean> =
|
|
59
|
-
(overTimeValue as Array<boolean>)
|
|
64
|
+
(overTimeValue as Array<boolean>) ??
|
|
60
65
|
(input.dataToProcess as ProbeMonitorResponse).isOnline;
|
|
61
66
|
|
|
62
67
|
return CompareCriteria.compareCriteriaBoolean({
|
|
@@ -76,9 +81,9 @@ export default class ExternalStatusPageMonitorCriteria {
|
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
const currentResponseTime: number | Array<number> =
|
|
79
|
-
(overTimeValue as Array<number>)
|
|
80
|
-
externalStatusPageResponse?.responseTimeInMs ||
|
|
81
|
-
|
|
84
|
+
(overTimeValue as Array<number>) ??
|
|
85
|
+
(externalStatusPageResponse?.responseTimeInMs ||
|
|
86
|
+
(input.dataToProcess as ProbeMonitorResponse).responseTimeInMs);
|
|
82
87
|
|
|
83
88
|
if (currentResponseTime === null || currentResponseTime === undefined) {
|
|
84
89
|
return null;
|