@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.
Files changed (195) hide show
  1. package/Models/DatabaseModels/GlobalOidc.ts +20 -0
  2. package/Models/DatabaseModels/GlobalSso.ts +20 -0
  3. package/Models/DatabaseModels/MarketingConversion.ts +19 -9
  4. package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +46 -0
  5. package/Models/DatabaseModels/StatusPage.ts +7 -4
  6. package/Server/API/StatusPageAPI.ts +29 -4
  7. package/Server/EnvironmentConfig.ts +7 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.ts +19 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.ts +40 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  11. package/Server/Middleware/SlackAuthorization.ts +43 -6
  12. package/Server/Middleware/UserAuthorization.ts +236 -26
  13. package/Server/Middleware/WhatsAppAuthorization.ts +43 -3
  14. package/Server/Services/GlobalOidcProjectService.ts +126 -1
  15. package/Server/Services/GlobalOidcService.ts +132 -0
  16. package/Server/Services/GlobalSsoProjectService.ts +126 -1
  17. package/Server/Services/GlobalSsoService.ts +132 -0
  18. package/Server/Services/UserEmailService.ts +4 -4
  19. package/Server/Utils/CronTab.ts +73 -0
  20. package/Server/Utils/GlobalSsoAuthorization.ts +175 -0
  21. package/Server/Utils/Marketing/ConversionUploadProvider.ts +35 -5
  22. package/Server/Utils/Marketing/Providers/GoogleAds.ts +1 -1
  23. package/Server/Utils/Marketing/Providers/LinkedIn.ts +1 -1
  24. package/Server/Utils/Marketing/Providers/Meta.ts +1 -1
  25. package/Server/Utils/Marketing/Providers/MicrosoftAds.ts +1 -1
  26. package/Server/Utils/Marketing/Providers/Reddit.ts +1 -1
  27. package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +48 -33
  28. package/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.ts +35 -30
  29. package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +33 -28
  30. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +475 -47
  31. package/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.ts +35 -30
  32. package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +34 -28
  33. package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +33 -28
  34. package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +69 -40
  35. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +35 -29
  36. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +8 -0
  37. package/Server/Utils/Monitor/MonitorResource.ts +161 -21
  38. package/Server/Utils/StatusPageContentSecurityPolicy.ts +56 -0
  39. package/Server/Utils/StatusPageCustomizationAccess.ts +117 -0
  40. package/Tests/Server/API/StatusPageCustomizationOrigin.test.ts +348 -0
  41. package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +9 -59
  42. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +227 -0
  43. package/Tests/Server/Middleware/SlackAuthorization.test.ts +149 -0
  44. package/Tests/Server/Middleware/UserAuthorization.test.ts +27 -13
  45. package/Tests/Server/Middleware/UserAuthorizationGlobalSsoGovernance.test.ts +1455 -0
  46. package/Tests/Server/Middleware/UserAuthorizationSSOProvider.test.ts +91 -2
  47. package/Tests/Server/Middleware/WhatsAppAuthorization.test.ts +233 -0
  48. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +21 -8
  49. package/Tests/Server/Services/GlobalSsoProviderAuthorization.test.ts +1242 -0
  50. package/Tests/Server/Services/MonitorResourceProbeAgreementHydration.test.ts +459 -0
  51. package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +10 -0
  52. package/Tests/Server/Types/AnalyticsDatabase/AggregateUtilBucketTimestamp.test.ts +416 -0
  53. package/Tests/Server/Types/Database/QueryHelperManyToManyAndEmptyValues.test.ts +551 -0
  54. package/Tests/Server/Types/Database/SelectUtil.test.ts +348 -0
  55. package/Tests/Server/Utils/CronTab.test.ts +116 -0
  56. package/Tests/Server/Utils/GlobalSSOToken.test.ts +581 -0
  57. package/Tests/Server/Utils/GlobalSsoAuthorization.test.ts +1401 -0
  58. package/Tests/Server/Utils/Marketing/AdUploadableConversionTypes.test.ts +254 -0
  59. package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +1 -1
  60. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaEvaluateOverTime.test.ts +508 -0
  61. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +30 -9
  62. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +987 -0
  63. package/Tests/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.test.ts +916 -0
  64. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +382 -0
  65. package/Tests/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.test.ts +1219 -0
  66. package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +86 -0
  67. package/Tests/Server/Utils/StatusPageContentSecurityPolicy.test.ts +136 -0
  68. package/Tests/Server/Utils/StatusPageCustomizationAccess.test.ts +223 -0
  69. package/Tests/Types/Monitor/MonitorStepConfigHelpers.test.ts +165 -0
  70. package/Tests/Types/NetworkDevice/NetworkDeviceLinkRuleScope.test.ts +215 -0
  71. package/Tests/UI/Components/Forms/FormSubmitAnalytics.test.tsx +206 -0
  72. package/Tests/UI/Utils/AIChatExport/ConversationMarkdown.test.ts +774 -0
  73. package/Tests/UI/Utils/AIChatExport/MarkdownBlocks.test.ts +791 -0
  74. package/Tests/UI/Utils/AIChatExport/MarkdownSafety.test.ts +544 -0
  75. package/Tests/Utils/Analytics.test.ts +187 -0
  76. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +80 -0
  77. package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +1291 -0
  78. package/Tests/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.test.ts +214 -0
  79. package/Types/Marketing/MarketingConversion.ts +12 -0
  80. package/Types/Monitor/CriteriaFilter.ts +9 -0
  81. package/Types/NetworkDevice/NetworkDeviceLinkRuleScope.ts +51 -0
  82. package/UI/Components/FormModal/BasicFormModal.tsx +12 -0
  83. package/UI/Components/Forms/BasicForm.tsx +13 -1
  84. package/UI/Components/Forms/BasicModelForm.tsx +2 -1
  85. package/UI/Components/Forms/ModelForm.tsx +10 -1
  86. package/UI/Components/Forms/Utils/FormAnalyticsName.ts +39 -0
  87. package/UI/Components/ModelFormModal/ModelFormModal.tsx +6 -1
  88. package/Utils/Analytics.ts +55 -2
  89. package/Utils/Monitor/MonitorMetricType.ts +40 -0
  90. package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +587 -37
  91. package/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.ts +115 -0
  92. package/build/dist/Models/DatabaseModels/GlobalOidc.js +21 -0
  93. package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
  94. package/build/dist/Models/DatabaseModels/GlobalSso.js +21 -0
  95. package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
  96. package/build/dist/Models/DatabaseModels/MarketingConversion.js +20 -10
  97. package/build/dist/Models/DatabaseModels/MarketingConversion.js.map +1 -1
  98. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +47 -0
  99. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -1
  100. package/build/dist/Models/DatabaseModels/StatusPage.js +4 -4
  101. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  102. package/build/dist/Server/API/StatusPageAPI.js +25 -4
  103. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  104. package/build/dist/Server/EnvironmentConfig.js +6 -0
  105. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  106. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js +12 -0
  107. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js.map +1 -0
  108. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js +29 -0
  109. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js.map +1 -0
  110. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  111. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  112. package/build/dist/Server/Middleware/SlackAuthorization.js +28 -4
  113. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  114. package/build/dist/Server/Middleware/UserAuthorization.js +197 -22
  115. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  116. package/build/dist/Server/Middleware/WhatsAppAuthorization.js +32 -2
  117. package/build/dist/Server/Middleware/WhatsAppAuthorization.js.map +1 -1
  118. package/build/dist/Server/Services/GlobalOidcProjectService.js +105 -0
  119. package/build/dist/Server/Services/GlobalOidcProjectService.js.map +1 -1
  120. package/build/dist/Server/Services/GlobalOidcService.js +127 -0
  121. package/build/dist/Server/Services/GlobalOidcService.js.map +1 -1
  122. package/build/dist/Server/Services/GlobalSsoProjectService.js +105 -0
  123. package/build/dist/Server/Services/GlobalSsoProjectService.js.map +1 -1
  124. package/build/dist/Server/Services/GlobalSsoService.js +127 -0
  125. package/build/dist/Server/Services/GlobalSsoService.js.map +1 -1
  126. package/build/dist/Server/Services/UserEmailService.js +4 -4
  127. package/build/dist/Server/Utils/CronTab.js +66 -0
  128. package/build/dist/Server/Utils/CronTab.js.map +1 -1
  129. package/build/dist/Server/Utils/GlobalSsoAuthorization.js +112 -0
  130. package/build/dist/Server/Utils/GlobalSsoAuthorization.js.map +1 -0
  131. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js +17 -1
  132. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js.map +1 -1
  133. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js +1 -1
  134. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js.map +1 -1
  135. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js +1 -1
  136. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js.map +1 -1
  137. package/build/dist/Server/Utils/Marketing/Providers/Meta.js +1 -1
  138. package/build/dist/Server/Utils/Marketing/Providers/Meta.js.map +1 -1
  139. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js +1 -1
  140. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js.map +1 -1
  141. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js +1 -1
  142. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js.map +1 -1
  143. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +37 -35
  144. package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
  145. package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js +21 -25
  146. package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js.map +1 -1
  147. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +20 -22
  148. package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
  149. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +370 -42
  150. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  151. package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js +21 -25
  152. package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js.map +1 -1
  153. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +21 -25
  154. package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
  155. package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +21 -25
  156. package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
  157. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +64 -52
  158. package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
  159. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +25 -29
  160. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  161. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +8 -0
  162. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  163. package/build/dist/Server/Utils/Monitor/MonitorResource.js +123 -23
  164. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  165. package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js +39 -0
  166. package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js.map +1 -0
  167. package/build/dist/Server/Utils/StatusPageCustomizationAccess.js +85 -0
  168. package/build/dist/Server/Utils/StatusPageCustomizationAccess.js.map +1 -0
  169. package/build/dist/Types/Marketing/MarketingConversion.js +10 -0
  170. package/build/dist/Types/Marketing/MarketingConversion.js.map +1 -1
  171. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  172. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  173. package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js +46 -0
  174. package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js.map +1 -0
  175. package/build/dist/UI/Components/FormModal/BasicFormModal.js +2 -1
  176. package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
  177. package/build/dist/UI/Components/Forms/BasicForm.js +10 -1
  178. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  179. package/build/dist/UI/Components/Forms/BasicModelForm.js +2 -1
  180. package/build/dist/UI/Components/Forms/BasicModelForm.js.map +1 -1
  181. package/build/dist/UI/Components/Forms/ModelForm.js +4 -1
  182. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  183. package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js +33 -0
  184. package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js.map +1 -0
  185. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js +2 -1
  186. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  187. package/build/dist/Utils/Analytics.js +50 -2
  188. package/build/dist/Utils/Analytics.js.map +1 -1
  189. package/build/dist/Utils/Monitor/MonitorMetricType.js +37 -0
  190. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  191. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +318 -37
  192. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -1
  193. package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js +87 -0
  194. package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js.map +1 -0
  195. package/package.json +1 -1
@@ -9,7 +9,7 @@ import {
9
9
  } from "../../../../Types/Monitor/CriteriaFilter";
10
10
  import IncomingMonitorRequest from "../../../../Types/Monitor/IncomingMonitor/IncomingMonitorRequest";
11
11
  import Typeof from "../../../../Types/Typeof";
12
- import EvaluateOverTime from "./EvaluateOverTime";
12
+ import EvaluateOverTime, { OverTimeCriteriaValue } from "./EvaluateOverTime";
13
13
  import CompareCriteria from "./CompareCriteria";
14
14
  import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
15
15
  import CaptureSpan from "../../Telemetry/CaptureSpan";
@@ -19,6 +19,13 @@ export default class IncomingRequestCriteria {
19
19
  public static async isMonitorInstanceCriteriaFilterMet(input: {
20
20
  dataToProcess: DataToProcess;
21
21
  criteriaFilter: CriteriaFilter;
22
+ /*
23
+ * The monitor's monitoringInterval cron. Over-time filters use it to
24
+ * work out how many samples a fully covered window should hold, so a
25
+ * monitor that has only just started is not mistaken for one whose
26
+ * whole window is breaching.
27
+ */
28
+ monitoringInterval?: string | undefined;
22
29
  }): Promise<string | null> {
23
30
  // Server Monitoring Checks
24
31
 
@@ -37,36 +44,35 @@ export default class IncomingRequestCriteria {
37
44
 
38
45
  let value: number | string | undefined = input.criteriaFilter.value;
39
46
 
40
- let overTimeValue: Array<number | boolean> | number | boolean | undefined =
41
- undefined;
42
-
43
- if (
44
- input.criteriaFilter.evaluateOverTime &&
45
- input.criteriaFilter.evaluateOverTimeOptions
46
- ) {
47
- try {
48
- overTimeValue = await EvaluateOverTime.getValueOverTime({
49
- projectId: (input.dataToProcess as IncomingMonitorRequest).projectId,
50
- monitorId: input.dataToProcess.monitorId!,
51
- evaluateOverTimeOptions: input.criteriaFilter.evaluateOverTimeOptions,
52
- metricType: input.criteriaFilter.checkOn,
53
- });
54
-
55
- if (Array.isArray(overTimeValue) && overTimeValue.length === 0) {
56
- overTimeValue = undefined;
57
- }
58
- } catch (err) {
59
- logger.error(
60
- `Error in getting over time value for ${input.criteriaFilter.checkOn}`,
61
- );
62
- logger.error(err);
63
- overTimeValue = undefined;
64
- }
47
+ const overTime: OverTimeCriteriaValue =
48
+ await EvaluateOverTime.getOverTimeValueForCriteriaFilter({
49
+ projectId: (input.dataToProcess as IncomingMonitorRequest).projectId,
50
+ monitorId: input.dataToProcess.monitorId!,
51
+ criteriaFilter: input.criteriaFilter,
52
+ monitoringInterval: input.monitoringInterval,
53
+ });
54
+
55
+ /*
56
+ * The window could not back this over-time filter (nothing recorded yet,
57
+ * or the monitor has not been running long enough to cover it). Return
58
+ * the decision the no-data policy already made instead of falling
59
+ * through to the value that arrived with this one check - that fallback
60
+ * is what let "all values over the last N minutes" fire off a single
61
+ * bad reading.
62
+ */
63
+ if (overTime.earlyReturn) {
64
+ return overTime.earlyReturn.result;
65
65
  }
66
66
 
67
+ const overTimeValue:
68
+ | Array<number | boolean>
69
+ | number
70
+ | boolean
71
+ | undefined = overTime.value;
72
+
67
73
  if (input.criteriaFilter.checkOn === CheckOn.IsOnline) {
68
74
  const currentIsOnline: boolean | Array<boolean> =
69
- (overTimeValue as Array<boolean>) ||
75
+ (overTimeValue as Array<boolean>) ??
70
76
  (input.dataToProcess as ProbeMonitorResponse).isOnline;
71
77
 
72
78
  return CompareCriteria.compareCriteriaBoolean({
@@ -78,7 +84,7 @@ export default class IncomingRequestCriteria {
78
84
  // timeout.
79
85
  if (input.criteriaFilter.checkOn === CheckOn.IsRequestTimeout) {
80
86
  const currentIsTimeout: boolean | Array<boolean> =
81
- (overTimeValue as Array<boolean>) ||
87
+ (overTimeValue as Array<boolean>) ??
82
88
  (input.dataToProcess as ProbeMonitorResponse).isTimeout;
83
89
 
84
90
  return CompareCriteria.compareCriteriaBoolean({
@@ -8,15 +8,21 @@ import {
8
8
  } from "../../../../Types/Monitor/CriteriaFilter";
9
9
  import SslMonitorResponse from "../../../../Types/Monitor/SSLMonitor/SslMonitorResponse";
10
10
  import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
11
- import EvaluateOverTime from "./EvaluateOverTime";
11
+ import EvaluateOverTime, { OverTimeCriteriaValue } from "./EvaluateOverTime";
12
12
  import CaptureSpan from "../../Telemetry/CaptureSpan";
13
- import logger from "../../Logger";
14
13
 
15
14
  export default class ServerMonitorCriteria {
16
15
  @CaptureSpan()
17
16
  public static async isMonitorInstanceCriteriaFilterMet(input: {
18
17
  dataToProcess: DataToProcess;
19
18
  criteriaFilter: CriteriaFilter;
19
+ /*
20
+ * The monitor's monitoringInterval cron. Over-time filters use it to
21
+ * work out how many samples a fully covered window should hold, so a
22
+ * monitor that has only just started is not mistaken for one whose
23
+ * whole window is breaching.
24
+ */
25
+ monitoringInterval?: string | undefined;
20
26
  }): Promise<string | null> {
21
27
  let threshold: number | string | undefined | null =
22
28
  input.criteriaFilter.value;
@@ -27,36 +33,35 @@ export default class ServerMonitorCriteria {
27
33
  const sslResponse: SslMonitorResponse | undefined =
28
34
  dataToProcess.sslResponse;
29
35
 
30
- let overTimeValue: Array<number | boolean> | number | boolean | undefined =
31
- undefined;
36
+ const overTime: OverTimeCriteriaValue =
37
+ await EvaluateOverTime.getOverTimeValueForCriteriaFilter({
38
+ projectId: (input.dataToProcess as ProbeMonitorResponse).projectId,
39
+ monitorId: input.dataToProcess.monitorId!,
40
+ criteriaFilter: input.criteriaFilter,
41
+ monitoringInterval: input.monitoringInterval,
42
+ });
32
43
 
33
- if (
34
- input.criteriaFilter.evaluateOverTime &&
35
- input.criteriaFilter.evaluateOverTimeOptions
36
- ) {
37
- try {
38
- overTimeValue = await EvaluateOverTime.getValueOverTime({
39
- projectId: (input.dataToProcess as ProbeMonitorResponse).projectId,
40
- monitorId: input.dataToProcess.monitorId!,
41
- evaluateOverTimeOptions: input.criteriaFilter.evaluateOverTimeOptions,
42
- metricType: input.criteriaFilter.checkOn,
43
- });
44
-
45
- if (Array.isArray(overTimeValue) && overTimeValue.length === 0) {
46
- overTimeValue = undefined;
47
- }
48
- } catch (err) {
49
- logger.error(
50
- `Error in getting over time value for ${input.criteriaFilter.checkOn}`,
51
- );
52
- logger.error(err);
53
- overTimeValue = undefined;
54
- }
44
+ /*
45
+ * The window could not back this over-time filter (nothing recorded yet,
46
+ * or the monitor has not been running long enough to cover it). Return
47
+ * the decision the no-data policy already made instead of falling
48
+ * through to the value that arrived with this one check - that fallback
49
+ * is what let "all values over the last N minutes" fire off a single
50
+ * bad reading.
51
+ */
52
+ if (overTime.earlyReturn) {
53
+ return overTime.earlyReturn.result;
55
54
  }
56
55
 
56
+ const overTimeValue:
57
+ | Array<number | boolean>
58
+ | number
59
+ | boolean
60
+ | undefined = overTime.value;
61
+
57
62
  if (input.criteriaFilter.checkOn === CheckOn.IsOnline) {
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({
@@ -68,7 +73,7 @@ export default class ServerMonitorCriteria {
68
73
  // timeout.
69
74
  if (input.criteriaFilter.checkOn === CheckOn.IsRequestTimeout) {
70
75
  const currentIsTimeout: boolean | Array<boolean> =
71
- (overTimeValue as Array<boolean>) ||
76
+ (overTimeValue as Array<boolean>) ??
72
77
  (input.dataToProcess as ProbeMonitorResponse).isTimeout;
73
78
 
74
79
  return CompareCriteria.compareCriteriaBoolean({
@@ -1,6 +1,6 @@
1
1
  import DataToProcess from "../DataToProcess";
2
2
  import CompareCriteria from "./CompareCriteria";
3
- import EvaluateOverTime from "./EvaluateOverTime";
3
+ import EvaluateOverTime, { OverTimeCriteriaValue } from "./EvaluateOverTime";
4
4
  import OneUptimeDate from "../../../../Types/Date";
5
5
  import { BasicDiskMetrics } from "../../../../Types/Infrastructure/BasicMetrics";
6
6
  import { JSONObject } from "../../../../Types/JSON";
@@ -20,39 +20,60 @@ export default class ServerMonitorCriteria {
20
20
  public static async isMonitorInstanceCriteriaFilterMet(input: {
21
21
  dataToProcess: DataToProcess;
22
22
  criteriaFilter: CriteriaFilter;
23
+ /*
24
+ * The monitor's monitoringInterval cron. Over-time filters use it to
25
+ * work out how many samples a fully covered window should hold, so a
26
+ * monitor that has only just started is not mistaken for one whose
27
+ * whole window is breaching.
28
+ */
29
+ monitoringInterval?: string | undefined;
23
30
  }): Promise<string | null> {
24
31
  // Server Monitoring Checks
25
32
 
26
33
  let threshold: number | string | undefined | null =
27
34
  input.criteriaFilter.value;
28
- let overTimeValue: Array<number | boolean> | number | boolean | undefined =
29
- undefined;
35
+ const overTime: OverTimeCriteriaValue =
36
+ await EvaluateOverTime.getOverTimeValueForCriteriaFilter({
37
+ projectId: (input.dataToProcess as ServerMonitorResponse).projectId,
38
+ monitorId: input.dataToProcess.monitorId!,
39
+ criteriaFilter: input.criteriaFilter,
40
+ /*
41
+ * Only the disk-usage series carries a diskPath attribute, so
42
+ * scoping any other series by it would filter against an attribute
43
+ * no row has - and an empty window now means "cannot judge yet"
44
+ * rather than "compare the live value", which would silence the
45
+ * filter outright.
46
+ */
47
+ miscData:
48
+ input.criteriaFilter.checkOn === CheckOn.DiskUsagePercent
49
+ ? (input.criteriaFilter.serverMonitorOptions as JSONObject)
50
+ : undefined,
51
+ monitoringInterval: input.monitoringInterval,
52
+ });
30
53
 
54
+ /*
55
+ * The window could not back this over-time filter, so the no-data policy
56
+ * has already decided it - do not fall through to the value that arrived
57
+ * with this one check.
58
+ *
59
+ * "Is Online" is exempt: for a server monitor the absence of data IS the
60
+ * signal, and the differenceInMinutes check below already implements the
61
+ * "wait this long before calling it offline" behaviour off the agent's
62
+ * last check-in time. Letting it fall through preserves that.
63
+ */
31
64
  if (
32
- input.criteriaFilter.evaluateOverTime &&
33
- input.criteriaFilter.evaluateOverTimeOptions
65
+ overTime.earlyReturn &&
66
+ input.criteriaFilter.checkOn !== CheckOn.IsOnline
34
67
  ) {
35
- try {
36
- overTimeValue = await EvaluateOverTime.getValueOverTime({
37
- projectId: (input.dataToProcess as ServerMonitorResponse).projectId,
38
- monitorId: input.dataToProcess.monitorId!,
39
- evaluateOverTimeOptions: input.criteriaFilter.evaluateOverTimeOptions,
40
- metricType: input.criteriaFilter.checkOn,
41
- miscData: input.criteriaFilter.serverMonitorOptions as JSONObject,
42
- });
43
-
44
- if (Array.isArray(overTimeValue) && overTimeValue.length === 0) {
45
- overTimeValue = undefined;
46
- }
47
- } catch (err) {
48
- logger.error(
49
- `Error in getting over time value for ${input.criteriaFilter.checkOn}`,
50
- );
51
- logger.error(err);
52
- overTimeValue = undefined;
53
- }
68
+ return overTime.earlyReturn.result;
54
69
  }
55
70
 
71
+ const overTimeValue:
72
+ | Array<number | boolean>
73
+ | number
74
+ | boolean
75
+ | undefined = overTime.value;
76
+
56
77
  const lastCheckTime: Date = (input.dataToProcess as ServerMonitorResponse)
57
78
  .requestReceivedAt;
58
79
 
@@ -108,7 +129,7 @@ export default class ServerMonitorCriteria {
108
129
  differenceInMinutes >= offlineIfNotCheckedInMinutes
109
130
  ) {
110
131
  const currentIsOnline: boolean | Array<boolean> =
111
- (overTimeValue as Array<boolean>) || false; // false because no request receieved in the last 2 minutes
132
+ (overTimeValue as Array<boolean>) ?? false; // false because no request receieved in the last 2 minutes
112
133
 
113
134
  logger.debug(`Current Is Online: ${currentIsOnline}`);
114
135
 
@@ -127,7 +148,7 @@ export default class ServerMonitorCriteria {
127
148
  differenceInMinutes < offlineIfNotCheckedInMinutes
128
149
  ) {
129
150
  const currentIsOnline: boolean | Array<boolean> =
130
- (overTimeValue as Array<boolean>) || true; // true because request receieved in the last 2 minutes
151
+ (overTimeValue as Array<boolean>) ?? true; // true because request receieved in the last 2 minutes
131
152
 
132
153
  logger.debug(`Current Is Online: ${currentIsOnline}`);
133
154
 
@@ -148,10 +169,10 @@ export default class ServerMonitorCriteria {
148
169
  threshold = CompareCriteria.convertToNumber(threshold);
149
170
 
150
171
  const currentCpuPercent: number | Array<number> =
151
- (overTimeValue as Array<number>) ||
152
- (input.dataToProcess as ServerMonitorResponse)
172
+ (overTimeValue as Array<number>) ??
173
+ ((input.dataToProcess as ServerMonitorResponse)
153
174
  .basicInfrastructureMetrics?.cpuMetrics.percentUsed ||
154
- 0;
175
+ 0);
155
176
 
156
177
  return CompareCriteria.compareCriteriaNumbers({
157
178
  value: currentCpuPercent,
@@ -167,10 +188,10 @@ export default class ServerMonitorCriteria {
167
188
  threshold = CompareCriteria.convertToNumber(threshold);
168
189
 
169
190
  const memoryPercent: number | Array<number> =
170
- (overTimeValue as Array<number>) ||
171
- (input.dataToProcess as ServerMonitorResponse)
191
+ (overTimeValue as Array<number>) ??
192
+ ((input.dataToProcess as ServerMonitorResponse)
172
193
  .basicInfrastructureMetrics?.memoryMetrics.percentUsed ||
173
- 0;
194
+ 0);
174
195
 
175
196
  return CompareCriteria.compareCriteriaNumbers({
176
197
  value: memoryPercent,
@@ -201,8 +222,16 @@ export default class ServerMonitorCriteria {
201
222
  const diskUsagePercent: number =
202
223
  diskMetric?.percentUsed ?? diskMetric?.percentFree ?? 0;
203
224
 
225
+ /*
226
+ * Disk usage was the one server metric that computed its over-time
227
+ * window and then threw it away, comparing the reading from this check
228
+ * instead - so "evaluate over time" was a no-op here.
229
+ */
230
+ const value: number | Array<number> =
231
+ (overTimeValue as Array<number>) ?? diskUsagePercent;
232
+
204
233
  return CompareCriteria.compareCriteriaNumbers({
205
- value: diskUsagePercent,
234
+ value: value,
206
235
  threshold: threshold as number,
207
236
  criteriaFilter: input.criteriaFilter,
208
237
  });
@@ -232,7 +261,7 @@ export default class ServerMonitorCriteria {
232
261
  }
233
262
 
234
263
  const value: number | Array<number> =
235
- (overTimeValue as Array<number>) || currentLoad || 0;
264
+ (overTimeValue as Array<number>) ?? (currentLoad || 0);
236
265
 
237
266
  return CompareCriteria.compareCriteriaNumbers({
238
267
  value: value,
@@ -248,10 +277,10 @@ export default class ServerMonitorCriteria {
248
277
  threshold = CompareCriteria.convertToNumber(threshold);
249
278
 
250
279
  const swapPercent: number | Array<number> =
251
- (overTimeValue as Array<number>) ||
252
- (input.dataToProcess as ServerMonitorResponse)
280
+ (overTimeValue as Array<number>) ??
281
+ ((input.dataToProcess as ServerMonitorResponse)
253
282
  .basicInfrastructureMetrics?.memoryMetrics?.swapPercentUsed ||
254
- 0;
283
+ 0);
255
284
 
256
285
  return CompareCriteria.compareCriteriaNumbers({
257
286
  value: swapPercent,
@@ -267,10 +296,10 @@ export default class ServerMonitorCriteria {
267
296
  threshold = CompareCriteria.convertToNumber(threshold);
268
297
 
269
298
  const ioWaitPercent: number | Array<number> =
270
- (overTimeValue as Array<number>) ||
271
- (input.dataToProcess as ServerMonitorResponse)
299
+ (overTimeValue as Array<number>) ??
300
+ ((input.dataToProcess as ServerMonitorResponse)
272
301
  .basicInfrastructureMetrics?.cpuMetrics?.timeIoWaitPercent ||
273
- 0;
302
+ 0);
274
303
 
275
304
  return CompareCriteria.compareCriteriaNumbers({
276
305
  value: ioWaitPercent,
@@ -16,7 +16,7 @@ import SnmpMonitorResponse, {
16
16
  } from "../../../../Types/Monitor/SnmpMonitor/SnmpMonitorResponse";
17
17
  import SnmpTrap from "../../../../Types/Monitor/SnmpMonitor/SnmpTrap";
18
18
  import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
19
- import EvaluateOverTime from "./EvaluateOverTime";
19
+ import EvaluateOverTime, { OverTimeCriteriaValue } from "./EvaluateOverTime";
20
20
  import MetricBaselineService, {
21
21
  BaselineSummary,
22
22
  MetricBaselineService as MetricBaselineServiceClass,
@@ -173,6 +173,13 @@ export default class SnmpMonitorCriteria {
173
173
  public static async isMonitorInstanceCriteriaFilterMet(input: {
174
174
  dataToProcess: DataToProcess;
175
175
  criteriaFilter: CriteriaFilter;
176
+ /*
177
+ * The monitor's monitoringInterval cron. Over-time filters use it to
178
+ * work out how many samples a fully covered window should hold, so a
179
+ * monitor that has only just started is not mistaken for one whose
180
+ * whole window is breaching.
181
+ */
182
+ monitoringInterval?: string | undefined;
176
183
  }): Promise<string | null> {
177
184
  let threshold: number | string | undefined | null =
178
185
  input.criteriaFilter.value;
@@ -240,37 +247,36 @@ export default class SnmpMonitorCriteria {
240
247
  return null;
241
248
  }
242
249
 
243
- let overTimeValue: Array<number | boolean> | number | boolean | undefined =
244
- undefined;
245
-
246
- if (
247
- input.criteriaFilter.evaluateOverTime &&
248
- input.criteriaFilter.evaluateOverTimeOptions
249
- ) {
250
- try {
251
- overTimeValue = await EvaluateOverTime.getValueOverTime({
252
- projectId: (input.dataToProcess as ProbeMonitorResponse).projectId,
253
- monitorId: input.dataToProcess.monitorId!,
254
- evaluateOverTimeOptions: input.criteriaFilter.evaluateOverTimeOptions,
255
- metricType: input.criteriaFilter.checkOn,
256
- });
250
+ const overTime: OverTimeCriteriaValue =
251
+ await EvaluateOverTime.getOverTimeValueForCriteriaFilter({
252
+ projectId: (input.dataToProcess as ProbeMonitorResponse).projectId,
253
+ monitorId: input.dataToProcess.monitorId!,
254
+ criteriaFilter: input.criteriaFilter,
255
+ monitoringInterval: input.monitoringInterval,
256
+ });
257
257
 
258
- if (Array.isArray(overTimeValue) && overTimeValue.length === 0) {
259
- overTimeValue = undefined;
260
- }
261
- } catch (err) {
262
- logger.error(
263
- `Error in getting over time value for ${input.criteriaFilter.checkOn}`,
264
- );
265
- logger.error(err);
266
- overTimeValue = undefined;
267
- }
258
+ /*
259
+ * The window could not back this over-time filter (nothing recorded yet,
260
+ * or the monitor has not been running long enough to cover it). Return
261
+ * the decision the no-data policy already made instead of falling
262
+ * through to the value that arrived with this one check - that fallback
263
+ * is what let "all values over the last N minutes" fire off a single
264
+ * bad reading.
265
+ */
266
+ if (overTime.earlyReturn) {
267
+ return overTime.earlyReturn.result;
268
268
  }
269
269
 
270
+ const overTimeValue:
271
+ | Array<number | boolean>
272
+ | number
273
+ | boolean
274
+ | undefined = overTime.value;
275
+
270
276
  // Check if SNMP device is online
271
277
  if (input.criteriaFilter.checkOn === CheckOn.SnmpIsOnline) {
272
278
  const currentIsOnline: boolean | Array<boolean> =
273
- (overTimeValue as Array<boolean>) ||
279
+ (overTimeValue as Array<boolean>) ??
274
280
  (input.dataToProcess as ProbeMonitorResponse).isOnline;
275
281
 
276
282
  return CompareCriteria.compareCriteriaBoolean({
@@ -288,9 +294,9 @@ export default class SnmpMonitorCriteria {
288
294
  }
289
295
 
290
296
  const currentResponseTime: number | Array<number> =
291
- (overTimeValue as Array<number>) ||
292
- snmpResponse?.responseTimeInMs ||
293
- (input.dataToProcess as ProbeMonitorResponse).responseTimeInMs;
297
+ (overTimeValue as Array<number>) ??
298
+ (snmpResponse?.responseTimeInMs ||
299
+ (input.dataToProcess as ProbeMonitorResponse).responseTimeInMs);
294
300
 
295
301
  if (currentResponseTime === null || currentResponseTime === undefined) {
296
302
  return null;
@@ -666,6 +666,7 @@ ${contextBlock}
666
666
  await APIRequestCriteria.isMonitorInstanceCriteriaFilterMet({
667
667
  dataToProcess: input.dataToProcess,
668
668
  criteriaFilter: input.criteriaFilter,
669
+ monitoringInterval: input.monitor.monitoringInterval,
669
670
  });
670
671
 
671
672
  if (apiRequestCriteriaResult) {
@@ -711,6 +712,7 @@ ${contextBlock}
711
712
  await IncomingRequestCriteria.isMonitorInstanceCriteriaFilterMet({
712
713
  dataToProcess: input.dataToProcess,
713
714
  criteriaFilter: input.criteriaFilter,
715
+ monitoringInterval: input.monitor.monitoringInterval,
714
716
  });
715
717
 
716
718
  if (incomingRequestResult) {
@@ -735,6 +737,7 @@ ${contextBlock}
735
737
  await SSLMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
736
738
  dataToProcess: input.dataToProcess,
737
739
  criteriaFilter: input.criteriaFilter,
740
+ monitoringInterval: input.monitor.monitoringInterval,
738
741
  });
739
742
 
740
743
  if (sslMonitorResult) {
@@ -747,6 +750,7 @@ ${contextBlock}
747
750
  await ServerMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
748
751
  dataToProcess: input.dataToProcess,
749
752
  criteriaFilter: input.criteriaFilter,
753
+ monitoringInterval: input.monitor.monitoringInterval,
750
754
  });
751
755
 
752
756
  if (serverMonitorResult) {
@@ -830,6 +834,7 @@ ${contextBlock}
830
834
  await SnmpMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
831
835
  dataToProcess: input.dataToProcess,
832
836
  criteriaFilter: input.criteriaFilter,
837
+ monitoringInterval: input.monitor.monitoringInterval,
833
838
  });
834
839
 
835
840
  if (snmpMonitorResult) {
@@ -842,6 +847,7 @@ ${contextBlock}
842
847
  await DnsMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
843
848
  dataToProcess: input.dataToProcess,
844
849
  criteriaFilter: input.criteriaFilter,
850
+ monitoringInterval: input.monitor.monitoringInterval,
845
851
  });
846
852
 
847
853
  if (dnsMonitorResult) {
@@ -854,6 +860,7 @@ ${contextBlock}
854
860
  await DomainMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
855
861
  dataToProcess: input.dataToProcess,
856
862
  criteriaFilter: input.criteriaFilter,
863
+ monitoringInterval: input.monitor.monitoringInterval,
857
864
  });
858
865
 
859
866
  if (domainMonitorResult) {
@@ -891,6 +898,7 @@ ${contextBlock}
891
898
  {
892
899
  dataToProcess: input.dataToProcess,
893
900
  criteriaFilter: input.criteriaFilter,
901
+ monitoringInterval: input.monitor.monitoringInterval,
894
902
  },
895
903
  );
896
904