@oneuptime/common 11.6.1 → 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 (397) hide show
  1. package/Models/AnalyticsModels/Index.ts +4 -0
  2. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
  3. package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
  4. package/Models/AnalyticsModels/SloHistory.ts +240 -0
  5. package/Models/DatabaseModels/Index.ts +20 -0
  6. package/Models/DatabaseModels/NetworkDevice.ts +453 -6
  7. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
  8. package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
  9. package/Models/DatabaseModels/NetworkSite.ts +1155 -0
  10. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
  11. package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
  12. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
  13. package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
  14. package/Models/DatabaseModels/ServiceLevelObjective.ts +1106 -0
  15. package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
  16. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
  17. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  24. package/Server/Services/AnalyticsDatabaseService.ts +25 -9
  25. package/Server/Services/Index.ts +24 -0
  26. package/Server/Services/KubernetesCostAllocationService.ts +14 -0
  27. package/Server/Services/MetricService.ts +21 -2
  28. package/Server/Services/MonitorService.ts +22 -0
  29. package/Server/Services/NetworkDeviceService.ts +438 -2
  30. package/Server/Services/NetworkEndpointService.ts +414 -0
  31. package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
  32. package/Server/Services/NetworkSiteLinkService.ts +10 -0
  33. package/Server/Services/NetworkSiteService.ts +1254 -0
  34. package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
  35. package/Server/Services/NetworkSiteTypeService.ts +10 -0
  36. package/Server/Services/ProjectService.ts +122 -2
  37. package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
  38. package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
  39. package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
  40. package/Server/Services/ServiceLevelObjectiveService.ts +677 -0
  41. package/Server/Services/SloHistoryService.ts +101 -0
  42. package/Server/Services/UserNotificationSettingService.ts +37 -0
  43. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
  44. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
  45. package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
  46. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +87 -48
  47. package/Server/Utils/Memory.ts +9 -1
  48. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
  49. package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  50. package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
  51. package/Server/Utils/Monitor/MonitorResource.ts +4 -30
  52. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
  53. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
  54. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
  55. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
  56. package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
  57. package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
  58. package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
  59. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
  60. package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
  61. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
  62. package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
  63. package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
  64. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
  65. package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
  66. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
  67. package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
  68. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
  69. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
  70. package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
  71. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +404 -0
  72. package/Tests/Server/Utils/Encryption.test.ts +70 -0
  73. package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
  74. package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
  75. package/Tests/Server/Utils/LocalFile.test.ts +258 -0
  76. package/Tests/Server/Utils/Memory.test.ts +213 -0
  77. package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
  78. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
  79. package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
  80. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
  81. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
  82. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
  83. package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
  84. package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
  85. package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
  86. package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
  87. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
  88. package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
  89. package/Tests/Server/Utils/Stream.test.ts +87 -0
  90. package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
  91. package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
  92. package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
  93. package/Tests/Types/Email.test.ts +198 -0
  94. package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
  95. package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
  96. package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
  97. package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
  98. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
  99. package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
  100. package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
  101. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
  102. package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
  103. package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
  104. package/Tests/Types/WebsiteRequest.test.ts +230 -0
  105. package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
  106. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
  107. package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
  108. package/Tests/UI/Utils/LogExport.test.ts +159 -0
  109. package/Tests/UI/Utils/Navigation.test.ts +183 -0
  110. package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
  111. package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
  112. package/Tests/Utils/Base64.test.ts +51 -0
  113. package/Tests/Utils/Boolean.test.ts +76 -0
  114. package/Tests/Utils/Crypto.test.ts +48 -0
  115. package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
  116. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
  117. package/Tests/Utils/Enum.test.ts +54 -0
  118. package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
  119. package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
  120. package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
  121. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
  122. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
  123. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
  124. package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
  125. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
  126. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
  127. package/Tests/Utils/ObjectUtil.test.ts +30 -0
  128. package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
  129. package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
  130. package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
  131. package/Tests/Utils/TechStack.test.ts +50 -0
  132. package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
  133. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
  134. package/Types/BaseDatabase/EqualTo.ts +9 -1
  135. package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
  136. package/Types/BaseDatabase/NotEqual.ts +9 -1
  137. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  138. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  139. package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
  140. package/Types/Dashboard/DashboardTemplates.ts +214 -0
  141. package/Types/Email/EmailTemplateType.ts +2 -0
  142. package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
  143. package/Types/Monitor/CriteriaFilter.ts +9 -0
  144. package/Types/Monitor/MonitorStep.ts +5 -8
  145. package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
  146. package/Types/Monitor/MonitorType.ts +15 -5
  147. package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
  148. package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
  149. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
  150. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
  151. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
  152. package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
  153. package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
  154. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  155. package/Types/Permission.ts +449 -0
  156. package/Types/ServiceLevelObjective/SliType.ts +6 -0
  157. package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
  158. package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
  159. package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
  160. package/Types/Telemetry/ServiceType.ts +1 -0
  161. package/UI/Components/Filters/EntityFilter.tsx +16 -0
  162. package/UI/Components/Filters/FilterViewer.tsx +22 -5
  163. package/UI/Components/List/List.tsx +8 -0
  164. package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
  165. package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
  166. package/UI/Components/Navbar/NavBar.tsx +16 -2
  167. package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
  168. package/UI/Utils/Navigation.ts +10 -0
  169. package/UI/Utils/TableFilterUrlState.ts +204 -17
  170. package/UI/Utils/TableViewUrlState.ts +165 -0
  171. package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
  172. package/Utils/Dashboard/Components/Index.ts +7 -0
  173. package/Utils/IpCanonicalUtil.ts +134 -0
  174. package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
  175. package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
  176. package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
  177. package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
  178. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
  179. package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
  180. package/Utils/Slo/SloStatusColor.ts +54 -0
  181. package/Utils/Slo/SloUtil.ts +637 -0
  182. package/Utils/Slo/SloWidgetFormat.ts +383 -0
  183. package/build/dist/Models/AnalyticsModels/Index.js +4 -0
  184. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  185. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
  186. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
  187. package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
  188. package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
  189. package/build/dist/Models/AnalyticsModels/SloHistory.js +215 -0
  190. package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
  191. package/build/dist/Models/DatabaseModels/Index.js +20 -0
  192. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  193. package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
  194. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  195. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
  196. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  197. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
  198. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
  199. package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
  200. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
  201. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
  202. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
  203. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
  204. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
  205. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
  206. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
  207. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
  208. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
  209. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1124 -0
  210. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
  211. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
  212. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
  213. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
  214. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
  215. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
  216. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
  217. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
  218. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
  219. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
  220. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
  221. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
  222. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
  223. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
  224. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
  225. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
  226. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
  227. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  229. package/build/dist/Server/Services/AnalyticsDatabaseService.js +23 -6
  230. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  231. package/build/dist/Server/Services/Index.js +24 -0
  232. package/build/dist/Server/Services/Index.js.map +1 -1
  233. package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
  234. package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
  235. package/build/dist/Server/Services/MetricService.js +21 -3
  236. package/build/dist/Server/Services/MetricService.js.map +1 -1
  237. package/build/dist/Server/Services/MonitorService.js +19 -0
  238. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  239. package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
  240. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  241. package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
  242. package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
  243. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
  244. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
  245. package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
  246. package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
  247. package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
  248. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
  249. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
  250. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
  251. package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
  252. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
  253. package/build/dist/Server/Services/ProjectService.js +98 -2
  254. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  255. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
  256. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
  257. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
  258. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
  259. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
  260. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
  261. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +582 -0
  262. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
  263. package/build/dist/Server/Services/SloHistoryService.js +77 -0
  264. package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
  265. package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
  266. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  267. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
  268. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  269. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
  270. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  271. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
  272. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  273. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +76 -48
  274. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  275. package/build/dist/Server/Utils/Memory.js +9 -1
  276. package/build/dist/Server/Utils/Memory.js.map +1 -1
  277. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
  278. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  279. package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  280. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
  281. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
  282. package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
  283. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  284. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
  285. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  286. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
  287. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
  288. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
  289. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
  290. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
  291. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  292. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
  293. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
  294. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
  295. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
  296. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
  297. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
  298. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
  299. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  300. package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
  301. package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
  302. package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
  303. package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
  304. package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
  305. package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
  306. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  307. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  308. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  309. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  310. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
  311. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
  312. package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
  313. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  314. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  315. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  316. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
  317. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
  318. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  319. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  320. package/build/dist/Types/Monitor/MonitorStep.js +5 -5
  321. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  322. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
  323. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
  324. package/build/dist/Types/Monitor/MonitorType.js +15 -5
  325. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  326. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
  327. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
  328. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
  329. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
  330. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
  331. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  332. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
  333. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
  334. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
  335. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
  336. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  337. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  338. package/build/dist/Types/Permission.js +409 -0
  339. package/build/dist/Types/Permission.js.map +1 -1
  340. package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
  341. package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
  342. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
  343. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
  344. package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
  345. package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
  346. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
  347. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
  348. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  349. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  350. package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
  351. package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
  352. package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
  353. package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
  354. package/build/dist/UI/Components/List/List.js +1 -1
  355. package/build/dist/UI/Components/List/List.js.map +1 -1
  356. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
  357. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  358. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
  359. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
  360. package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
  361. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  362. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
  363. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  364. package/build/dist/UI/Utils/Navigation.js +9 -0
  365. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  366. package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
  367. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  368. package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
  369. package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
  370. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
  371. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
  372. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  373. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  374. package/build/dist/Utils/IpCanonicalUtil.js +110 -0
  375. package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
  376. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
  377. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
  378. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
  379. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  380. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
  381. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
  382. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
  383. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
  384. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
  385. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
  386. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
  387. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
  388. package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
  389. package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
  390. package/build/dist/Utils/Slo/SloUtil.js +393 -0
  391. package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
  392. package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
  393. package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
  394. package/package.json +2 -2
  395. package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
  396. package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
  397. package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
@@ -0,0 +1,600 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
2
+ import NetworkDeviceWalkUtil from "../../../../Server/Utils/Monitor/NetworkDeviceWalkUtil";
3
+ import MonitorResourceUtil from "../../../../Server/Utils/Monitor/MonitorResource";
4
+ import NetworkDeviceMetricUtil from "../../../../Server/Utils/Monitor/NetworkDeviceMetricUtil";
5
+ import NetworkInventoryUtil from "../../../../Server/Utils/Monitor/NetworkInventoryUtil";
6
+ import SnmpInterfaceRateUtil from "../../../../Server/Utils/Monitor/SnmpInterfaceRateUtil";
7
+ import MonitorService from "../../../../Server/Services/MonitorService";
8
+ import NetworkDeviceService from "../../../../Server/Services/NetworkDeviceService";
9
+ import Monitor from "../../../../Models/DatabaseModels/Monitor";
10
+ import NetworkDevice from "../../../../Models/DatabaseModels/NetworkDevice";
11
+ import MonitorStep from "../../../../Types/Monitor/MonitorStep";
12
+ import MonitorSteps from "../../../../Types/Monitor/MonitorSteps";
13
+ import MonitorType from "../../../../Types/Monitor/MonitorType";
14
+ import SnmpMonitorResponse from "../../../../Types/Monitor/SnmpMonitor/SnmpMonitorResponse";
15
+ import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
16
+ import { JSONObject } from "../../../../Types/JSON";
17
+ import ObjectID from "../../../../Types/ObjectID";
18
+ import OneUptimeDate from "../../../../Types/Date";
19
+
20
+ /*
21
+ * NetworkDeviceWalkUtil is the server half of device-owned polling: the
22
+ * device's assigned probe reports each SNMP walk here, and this util
23
+ * computes interface rates against the previous walk, persists the new
24
+ * delta baseline, syncs inventory, emits device-scoped metrics, and fans
25
+ * the walk out to every Network Device monitor referencing the device.
26
+ *
27
+ * These tests mock every collaborator and pin the orchestration contract:
28
+ * the probe-scoping security guard, what flows into each collaborator (and
29
+ * in what order), the lastWalkLog persistence gating, the fan-out
30
+ * filtering, the synthesized ProbeMonitorResponse shape, and the
31
+ * fault-isolation guarantees (metrics/criteria failures never break the
32
+ * pipeline).
33
+ */
34
+
35
+ const DEVICE_ID: string = "8f2c1f0e-0000-4000-8000-0000000000aa";
36
+ const OTHER_DEVICE_ID: string = "9a1b2c3d-0000-4000-8000-0000000000bb";
37
+ const PROJECT_ID: ObjectID = new ObjectID(
38
+ "22222222-2222-4222-8222-222222222222",
39
+ );
40
+ const PROBE_ID: ObjectID = new ObjectID("33333333-3333-4333-8333-333333333333");
41
+ const NOW: Date = new Date("2026-07-16T12:00:00.000Z");
42
+ const MONITORED_AT: Date = new Date("2026-07-16T11:59:58.000Z");
43
+
44
+ const PREVIOUS_WALK_LOG: JSONObject = {
45
+ snmpResponse: {
46
+ interfaces: [{ interfaceIndex: 1, inOctets: 1000, outOctets: 2000 }],
47
+ },
48
+ monitoredAt: "2026-07-16T11:55:00.000Z",
49
+ };
50
+
51
+ let deviceFindSpy: jest.SpyInstance;
52
+ let deviceUpdateSpy: jest.SpyInstance;
53
+ let monitorFindSpy: jest.SpyInstance;
54
+ let monitorResourceSpy: jest.SpyInstance;
55
+ let inventorySpy: jest.SpyInstance;
56
+ let metricsSpy: jest.SpyInstance;
57
+ let rateSpy: jest.SpyInstance;
58
+
59
+ function buildDevice(): NetworkDevice {
60
+ const device: NetworkDevice = new NetworkDevice();
61
+ device.id = new ObjectID(DEVICE_ID);
62
+ device.projectId = PROJECT_ID;
63
+ device.name = "core-sw-01";
64
+ device.lastWalkLog = PREVIOUS_WALK_LOG;
65
+ return device;
66
+ }
67
+
68
+ function mockPipeline(options?: {
69
+ device?: NetworkDevice | null | undefined;
70
+ monitors?: Array<Monitor> | undefined;
71
+ }): void {
72
+ deviceFindSpy = jest
73
+ .spyOn(NetworkDeviceService, "findOneBy")
74
+ .mockResolvedValue(
75
+ options && "device" in options ? options.device ?? null : buildDevice(),
76
+ );
77
+ deviceUpdateSpy = jest
78
+ .spyOn(NetworkDeviceService, "updateOneById")
79
+ .mockResolvedValue(undefined);
80
+ monitorFindSpy = jest
81
+ .spyOn(MonitorService, "findBy")
82
+ .mockResolvedValue(options?.monitors || []);
83
+ monitorResourceSpy = jest
84
+ .spyOn(MonitorResourceUtil, "monitorResource")
85
+ .mockResolvedValue(undefined as never);
86
+ inventorySpy = jest
87
+ .spyOn(NetworkInventoryUtil, "updateFromWalk")
88
+ .mockResolvedValue(undefined);
89
+ metricsSpy = jest
90
+ .spyOn(NetworkDeviceMetricUtil, "saveWalkMetrics")
91
+ .mockResolvedValue(undefined);
92
+ rateSpy = jest
93
+ .spyOn(SnmpInterfaceRateUtil, "attachInterfaceRates")
94
+ .mockImplementation(() => {
95
+ return undefined;
96
+ });
97
+ }
98
+
99
+ function buildSnmpResponse(
100
+ overrides?: Partial<SnmpMonitorResponse>,
101
+ ): SnmpMonitorResponse {
102
+ return {
103
+ isOnline: true,
104
+ responseTimeInMs: 42,
105
+ failureCause: "",
106
+ oidResponses: [],
107
+ isTimeout: false,
108
+ interfaces: [
109
+ {
110
+ interfaceIndex: 1,
111
+ name: "GigabitEthernet0/1",
112
+ isOperationallyUp: true,
113
+ isAdministrativelyUp: true,
114
+ inOctets: 5000,
115
+ outOctets: 7000,
116
+ },
117
+ ],
118
+ ...overrides,
119
+ };
120
+ }
121
+
122
+ function buildStep(networkDeviceId: string | undefined): MonitorStep {
123
+ const step: MonitorStep = new MonitorStep();
124
+ step.data = {
125
+ ...step.data,
126
+ networkDeviceMonitor:
127
+ networkDeviceId === undefined
128
+ ? undefined
129
+ : {
130
+ networkDeviceId: networkDeviceId,
131
+ monitorInterfaces: true,
132
+ oids: [],
133
+ },
134
+ } as MonitorStep["data"];
135
+ return step;
136
+ }
137
+
138
+ function buildMonitor(options: {
139
+ steps: Array<MonitorStep>;
140
+ disableActiveMonitoring?: boolean | undefined;
141
+ disabledByIncident?: boolean | undefined;
142
+ disabledByMaintenance?: boolean | undefined;
143
+ }): Monitor {
144
+ const monitorSteps: MonitorSteps = new MonitorSteps();
145
+ monitorSteps.data = {
146
+ monitorStepsInstanceArray: options.steps,
147
+ defaultMonitorStatusId: undefined,
148
+ };
149
+
150
+ const monitor: Monitor = new Monitor();
151
+ monitor.id = ObjectID.generate();
152
+ monitor.projectId = PROJECT_ID;
153
+ monitor.monitorSteps = monitorSteps;
154
+ monitor.disableActiveMonitoring = options.disableActiveMonitoring || false;
155
+ monitor.disableActiveMonitoringBecauseOfManualIncident =
156
+ options.disabledByIncident || false;
157
+ monitor.disableActiveMonitoringBecauseOfScheduledMaintenanceEvent =
158
+ options.disabledByMaintenance || false;
159
+ return monitor;
160
+ }
161
+
162
+ async function runWalk(snmpResponse: SnmpMonitorResponse): Promise<void> {
163
+ await NetworkDeviceWalkUtil.processWalkResult({
164
+ probeId: PROBE_ID,
165
+ networkDeviceId: new ObjectID(DEVICE_ID),
166
+ snmpResponse: snmpResponse,
167
+ monitoredAt: MONITORED_AT,
168
+ });
169
+ }
170
+
171
+ beforeEach(() => {
172
+ jest.spyOn(OneUptimeDate, "getCurrentDate").mockReturnValue(NOW);
173
+ });
174
+
175
+ afterEach(() => {
176
+ jest.restoreAllMocks();
177
+ });
178
+
179
+ describe("NetworkDeviceWalkUtil.processWalkResult — probe-scoping guard", () => {
180
+ test("the device lookup is scoped to the reporting probe", async () => {
181
+ mockPipeline();
182
+
183
+ await runWalk(buildSnmpResponse());
184
+
185
+ expect(deviceFindSpy).toHaveBeenCalledTimes(1);
186
+ const query: JSONObject = deviceFindSpy.mock.calls[0][0].query;
187
+ expect((query["_id"] as ObjectID).toString()).toBe(DEVICE_ID);
188
+ expect((query["probeId"] as ObjectID).toString()).toBe(PROBE_ID.toString());
189
+ });
190
+
191
+ /*
192
+ * The auth middleware only proves the caller is SOME valid probe; a walk
193
+ * for a device the probe is not assigned to must be dropped before any
194
+ * write, or a compromised probe could overwrite another project's
195
+ * inventory and trigger its monitors.
196
+ */
197
+ test("a walk from a probe the device is not assigned to is ignored entirely", async () => {
198
+ mockPipeline({ device: null });
199
+
200
+ await runWalk(buildSnmpResponse());
201
+
202
+ expect(rateSpy).not.toHaveBeenCalled();
203
+ expect(deviceUpdateSpy).not.toHaveBeenCalled();
204
+ expect(inventorySpy).not.toHaveBeenCalled();
205
+ expect(metricsSpy).not.toHaveBeenCalled();
206
+ expect(monitorFindSpy).not.toHaveBeenCalled();
207
+ expect(monitorResourceSpy).not.toHaveBeenCalled();
208
+ });
209
+ });
210
+
211
+ describe("NetworkDeviceWalkUtil.processWalkResult — happy path", () => {
212
+ test("rates are computed against the device's stored lastWalkLog, before the new baseline is persisted", async () => {
213
+ mockPipeline();
214
+ const snmpResponse: SnmpMonitorResponse = buildSnmpResponse();
215
+
216
+ await runWalk(snmpResponse);
217
+
218
+ expect(rateSpy).toHaveBeenCalledTimes(1);
219
+ // Rates work on the very object the rest of the pipeline consumes.
220
+ expect(rateSpy.mock.calls[0][0].snmpResponse).toBe(snmpResponse);
221
+ expect(rateSpy.mock.calls[0][0].previousWalkLog).toBe(PREVIOUS_WALK_LOG);
222
+
223
+ /*
224
+ * Persisting first would make the delta baseline the walk itself —
225
+ * every rate would compute to zero.
226
+ */
227
+ expect(rateSpy.mock.invocationCallOrder[0]).toBeLessThan(
228
+ deviceUpdateSpy.mock.invocationCallOrder[0] as number,
229
+ );
230
+ });
231
+
232
+ test("a walk with interfaces persists itself as the next delta baseline", async () => {
233
+ mockPipeline();
234
+ const snmpResponse: SnmpMonitorResponse = buildSnmpResponse();
235
+
236
+ await runWalk(snmpResponse);
237
+
238
+ expect(deviceUpdateSpy).toHaveBeenCalledTimes(1);
239
+ const updateArgs: JSONObject = deviceUpdateSpy.mock.calls[0][0];
240
+ expect((updateArgs["id"] as ObjectID).toString()).toBe(DEVICE_ID);
241
+
242
+ const lastWalkLog: JSONObject = (updateArgs["data"] as JSONObject)[
243
+ "lastWalkLog"
244
+ ] as JSONObject;
245
+ // A plain-JSON snapshot of the walk, not the live object.
246
+ expect(lastWalkLog["snmpResponse"]).toEqual(
247
+ JSON.parse(JSON.stringify(snmpResponse)),
248
+ );
249
+ expect(lastWalkLog["snmpResponse"]).not.toBe(snmpResponse);
250
+ expect(lastWalkLog["monitoredAt"]).toEqual(NOW);
251
+ });
252
+
253
+ test("inventory is synced with the device's own projectId/deviceId and the in-flight response", async () => {
254
+ mockPipeline();
255
+ const snmpResponse: SnmpMonitorResponse = buildSnmpResponse();
256
+
257
+ await runWalk(snmpResponse);
258
+
259
+ expect(inventorySpy).toHaveBeenCalledTimes(1);
260
+ const inventoryArgs: JSONObject = inventorySpy.mock.calls[0][0];
261
+ expect((inventoryArgs["projectId"] as ObjectID).toString()).toBe(
262
+ PROJECT_ID.toString(),
263
+ );
264
+ expect((inventoryArgs["deviceId"] as ObjectID).toString()).toBe(DEVICE_ID);
265
+ expect(inventoryArgs["snmpResponse"]).toBe(snmpResponse);
266
+ expect(inventoryArgs["isOnline"]).toBe(true);
267
+ });
268
+
269
+ test("device-scoped metrics are emitted with the device and probe identity", async () => {
270
+ mockPipeline();
271
+ const snmpResponse: SnmpMonitorResponse = buildSnmpResponse();
272
+
273
+ await runWalk(snmpResponse);
274
+
275
+ expect(metricsSpy).toHaveBeenCalledTimes(1);
276
+ const metricArgs: JSONObject = metricsSpy.mock.calls[0][0];
277
+ expect((metricArgs["projectId"] as ObjectID).toString()).toBe(
278
+ PROJECT_ID.toString(),
279
+ );
280
+ expect((metricArgs["networkDeviceId"] as ObjectID).toString()).toBe(
281
+ DEVICE_ID,
282
+ );
283
+ expect(metricArgs["deviceName"]).toBe("core-sw-01");
284
+ expect((metricArgs["probeId"] as ObjectID).toString()).toBe(
285
+ PROBE_ID.toString(),
286
+ );
287
+ expect(metricArgs["snmpResponse"]).toBe(snmpResponse);
288
+ expect(metricArgs["responseTimeInMs"]).toBe(42);
289
+ expect(metricArgs["isOnline"]).toBe(true);
290
+ });
291
+ });
292
+
293
+ describe("NetworkDeviceWalkUtil.processWalkResult — failed poll", () => {
294
+ /*
295
+ * Keeping the last GOOD counters across failed polls means rates resume
296
+ * with a correct (longer-window) delta instead of losing a cycle.
297
+ */
298
+ test("a poll that walked no interfaces never overwrites the stored baseline", async () => {
299
+ mockPipeline();
300
+
301
+ await runWalk(
302
+ buildSnmpResponse({
303
+ isOnline: false,
304
+ isTimeout: true,
305
+ failureCause: "Device did not respond",
306
+ interfaces: undefined,
307
+ }),
308
+ );
309
+
310
+ expect(deviceUpdateSpy).not.toHaveBeenCalled();
311
+ });
312
+
313
+ test("an empty interface array is treated the same as no interfaces", async () => {
314
+ mockPipeline();
315
+
316
+ await runWalk(buildSnmpResponse({ interfaces: [] }));
317
+
318
+ expect(deviceUpdateSpy).not.toHaveBeenCalled();
319
+ });
320
+
321
+ test("inventory and metrics still run on a failed poll (lastSeenAt gating is inventory's job)", async () => {
322
+ mockPipeline();
323
+
324
+ await runWalk(
325
+ buildSnmpResponse({
326
+ isOnline: false,
327
+ isTimeout: true,
328
+ failureCause: "Device did not respond",
329
+ interfaces: undefined,
330
+ }),
331
+ );
332
+
333
+ expect(inventorySpy).toHaveBeenCalledTimes(1);
334
+ expect(inventorySpy.mock.calls[0][0]["isOnline"]).toBe(false);
335
+ expect(metricsSpy).toHaveBeenCalledTimes(1);
336
+ expect(metricsSpy.mock.calls[0][0]["isOnline"]).toBe(false);
337
+ });
338
+ });
339
+
340
+ describe("NetworkDeviceWalkUtil.processWalkResult — fault isolation", () => {
341
+ test("a metrics failure does not break the pipeline: fan-out still happens", async () => {
342
+ const watching: Monitor = buildMonitor({ steps: [buildStep(DEVICE_ID)] });
343
+ mockPipeline({ monitors: [watching] });
344
+ metricsSpy.mockRejectedValue(new Error("clickhouse is down"));
345
+
346
+ await expect(runWalk(buildSnmpResponse())).resolves.toBeUndefined();
347
+
348
+ expect(monitorFindSpy).toHaveBeenCalledTimes(1);
349
+ expect(monitorResourceSpy).toHaveBeenCalledTimes(1);
350
+ });
351
+
352
+ test("one monitor's evaluation failure does not prevent evaluating the next", async () => {
353
+ const first: Monitor = buildMonitor({ steps: [buildStep(DEVICE_ID)] });
354
+ const second: Monitor = buildMonitor({ steps: [buildStep(DEVICE_ID)] });
355
+ mockPipeline({ monitors: [first, second] });
356
+ monitorResourceSpy.mockRejectedValueOnce(
357
+ new Error("criteria evaluation exploded"),
358
+ );
359
+
360
+ await expect(runWalk(buildSnmpResponse())).resolves.toBeUndefined();
361
+
362
+ expect(monitorResourceSpy).toHaveBeenCalledTimes(2);
363
+ expect(
364
+ (
365
+ monitorResourceSpy.mock.calls[1][0] as ProbeMonitorResponse
366
+ ).monitorId.toString(),
367
+ ).toBe(second.id!.toString());
368
+ });
369
+ });
370
+
371
+ describe("NetworkDeviceWalkUtil.processWalkResult — monitor fan-out", () => {
372
+ test("only enabled monitors' steps referencing the walked device are evaluated", async () => {
373
+ const watching: Monitor = buildMonitor({ steps: [buildStep(DEVICE_ID)] });
374
+ const disabled: Monitor = buildMonitor({
375
+ steps: [buildStep(DEVICE_ID)],
376
+ disableActiveMonitoring: true,
377
+ });
378
+ const disabledByIncident: Monitor = buildMonitor({
379
+ steps: [buildStep(DEVICE_ID)],
380
+ disabledByIncident: true,
381
+ });
382
+ const disabledByMaintenance: Monitor = buildMonitor({
383
+ steps: [buildStep(DEVICE_ID)],
384
+ disabledByMaintenance: true,
385
+ });
386
+ const watchingOtherDevice: Monitor = buildMonitor({
387
+ steps: [buildStep(OTHER_DEVICE_ID)],
388
+ });
389
+ const watchingTwice: Monitor = buildMonitor({
390
+ steps: [buildStep(DEVICE_ID), buildStep(DEVICE_ID)],
391
+ });
392
+ const watchingBoth: Monitor = buildMonitor({
393
+ steps: [buildStep(DEVICE_ID), buildStep(OTHER_DEVICE_ID)],
394
+ });
395
+
396
+ mockPipeline({
397
+ monitors: [
398
+ watching,
399
+ disabled,
400
+ disabledByIncident,
401
+ disabledByMaintenance,
402
+ watchingOtherDevice,
403
+ watchingTwice,
404
+ watchingBoth,
405
+ ],
406
+ });
407
+
408
+ await runWalk(buildSnmpResponse());
409
+
410
+ // watching(1) + watchingTwice(2) + watchingBoth's matching step(1).
411
+ expect(monitorResourceSpy).toHaveBeenCalledTimes(4);
412
+
413
+ const evaluatedMonitorIds: Array<string> =
414
+ monitorResourceSpy.mock.calls.map((call: Array<ProbeMonitorResponse>) => {
415
+ return call[0]!.monitorId.toString();
416
+ });
417
+ expect(evaluatedMonitorIds).toEqual([
418
+ watching.id!.toString(),
419
+ watchingTwice.id!.toString(),
420
+ watchingTwice.id!.toString(),
421
+ watchingBoth.id!.toString(),
422
+ ]);
423
+
424
+ // The two-step monitor is evaluated once per referencing step.
425
+ const twiceStepIds: Array<string> = monitorResourceSpy.mock.calls
426
+ .filter((call: Array<ProbeMonitorResponse>) => {
427
+ return call[0]!.monitorId.toString() === watchingTwice.id!.toString();
428
+ })
429
+ .map((call: Array<ProbeMonitorResponse>) => {
430
+ return call[0]!.monitorStepId.toString();
431
+ });
432
+ expect(twiceStepIds).toEqual(
433
+ watchingTwice.monitorSteps!.data!.monitorStepsInstanceArray.map(
434
+ (step: MonitorStep) => {
435
+ return step.id.toString();
436
+ },
437
+ ),
438
+ );
439
+
440
+ // The mixed monitor is only evaluated for the step watching THIS device.
441
+ const mixedCalls: Array<Array<ProbeMonitorResponse>> =
442
+ monitorResourceSpy.mock.calls.filter(
443
+ (call: Array<ProbeMonitorResponse>) => {
444
+ return call[0]!.monitorId.toString() === watchingBoth.id!.toString();
445
+ },
446
+ );
447
+ expect(mixedCalls).toHaveLength(1);
448
+ expect(mixedCalls[0]![0]!.monitorStepId.toString()).toBe(
449
+ watchingBoth.monitorSteps!.data!.monitorStepsInstanceArray[0]!.id.toString(),
450
+ );
451
+ });
452
+
453
+ test("the synthesized response carries the walk verbatim into the criteria pipeline", async () => {
454
+ const step: MonitorStep = buildStep(DEVICE_ID);
455
+ const monitor: Monitor = buildMonitor({ steps: [step] });
456
+ mockPipeline({ monitors: [monitor] });
457
+
458
+ const snmpResponse: SnmpMonitorResponse = buildSnmpResponse({
459
+ isOnline: false,
460
+ responseTimeInMs: 5000,
461
+ isTimeout: true,
462
+ failureCause: "SNMP timed out after 3 attempts",
463
+ });
464
+
465
+ await runWalk(snmpResponse);
466
+
467
+ expect(monitorResourceSpy).toHaveBeenCalledTimes(1);
468
+ const synthesized: ProbeMonitorResponse =
469
+ monitorResourceSpy.mock.calls[0][0];
470
+
471
+ expect(synthesized.projectId.toString()).toBe(PROJECT_ID.toString());
472
+ expect(synthesized.monitorId.toString()).toBe(monitor.id!.toString());
473
+ expect(synthesized.monitorStepId.toString()).toBe(step.id.toString());
474
+ expect(synthesized.probeId.toString()).toBe(PROBE_ID.toString());
475
+ expect(synthesized.snmpResponse).toBe(snmpResponse);
476
+ expect(synthesized.isOnline).toBe(false);
477
+ expect(synthesized.responseTimeInMs).toBe(5000);
478
+ expect(synthesized.isTimeout).toBe(true);
479
+ expect(synthesized.failureCause).toBe("SNMP timed out after 3 attempts");
480
+ expect(synthesized.monitoredAt).toEqual(MONITORED_AT);
481
+ expect(synthesized.ingestedAt).toEqual(NOW);
482
+ });
483
+
484
+ test("a walk with no failure cause synthesizes an empty string, never undefined", async () => {
485
+ mockPipeline({
486
+ monitors: [buildMonitor({ steps: [buildStep(DEVICE_ID)] })],
487
+ });
488
+
489
+ const snmpResponse: SnmpMonitorResponse = buildSnmpResponse();
490
+ delete (snmpResponse as Partial<SnmpMonitorResponse>).failureCause;
491
+
492
+ await runWalk(snmpResponse);
493
+
494
+ expect(
495
+ (monitorResourceSpy.mock.calls[0][0] as ProbeMonitorResponse)
496
+ .failureCause,
497
+ ).toBe("");
498
+ });
499
+ });
500
+
501
+ describe("NetworkDeviceWalkUtil.findMonitorsWatchingDevices", () => {
502
+ test("an empty device list short-circuits without querying", async () => {
503
+ mockPipeline();
504
+
505
+ const monitors: Array<Monitor> =
506
+ await NetworkDeviceWalkUtil.findMonitorsWatchingDevices({
507
+ projectId: PROJECT_ID,
508
+ deviceIds: [],
509
+ });
510
+
511
+ expect(monitors).toEqual([]);
512
+ expect(monitorFindSpy).not.toHaveBeenCalled();
513
+ });
514
+
515
+ test("queries the project's Network Device monitors", async () => {
516
+ mockPipeline();
517
+
518
+ await NetworkDeviceWalkUtil.findMonitorsWatchingDevices({
519
+ projectId: PROJECT_ID,
520
+ deviceIds: [DEVICE_ID],
521
+ });
522
+
523
+ expect(monitorFindSpy).toHaveBeenCalledTimes(1);
524
+ const query: JSONObject = monitorFindSpy.mock.calls[0][0].query;
525
+ expect((query["projectId"] as ObjectID).toString()).toBe(
526
+ PROJECT_ID.toString(),
527
+ );
528
+ expect(query["monitorType"]).toBe(MonitorType.NetworkDevice);
529
+ });
530
+
531
+ test("keeps only monitors with at least one step referencing a given device, tolerating malformed steps", async () => {
532
+ const watching: Monitor = buildMonitor({ steps: [buildStep(DEVICE_ID)] });
533
+ const watchingOther: Monitor = buildMonitor({
534
+ steps: [buildStep(OTHER_DEVICE_ID)],
535
+ });
536
+ const mixedSteps: Monitor = buildMonitor({
537
+ steps: [buildStep(undefined), buildStep(DEVICE_ID)],
538
+ });
539
+
540
+ // Degenerate rows must be skipped, not crash the filter.
541
+ const noSteps: Monitor = new Monitor();
542
+ noSteps.id = ObjectID.generate();
543
+ noSteps.projectId = PROJECT_ID;
544
+
545
+ const stepsWithoutData: Monitor = buildMonitor({ steps: [] });
546
+ stepsWithoutData.monitorSteps!.data = undefined;
547
+
548
+ const stepWithoutData: MonitorStep = new MonitorStep();
549
+ stepWithoutData.data = undefined;
550
+ const stepDataMissing: Monitor = buildMonitor({
551
+ steps: [stepWithoutData],
552
+ });
553
+
554
+ const noDeviceReference: Monitor = buildMonitor({
555
+ steps: [buildStep(undefined)],
556
+ });
557
+
558
+ mockPipeline({
559
+ monitors: [
560
+ watching,
561
+ watchingOther,
562
+ mixedSteps,
563
+ noSteps,
564
+ stepsWithoutData,
565
+ stepDataMissing,
566
+ noDeviceReference,
567
+ ],
568
+ });
569
+
570
+ const monitors: Array<Monitor> =
571
+ await NetworkDeviceWalkUtil.findMonitorsWatchingDevices({
572
+ projectId: PROJECT_ID,
573
+ deviceIds: [DEVICE_ID],
574
+ });
575
+
576
+ expect(
577
+ monitors.map((monitor: Monitor) => {
578
+ return monitor.id!.toString();
579
+ }),
580
+ ).toEqual([watching.id!.toString(), mixedSteps.id!.toString()]);
581
+ });
582
+
583
+ test("matches monitors referencing ANY of the given devices", async () => {
584
+ const watchingFirst: Monitor = buildMonitor({
585
+ steps: [buildStep(DEVICE_ID)],
586
+ });
587
+ const watchingSecond: Monitor = buildMonitor({
588
+ steps: [buildStep(OTHER_DEVICE_ID)],
589
+ });
590
+ mockPipeline({ monitors: [watchingFirst, watchingSecond] });
591
+
592
+ const monitors: Array<Monitor> =
593
+ await NetworkDeviceWalkUtil.findMonitorsWatchingDevices({
594
+ projectId: PROJECT_ID,
595
+ deviceIds: [DEVICE_ID, OTHER_DEVICE_ID],
596
+ });
597
+
598
+ expect(monitors).toHaveLength(2);
599
+ });
600
+ });