@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,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/NetworkSiteStatusTimeline";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/NetworkSiteType";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();
@@ -24,6 +24,7 @@ import IncidentStateService from "./IncidentStateService";
24
24
  import IncidentRoleService from "./IncidentRoleService";
25
25
  import MailService from "./MailService";
26
26
  import MonitorStatusService from "./MonitorStatusService";
27
+ import NetworkSiteTypeService from "./NetworkSiteTypeService";
27
28
  import NotificationService from "./NotificationService";
28
29
  import PromoCodeService from "./PromoCodeService";
29
30
  import ScheduledMaintenanceStateService from "./ScheduledMaintenanceStateService";
@@ -63,6 +64,8 @@ import IncidentSeverity from "../../Models/DatabaseModels/IncidentSeverity";
63
64
  import IncidentState from "../../Models/DatabaseModels/IncidentState";
64
65
  import IncidentRole from "../../Models/DatabaseModels/IncidentRole";
65
66
  import MonitorStatus from "../../Models/DatabaseModels/MonitorStatus";
67
+ import NetworkSiteType from "../../Models/DatabaseModels/NetworkSiteType";
68
+ import DefaultNetworkSiteType from "../../Types/NetworkSite/DefaultNetworkSiteType";
66
69
  import Model from "../../Models/DatabaseModels/Project";
67
70
  import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
68
71
  import PromoCode from "../../Models/DatabaseModels/PromoCode";
@@ -963,8 +966,8 @@ export class ProjectService extends DatabaseService<Model> {
963
966
  /*
964
967
  * Each addDefault* method only reads `createdItem.id` and writes rows to a
965
968
  * distinct table; none of them mutate `createdItem`. Running them in
966
- * parallel cuts the onCreate hook latency from sum-of-8 sequential DB
967
- * round-trips to max-of-8, which removes ~hundreds of ms on project
969
+ * parallel cuts the onCreate hook latency from sum-of-9 sequential DB
970
+ * round-trips to max-of-9, which removes ~hundreds of ms on project
968
971
  * create.
969
972
  */
970
973
  await Promise.all([
@@ -976,6 +979,7 @@ export class ProjectService extends DatabaseService<Model> {
976
979
  this.addDefaultScheduledMaintenanceState(createdItem),
977
980
  this.addDefaultAlertState(createdItem),
978
981
  this.addDefaultIncidentRoles(createdItem),
982
+ this.addDefaultNetworkSiteTypes(createdItem),
979
983
  ]);
980
984
 
981
985
  if (createdItem.createdOwnerEmail) {
@@ -1425,6 +1429,122 @@ export class ProjectService extends DatabaseService<Model> {
1425
1429
  return createdItem;
1426
1430
  }
1427
1431
 
1432
+ /**
1433
+ * Seeds the per-project network site type lookup table.
1434
+ *
1435
+ * Site types used to be a hardcoded enum. They are now a configurable
1436
+ * per-project lookup table so a project can rename "Unit" to "Store" or add
1437
+ * hierarchy levels of its own — which means every project needs its own
1438
+ * seeded copy of the defaults.
1439
+ *
1440
+ * Public (unlike the sibling seeders above) because the
1441
+ * BackfillNetworkSiteTypes data migration calls it to seed types into
1442
+ * projects that existed before the table did — same precedent as
1443
+ * addDefaultAlertSeverity / addDefaultAlertState.
1444
+ */
1445
+ @CaptureSpan()
1446
+ public async addDefaultNetworkSiteTypes(createdItem: Model): Promise<Model> {
1447
+ const projectId: ObjectID = createdItem.id!;
1448
+
1449
+ // Idempotent — see getExistingProjectScopedNames.
1450
+ const existingNames: Set<string | undefined> =
1451
+ await this.getExistingProjectScopedNames(
1452
+ NetworkSiteTypeService,
1453
+ projectId,
1454
+ );
1455
+
1456
+ /*
1457
+ * Listed broadest-first: the array position is the hierarchy level, so the
1458
+ * index drives `order` (1..7, lower = higher in the hierarchy). Names come
1459
+ * from DefaultNetworkSiteType so that enum stays the single source of
1460
+ * truth for the defaults, shared with the backfill data migration.
1461
+ *
1462
+ * isUnitLevel is true for "Unit" only. It is load-bearing, not a label:
1463
+ * the network map drills sites of a unit-level type into their device
1464
+ * topology instead of a child-site map, and the health rollup counts them
1465
+ * as units. Downstream code keys off this flag rather than the name,
1466
+ * because the name is user-editable once seeded.
1467
+ */
1468
+ const defaultNetworkSiteTypes: Array<{
1469
+ name: DefaultNetworkSiteType;
1470
+ description: string;
1471
+ isUnitLevel: boolean;
1472
+ }> = [
1473
+ {
1474
+ name: DefaultNetworkSiteType.AccountType,
1475
+ description:
1476
+ "Top level grouping - the kind of account the sites underneath it belong to.",
1477
+ isUnitLevel: false,
1478
+ },
1479
+ {
1480
+ name: DefaultNetworkSiteType.Region,
1481
+ description:
1482
+ "A broad geographic region that groups markets and the sites within them.",
1483
+ isUnitLevel: false,
1484
+ },
1485
+ {
1486
+ name: DefaultNetworkSiteType.Franchisee,
1487
+ description:
1488
+ "An operator or franchise partner responsible for a group of sites.",
1489
+ isUnitLevel: false,
1490
+ },
1491
+ {
1492
+ name: DefaultNetworkSiteType.Market,
1493
+ description: "A metro or trade area that groups the sites within it.",
1494
+ isUnitLevel: false,
1495
+ },
1496
+ {
1497
+ name: DefaultNetworkSiteType.Unit,
1498
+ description:
1499
+ "An individual location with network devices. This is the leaf level of the hierarchy.",
1500
+ isUnitLevel: true,
1501
+ },
1502
+ {
1503
+ name: DefaultNetworkSiteType.DataCenter,
1504
+ description:
1505
+ "A data center or core facility that hosts shared infrastructure.",
1506
+ isUnitLevel: false,
1507
+ },
1508
+ {
1509
+ name: DefaultNetworkSiteType.Other,
1510
+ description: "Any site that does not fit the other levels.",
1511
+ isUnitLevel: false,
1512
+ },
1513
+ ];
1514
+
1515
+ for (
1516
+ let index: number = 0;
1517
+ index < defaultNetworkSiteTypes.length;
1518
+ index++
1519
+ ) {
1520
+ const defaultNetworkSiteType: {
1521
+ name: DefaultNetworkSiteType;
1522
+ description: string;
1523
+ isUnitLevel: boolean;
1524
+ } = defaultNetworkSiteTypes[index]!;
1525
+
1526
+ if (existingNames.has(defaultNetworkSiteType.name)) {
1527
+ continue;
1528
+ }
1529
+
1530
+ const networkSiteType: NetworkSiteType = new NetworkSiteType();
1531
+ networkSiteType.name = defaultNetworkSiteType.name;
1532
+ networkSiteType.description = defaultNetworkSiteType.description;
1533
+ networkSiteType.isUnitLevel = defaultNetworkSiteType.isUnitLevel;
1534
+ networkSiteType.projectId = projectId;
1535
+ networkSiteType.order = index + 1;
1536
+
1537
+ await NetworkSiteTypeService.create({
1538
+ data: networkSiteType,
1539
+ props: {
1540
+ isRoot: true,
1541
+ },
1542
+ });
1543
+ }
1544
+
1545
+ return createdItem;
1546
+ }
1547
+
1428
1548
  private async addDefaultProjectTeams(createdItem: Model): Promise<Model> {
1429
1549
  // add a team member.
1430
1550
 
@@ -0,0 +1,457 @@
1
+ import Alert from "../../Models/DatabaseModels/Alert";
2
+ import AlertStateTimeline from "../../Models/DatabaseModels/AlertStateTimeline";
3
+ import Model from "../../Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule";
4
+ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
5
+ import BadDataException from "../../Types/Exception/BadDataException";
6
+ import ObjectID from "../../Types/ObjectID";
7
+ import CreateBy from "../Types/Database/CreateBy";
8
+ import DeleteBy from "../Types/Database/DeleteBy";
9
+ import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
10
+ import UpdateBy from "../Types/Database/UpdateBy";
11
+ import logger, { LogAttributes } from "../Utils/Logger";
12
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
13
+ import AlertService from "./AlertService";
14
+ import AlertStateTimelineService from "./AlertStateTimelineService";
15
+ import DatabaseService from "./DatabaseService";
16
+
17
+ const THRESHOLD_ERROR_MESSAGE: string =
18
+ "Burn rate threshold must be greater than 0.";
19
+ const WINDOWS_REQUIRED_ERROR_MESSAGE: string =
20
+ "Long window and short window are required for a burn rate rule.";
21
+ const WINDOWS_NOT_NUMERIC_ERROR_MESSAGE: string =
22
+ "Long window and short window must be a number of minutes.";
23
+
24
+ export class Service extends DatabaseService<Model> {
25
+ public constructor() {
26
+ super(Model);
27
+ }
28
+
29
+ /*
30
+ * Deterministic fingerprint carried on Alerts created by a burn rate rule.
31
+ * The evaluation worker sets this as `seriesFingerprint` when it fires an
32
+ * alert, and lifecycle hooks use it to find (and resolve) those alerts when
33
+ * the rule or its SLO goes away.
34
+ */
35
+ public getBurnRateAlertFingerprint(data: {
36
+ serviceLevelObjectiveId: ObjectID;
37
+ burnRateRuleId: ObjectID;
38
+ }): string {
39
+ return `slo:${data.serviceLevelObjectiveId.toString()}:burn-rule:${data.burnRateRuleId.toString()}`;
40
+ }
41
+
42
+ @CaptureSpan()
43
+ protected override async onBeforeCreate(
44
+ createBy: CreateBy<Model>,
45
+ ): Promise<OnCreate<Model>> {
46
+ /*
47
+ * Every numeric column can arrive as a string: the dashboard's number
48
+ * fields hand Formik `e.target.value`, ModelForm copies it verbatim and
49
+ * BaseModel.fromJSON does not coerce Number/Decimal columns. Comparing
50
+ * those strings is lexicographic ("1440" <= "60" is true), so coerce
51
+ * first, then validate, then write the number back onto the payload so
52
+ * Postgres never sees a string either.
53
+ */
54
+ createBy.data.burnRateThreshold = this.validateBurnRateThreshold(
55
+ createBy.data.burnRateThreshold,
56
+ );
57
+
58
+ if (
59
+ createBy.data.longWindowInMinutes === undefined ||
60
+ createBy.data.longWindowInMinutes === null ||
61
+ createBy.data.shortWindowInMinutes === undefined ||
62
+ createBy.data.shortWindowInMinutes === null
63
+ ) {
64
+ throw new BadDataException(WINDOWS_REQUIRED_ERROR_MESSAGE);
65
+ }
66
+
67
+ const windows: {
68
+ longWindowInMinutes: number;
69
+ shortWindowInMinutes: number;
70
+ } = this.validateWindows({
71
+ longWindowInMinutes: createBy.data.longWindowInMinutes,
72
+ shortWindowInMinutes: createBy.data.shortWindowInMinutes,
73
+ });
74
+
75
+ createBy.data.longWindowInMinutes = windows.longWindowInMinutes;
76
+ createBy.data.shortWindowInMinutes = windows.shortWindowInMinutes;
77
+
78
+ if (
79
+ createBy.data.minimumSampleCount !== undefined &&
80
+ createBy.data.minimumSampleCount !== null
81
+ ) {
82
+ createBy.data.minimumSampleCount = this.validateMinimumSampleCount(
83
+ createBy.data.minimumSampleCount,
84
+ );
85
+ }
86
+
87
+ if (
88
+ createBy.data.refireSuppressionMinutes !== undefined &&
89
+ createBy.data.refireSuppressionMinutes !== null
90
+ ) {
91
+ createBy.data.refireSuppressionMinutes =
92
+ this.validateRefireSuppressionMinutes(
93
+ createBy.data.refireSuppressionMinutes,
94
+ );
95
+ }
96
+
97
+ return {
98
+ createBy,
99
+ carryForward: null,
100
+ };
101
+ }
102
+
103
+ @CaptureSpan()
104
+ protected override async onBeforeUpdate(
105
+ updateBy: UpdateBy<Model>,
106
+ ): Promise<OnUpdate<Model>> {
107
+ // Same string-arrival path as onBeforeCreate: coerce, validate, write back.
108
+ const newThreshold: unknown = updateBy.data.burnRateThreshold as unknown;
109
+
110
+ if (newThreshold !== undefined && newThreshold !== null) {
111
+ updateBy.data.burnRateThreshold =
112
+ this.validateBurnRateThreshold(newThreshold);
113
+ }
114
+
115
+ if (
116
+ updateBy.data.minimumSampleCount !== undefined &&
117
+ updateBy.data.minimumSampleCount !== null
118
+ ) {
119
+ updateBy.data.minimumSampleCount = this.validateMinimumSampleCount(
120
+ updateBy.data.minimumSampleCount as unknown,
121
+ );
122
+ }
123
+
124
+ if (
125
+ updateBy.data.refireSuppressionMinutes !== undefined &&
126
+ updateBy.data.refireSuppressionMinutes !== null
127
+ ) {
128
+ updateBy.data.refireSuppressionMinutes =
129
+ this.validateRefireSuppressionMinutes(
130
+ updateBy.data.refireSuppressionMinutes as unknown,
131
+ );
132
+ }
133
+
134
+ const newLongWindow: unknown = updateBy.data.longWindowInMinutes as unknown;
135
+ const newShortWindow: unknown = updateBy.data
136
+ .shortWindowInMinutes as unknown;
137
+
138
+ const isLongWindowUpdated: boolean =
139
+ newLongWindow !== undefined && newLongWindow !== null;
140
+ const isShortWindowUpdated: boolean =
141
+ newShortWindow !== undefined && newShortWindow !== null;
142
+
143
+ if (isLongWindowUpdated || isShortWindowUpdated) {
144
+ if (isLongWindowUpdated && isShortWindowUpdated) {
145
+ const windows: {
146
+ longWindowInMinutes: number;
147
+ shortWindowInMinutes: number;
148
+ } = this.validateWindows({
149
+ longWindowInMinutes: newLongWindow,
150
+ shortWindowInMinutes: newShortWindow,
151
+ });
152
+
153
+ updateBy.data.longWindowInMinutes = windows.longWindowInMinutes;
154
+ updateBy.data.shortWindowInMinutes = windows.shortWindowInMinutes;
155
+ } else {
156
+ /*
157
+ * Only one of the two windows is being updated. Coerce it up front so
158
+ * a non-numeric value is rejected even when the query matches no rows,
159
+ * then load the affected rules so the updated value can be validated
160
+ * against the value that will remain on each row.
161
+ */
162
+ const normalizedNewWindow: number = this.normalizeNumericInput(
163
+ isLongWindowUpdated ? newLongWindow : newShortWindow,
164
+ );
165
+
166
+ if (!Number.isFinite(normalizedNewWindow)) {
167
+ throw new BadDataException(WINDOWS_NOT_NUMERIC_ERROR_MESSAGE);
168
+ }
169
+
170
+ const rulesToUpdate: Array<Model> = await this.findBy({
171
+ query: updateBy.query,
172
+ select: {
173
+ _id: true,
174
+ longWindowInMinutes: true,
175
+ shortWindowInMinutes: true,
176
+ },
177
+ limit: LIMIT_PER_PROJECT,
178
+ skip: 0,
179
+ props: {
180
+ isRoot: true,
181
+ },
182
+ });
183
+
184
+ for (const rule of rulesToUpdate) {
185
+ /*
186
+ * The persisted sibling is coerced too — rows written before numeric
187
+ * coercion existed can still hold a string in a Decimal/Number
188
+ * column, and validateWindows must not compare against it as text.
189
+ */
190
+ this.validateWindows({
191
+ longWindowInMinutes: isLongWindowUpdated
192
+ ? normalizedNewWindow
193
+ : rule.longWindowInMinutes,
194
+ shortWindowInMinutes: isShortWindowUpdated
195
+ ? normalizedNewWindow
196
+ : rule.shortWindowInMinutes,
197
+ });
198
+ }
199
+
200
+ if (isLongWindowUpdated) {
201
+ updateBy.data.longWindowInMinutes = normalizedNewWindow;
202
+ } else {
203
+ updateBy.data.shortWindowInMinutes = normalizedNewWindow;
204
+ }
205
+ }
206
+ }
207
+
208
+ return {
209
+ updateBy,
210
+ carryForward: null,
211
+ };
212
+ }
213
+
214
+ @CaptureSpan()
215
+ protected override async onBeforeDelete(
216
+ deleteBy: DeleteBy<Model>,
217
+ ): Promise<OnDelete<Model>> {
218
+ /*
219
+ * Resolve any open alert fired by the rules being deleted — otherwise the
220
+ * alert (and its on-call escalations) stays open forever because the
221
+ * evaluation worker only resolves alerts for rules that still exist.
222
+ */
223
+ const itemsToDelete: Array<Model> = await this.findBy({
224
+ query: deleteBy.query,
225
+ limit: deleteBy.limit,
226
+ skip: deleteBy.skip,
227
+ select: {
228
+ _id: true,
229
+ projectId: true,
230
+ serviceLevelObjectiveId: true,
231
+ },
232
+ props: {
233
+ isRoot: true,
234
+ },
235
+ });
236
+
237
+ for (const item of itemsToDelete) {
238
+ if (!item.id || !item.projectId || !item.serviceLevelObjectiveId) {
239
+ continue;
240
+ }
241
+
242
+ try {
243
+ await this.resolveOpenAlertsForRule({
244
+ serviceLevelObjectiveId: item.serviceLevelObjectiveId,
245
+ burnRateRuleId: item.id,
246
+ projectId: item.projectId,
247
+ rootCause:
248
+ "Alert auto-resolved because the SLO burn rate rule that created it was deleted.",
249
+ });
250
+ } catch (err) {
251
+ logger.error(
252
+ `Error resolving open alerts for SLO burn rate rule ${item.id?.toString()} before delete: ${err}`,
253
+ { projectId: item.projectId?.toString() } as LogAttributes,
254
+ );
255
+ }
256
+ }
257
+
258
+ return {
259
+ deleteBy,
260
+ carryForward: {
261
+ itemsToDelete: itemsToDelete,
262
+ },
263
+ };
264
+ }
265
+
266
+ /*
267
+ * Resolve all open Alerts carrying this rule's fingerprint by appending a
268
+ * resolved AlertStateTimeline row. Mirrors
269
+ * MonitorAlert.resolveOpenAlert mechanics, including tolerating the benign
270
+ * same-state concurrency race.
271
+ */
272
+ @CaptureSpan()
273
+ public async resolveOpenAlertsForRule(data: {
274
+ serviceLevelObjectiveId: ObjectID;
275
+ burnRateRuleId: ObjectID;
276
+ projectId: ObjectID;
277
+ rootCause?: string | undefined;
278
+ }): Promise<void> {
279
+ const fingerprint: string = this.getBurnRateAlertFingerprint({
280
+ serviceLevelObjectiveId: data.serviceLevelObjectiveId,
281
+ burnRateRuleId: data.burnRateRuleId,
282
+ });
283
+
284
+ const openAlerts: Array<Alert> = await AlertService.findBy({
285
+ query: {
286
+ projectId: data.projectId,
287
+ seriesFingerprint: fingerprint,
288
+ currentAlertState: {
289
+ isResolvedState: false,
290
+ },
291
+ },
292
+ select: {
293
+ _id: true,
294
+ projectId: true,
295
+ },
296
+ skip: 0,
297
+ limit: LIMIT_PER_PROJECT,
298
+ props: {
299
+ isRoot: true,
300
+ },
301
+ });
302
+
303
+ if (openAlerts.length === 0) {
304
+ return;
305
+ }
306
+
307
+ const resolvedStateId: ObjectID =
308
+ await AlertStateTimelineService.getResolvedStateIdForProject(
309
+ data.projectId,
310
+ );
311
+
312
+ for (const openAlert of openAlerts) {
313
+ try {
314
+ const alertStateTimeline: AlertStateTimeline = new AlertStateTimeline();
315
+ alertStateTimeline.alertId = openAlert.id!;
316
+ alertStateTimeline.alertStateId = resolvedStateId;
317
+ alertStateTimeline.projectId = openAlert.projectId!;
318
+ alertStateTimeline.rootCause =
319
+ data.rootCause ||
320
+ "Alert auto-resolved because the SLO burn rate rule that created it is no longer active.";
321
+
322
+ try {
323
+ await AlertStateTimelineService.create({
324
+ data: alertStateTimeline,
325
+ props: {
326
+ isRoot: true,
327
+ },
328
+ });
329
+ } catch (err) {
330
+ /*
331
+ * Idempotent concurrency race: the evaluation worker and a
332
+ * lifecycle hook can both decide to resolve the same open alert
333
+ * near-simultaneously. The loser's onBeforeCreate dedupe throws
334
+ * this exact BadDataException. Treat as a no-op at debug level.
335
+ * Mirrors MonitorAlert.resolveOpenAlert.
336
+ */
337
+ if (
338
+ err instanceof BadDataException &&
339
+ err.message === "Alert state cannot be same as previous state."
340
+ ) {
341
+ logger.debug(
342
+ `${openAlert.id?.toString()} - Alert already in resolved state; skipping duplicate state timeline (concurrent race).`,
343
+ );
344
+ } else {
345
+ throw err;
346
+ }
347
+ }
348
+ } catch (err) {
349
+ logger.error(
350
+ `Error resolving open alert ${openAlert.id?.toString()} for SLO burn rate rule ${data.burnRateRuleId?.toString()}: ${err}`,
351
+ { projectId: data.projectId?.toString() } as LogAttributes,
352
+ );
353
+ }
354
+ }
355
+ }
356
+
357
+ /*
358
+ * Coerce an API-supplied numeric column to a number. HTML number inputs hand
359
+ * Formik strings and neither ModelForm nor BaseModel.fromJSON coerces
360
+ * Number/Decimal columns, so "1440" reaches these hooks as a string — and
361
+ * `"1440" <= "60"` is a lexicographic comparison that is true. Anything that
362
+ * is not a finite numeric string or number becomes NaN, which every caller
363
+ * below rejects. Mirrors GlobalConfigService.normalizePercent.
364
+ */
365
+ private normalizeNumericInput(value: unknown): number {
366
+ if (typeof value === "string") {
367
+ const trimmed: string = value.trim();
368
+ return trimmed === "" ? Number.NaN : Number(trimmed);
369
+ }
370
+
371
+ if (typeof value === "number") {
372
+ return value;
373
+ }
374
+
375
+ return Number.NaN;
376
+ }
377
+
378
+ private validateBurnRateThreshold(value: unknown): number {
379
+ const burnRateThreshold: number = this.normalizeNumericInput(value);
380
+
381
+ if (!Number.isFinite(burnRateThreshold) || burnRateThreshold <= 0) {
382
+ throw new BadDataException(THRESHOLD_ERROR_MESSAGE);
383
+ }
384
+
385
+ return burnRateThreshold;
386
+ }
387
+
388
+ private validateMinimumSampleCount(value: unknown): number {
389
+ const minimumSampleCount: number = this.normalizeNumericInput(value);
390
+
391
+ if (!Number.isFinite(minimumSampleCount) || minimumSampleCount < 0) {
392
+ throw new BadDataException(
393
+ "Minimum sample count must be a number greater than or equal to 0.",
394
+ );
395
+ }
396
+
397
+ return minimumSampleCount;
398
+ }
399
+
400
+ private validateRefireSuppressionMinutes(value: unknown): number {
401
+ const refireSuppressionMinutes: number = this.normalizeNumericInput(value);
402
+
403
+ if (
404
+ !Number.isFinite(refireSuppressionMinutes) ||
405
+ refireSuppressionMinutes < 0
406
+ ) {
407
+ throw new BadDataException(
408
+ "Re-fire suppression must be a number of minutes greater than or equal to 0.",
409
+ );
410
+ }
411
+
412
+ return refireSuppressionMinutes;
413
+ }
414
+
415
+ /*
416
+ * Coerces both windows, then enforces the multi-window invariant numerically.
417
+ * Returns the coerced pair so callers can write numbers back onto the
418
+ * create/update payload.
419
+ */
420
+ private validateWindows(data: {
421
+ longWindowInMinutes: unknown;
422
+ shortWindowInMinutes: unknown;
423
+ }): { longWindowInMinutes: number; shortWindowInMinutes: number } {
424
+ const longWindowInMinutes: number = this.normalizeNumericInput(
425
+ data.longWindowInMinutes,
426
+ );
427
+ const shortWindowInMinutes: number = this.normalizeNumericInput(
428
+ data.shortWindowInMinutes,
429
+ );
430
+
431
+ if (
432
+ !Number.isFinite(longWindowInMinutes) ||
433
+ !Number.isFinite(shortWindowInMinutes)
434
+ ) {
435
+ throw new BadDataException(WINDOWS_NOT_NUMERIC_ERROR_MESSAGE);
436
+ }
437
+
438
+ if (shortWindowInMinutes <= 0) {
439
+ throw new BadDataException(
440
+ "Short window must be greater than 0 minutes.",
441
+ );
442
+ }
443
+
444
+ if (longWindowInMinutes <= shortWindowInMinutes) {
445
+ throw new BadDataException(
446
+ "Long window must be greater than the short window.",
447
+ );
448
+ }
449
+
450
+ return {
451
+ longWindowInMinutes: longWindowInMinutes,
452
+ shortWindowInMinutes: shortWindowInMinutes,
453
+ };
454
+ }
455
+ }
456
+
457
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerUser";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();