@oneuptime/common 11.6.0 → 11.6.2

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 (427) hide show
  1. package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +41 -24
  2. package/Models/AnalyticsModels/Index.ts +4 -0
  3. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
  4. package/Models/AnalyticsModels/MetricBaselineHourly.ts +2 -0
  5. package/Models/AnalyticsModels/MetricItemAggMV1m.ts +5 -2
  6. package/Models/AnalyticsModels/MetricItemAggMV1mByContainer.ts +5 -2
  7. package/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.ts +5 -2
  8. package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +5 -2
  9. package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +5 -2
  10. package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
  11. package/Models/AnalyticsModels/SloHistory.ts +240 -0
  12. package/Models/DatabaseModels/Index.ts +20 -0
  13. package/Models/DatabaseModels/NetworkDevice.ts +453 -6
  14. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
  15. package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
  16. package/Models/DatabaseModels/NetworkSite.ts +1155 -0
  17. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
  18. package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
  19. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
  20. package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
  21. package/Models/DatabaseModels/ServiceLevelObjective.ts +1106 -0
  22. package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
  23. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
  24. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  31. package/Server/Services/AnalyticsDatabaseService.ts +38 -10
  32. package/Server/Services/Index.ts +24 -0
  33. package/Server/Services/KubernetesCostAllocationService.ts +14 -0
  34. package/Server/Services/MetricService.ts +21 -2
  35. package/Server/Services/MonitorService.ts +22 -0
  36. package/Server/Services/NetworkDeviceService.ts +438 -2
  37. package/Server/Services/NetworkEndpointService.ts +414 -0
  38. package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
  39. package/Server/Services/NetworkSiteLinkService.ts +10 -0
  40. package/Server/Services/NetworkSiteService.ts +1254 -0
  41. package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
  42. package/Server/Services/NetworkSiteTypeService.ts +10 -0
  43. package/Server/Services/ProjectService.ts +122 -2
  44. package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
  45. package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
  46. package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
  47. package/Server/Services/ServiceLevelObjectiveService.ts +677 -0
  48. package/Server/Services/SloHistoryService.ts +101 -0
  49. package/Server/Services/UserNotificationSettingService.ts +37 -0
  50. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
  51. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
  52. package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
  53. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +128 -52
  54. package/Server/Utils/Memory.ts +9 -1
  55. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
  56. package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  57. package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
  58. package/Server/Utils/Monitor/MonitorResource.ts +4 -30
  59. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
  60. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
  61. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
  62. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
  63. package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
  64. package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
  65. package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
  66. package/Tests/Models/AnalyticsModels/AnalyticsBaseModel.test.ts +122 -0
  67. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
  68. package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
  69. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
  70. package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
  71. package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
  72. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
  73. package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
  74. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
  75. package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
  76. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
  77. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
  78. package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +164 -3
  79. package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
  80. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +503 -0
  81. package/Tests/Server/Utils/Encryption.test.ts +70 -0
  82. package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
  83. package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
  84. package/Tests/Server/Utils/LocalFile.test.ts +258 -0
  85. package/Tests/Server/Utils/Memory.test.ts +213 -0
  86. package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
  87. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
  88. package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
  89. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
  90. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
  91. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
  92. package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
  93. package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
  94. package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
  95. package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
  96. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
  97. package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
  98. package/Tests/Server/Utils/Stream.test.ts +87 -0
  99. package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
  100. package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
  101. package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
  102. package/Tests/Types/Email.test.ts +198 -0
  103. package/Tests/Types/HashCode.test.ts +41 -0
  104. package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
  105. package/Tests/Types/Log/LogQueryParser.test.ts +186 -0
  106. package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
  107. package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
  108. package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
  109. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
  110. package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
  111. package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
  112. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
  113. package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
  114. package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
  115. package/Tests/Types/WebsiteRequest.test.ts +230 -0
  116. package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
  117. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
  118. package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
  119. package/Tests/UI/Utils/LogExport.test.ts +159 -0
  120. package/Tests/UI/Utils/Navigation.test.ts +183 -0
  121. package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
  122. package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
  123. package/Tests/Utils/Base64.test.ts +51 -0
  124. package/Tests/Utils/Boolean.test.ts +76 -0
  125. package/Tests/Utils/Crypto.test.ts +48 -0
  126. package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
  127. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
  128. package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +197 -0
  129. package/Tests/Utils/Enum.test.ts +54 -0
  130. package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
  131. package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
  132. package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
  133. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
  134. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
  135. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
  136. package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
  137. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
  138. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
  139. package/Tests/Utils/ObjectUtil.test.ts +30 -0
  140. package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
  141. package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
  142. package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
  143. package/Tests/Utils/TechStack.test.ts +50 -0
  144. package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
  145. package/Tests/Utils/ValueFormatter.test.ts +305 -0
  146. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
  147. package/Types/AnalyticsDatabase/TableColumn.ts +23 -0
  148. package/Types/BaseDatabase/EqualTo.ts +9 -1
  149. package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
  150. package/Types/BaseDatabase/NotEqual.ts +9 -1
  151. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  152. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  153. package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
  154. package/Types/Dashboard/DashboardTemplates.ts +214 -0
  155. package/Types/Email/EmailTemplateType.ts +2 -0
  156. package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
  157. package/Types/Monitor/CriteriaFilter.ts +9 -0
  158. package/Types/Monitor/MonitorStep.ts +5 -8
  159. package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
  160. package/Types/Monitor/MonitorType.ts +15 -5
  161. package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
  162. package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
  163. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
  164. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
  165. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
  166. package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
  167. package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
  168. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  169. package/Types/Permission.ts +449 -0
  170. package/Types/ServiceLevelObjective/SliType.ts +6 -0
  171. package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
  172. package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
  173. package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
  174. package/Types/Telemetry/ServiceType.ts +1 -0
  175. package/UI/Components/Filters/EntityFilter.tsx +16 -0
  176. package/UI/Components/Filters/FilterViewer.tsx +22 -5
  177. package/UI/Components/List/List.tsx +8 -0
  178. package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
  179. package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
  180. package/UI/Components/Navbar/NavBar.tsx +16 -2
  181. package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
  182. package/UI/Utils/Navigation.ts +10 -0
  183. package/UI/Utils/TableFilterUrlState.ts +204 -17
  184. package/UI/Utils/TableViewUrlState.ts +165 -0
  185. package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
  186. package/Utils/Dashboard/Components/Index.ts +7 -0
  187. package/Utils/IpCanonicalUtil.ts +134 -0
  188. package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
  189. package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
  190. package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
  191. package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
  192. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
  193. package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
  194. package/Utils/Slo/SloStatusColor.ts +54 -0
  195. package/Utils/Slo/SloUtil.ts +637 -0
  196. package/Utils/Slo/SloWidgetFormat.ts +383 -0
  197. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +25 -20
  198. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
  199. package/build/dist/Models/AnalyticsModels/Index.js +4 -0
  200. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  201. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
  202. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
  203. package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js +2 -0
  204. package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js.map +1 -1
  205. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js +5 -2
  206. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js.map +1 -1
  207. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js +5 -2
  208. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js.map +1 -1
  209. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js +5 -2
  210. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js.map +1 -1
  211. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +5 -2
  212. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js.map +1 -1
  213. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +5 -2
  214. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js.map +1 -1
  215. package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
  216. package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
  217. package/build/dist/Models/AnalyticsModels/SloHistory.js +215 -0
  218. package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
  219. package/build/dist/Models/DatabaseModels/Index.js +20 -0
  220. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  221. package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
  222. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  223. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
  224. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  225. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
  226. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
  227. package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
  228. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
  229. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
  230. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
  231. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
  232. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
  233. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
  234. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
  235. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
  236. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
  237. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1124 -0
  238. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
  239. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
  240. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
  241. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
  242. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
  243. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
  244. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
  245. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
  246. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
  247. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
  248. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
  249. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  257. package/build/dist/Server/Services/AnalyticsDatabaseService.js +32 -7
  258. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  259. package/build/dist/Server/Services/Index.js +24 -0
  260. package/build/dist/Server/Services/Index.js.map +1 -1
  261. package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
  262. package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
  263. package/build/dist/Server/Services/MetricService.js +21 -3
  264. package/build/dist/Server/Services/MetricService.js.map +1 -1
  265. package/build/dist/Server/Services/MonitorService.js +19 -0
  266. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  267. package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
  268. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  269. package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
  270. package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
  271. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
  272. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
  273. package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
  274. package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
  275. package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
  276. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
  277. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
  278. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
  279. package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
  280. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
  281. package/build/dist/Server/Services/ProjectService.js +98 -2
  282. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  283. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
  284. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
  285. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
  286. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
  287. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
  288. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
  289. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +582 -0
  290. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
  291. package/build/dist/Server/Services/SloHistoryService.js +77 -0
  292. package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
  293. package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
  294. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  295. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
  296. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  297. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
  298. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  299. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
  300. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  301. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +105 -52
  302. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  303. package/build/dist/Server/Utils/Memory.js +9 -1
  304. package/build/dist/Server/Utils/Memory.js.map +1 -1
  305. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
  306. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  307. package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  308. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
  309. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
  310. package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
  311. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  312. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
  313. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  314. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
  315. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
  316. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
  317. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
  318. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
  319. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  320. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
  321. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
  322. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
  323. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
  324. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
  325. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
  326. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
  327. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  328. package/build/dist/Types/AnalyticsDatabase/TableColumn.js +7 -0
  329. package/build/dist/Types/AnalyticsDatabase/TableColumn.js.map +1 -1
  330. package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
  331. package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
  332. package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
  333. package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
  334. package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
  335. package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
  336. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  337. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  338. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  339. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  340. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
  341. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
  342. package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
  343. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  344. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  345. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  346. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
  347. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
  348. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  349. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  350. package/build/dist/Types/Monitor/MonitorStep.js +5 -5
  351. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  352. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
  353. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
  354. package/build/dist/Types/Monitor/MonitorType.js +15 -5
  355. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  356. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
  357. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
  358. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
  359. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
  360. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
  361. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  362. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
  363. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
  364. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
  365. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
  366. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  367. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  368. package/build/dist/Types/Permission.js +409 -0
  369. package/build/dist/Types/Permission.js.map +1 -1
  370. package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
  371. package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
  372. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
  373. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
  374. package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
  375. package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
  376. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
  377. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
  378. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  379. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  380. package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
  381. package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
  382. package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
  383. package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
  384. package/build/dist/UI/Components/List/List.js +1 -1
  385. package/build/dist/UI/Components/List/List.js.map +1 -1
  386. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
  387. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  388. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
  389. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
  390. package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
  391. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  392. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
  393. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  394. package/build/dist/UI/Utils/Navigation.js +9 -0
  395. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  396. package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
  397. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  398. package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
  399. package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
  400. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
  401. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
  402. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  403. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  404. package/build/dist/Utils/IpCanonicalUtil.js +110 -0
  405. package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
  406. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
  407. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
  408. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
  409. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  410. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
  411. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
  412. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
  413. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
  414. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
  415. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
  416. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
  417. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
  418. package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
  419. package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
  420. package/build/dist/Utils/Slo/SloUtil.js +393 -0
  421. package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
  422. package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
  423. package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
  424. package/package.json +2 -2
  425. package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
  426. package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
  427. package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
@@ -0,0 +1,637 @@
1
+ import OneUptimeDate, { Moment } from "../../Types/Date";
2
+ import ObjectID from "../../Types/ObjectID";
3
+ import BadDataException from "../../Types/Exception/BadDataException";
4
+ import MonitorStatus from "../../Models/DatabaseModels/MonitorStatus";
5
+ import MonitorStatusTimeline from "../../Models/DatabaseModels/MonitorStatusTimeline";
6
+ import SloMultiMonitorMode from "../../Types/ServiceLevelObjective/SloMultiMonitorMode";
7
+ import SloStatus from "../../Types/ServiceLevelObjective/SloStatus";
8
+ import UptimePrecision from "../../Types/StatusPage/UptimePrecision";
9
+ import UptimeUtil, { UptimeWindow } from "../Uptime/UptimeUtil";
10
+ import MonitorEvent from "../Uptime/MonitorEvent";
11
+
12
+ /**
13
+ * A half-open-ish downtime interval [startDate, endDate]. Intervals produced by this
14
+ * util are already clipped to the reporting window and capped at "now".
15
+ */
16
+ export interface DowntimeInterval {
17
+ startDate: Date;
18
+ endDate: Date;
19
+ }
20
+
21
+ /**
22
+ * One monitor's status timeline rows. Rows for other monitors that leak into the
23
+ * `timelines` array are ignored (they are filtered by `monitorId`).
24
+ */
25
+ export interface MonitorTimelineSet {
26
+ monitorId: ObjectID;
27
+ timelines: Array<MonitorStatusTimeline>;
28
+ }
29
+
30
+ export interface TimeSliResult {
31
+ /** Seconds counted against the SLO (downtime seconds). UNROUNDED. */
32
+ badSeconds: number;
33
+ /** Denominator seconds. 0 means "no data at all" (and sliPercentage is 100). */
34
+ totalSeconds: number;
35
+ /** UNROUNDED. Round only at render time via SloUtil.roundForDisplay. */
36
+ sliPercentage: number;
37
+ }
38
+
39
+ export interface ErrorBudgetResult {
40
+ /** allowedBadFraction * totalSeconds. */
41
+ budgetTotalSeconds: number;
42
+ /** Bad seconds consumed so far. */
43
+ budgetConsumedSeconds: number;
44
+ /**
45
+ * SIGNED: negative when the SLO is over budget ("-40 min over budget" is
46
+ * operationally useful). Clamp in the UI only, never here.
47
+ */
48
+ budgetRemainingSeconds: number;
49
+ /** Signed, uncapped below 0, capped at 100. UNROUNDED. */
50
+ budgetRemainingPercentage: number;
51
+ }
52
+
53
+ export interface CalendarMonthWindow {
54
+ /** Start of the calendar month containing `at`, in the SLO's timezone. */
55
+ startDate: Date;
56
+ /** EXCLUSIVE end: the first instant of the next calendar month. */
57
+ endDate: Date;
58
+ /**
59
+ * Real elapsed seconds in the FULL calendar period (fixed at period start -
60
+ * NOT elapsed time, or a 1-minute blip at 00:10 on the 1st reads as instant
61
+ * budget exhaustion). This is the budget denominator for calendar windows.
62
+ * DST months in non-UTC timezones are 3600s shorter/longer - real seconds,
63
+ * on purpose.
64
+ */
65
+ totalSecondsInFullPeriod: number;
66
+ }
67
+
68
+ /**
69
+ * SLO / error budget math. Isomorphic (no server imports) so it is shared by the
70
+ * worker, the dashboard, and later the status page - exactly like UptimeUtil.
71
+ *
72
+ * Design notes (see SLO design doc paragraph 3.1 / 5):
73
+ *
74
+ * - Multi-monitor downtime must NOT be computed by feeding several monitors into
75
+ * UptimeUtil.getNonOverlappingMonitorEvents: its priority flatten lets a
76
+ * better-status event that merely ends later truncate a concurrent worse-status
77
+ * event (Monitor A Offline 10:00-11:00 + Monitor B Operational 10:30-12:00
78
+ * silently loses 30 minutes of downtime). That flatten was built for rendering
79
+ * one status-page bar, not cross-monitor budget math. This util therefore works
80
+ * per monitor (getMonitorEventsForId is per-monitor and correct) and combines
81
+ * monitors with explicit semantics (SloMultiMonitorMode).
82
+ *
83
+ * - Every comparison against a threshold uses UNROUNDED values. Round only at
84
+ * render time (roundForDisplay floors - fine for display, wrong for
85
+ * classification).
86
+ */
87
+ export default class SloUtil {
88
+ /**
89
+ * Extracts the downtime intervals of a SINGLE monitor inside the window.
90
+ * Uses UptimeUtil.getMonitorEventsForId, which is per-monitor: it clips events
91
+ * to the window, caps them at "now" and imputes an end for open
92
+ * (endsAt = null) rows. Events whose status is not in `downtimeStatuses` are
93
+ * dropped.
94
+ */
95
+ public static getDowntimeIntervalsForMonitor(
96
+ monitorId: ObjectID,
97
+ timelines: Array<MonitorStatusTimeline>,
98
+ downtimeStatuses: Array<MonitorStatus>,
99
+ window: UptimeWindow,
100
+ ): Array<DowntimeInterval> {
101
+ const events: Array<MonitorEvent> = UptimeUtil.getMonitorEventsForId(
102
+ monitorId,
103
+ timelines,
104
+ window,
105
+ );
106
+
107
+ const intervals: Array<DowntimeInterval> = [];
108
+
109
+ for (const event of events) {
110
+ const isDowntimeEvent: boolean = Boolean(
111
+ downtimeStatuses.find((status: MonitorStatus) => {
112
+ return status.id?.toString() === event.eventStatusId.toString();
113
+ }),
114
+ );
115
+
116
+ if (isDowntimeEvent) {
117
+ intervals.push({
118
+ startDate: event.startDate,
119
+ endDate: event.endDate,
120
+ });
121
+ }
122
+ }
123
+
124
+ return intervals;
125
+ }
126
+
127
+ /**
128
+ * The EARLIEST event start across the attached monitors inside `window`, or
129
+ * null when no monitor has an event that overlaps the window at all.
130
+ *
131
+ * Uses the SAME UptimeUtil.getMonitorEventsForId clipping path the SLI
132
+ * denominator uses, so the answer has identical semantics to the clamp inside
133
+ * computeTimeSli: because events are clipped to the window, the returned date
134
+ * is always >= window.startDate, i.e. it is "how far back this window can
135
+ * actually see data".
136
+ *
137
+ * This exists for callers that must distinguish "the metric is fine" from
138
+ * "we have not observed enough history to judge it yet" - most importantly the
139
+ * burn-rate evaluator, whose FIXED-LENGTH long window would otherwise silently
140
+ * collapse to the data age (see EvaluateSlos.evaluateBurnRateRule).
141
+ */
142
+ public static getEarliestEventStartDate(
143
+ perMonitorTimelines: Array<MonitorTimelineSet>,
144
+ window: UptimeWindow,
145
+ ): Date | null {
146
+ let earliestEventStart: Date | null = null;
147
+
148
+ for (const monitor of perMonitorTimelines) {
149
+ const events: Array<MonitorEvent> = UptimeUtil.getMonitorEventsForId(
150
+ monitor.monitorId,
151
+ monitor.timelines,
152
+ window,
153
+ );
154
+
155
+ for (const event of events) {
156
+ if (
157
+ !earliestEventStart ||
158
+ event.startDate.getTime() < earliestEventStart.getTime()
159
+ ) {
160
+ earliestEventStart = event.startDate;
161
+ }
162
+ }
163
+ }
164
+
165
+ return earliestEventStart;
166
+ }
167
+
168
+ /**
169
+ * Merges overlapping and adjacent intervals into a disjoint, sorted set.
170
+ * Millisecond-precise (raw timestamps, not second-granularity moment
171
+ * comparisons) so the merged length agrees with
172
+ * OneUptimeDate.getSecondsBetweenDates.
173
+ */
174
+ public static mergeIntervals(
175
+ intervals: Array<DowntimeInterval>,
176
+ ): Array<DowntimeInterval> {
177
+ const sorted: Array<DowntimeInterval> = [...intervals].sort(
178
+ (a: DowntimeInterval, b: DowntimeInterval) => {
179
+ return a.startDate.getTime() - b.startDate.getTime();
180
+ },
181
+ );
182
+
183
+ const merged: Array<DowntimeInterval> = [];
184
+
185
+ for (const interval of sorted) {
186
+ // skip empty / inverted intervals.
187
+ if (interval.endDate.getTime() <= interval.startDate.getTime()) {
188
+ continue;
189
+ }
190
+
191
+ const last: DowntimeInterval | undefined = merged[merged.length - 1];
192
+
193
+ // overlapping OR adjacent (start === last end) -> extend the last interval.
194
+ if (last && interval.startDate.getTime() <= last.endDate.getTime()) {
195
+ if (interval.endDate.getTime() > last.endDate.getTime()) {
196
+ last.endDate = interval.endDate;
197
+ }
198
+ continue;
199
+ }
200
+
201
+ merged.push({
202
+ startDate: interval.startDate,
203
+ endDate: interval.endDate,
204
+ });
205
+ }
206
+
207
+ return merged;
208
+ }
209
+
210
+ /**
211
+ * Union downtime across monitors: per monitor, extract its down intervals from
212
+ * its OWN event list, then take the interval union across monitors and sum the
213
+ * seconds. This is the AnyDown numerator.
214
+ *
215
+ * The correctness case this exists for: Monitor A Offline 10:00-11:00 while
216
+ * Monitor B is Operational 10:30-12:00 must yield 3600 seconds of downtime,
217
+ * NOT 1800 - which is what the cross-monitor priority flatten in
218
+ * UptimeUtil.getNonOverlappingMonitorEvents produces.
219
+ */
220
+ public static getUnionDowntimeSeconds(
221
+ perMonitor: Array<MonitorTimelineSet>,
222
+ downtimeStatuses: Array<MonitorStatus>,
223
+ window: UptimeWindow,
224
+ ): number {
225
+ const allIntervals: Array<DowntimeInterval> = [];
226
+
227
+ for (const monitor of perMonitor) {
228
+ allIntervals.push(
229
+ ...this.getDowntimeIntervalsForMonitor(
230
+ monitor.monitorId,
231
+ monitor.timelines,
232
+ downtimeStatuses,
233
+ window,
234
+ ),
235
+ );
236
+ }
237
+
238
+ const merged: Array<DowntimeInterval> = this.mergeIntervals(allIntervals);
239
+
240
+ let totalSeconds: number = 0;
241
+
242
+ for (const interval of merged) {
243
+ totalSeconds += OneUptimeDate.getSecondsBetweenDates(
244
+ interval.startDate,
245
+ interval.endDate,
246
+ );
247
+ }
248
+
249
+ return totalSeconds;
250
+ }
251
+
252
+ /**
253
+ * Time-based SLI over MonitorStatusTimeline data.
254
+ *
255
+ * Denominator rules:
256
+ * - The window end is always clipped to "now" (a window reaching into the
257
+ * future must not inflate the denominator).
258
+ * - AnyDown: the window start is clamped forward to the EARLIEST first event
259
+ * across the attached monitors, so a young SLO is measured from its first
260
+ * data point, not diluted by time before any monitor existed. The clamp uses
261
+ * the merged set's earliest event so that one old monitor anchors the window
262
+ * for the whole SLO.
263
+ * - MonitorSecondsAverage: the clamp happens PER MONITOR (each monitor's own
264
+ * first event), mirroring UptimeUtil.getTotalDowntimeInSeconds - otherwise
265
+ * adding a young monitor dilutes the SLI.
266
+ *
267
+ * No data at all (no timeline rows for any monitor) => totalSeconds 0,
268
+ * sliPercentage 100 - callers decide what "no data" means (the evaluator marks
269
+ * such SLOs Misconfigured/Paused; it never treats them as healthy 100%).
270
+ *
271
+ * Rows exist but none overlap the window => the monitor was up for the whole
272
+ * window as far as the window can tell: full-window denominator, 0 bad seconds
273
+ * (same answer UptimeUtil gives - see the "orphaned row" production incident
274
+ * test in UptimeUtil.test.ts).
275
+ *
276
+ * All values are UNROUNDED.
277
+ */
278
+ public static computeTimeSli(data: {
279
+ perMonitorTimelines: Array<MonitorTimelineSet>;
280
+ downtimeStatuses: Array<MonitorStatus>;
281
+ window: UptimeWindow;
282
+ mode: SloMultiMonitorMode;
283
+ }): TimeSliResult {
284
+ const { perMonitorTimelines, downtimeStatuses, window, mode } = data;
285
+
286
+ const hasAnyTimelineRows: boolean = perMonitorTimelines.some(
287
+ (monitor: MonitorTimelineSet) => {
288
+ return monitor.timelines.length > 0;
289
+ },
290
+ );
291
+
292
+ if (!hasAnyTimelineRows) {
293
+ return {
294
+ badSeconds: 0,
295
+ totalSeconds: 0,
296
+ sliPercentage: 100,
297
+ };
298
+ }
299
+
300
+ if (mode === SloMultiMonitorMode.MonitorSecondsAverage) {
301
+ return this.computeMonitorSecondsAverageSli({
302
+ perMonitorTimelines,
303
+ downtimeStatuses,
304
+ window,
305
+ });
306
+ }
307
+
308
+ return this.computeAnyDownSli({
309
+ perMonitorTimelines,
310
+ downtimeStatuses,
311
+ window,
312
+ });
313
+ }
314
+
315
+ private static computeAnyDownSli(data: {
316
+ perMonitorTimelines: Array<MonitorTimelineSet>;
317
+ downtimeStatuses: Array<MonitorStatus>;
318
+ window: UptimeWindow;
319
+ }): TimeSliResult {
320
+ const { perMonitorTimelines, downtimeStatuses, window } = data;
321
+
322
+ const windowEndDate: Date = OneUptimeDate.getLesserDate(
323
+ window.endDate,
324
+ OneUptimeDate.getCurrentDate(),
325
+ );
326
+
327
+ /*
328
+ * Earliest first event across monitors. Events from getMonitorEventsForId are
329
+ * already clipped to the window, so every start is >= window.startDate: the
330
+ * clamp can only move the window start FORWARD (young SLO), never backward.
331
+ */
332
+ const earliestEventStart: Date | null = this.getEarliestEventStartDate(
333
+ perMonitorTimelines,
334
+ window,
335
+ );
336
+
337
+ /*
338
+ * Rows exist but none clip into the window: as far as the window can tell the
339
+ * monitors were up throughout - full-window denominator, zero bad seconds
340
+ * (matches UptimeUtil's behaviour for the same input).
341
+ */
342
+ const windowStartDate: Date = earliestEventStart
343
+ ? OneUptimeDate.getGreaterDate(window.startDate, earliestEventStart)
344
+ : window.startDate;
345
+
346
+ const totalSeconds: number = OneUptimeDate.getSecondsBetweenDates(
347
+ windowStartDate,
348
+ windowEndDate,
349
+ );
350
+
351
+ if (totalSeconds <= 0) {
352
+ return {
353
+ badSeconds: 0,
354
+ totalSeconds: 0,
355
+ sliPercentage: 100,
356
+ };
357
+ }
358
+
359
+ const badSeconds: number = this.getUnionDowntimeSeconds(
360
+ perMonitorTimelines,
361
+ downtimeStatuses,
362
+ window,
363
+ );
364
+
365
+ return {
366
+ badSeconds,
367
+ totalSeconds,
368
+ sliPercentage: ((totalSeconds - badSeconds) / totalSeconds) * 100,
369
+ };
370
+ }
371
+
372
+ private static computeMonitorSecondsAverageSli(data: {
373
+ perMonitorTimelines: Array<MonitorTimelineSet>;
374
+ downtimeStatuses: Array<MonitorStatus>;
375
+ window: UptimeWindow;
376
+ }): TimeSliResult {
377
+ const { perMonitorTimelines, downtimeStatuses, window } = data;
378
+
379
+ let badSeconds: number = 0;
380
+ let totalSeconds: number = 0;
381
+
382
+ for (const monitor of perMonitorTimelines) {
383
+ /*
384
+ * Guard against rows of other monitors leaking into this monitor's array -
385
+ * getTotalDowntimeInSeconds does not filter by monitor id, and feeding it a
386
+ * multi-monitor array would reintroduce the priority-flatten bug.
387
+ */
388
+ const ownTimelines: Array<MonitorStatusTimeline> =
389
+ monitor.timelines.filter((timeline: MonitorStatusTimeline) => {
390
+ return (
391
+ timeline.monitorId?.toString() === monitor.monitorId.toString()
392
+ );
393
+ });
394
+
395
+ /*
396
+ * A monitor with no timeline rows at all has no data - skip it instead of
397
+ * letting it contribute a full window of implied uptime.
398
+ */
399
+ if (ownTimelines.length === 0) {
400
+ continue;
401
+ }
402
+
403
+ const {
404
+ totalDowntimeInSeconds,
405
+ totalSecondsInTimePeriod,
406
+ }: { totalDowntimeInSeconds: number; totalSecondsInTimePeriod: number } =
407
+ UptimeUtil.getTotalDowntimeInSeconds(
408
+ ownTimelines,
409
+ downtimeStatuses,
410
+ window,
411
+ );
412
+
413
+ badSeconds += totalDowntimeInSeconds;
414
+ totalSeconds += totalSecondsInTimePeriod;
415
+ }
416
+
417
+ if (totalSeconds <= 0) {
418
+ return {
419
+ badSeconds: 0,
420
+ totalSeconds: 0,
421
+ sliPercentage: 100,
422
+ };
423
+ }
424
+
425
+ return {
426
+ badSeconds,
427
+ totalSeconds,
428
+ sliPercentage: (1 - badSeconds / totalSeconds) * 100,
429
+ };
430
+ }
431
+
432
+ /**
433
+ * Error budget from an SLI measurement.
434
+ *
435
+ * Provide either `sliPercentage` or `badSeconds` (badSeconds wins when both are
436
+ * given, since it is the exact number the SLI was derived from).
437
+ *
438
+ * budgetRemainingSeconds is SIGNED - negative when over budget. Never clamp it
439
+ * here; clamp in the UI only. budgetRemainingPercentage is capped at 100 but
440
+ * NOT floored at 0.
441
+ */
442
+ public static getErrorBudget(data: {
443
+ sliPercentage?: number | undefined;
444
+ badSeconds?: number | undefined;
445
+ totalSeconds: number;
446
+ targetPercentage: number;
447
+ }): ErrorBudgetResult {
448
+ const { sliPercentage, badSeconds, totalSeconds, targetPercentage } = data;
449
+
450
+ this.validateTargetPercentage(targetPercentage);
451
+
452
+ if (badSeconds === undefined && sliPercentage === undefined) {
453
+ throw new BadDataException(
454
+ "Either sliPercentage or badSeconds must be provided to compute the error budget.",
455
+ );
456
+ }
457
+
458
+ // no elapsed window yet => nothing consumed, full budget remaining.
459
+ if (totalSeconds === 0) {
460
+ return {
461
+ budgetTotalSeconds: 0,
462
+ budgetConsumedSeconds: 0,
463
+ budgetRemainingSeconds: 0,
464
+ budgetRemainingPercentage: 100,
465
+ };
466
+ }
467
+
468
+ const allowedBadFraction: number = 1 - targetPercentage / 100;
469
+
470
+ const budgetTotalSeconds: number = allowedBadFraction * totalSeconds;
471
+
472
+ const budgetConsumedSeconds: number =
473
+ badSeconds !== undefined
474
+ ? badSeconds
475
+ : (1 - sliPercentage! / 100) * totalSeconds;
476
+
477
+ const budgetRemainingSeconds: number =
478
+ budgetTotalSeconds - budgetConsumedSeconds;
479
+
480
+ const budgetRemainingPercentage: number = Math.min(
481
+ 100,
482
+ (budgetRemainingSeconds / budgetTotalSeconds) * 100,
483
+ );
484
+
485
+ return {
486
+ budgetTotalSeconds,
487
+ budgetConsumedSeconds,
488
+ budgetRemainingSeconds,
489
+ budgetRemainingPercentage,
490
+ };
491
+ }
492
+
493
+ /**
494
+ * Burn rate: how many times faster than "exactly on target" the budget is being
495
+ * consumed over the measured period. 1 = burning exactly the sustainable rate,
496
+ * 14.4 = the canonical fast-burn page threshold for a 30-day window.
497
+ *
498
+ * Works identically for seconds (time-based SLIs) and event counts (event-based
499
+ * SLIs) - pass bad/total counts in badSeconds/totalSeconds.
500
+ *
501
+ * totalSeconds === 0 (no data in the lookback) => 0: no evidence of burn -
502
+ * callers skip burn rules on no-data windows.
503
+ */
504
+ public static computeBurnRate(data: {
505
+ badSeconds: number;
506
+ totalSeconds: number;
507
+ targetPercentage: number;
508
+ }): number {
509
+ const { badSeconds, totalSeconds, targetPercentage } = data;
510
+
511
+ this.validateTargetPercentage(targetPercentage);
512
+
513
+ if (totalSeconds === 0) {
514
+ return 0;
515
+ }
516
+
517
+ const allowedBadFraction: number = 1 - targetPercentage / 100;
518
+
519
+ return badSeconds / totalSeconds / allowedBadFraction;
520
+ }
521
+
522
+ /**
523
+ * Status from remaining budget, with hysteresis so rolling windows that
524
+ * re-cross a boundary as bad seconds age out do not flap:
525
+ *
526
+ * - enter BudgetExhausted when remaining <= 0; exit only when remaining >= 2
527
+ * - enter AtRisk when remaining <= atRiskThreshold; exit back to Healthy only
528
+ * when remaining >= atRiskThreshold + 5
529
+ *
530
+ * All comparisons use UNROUNDED percentages. This function never emits
531
+ * Misconfigured or Paused - those are set by the caller (zero monitors /
532
+ * all monitors paused) before any math runs.
533
+ */
534
+ public static computeSloStatus(data: {
535
+ budgetRemainingPercentage: number;
536
+ currentStatus: SloStatus;
537
+ atRiskThresholdPercentage: number;
538
+ }): SloStatus {
539
+ const { budgetRemainingPercentage, currentStatus } = data;
540
+ const threshold: number = data.atRiskThresholdPercentage;
541
+
542
+ // enter exhausted.
543
+ if (budgetRemainingPercentage <= 0) {
544
+ return SloStatus.BudgetExhausted;
545
+ }
546
+
547
+ // hysteresis: stay exhausted until the budget has meaningfully recovered.
548
+ if (
549
+ currentStatus === SloStatus.BudgetExhausted &&
550
+ budgetRemainingPercentage < 2
551
+ ) {
552
+ return SloStatus.BudgetExhausted;
553
+ }
554
+
555
+ // enter at risk.
556
+ if (budgetRemainingPercentage <= threshold) {
557
+ return SloStatus.AtRisk;
558
+ }
559
+
560
+ // hysteresis: stay at risk until comfortably above the threshold.
561
+ if (
562
+ currentStatus === SloStatus.AtRisk &&
563
+ budgetRemainingPercentage < threshold + 5
564
+ ) {
565
+ return SloStatus.AtRisk;
566
+ }
567
+
568
+ return SloStatus.Healthy;
569
+ }
570
+
571
+ /**
572
+ * The full calendar month containing `at`, resolved in the given IANA timezone
573
+ * (default UTC - calendar boundaries are undefined without a zone). Timezone
574
+ * support comes from moment-timezone, which OneUptimeDate already wraps.
575
+ *
576
+ * `endDate` is EXCLUSIVE (the first instant of the next month).
577
+ * `totalSecondsInFullPeriod` is the real elapsed seconds of the whole month and
578
+ * is the budget denominator for calendar windows - fixed at period start, NOT
579
+ * elapsed time. Note the rollover consequence: on the 1st the budget silently
580
+ * resets to full.
581
+ */
582
+ public static getCalendarMonthWindow(data: {
583
+ timezone?: string | undefined;
584
+ at: Date;
585
+ }): CalendarMonthWindow {
586
+ const timezone: string = data.timezone || "UTC";
587
+
588
+ if (!Moment.tz.zone(timezone)) {
589
+ throw new BadDataException(`Unknown timezone: ${timezone}`);
590
+ }
591
+
592
+ const startOfMonth: ReturnType<typeof Moment.tz> = Moment.tz(
593
+ data.at,
594
+ timezone,
595
+ ).startOf("month");
596
+
597
+ const startDate: Date = startOfMonth.toDate();
598
+ const endDate: Date = startOfMonth.clone().add(1, "month").toDate();
599
+
600
+ return {
601
+ startDate,
602
+ endDate,
603
+ totalSecondsInFullPeriod: OneUptimeDate.getSecondsBetweenDates(
604
+ startDate,
605
+ endDate,
606
+ ),
607
+ };
608
+ }
609
+
610
+ /**
611
+ * Display-only rounding (delegates to UptimeUtil.roundToPrecision, which
612
+ * FLOORS). All status/threshold comparisons in this util use unrounded values;
613
+ * use this at render time only - never before classification.
614
+ */
615
+ public static roundForDisplay(
616
+ value: number,
617
+ precision: UptimePrecision,
618
+ ): number {
619
+ return UptimeUtil.roundToPrecision({
620
+ number: value,
621
+ precision,
622
+ });
623
+ }
624
+
625
+ private static validateTargetPercentage(targetPercentage: number): void {
626
+ /*
627
+ * target >= 100 makes allowedBadFraction 0 (or negative): every budget
628
+ * formula divides by zero and NaN propagates everywhere. target <= 0 is
629
+ * meaningless.
630
+ */
631
+ if (targetPercentage >= 100 || targetPercentage <= 0) {
632
+ throw new BadDataException(
633
+ "SLO target percentage must be greater than 0 and less than 100.",
634
+ );
635
+ }
636
+ }
637
+ }