@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.
- package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +41 -24
- package/Models/AnalyticsModels/Index.ts +4 -0
- package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
- package/Models/AnalyticsModels/MetricBaselineHourly.ts +2 -0
- package/Models/AnalyticsModels/MetricItemAggMV1m.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByContainer.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +5 -2
- package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
- package/Models/AnalyticsModels/SloHistory.ts +240 -0
- package/Models/DatabaseModels/Index.ts +20 -0
- package/Models/DatabaseModels/NetworkDevice.ts +453 -6
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
- package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
- package/Models/DatabaseModels/NetworkSite.ts +1155 -0
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
- package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
- package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
- package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
- package/Models/DatabaseModels/ServiceLevelObjective.ts +1106 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AnalyticsDatabaseService.ts +38 -10
- package/Server/Services/Index.ts +24 -0
- package/Server/Services/KubernetesCostAllocationService.ts +14 -0
- package/Server/Services/MetricService.ts +21 -2
- package/Server/Services/MonitorService.ts +22 -0
- package/Server/Services/NetworkDeviceService.ts +438 -2
- package/Server/Services/NetworkEndpointService.ts +414 -0
- package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
- package/Server/Services/NetworkSiteLinkService.ts +10 -0
- package/Server/Services/NetworkSiteService.ts +1254 -0
- package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
- package/Server/Services/NetworkSiteTypeService.ts +10 -0
- package/Server/Services/ProjectService.ts +122 -2
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
- package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +677 -0
- package/Server/Services/SloHistoryService.ts +101 -0
- package/Server/Services/UserNotificationSettingService.ts +37 -0
- package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
- package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +128 -52
- package/Server/Utils/Memory.ts +9 -1
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
- package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
- package/Server/Utils/Monitor/MonitorResource.ts +4 -30
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
- package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
- package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
- package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
- package/Tests/Models/AnalyticsModels/AnalyticsBaseModel.test.ts +122 -0
- package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
- package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
- package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
- package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
- package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
- package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +164 -3
- package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +503 -0
- package/Tests/Server/Utils/Encryption.test.ts +70 -0
- package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
- package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
- package/Tests/Server/Utils/LocalFile.test.ts +258 -0
- package/Tests/Server/Utils/Memory.test.ts +213 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
- package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
- package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
- package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
- package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
- package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
- package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
- package/Tests/Server/Utils/Stream.test.ts +87 -0
- package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
- package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
- package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
- package/Tests/Types/Email.test.ts +198 -0
- package/Tests/Types/HashCode.test.ts +41 -0
- package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
- package/Tests/Types/Log/LogQueryParser.test.ts +186 -0
- package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
- package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
- package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
- package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
- package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
- package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
- package/Tests/Types/WebsiteRequest.test.ts +230 -0
- package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
- package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
- package/Tests/UI/Utils/LogExport.test.ts +159 -0
- package/Tests/UI/Utils/Navigation.test.ts +183 -0
- package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
- package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
- package/Tests/Utils/Base64.test.ts +51 -0
- package/Tests/Utils/Boolean.test.ts +76 -0
- package/Tests/Utils/Crypto.test.ts +48 -0
- package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
- package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +197 -0
- package/Tests/Utils/Enum.test.ts +54 -0
- package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
- package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
- package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
- package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
- package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
- package/Tests/Utils/ObjectUtil.test.ts +30 -0
- package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
- package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
- package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
- package/Tests/Utils/TechStack.test.ts +50 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
- package/Tests/Utils/ValueFormatter.test.ts +305 -0
- package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
- package/Types/AnalyticsDatabase/TableColumn.ts +23 -0
- package/Types/BaseDatabase/EqualTo.ts +9 -1
- package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
- package/Types/BaseDatabase/NotEqual.ts +9 -1
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
- package/Types/Dashboard/DashboardTemplates.ts +214 -0
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/Monitor/MonitorStep.ts +5 -8
- package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
- package/Types/Monitor/MonitorType.ts +15 -5
- package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
- package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
- package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
- package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
- package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
- package/Types/Permission.ts +449 -0
- package/Types/ServiceLevelObjective/SliType.ts +6 -0
- package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
- package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
- package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
- package/Types/Telemetry/ServiceType.ts +1 -0
- package/UI/Components/Filters/EntityFilter.tsx +16 -0
- package/UI/Components/Filters/FilterViewer.tsx +22 -5
- package/UI/Components/List/List.tsx +8 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
- package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
- package/UI/Components/Navbar/NavBar.tsx +16 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
- package/UI/Utils/Navigation.ts +10 -0
- package/UI/Utils/TableFilterUrlState.ts +204 -17
- package/UI/Utils/TableViewUrlState.ts +165 -0
- package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/IpCanonicalUtil.ts +134 -0
- package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
- package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
- package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
- package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
- package/Utils/Slo/SloStatusColor.ts +54 -0
- package/Utils/Slo/SloUtil.ts +637 -0
- package/Utils/Slo/SloWidgetFormat.ts +383 -0
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +25 -20
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/Index.js +4 -0
- package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
- package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js +2 -0
- package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/SloHistory.js +215 -0
- package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +20 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1124 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +32 -7
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +24 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
- package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
- package/build/dist/Server/Services/MetricService.js +21 -3
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +19 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
- package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
- package/build/dist/Server/Services/ProjectService.js +98 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +582 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
- package/build/dist/Server/Services/SloHistoryService.js +77 -0
- package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +105 -52
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Memory.js +9 -1
- package/build/dist/Server/Utils/Memory.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
- package/build/dist/Types/AnalyticsDatabase/TableColumn.js +7 -0
- package/build/dist/Types/AnalyticsDatabase/TableColumn.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
- package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
- package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -5
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +15 -5
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/Permission.js +409 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
- package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +1 -1
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +9 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
- package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
- package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
- package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/IpCanonicalUtil.js +110 -0
- package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
- package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
- package/build/dist/Utils/Slo/SloUtil.js +393 -0
- package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
- package/package.json +2 -2
- package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
import ArpEntry from "../../Types/Monitor/SnmpMonitor/ArpEntry";
|
|
2
|
+
import CdpNeighbor from "../../Types/Monitor/SnmpMonitor/CdpNeighbor";
|
|
3
|
+
import FdbEntry from "../../Types/Monitor/SnmpMonitor/FdbEntry";
|
|
4
|
+
import LldpNeighbor from "../../Types/Monitor/SnmpMonitor/LldpNeighbor";
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* Pure helpers that turn ONE device's ARP/FDB walk snapshot into endpoint
|
|
8
|
+
* attachments (which MAC sits on which switch port) and IP bindings (which
|
|
9
|
+
* MAC answers for which IP on a router). Everything here is deterministic
|
|
10
|
+
* and side-effect free so it can run — and be tested — anywhere; persistence
|
|
11
|
+
* lives in NetworkEndpointService, which consumes this output.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// One interface row from the walk, reduced to what attachment needs.
|
|
15
|
+
export interface EndpointWalkInterface {
|
|
16
|
+
interfaceIndex: number;
|
|
17
|
+
name?: string | undefined;
|
|
18
|
+
macAddress?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Everything one device's walk knows that endpoint discovery cares about.
|
|
22
|
+
export interface EndpointWalkSnapshot {
|
|
23
|
+
deviceId: string;
|
|
24
|
+
fdbEntries?: Array<FdbEntry> | undefined;
|
|
25
|
+
arpEntries?: Array<ArpEntry> | undefined;
|
|
26
|
+
lldpNeighbors?: Array<LldpNeighbor> | undefined;
|
|
27
|
+
cdpNeighbors?: Array<CdpNeighbor> | undefined;
|
|
28
|
+
interfaces?: Array<EndpointWalkInterface> | undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// "This MAC was learned on this access port of the walked device."
|
|
32
|
+
export interface EndpointAttachment {
|
|
33
|
+
macAddress: string;
|
|
34
|
+
attachedInterfaceIndex: number;
|
|
35
|
+
attachedPortName?: string | undefined;
|
|
36
|
+
vlanId?: number | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// "This MAC answers for this IP in the walked device's ARP table."
|
|
40
|
+
export interface EndpointIpBinding {
|
|
41
|
+
macAddress: string;
|
|
42
|
+
ipAddress: string;
|
|
43
|
+
routerInterfaceIndex: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface EndpointAttachmentResult {
|
|
47
|
+
/*
|
|
48
|
+
* Interfaces with an LLDP/CDP neighbor on them. MACs learned there are
|
|
49
|
+
* transit traffic from the rest of the network, not local endpoints.
|
|
50
|
+
*/
|
|
51
|
+
uplinkInterfaceIndexes: Array<number>;
|
|
52
|
+
// The device's own interface MACs — never endpoints.
|
|
53
|
+
selfMacs: Array<string>;
|
|
54
|
+
attachments: Array<EndpointAttachment>;
|
|
55
|
+
ipBindings: Array<EndpointIpBinding>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* What the persistence layer should do for one (existing row, new
|
|
60
|
+
* observation) pair. Kept as plain data so the precedence rules are
|
|
61
|
+
* exhaustively unit-testable without a database.
|
|
62
|
+
*/
|
|
63
|
+
export interface EndpointIncomingObservation {
|
|
64
|
+
macAddress: string;
|
|
65
|
+
// The walked device (switch and/or router) that saw this MAC.
|
|
66
|
+
deviceId: string;
|
|
67
|
+
// Present when the device's FDB learned the MAC on an access port.
|
|
68
|
+
attachment?:
|
|
69
|
+
| {
|
|
70
|
+
interfaceIndex: number;
|
|
71
|
+
portName?: string | undefined;
|
|
72
|
+
vlanId?: number | undefined;
|
|
73
|
+
}
|
|
74
|
+
| undefined;
|
|
75
|
+
// Present when the device's ARP table binds the MAC to an IP.
|
|
76
|
+
ipBinding?:
|
|
77
|
+
| {
|
|
78
|
+
ipAddress: string;
|
|
79
|
+
routerInterfaceIndex: number;
|
|
80
|
+
}
|
|
81
|
+
| undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
* The stored row, as far as the precedence rules care. Everything past
|
|
86
|
+
* attachedNetworkDeviceId exists so decideUpsert can tell a genuinely
|
|
87
|
+
* new observation from a re-sighting of an endpoint that has not moved
|
|
88
|
+
* since the last poll (see ENDPOINT_LAST_SEEN_REFRESH_MS).
|
|
89
|
+
*/
|
|
90
|
+
export interface EndpointExistingRowSnapshot {
|
|
91
|
+
attachedNetworkDeviceId?: string | undefined;
|
|
92
|
+
attachedInterfaceIndex?: number | undefined;
|
|
93
|
+
attachedPortName?: string | undefined;
|
|
94
|
+
vlanId?: number | undefined;
|
|
95
|
+
ipAddress?: string | undefined;
|
|
96
|
+
siteId?: string | undefined;
|
|
97
|
+
firstSeenAt?: Date | undefined;
|
|
98
|
+
lastSeenAt?: Date | undefined;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* How stale a row's lastSeenAt is allowed to get before an otherwise
|
|
103
|
+
* unchanged observation is written purely to refresh it.
|
|
104
|
+
*
|
|
105
|
+
* Freshness is load-bearing: NetworkTopologyUtil calls an endpoint
|
|
106
|
+
* "down" once lastSeenAt is older than 15 minutes. Suppressing the
|
|
107
|
+
* refresh entirely would mark every stable endpoint down, so the real
|
|
108
|
+
* bound is that stored lastSeenAt may lag reality by at most
|
|
109
|
+
* (refresh threshold + poll interval). At 5 minutes that stays inside
|
|
110
|
+
* the 15-minute window for any poll interval up to 10 minutes, and for
|
|
111
|
+
* slower polls the threshold simply stops suppressing anything (age is
|
|
112
|
+
* always past it) and the behaviour degrades back to write-every-poll —
|
|
113
|
+
* so the optimisation can never make a device look down.
|
|
114
|
+
*/
|
|
115
|
+
export const ENDPOINT_LAST_SEEN_REFRESH_MS: number = 5 * 60 * 1000;
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* Caller-supplied context for the "has anything actually changed?"
|
|
119
|
+
* check. Optional: without it decideUpsert keeps its original
|
|
120
|
+
* write-on-every-sighting behaviour.
|
|
121
|
+
*/
|
|
122
|
+
export interface EndpointUpsertContext {
|
|
123
|
+
now: Date;
|
|
124
|
+
// Site of the observing device, when the caller knows it.
|
|
125
|
+
siteId?: string | undefined;
|
|
126
|
+
lastSeenRefreshMs?: number | undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface EndpointUpsertDecision {
|
|
130
|
+
action: "create" | "update" | "none";
|
|
131
|
+
/*
|
|
132
|
+
* When true, write attachedNetworkDeviceId (the observing device),
|
|
133
|
+
* attachedInterfaceIndex, and — when defined — attachedPortName / vlanId.
|
|
134
|
+
* Undefined port/vlan never clear previously stored values.
|
|
135
|
+
*/
|
|
136
|
+
setAttachment: boolean;
|
|
137
|
+
attachedInterfaceIndex?: number | undefined;
|
|
138
|
+
attachedPortName?: string | undefined;
|
|
139
|
+
vlanId?: number | undefined;
|
|
140
|
+
setIpAddress: boolean;
|
|
141
|
+
ipAddress?: string | undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/*
|
|
145
|
+
* Multicast/broadcast MACs (group bit set in the first octet) are traffic
|
|
146
|
+
* artifacts, not endpoints — e.g. 01:00:5e:… IPv4 multicast and the
|
|
147
|
+
* ff:ff:ff:ff:ff:ff broadcast rows some ARP tables carry.
|
|
148
|
+
*/
|
|
149
|
+
const GROUP_ADDRESS_BIT: number = 0x01;
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* Hoisted out of the call site so the literal is not the object of a member
|
|
153
|
+
* expression, which `wrap-regex` and Prettier cannot agree on.
|
|
154
|
+
*/
|
|
155
|
+
const MAC_HEX_PATTERN: RegExp = /^[0-9a-f]{12}$/;
|
|
156
|
+
|
|
157
|
+
type MacCandidate = {
|
|
158
|
+
entry: FdbEntry;
|
|
159
|
+
interfaceIndex: number;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export default class EndpointAttachmentUtil {
|
|
163
|
+
/*
|
|
164
|
+
* Normalizes any common MAC spelling — AA-BB-CC-DD-EE-FF,
|
|
165
|
+
* aabb.ccdd.eeff (Cisco dot form), aa:bb:cc:dd:ee:ff, bare hex, with or
|
|
166
|
+
* without an 0x prefix — to lowercase colon form. Returns undefined for
|
|
167
|
+
* anything that isn't exactly 12 hex digits once separators are removed.
|
|
168
|
+
*/
|
|
169
|
+
public static normalizeMac(value: string | undefined): string | undefined {
|
|
170
|
+
if (!value) {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
let hex: string = value.trim().toLowerCase();
|
|
174
|
+
if (hex.startsWith("0x")) {
|
|
175
|
+
hex = hex.substring(2);
|
|
176
|
+
}
|
|
177
|
+
hex = hex.replace(/[:\-.\s]/g, "");
|
|
178
|
+
if (!MAC_HEX_PATTERN.test(hex)) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
const pairs: Array<string> = [];
|
|
182
|
+
for (let i: number = 0; i < 12; i += 2) {
|
|
183
|
+
pairs.push(hex.substring(i, i + 2));
|
|
184
|
+
}
|
|
185
|
+
return pairs.join(":");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public static computeEndpointAttachments(
|
|
189
|
+
snapshot: EndpointWalkSnapshot,
|
|
190
|
+
): EndpointAttachmentResult {
|
|
191
|
+
/*
|
|
192
|
+
* Uplinks: any interface an LLDP or CDP neighbor claims sits on. This
|
|
193
|
+
* is the same local-port linkage NetworkTopologyUtil uses to draw
|
|
194
|
+
* device-to-device edges — both protocols report the local ifIndex
|
|
195
|
+
* directly on the neighbor entry.
|
|
196
|
+
*/
|
|
197
|
+
const uplinkSet: Set<number> = new Set();
|
|
198
|
+
for (const neighbor of snapshot.lldpNeighbors || []) {
|
|
199
|
+
if (neighbor.localInterfaceIndex !== undefined) {
|
|
200
|
+
uplinkSet.add(neighbor.localInterfaceIndex);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const neighbor of snapshot.cdpNeighbors || []) {
|
|
204
|
+
if (neighbor.localInterfaceIndex !== undefined) {
|
|
205
|
+
uplinkSet.add(neighbor.localInterfaceIndex);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const selfMacSet: Set<string> = new Set();
|
|
210
|
+
const interfaceNameByIndex: Map<number, string> = new Map();
|
|
211
|
+
for (const walkInterface of snapshot.interfaces || []) {
|
|
212
|
+
const selfMac: string | undefined = EndpointAttachmentUtil.normalizeMac(
|
|
213
|
+
walkInterface.macAddress,
|
|
214
|
+
);
|
|
215
|
+
if (selfMac) {
|
|
216
|
+
selfMacSet.add(selfMac);
|
|
217
|
+
}
|
|
218
|
+
if (walkInterface.name) {
|
|
219
|
+
interfaceNameByIndex.set(
|
|
220
|
+
walkInterface.interfaceIndex,
|
|
221
|
+
walkInterface.name,
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/*
|
|
227
|
+
* FDB → attachments. An entry qualifies when:
|
|
228
|
+
* - its MAC normalizes, is unicast, and is not one of the device's own,
|
|
229
|
+
* - its status (when reported) is "learned" — "self"/"mgmt" rows are
|
|
230
|
+
* the bridge talking about itself,
|
|
231
|
+
* - its bridge port resolved to an ifIndex (without one we cannot rule
|
|
232
|
+
* out an uplink, and misattaching every transit MAC to this switch
|
|
233
|
+
* is worse than skipping the entry), and
|
|
234
|
+
* - that ifIndex is not an uplink.
|
|
235
|
+
*/
|
|
236
|
+
const candidatesByMac: Map<string, Array<MacCandidate>> = new Map();
|
|
237
|
+
for (const entry of snapshot.fdbEntries || []) {
|
|
238
|
+
const mac: string | undefined = EndpointAttachmentUtil.normalizeMac(
|
|
239
|
+
entry.macAddress,
|
|
240
|
+
);
|
|
241
|
+
if (!mac || EndpointAttachmentUtil.isGroupMac(mac)) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (selfMacSet.has(mac)) {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (
|
|
248
|
+
entry.status !== undefined &&
|
|
249
|
+
entry.status.toLowerCase() !== "learned"
|
|
250
|
+
) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (entry.interfaceIndex === undefined) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (uplinkSet.has(entry.interfaceIndex)) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const candidates: Array<MacCandidate> = candidatesByMac.get(mac) || [];
|
|
260
|
+
candidates.push({ entry, interfaceIndex: entry.interfaceIndex });
|
|
261
|
+
candidatesByMac.set(mac, candidates);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const attachments: Array<EndpointAttachment> = [];
|
|
265
|
+
for (const mac of Array.from(candidatesByMac.keys()).sort()) {
|
|
266
|
+
/*
|
|
267
|
+
* One attachment per MAC. Duplicates (Q-BRIDGE reports the same MAC
|
|
268
|
+
* per VLAN) collapse deterministically: lowest ifIndex, then lowest
|
|
269
|
+
* VLAN (undefined last), then lowest bridge port.
|
|
270
|
+
*/
|
|
271
|
+
const candidates: Array<MacCandidate> = candidatesByMac.get(mac)!;
|
|
272
|
+
candidates.sort((a: MacCandidate, b: MacCandidate) => {
|
|
273
|
+
if (a.interfaceIndex !== b.interfaceIndex) {
|
|
274
|
+
return a.interfaceIndex - b.interfaceIndex;
|
|
275
|
+
}
|
|
276
|
+
const aVlan: number = a.entry.vlanId ?? Number.MAX_SAFE_INTEGER;
|
|
277
|
+
const bVlan: number = b.entry.vlanId ?? Number.MAX_SAFE_INTEGER;
|
|
278
|
+
if (aVlan !== bVlan) {
|
|
279
|
+
return aVlan - bVlan;
|
|
280
|
+
}
|
|
281
|
+
return a.entry.bridgePort - b.entry.bridgePort;
|
|
282
|
+
});
|
|
283
|
+
const chosen: MacCandidate = candidates[0]!;
|
|
284
|
+
attachments.push({
|
|
285
|
+
macAddress: mac,
|
|
286
|
+
attachedInterfaceIndex: chosen.interfaceIndex,
|
|
287
|
+
attachedPortName: interfaceNameByIndex.get(chosen.interfaceIndex),
|
|
288
|
+
vlanId: chosen.entry.vlanId,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/*
|
|
293
|
+
* ARP → IP bindings. Self and group MACs are excluded, as are rows the
|
|
294
|
+
* device itself marked invalid. Duplicates for one MAC collapse to the
|
|
295
|
+
* lexicographically smallest IP (then lowest ifIndex) so repeated walks
|
|
296
|
+
* always report the same binding.
|
|
297
|
+
*/
|
|
298
|
+
const bindingsByMac: Map<string, Array<ArpEntry>> = new Map();
|
|
299
|
+
for (const entry of snapshot.arpEntries || []) {
|
|
300
|
+
const mac: string | undefined = EndpointAttachmentUtil.normalizeMac(
|
|
301
|
+
entry.macAddress,
|
|
302
|
+
);
|
|
303
|
+
if (!mac || EndpointAttachmentUtil.isGroupMac(mac)) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
if (selfMacSet.has(mac)) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (
|
|
310
|
+
entry.entryType !== undefined &&
|
|
311
|
+
entry.entryType.toLowerCase() === "invalid"
|
|
312
|
+
) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
if (!entry.ipAddress) {
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const rows: Array<ArpEntry> = bindingsByMac.get(mac) || [];
|
|
319
|
+
rows.push(entry);
|
|
320
|
+
bindingsByMac.set(mac, rows);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const ipBindings: Array<EndpointIpBinding> = [];
|
|
324
|
+
for (const mac of Array.from(bindingsByMac.keys()).sort()) {
|
|
325
|
+
const rows: Array<ArpEntry> = bindingsByMac.get(mac)!;
|
|
326
|
+
rows.sort((a: ArpEntry, b: ArpEntry) => {
|
|
327
|
+
if (a.ipAddress !== b.ipAddress) {
|
|
328
|
+
return a.ipAddress < b.ipAddress ? -1 : 1;
|
|
329
|
+
}
|
|
330
|
+
return a.interfaceIndex - b.interfaceIndex;
|
|
331
|
+
});
|
|
332
|
+
const chosen: ArpEntry = rows[0]!;
|
|
333
|
+
ipBindings.push({
|
|
334
|
+
macAddress: mac,
|
|
335
|
+
ipAddress: chosen.ipAddress,
|
|
336
|
+
routerInterfaceIndex: chosen.interfaceIndex,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
uplinkInterfaceIndexes: Array.from(uplinkSet).sort(
|
|
342
|
+
(a: number, b: number) => {
|
|
343
|
+
return a - b;
|
|
344
|
+
},
|
|
345
|
+
),
|
|
346
|
+
selfMacs: Array.from(selfMacSet).sort(),
|
|
347
|
+
attachments,
|
|
348
|
+
ipBindings,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/*
|
|
353
|
+
* The precedence rules for persisting one observation onto one
|
|
354
|
+
* (projectId, macAddress) row:
|
|
355
|
+
*
|
|
356
|
+
* - A switch-FDB attachment always wins: the FDB says which physical
|
|
357
|
+
* port the endpoint hangs off, which no ARP row can know.
|
|
358
|
+
* - An ARP-only observation always refreshes ipAddress, but only claims
|
|
359
|
+
* the attachment (pointing at the router's own interface) when the row
|
|
360
|
+
* has no attachment yet or is already attached to that same router —
|
|
361
|
+
* it must never steal an attachment a switch reported.
|
|
362
|
+
* - Rows are created for both kinds; every observation counts as a
|
|
363
|
+
* "touch" (the caller bumps lastSeenAt on any create/update action).
|
|
364
|
+
*
|
|
365
|
+
* When `context` is supplied, an update that would write nothing but a
|
|
366
|
+
* lastSeenAt already refreshed within lastSeenRefreshMs collapses to
|
|
367
|
+
* "none" — a stable 4096-MAC switch must not issue 4096 writes a poll
|
|
368
|
+
* just to bump a timestamp nobody reads that precisely.
|
|
369
|
+
*/
|
|
370
|
+
public static decideUpsert(
|
|
371
|
+
existing: EndpointExistingRowSnapshot | null,
|
|
372
|
+
incoming: EndpointIncomingObservation,
|
|
373
|
+
context?: EndpointUpsertContext | undefined,
|
|
374
|
+
): EndpointUpsertDecision {
|
|
375
|
+
if (!incoming.attachment && !incoming.ipBinding) {
|
|
376
|
+
return {
|
|
377
|
+
action: "none",
|
|
378
|
+
setAttachment: false,
|
|
379
|
+
setIpAddress: false,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const decision: EndpointUpsertDecision = {
|
|
384
|
+
action: existing ? "update" : "create",
|
|
385
|
+
setAttachment: false,
|
|
386
|
+
setIpAddress: false,
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
if (incoming.ipBinding) {
|
|
390
|
+
decision.setIpAddress = true;
|
|
391
|
+
decision.ipAddress = incoming.ipBinding.ipAddress;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (incoming.attachment) {
|
|
395
|
+
decision.setAttachment = true;
|
|
396
|
+
decision.attachedInterfaceIndex = incoming.attachment.interfaceIndex;
|
|
397
|
+
decision.attachedPortName = incoming.attachment.portName;
|
|
398
|
+
decision.vlanId = incoming.attachment.vlanId;
|
|
399
|
+
} else {
|
|
400
|
+
// ARP-only from here on — incoming.ipBinding is set (guard above).
|
|
401
|
+
const attachedElsewhere: boolean = Boolean(
|
|
402
|
+
existing?.attachedNetworkDeviceId &&
|
|
403
|
+
existing.attachedNetworkDeviceId !== incoming.deviceId,
|
|
404
|
+
);
|
|
405
|
+
if (!attachedElsewhere) {
|
|
406
|
+
decision.setAttachment = true;
|
|
407
|
+
decision.attachedInterfaceIndex =
|
|
408
|
+
incoming.ipBinding!.routerInterfaceIndex;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (
|
|
413
|
+
existing &&
|
|
414
|
+
context &&
|
|
415
|
+
EndpointAttachmentUtil.isUnchangedSighting(
|
|
416
|
+
existing,
|
|
417
|
+
decision,
|
|
418
|
+
incoming.deviceId,
|
|
419
|
+
context,
|
|
420
|
+
)
|
|
421
|
+
) {
|
|
422
|
+
return {
|
|
423
|
+
action: "none",
|
|
424
|
+
setAttachment: false,
|
|
425
|
+
setIpAddress: false,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return decision;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/*
|
|
433
|
+
* True when applying `decision` to `existing` would change nothing a
|
|
434
|
+
* reader can observe, and lastSeenAt is fresh enough that skipping the
|
|
435
|
+
* refresh is safe. Deliberately conservative — any doubt (a row that
|
|
436
|
+
* still needs the firstSeenAt backfill, a row whose lastSeenAt sits in
|
|
437
|
+
* the future because of clock skew, a row we have never seen a
|
|
438
|
+
* timestamp for) falls through to a real write.
|
|
439
|
+
*/
|
|
440
|
+
private static isUnchangedSighting(
|
|
441
|
+
existing: EndpointExistingRowSnapshot,
|
|
442
|
+
decision: EndpointUpsertDecision,
|
|
443
|
+
incomingDeviceId: string,
|
|
444
|
+
context: EndpointUpsertContext,
|
|
445
|
+
): boolean {
|
|
446
|
+
// Rows predating first-seen tracking still owe us a backfill.
|
|
447
|
+
if (!existing.firstSeenAt || !existing.lastSeenAt) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const refreshMs: number =
|
|
452
|
+
context.lastSeenRefreshMs ?? ENDPOINT_LAST_SEEN_REFRESH_MS;
|
|
453
|
+
const ageMs: number =
|
|
454
|
+
context.now.getTime() - new Date(existing.lastSeenAt).getTime();
|
|
455
|
+
if (ageMs < 0 || ageMs >= refreshMs) {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (
|
|
460
|
+
decision.setIpAddress &&
|
|
461
|
+
decision.ipAddress &&
|
|
462
|
+
decision.ipAddress !== existing.ipAddress
|
|
463
|
+
) {
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (decision.setAttachment) {
|
|
468
|
+
if (existing.attachedNetworkDeviceId !== incomingDeviceId) {
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
471
|
+
if (
|
|
472
|
+
decision.attachedInterfaceIndex !== undefined &&
|
|
473
|
+
decision.attachedInterfaceIndex !== existing.attachedInterfaceIndex
|
|
474
|
+
) {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
/*
|
|
478
|
+
* Undefined port/vlan never clear a stored value, so "the walk did
|
|
479
|
+
* not report one" is not a change.
|
|
480
|
+
*/
|
|
481
|
+
if (
|
|
482
|
+
decision.attachedPortName !== undefined &&
|
|
483
|
+
decision.attachedPortName !== existing.attachedPortName
|
|
484
|
+
) {
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
if (
|
|
488
|
+
decision.vlanId !== undefined &&
|
|
489
|
+
decision.vlanId !== existing.vlanId
|
|
490
|
+
) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
if (context.siteId !== undefined && context.siteId !== existing.siteId) {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
private static isGroupMac(normalizedMac: string): boolean {
|
|
502
|
+
const firstOctet: number = parseInt(normalizedMac.substring(0, 2), 16);
|
|
503
|
+
return (firstOctet & GROUP_ADDRESS_BIT) !== 0;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export const normalizeMac: (value: string | undefined) => string | undefined =
|
|
508
|
+
EndpointAttachmentUtil.normalizeMac;
|