@oneuptime/common 11.0.2 → 11.0.3

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 (344) hide show
  1. package/Models/DatabaseModels/Alert.ts +166 -0
  2. package/Models/DatabaseModels/AlertLabelRule.ts +38 -0
  3. package/Models/DatabaseModels/AlertOwnerRule.ts +38 -0
  4. package/Models/DatabaseModels/DockerSwarmCluster.ts +989 -0
  5. package/Models/DatabaseModels/DockerSwarmClusterLabelRule.ts +514 -0
  6. package/Models/DatabaseModels/DockerSwarmClusterOwnerRule.ts +596 -0
  7. package/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.ts +487 -0
  8. package/Models/DatabaseModels/DockerSwarmClusterOwnerUser.ts +486 -0
  9. package/Models/DatabaseModels/DockerSwarmResource.ts +750 -0
  10. package/Models/DatabaseModels/Incident.ts +166 -0
  11. package/Models/DatabaseModels/IncidentLabelRule.ts +38 -0
  12. package/Models/DatabaseModels/IncidentOwnerRule.ts +38 -0
  13. package/Models/DatabaseModels/IncidentTemplate.ts +56 -0
  14. package/Models/DatabaseModels/Index.ts +24 -0
  15. package/Models/DatabaseModels/PodmanHost.ts +859 -0
  16. package/Models/DatabaseModels/PodmanHostLabelRule.ts +514 -0
  17. package/Models/DatabaseModels/PodmanHostOwnerRule.ts +596 -0
  18. package/Models/DatabaseModels/PodmanHostOwnerTeam.ts +487 -0
  19. package/Models/DatabaseModels/PodmanHostOwnerUser.ts +486 -0
  20. package/Models/DatabaseModels/PodmanResource.ts +498 -0
  21. package/Models/DatabaseModels/ScheduledMaintenance.ts +110 -0
  22. package/Models/DatabaseModels/ScheduledMaintenanceLabelRule.ts +38 -0
  23. package/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.ts +38 -0
  24. package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +56 -0
  25. package/Models/DatabaseModels/TelemetryException.ts +2 -0
  26. package/Server/API/DashboardAPI.ts +89 -0
  27. package/Server/API/DockerSwarmResourceAPI.ts +137 -0
  28. package/Server/API/TelemetryAPI.ts +8 -1
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1781587937032-MigrationName.ts +3199 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  31. package/Server/Services/AlertLabelRuleEngineService.ts +29 -0
  32. package/Server/Services/AlertOwnerRuleEngineService.ts +67 -0
  33. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +214 -0
  34. package/Server/Services/DockerSwarmClusterLabelRuleService.ts +14 -0
  35. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +232 -0
  36. package/Server/Services/DockerSwarmClusterOwnerRuleService.ts +14 -0
  37. package/Server/Services/DockerSwarmClusterOwnerTeamService.ts +10 -0
  38. package/Server/Services/DockerSwarmClusterOwnerUserService.ts +10 -0
  39. package/Server/Services/DockerSwarmClusterService.ts +404 -0
  40. package/Server/Services/DockerSwarmResourceService.ts +381 -0
  41. package/Server/Services/ExceptionAggregationService.ts +1 -0
  42. package/Server/Services/IncidentLabelRuleEngineService.ts +27 -0
  43. package/Server/Services/IncidentOwnerRuleEngineService.ts +67 -0
  44. package/Server/Services/IncidentService.ts +11 -0
  45. package/Server/Services/Index.ts +14 -0
  46. package/Server/Services/LogAggregationService.ts +1 -0
  47. package/Server/Services/MetricAggregationService.ts +1 -0
  48. package/Server/Services/OpenTelemetryIngestService.ts +37 -0
  49. package/Server/Services/PodmanHostLabelRuleEngineService.ts +198 -0
  50. package/Server/Services/PodmanHostLabelRuleService.ts +14 -0
  51. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +216 -0
  52. package/Server/Services/PodmanHostOwnerRuleService.ts +14 -0
  53. package/Server/Services/PodmanHostOwnerTeamService.ts +10 -0
  54. package/Server/Services/PodmanHostOwnerUserService.ts +10 -0
  55. package/Server/Services/PodmanHostService.ts +368 -0
  56. package/Server/Services/PodmanResourceService.ts +310 -0
  57. package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +29 -0
  58. package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +67 -0
  59. package/Server/Services/TelemetryUsageBillingService.ts +18 -0
  60. package/Server/Services/TraceAggregationService.ts +1 -0
  61. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +13 -0
  62. package/Server/Utils/Monitor/MonitorAlert.ts +10 -0
  63. package/Server/Utils/Monitor/MonitorClusterContext.ts +35 -6
  64. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +306 -0
  65. package/Server/Utils/Monitor/MonitorIncident.ts +45 -0
  66. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +17 -0
  67. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +3 -0
  68. package/Server/Utils/Monitor/SeriesResourceLabels.ts +26 -0
  69. package/Server/Utils/Telemetry/ResourceFacetResolver.ts +49 -0
  70. package/Server/Utils/Telemetry/Telemetry.ts +10 -0
  71. package/Server/Utils/Telemetry/TelemetryEntity.ts +22 -0
  72. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +1 -0
  73. package/Tests/Types/DockerSwarm/DockerSwarmInventoryExtractor.test.ts +667 -0
  74. package/Tests/Types/Monitor/DockerSwarmAlertTemplates.test.ts +528 -0
  75. package/Types/Dashboard/DashboardComponentType.ts +7 -0
  76. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +2 -0
  77. package/Types/Dashboard/DashboardComponents/DashboardDockerSwarmNodeListComponent.ts +17 -0
  78. package/Types/Dashboard/DashboardComponents/DashboardDockerSwarmServiceListComponent.ts +17 -0
  79. package/Types/Dashboard/DashboardComponents/DashboardPodmanContainerListComponent.ts +16 -0
  80. package/Types/Dashboard/DashboardComponents/DashboardPodmanHostListComponent.ts +15 -0
  81. package/Types/Dashboard/DashboardComponents/DashboardPodmanImageListComponent.ts +16 -0
  82. package/Types/Dashboard/DashboardComponents/DashboardPodmanNetworkListComponent.ts +15 -0
  83. package/Types/Dashboard/DashboardComponents/DashboardPodmanVolumeListComponent.ts +15 -0
  84. package/Types/Dashboard/DashboardTemplates.ts +194 -0
  85. package/Types/DockerSwarm/DockerSwarmInventoryExtractor.ts +452 -0
  86. package/Types/Icon/IconProp.ts +1 -0
  87. package/Types/Monitor/DockerSwarmAlertTemplates.ts +461 -0
  88. package/Types/Monitor/DockerSwarmMetricCatalog.ts +139 -0
  89. package/Types/Monitor/HostAlertTemplates.ts +455 -0
  90. package/Types/Monitor/HostMetricCatalog.ts +177 -0
  91. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +21 -0
  92. package/Types/Monitor/MonitorStep.ts +99 -0
  93. package/Types/Monitor/MonitorStepDockerSwarmMonitor.ts +74 -0
  94. package/Types/Monitor/MonitorStepHostMonitor.ts +30 -0
  95. package/Types/Monitor/MonitorStepPodmanMonitor.ts +38 -0
  96. package/Types/Monitor/MonitorType.ts +42 -0
  97. package/Types/Monitor/PodmanAlertTemplates.ts +507 -0
  98. package/Types/Monitor/PodmanMetricCatalog.ts +226 -0
  99. package/Types/Permission.ts +465 -4
  100. package/Types/Podman/PodmanInventoryExtractor.ts +343 -0
  101. package/Types/Telemetry/EntityType.ts +12 -0
  102. package/Types/Telemetry/ServiceType.ts +2 -0
  103. package/UI/Components/Icon/Icon.tsx +57 -0
  104. package/UI/Components/LogsViewer/LogsViewer.tsx +44 -1
  105. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +28 -0
  106. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +6 -0
  107. package/UI/Utils/TelemetryService.ts +1 -0
  108. package/Utils/Dashboard/Components/DashboardDockerSwarmNodeListComponent.ts +70 -0
  109. package/Utils/Dashboard/Components/DashboardDockerSwarmResourceListShared.ts +61 -0
  110. package/Utils/Dashboard/Components/DashboardDockerSwarmServiceListComponent.ts +71 -0
  111. package/Utils/Dashboard/Components/DashboardPodmanContainerListComponent.ts +100 -0
  112. package/Utils/Dashboard/Components/DashboardPodmanHostListComponent.ts +88 -0
  113. package/Utils/Dashboard/Components/DashboardPodmanImageListComponent.ts +97 -0
  114. package/Utils/Dashboard/Components/DashboardPodmanNetworkListComponent.ts +87 -0
  115. package/Utils/Dashboard/Components/DashboardPodmanVolumeListComponent.ts +87 -0
  116. package/Utils/Dashboard/Components/Index.ts +51 -0
  117. package/Utils/Telemetry/EntityKey.ts +18 -0
  118. package/build/dist/Models/DatabaseModels/Alert.js +162 -0
  119. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  120. package/build/dist/Models/DatabaseModels/AlertLabelRule.js +39 -0
  121. package/build/dist/Models/DatabaseModels/AlertLabelRule.js.map +1 -1
  122. package/build/dist/Models/DatabaseModels/AlertOwnerRule.js +39 -0
  123. package/build/dist/Models/DatabaseModels/AlertOwnerRule.js.map +1 -1
  124. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +1018 -0
  125. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -0
  126. package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js +522 -0
  127. package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js.map +1 -0
  128. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js +603 -0
  129. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js.map +1 -0
  130. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.js +503 -0
  131. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.js.map +1 -0
  132. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerUser.js +502 -0
  133. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerUser.js.map +1 -0
  134. package/build/dist/Models/DatabaseModels/DockerSwarmResource.js +787 -0
  135. package/build/dist/Models/DatabaseModels/DockerSwarmResource.js.map +1 -0
  136. package/build/dist/Models/DatabaseModels/Incident.js +162 -0
  137. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  138. package/build/dist/Models/DatabaseModels/IncidentLabelRule.js +39 -0
  139. package/build/dist/Models/DatabaseModels/IncidentLabelRule.js.map +1 -1
  140. package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js +39 -0
  141. package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js.map +1 -1
  142. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +54 -0
  143. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  144. package/build/dist/Models/DatabaseModels/Index.js +24 -0
  145. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  146. package/build/dist/Models/DatabaseModels/PodmanHost.js +885 -0
  147. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -0
  148. package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js +522 -0
  149. package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js.map +1 -0
  150. package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js +603 -0
  151. package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js.map +1 -0
  152. package/build/dist/Models/DatabaseModels/PodmanHostOwnerTeam.js +503 -0
  153. package/build/dist/Models/DatabaseModels/PodmanHostOwnerTeam.js.map +1 -0
  154. package/build/dist/Models/DatabaseModels/PodmanHostOwnerUser.js +502 -0
  155. package/build/dist/Models/DatabaseModels/PodmanHostOwnerUser.js.map +1 -0
  156. package/build/dist/Models/DatabaseModels/PodmanResource.js +526 -0
  157. package/build/dist/Models/DatabaseModels/PodmanResource.js.map +1 -0
  158. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +108 -0
  159. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js +39 -0
  161. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js.map +1 -1
  162. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js +39 -0
  163. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js.map +1 -1
  164. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +54 -0
  165. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
  166. package/build/dist/Models/DatabaseModels/TelemetryException.js +2 -0
  167. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  168. package/build/dist/Server/API/DashboardAPI.js +89 -0
  169. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  170. package/build/dist/Server/API/DockerSwarmResourceAPI.js +100 -0
  171. package/build/dist/Server/API/DockerSwarmResourceAPI.js.map +1 -0
  172. package/build/dist/Server/API/TelemetryAPI.js +8 -1
  173. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  174. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781587937032-MigrationName.js +1100 -0
  175. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781587937032-MigrationName.js.map +1 -0
  176. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  177. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  178. package/build/dist/Server/Services/AlertLabelRuleEngineService.js +30 -4
  179. package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
  180. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +62 -5
  181. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
  182. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +168 -0
  183. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -0
  184. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleService.js +13 -0
  185. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleService.js.map +1 -0
  186. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +188 -0
  187. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -0
  188. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleService.js +13 -0
  189. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleService.js.map +1 -0
  190. package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js +9 -0
  191. package/build/dist/Server/Services/DockerSwarmClusterOwnerTeamService.js.map +1 -0
  192. package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js +9 -0
  193. package/build/dist/Server/Services/DockerSwarmClusterOwnerUserService.js.map +1 -0
  194. package/build/dist/Server/Services/DockerSwarmClusterService.js +353 -0
  195. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -0
  196. package/build/dist/Server/Services/DockerSwarmResourceService.js +258 -0
  197. package/build/dist/Server/Services/DockerSwarmResourceService.js.map +1 -0
  198. package/build/dist/Server/Services/ExceptionAggregationService.js +1 -0
  199. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  200. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +28 -4
  201. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
  202. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +62 -5
  203. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
  204. package/build/dist/Server/Services/IncidentService.js +8 -0
  205. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  206. package/build/dist/Server/Services/Index.js +14 -0
  207. package/build/dist/Server/Services/Index.js.map +1 -1
  208. package/build/dist/Server/Services/LogAggregationService.js +1 -0
  209. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  210. package/build/dist/Server/Services/MetricAggregationService.js +1 -0
  211. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  212. package/build/dist/Server/Services/OpenTelemetryIngestService.js +43 -13
  213. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  214. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +166 -0
  215. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -0
  216. package/build/dist/Server/Services/PodmanHostLabelRuleService.js +13 -0
  217. package/build/dist/Server/Services/PodmanHostLabelRuleService.js.map +1 -0
  218. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +186 -0
  219. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -0
  220. package/build/dist/Server/Services/PodmanHostOwnerRuleService.js +13 -0
  221. package/build/dist/Server/Services/PodmanHostOwnerRuleService.js.map +1 -0
  222. package/build/dist/Server/Services/PodmanHostOwnerTeamService.js +9 -0
  223. package/build/dist/Server/Services/PodmanHostOwnerTeamService.js.map +1 -0
  224. package/build/dist/Server/Services/PodmanHostOwnerUserService.js +9 -0
  225. package/build/dist/Server/Services/PodmanHostOwnerUserService.js.map +1 -0
  226. package/build/dist/Server/Services/PodmanHostService.js +319 -0
  227. package/build/dist/Server/Services/PodmanHostService.js.map +1 -0
  228. package/build/dist/Server/Services/PodmanResourceService.js +196 -0
  229. package/build/dist/Server/Services/PodmanResourceService.js.map +1 -0
  230. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +30 -4
  231. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
  232. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +62 -5
  233. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
  234. package/build/dist/Server/Services/TelemetryUsageBillingService.js +13 -0
  235. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  236. package/build/dist/Server/Services/TraceAggregationService.js +1 -0
  237. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  238. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +13 -0
  239. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  240. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +8 -0
  241. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  242. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +35 -7
  243. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -1
  244. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +194 -0
  245. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  246. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +35 -1
  247. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  248. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +9 -0
  249. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  250. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +3 -0
  251. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  252. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +16 -0
  253. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  254. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +30 -0
  255. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
  256. package/build/dist/Server/Utils/Telemetry/Telemetry.js +6 -0
  257. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  258. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +18 -0
  259. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  260. package/build/dist/Types/Dashboard/DashboardComponentType.js +7 -0
  261. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  262. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +2 -0
  263. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  264. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDockerSwarmNodeListComponent.js +2 -0
  265. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDockerSwarmNodeListComponent.js.map +1 -0
  266. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDockerSwarmServiceListComponent.js +2 -0
  267. package/build/dist/Types/Dashboard/DashboardComponents/DashboardDockerSwarmServiceListComponent.js.map +1 -0
  268. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanContainerListComponent.js +2 -0
  269. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanContainerListComponent.js.map +1 -0
  270. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanHostListComponent.js +2 -0
  271. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanHostListComponent.js.map +1 -0
  272. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanImageListComponent.js +2 -0
  273. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanImageListComponent.js.map +1 -0
  274. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanNetworkListComponent.js +2 -0
  275. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanNetworkListComponent.js.map +1 -0
  276. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanVolumeListComponent.js +2 -0
  277. package/build/dist/Types/Dashboard/DashboardComponents/DashboardPodmanVolumeListComponent.js.map +1 -0
  278. package/build/dist/Types/Dashboard/DashboardTemplates.js +168 -0
  279. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  280. package/build/dist/Types/DockerSwarm/DockerSwarmInventoryExtractor.js +359 -0
  281. package/build/dist/Types/DockerSwarm/DockerSwarmInventoryExtractor.js.map +1 -0
  282. package/build/dist/Types/Icon/IconProp.js +1 -0
  283. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  284. package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js +358 -0
  285. package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js.map +1 -0
  286. package/build/dist/Types/Monitor/DockerSwarmMetricCatalog.js +103 -0
  287. package/build/dist/Types/Monitor/DockerSwarmMetricCatalog.js.map +1 -0
  288. package/build/dist/Types/Monitor/HostAlertTemplates.js +365 -0
  289. package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -0
  290. package/build/dist/Types/Monitor/HostMetricCatalog.js +138 -0
  291. package/build/dist/Types/Monitor/HostMetricCatalog.js.map +1 -0
  292. package/build/dist/Types/Monitor/MonitorStep.js +69 -0
  293. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  294. package/build/dist/Types/Monitor/MonitorStepDockerSwarmMonitor.js +21 -0
  295. package/build/dist/Types/Monitor/MonitorStepDockerSwarmMonitor.js.map +1 -0
  296. package/build/dist/Types/Monitor/MonitorStepHostMonitor.js +20 -0
  297. package/build/dist/Types/Monitor/MonitorStepHostMonitor.js.map +1 -0
  298. package/build/dist/Types/Monitor/MonitorStepPodmanMonitor.js +21 -0
  299. package/build/dist/Types/Monitor/MonitorStepPodmanMonitor.js.map +1 -0
  300. package/build/dist/Types/Monitor/MonitorType.js +39 -0
  301. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  302. package/build/dist/Types/Monitor/PodmanAlertTemplates.js +410 -0
  303. package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -0
  304. package/build/dist/Types/Monitor/PodmanMetricCatalog.js +192 -0
  305. package/build/dist/Types/Monitor/PodmanMetricCatalog.js.map +1 -0
  306. package/build/dist/Types/Permission.js +420 -4
  307. package/build/dist/Types/Permission.js.map +1 -1
  308. package/build/dist/Types/Podman/PodmanInventoryExtractor.js +293 -0
  309. package/build/dist/Types/Podman/PodmanInventoryExtractor.js.map +1 -0
  310. package/build/dist/Types/Telemetry/EntityType.js +12 -0
  311. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  312. package/build/dist/Types/Telemetry/ServiceType.js +2 -0
  313. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  314. package/build/dist/UI/Components/Icon/Icon.js +16 -0
  315. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  316. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +30 -2
  317. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  318. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +22 -0
  319. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  320. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +6 -0
  321. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  322. package/build/dist/UI/Utils/TelemetryService.js +1 -0
  323. package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
  324. package/build/dist/Utils/Dashboard/Components/DashboardDockerSwarmNodeListComponent.js +55 -0
  325. package/build/dist/Utils/Dashboard/Components/DashboardDockerSwarmNodeListComponent.js.map +1 -0
  326. package/build/dist/Utils/Dashboard/Components/DashboardDockerSwarmResourceListShared.js +46 -0
  327. package/build/dist/Utils/Dashboard/Components/DashboardDockerSwarmResourceListShared.js.map +1 -0
  328. package/build/dist/Utils/Dashboard/Components/DashboardDockerSwarmServiceListComponent.js +55 -0
  329. package/build/dist/Utils/Dashboard/Components/DashboardDockerSwarmServiceListComponent.js.map +1 -0
  330. package/build/dist/Utils/Dashboard/Components/DashboardPodmanContainerListComponent.js +77 -0
  331. package/build/dist/Utils/Dashboard/Components/DashboardPodmanContainerListComponent.js.map +1 -0
  332. package/build/dist/Utils/Dashboard/Components/DashboardPodmanHostListComponent.js +71 -0
  333. package/build/dist/Utils/Dashboard/Components/DashboardPodmanHostListComponent.js.map +1 -0
  334. package/build/dist/Utils/Dashboard/Components/DashboardPodmanImageListComponent.js +77 -0
  335. package/build/dist/Utils/Dashboard/Components/DashboardPodmanImageListComponent.js.map +1 -0
  336. package/build/dist/Utils/Dashboard/Components/DashboardPodmanNetworkListComponent.js +68 -0
  337. package/build/dist/Utils/Dashboard/Components/DashboardPodmanNetworkListComponent.js.map +1 -0
  338. package/build/dist/Utils/Dashboard/Components/DashboardPodmanVolumeListComponent.js +68 -0
  339. package/build/dist/Utils/Dashboard/Components/DashboardPodmanVolumeListComponent.js.map +1 -0
  340. package/build/dist/Utils/Dashboard/Components/Index.js +28 -0
  341. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  342. package/build/dist/Utils/Telemetry/EntityKey.js +14 -0
  343. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  344. package/package.json +1 -1
@@ -0,0 +1,232 @@
1
+ import Label from "../../Models/DatabaseModels/Label";
2
+ import DockerSwarmCluster from "../../Models/DatabaseModels/DockerSwarmCluster";
3
+ import DockerSwarmClusterOwnerRule from "../../Models/DatabaseModels/DockerSwarmClusterOwnerRule";
4
+ import DockerSwarmClusterOwnerUser from "../../Models/DatabaseModels/DockerSwarmClusterOwnerUser";
5
+ import DockerSwarmClusterOwnerTeam from "../../Models/DatabaseModels/DockerSwarmClusterOwnerTeam";
6
+ import DockerSwarmClusterOwnerRuleService from "./DockerSwarmClusterOwnerRuleService";
7
+ import DockerSwarmClusterOwnerUserService from "./DockerSwarmClusterOwnerUserService";
8
+ import DockerSwarmClusterOwnerTeamService from "./DockerSwarmClusterOwnerTeamService";
9
+ import DockerSwarmClusterService from "./DockerSwarmClusterService";
10
+ import ObjectID from "../../Types/ObjectID";
11
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
12
+ import logger, { LogAttributes } from "../Utils/Logger";
13
+
14
+ class DockerSwarmClusterOwnerRuleEngineServiceClass {
15
+ /**
16
+ * Evaluates DockerSwarmClusterOwnerRule rows for the given DockerSwarm cluster and adds matched
17
+ * owner users / teams via DockerSwarmClusterOwnerUserService / DockerSwarmClusterOwnerTeamService. Rules
18
+ * with notifyOwners set notify the added owners; rules with notifyOwners off
19
+ * add silently.
20
+ */
21
+ @CaptureSpan()
22
+ public async applyRulesToDockerSwarmCluster(
23
+ dockerSwarmCluster: DockerSwarmCluster,
24
+ ): Promise<void> {
25
+ if (!dockerSwarmCluster.id || !dockerSwarmCluster.projectId) {
26
+ return;
27
+ }
28
+
29
+ try {
30
+ const rules: Array<DockerSwarmClusterOwnerRule> =
31
+ await DockerSwarmClusterOwnerRuleService.findBy({
32
+ query: {
33
+ projectId: dockerSwarmCluster.projectId,
34
+ isEnabled: true,
35
+ },
36
+ props: { isRoot: true },
37
+ select: {
38
+ _id: true,
39
+ name: true,
40
+ notifyOwners: true,
41
+ dockerSwarmClusterLabels: { _id: true },
42
+ dockerSwarmClusterNamePattern: true,
43
+ dockerSwarmClusterDescriptionPattern: true,
44
+ ownerUsers: { _id: true },
45
+ ownerTeams: { _id: true },
46
+ },
47
+ limit: 100,
48
+ skip: 0,
49
+ });
50
+
51
+ if (rules.length === 0) {
52
+ return;
53
+ }
54
+
55
+ const dockerSwarmClusterWithDetails: DockerSwarmCluster | null =
56
+ await DockerSwarmClusterService.findOneById({
57
+ id: dockerSwarmCluster.id,
58
+ select: {
59
+ name: true,
60
+ description: true,
61
+ labels: { _id: true },
62
+ },
63
+ props: { isRoot: true },
64
+ });
65
+
66
+ if (!dockerSwarmClusterWithDetails) {
67
+ return;
68
+ }
69
+
70
+ const usersByNotify: Map<boolean, Set<string>> = new Map([
71
+ [true, new Set()],
72
+ [false, new Set()],
73
+ ]);
74
+ const teamsByNotify: Map<boolean, Set<string>> = new Map([
75
+ [true, new Set()],
76
+ [false, new Set()],
77
+ ]);
78
+
79
+ const matchedRules: Array<DockerSwarmClusterOwnerRule> = [];
80
+
81
+ for (const rule of rules) {
82
+ const matches: boolean = this.doesDockerSwarmClusterMatchRule(
83
+ dockerSwarmClusterWithDetails,
84
+ rule,
85
+ );
86
+ if (!matches) {
87
+ continue;
88
+ }
89
+ let ruleAddedAny: boolean = false;
90
+ const notify: boolean = rule.notifyOwners !== false;
91
+ for (const user of rule.ownerUsers || []) {
92
+ if (user.id) {
93
+ usersByNotify.get(notify)!.add(user.id.toString());
94
+ ruleAddedAny = true;
95
+ }
96
+ }
97
+ for (const team of rule.ownerTeams || []) {
98
+ if (team.id) {
99
+ teamsByNotify.get(notify)!.add(team.id.toString());
100
+ ruleAddedAny = true;
101
+ }
102
+ }
103
+ if (ruleAddedAny) {
104
+ matchedRules.push(rule);
105
+ }
106
+ }
107
+
108
+ if (matchedRules.length === 0) {
109
+ return;
110
+ }
111
+
112
+ for (const notify of [true, false]) {
113
+ const userIds: Set<string> = usersByNotify.get(notify)!;
114
+ const teamIds: Set<string> = teamsByNotify.get(notify)!;
115
+
116
+ for (const userId of userIds) {
117
+ const owner: DockerSwarmClusterOwnerUser =
118
+ new DockerSwarmClusterOwnerUser();
119
+ owner.dockerSwarmClusterId = dockerSwarmCluster.id;
120
+ owner.projectId = dockerSwarmCluster.projectId;
121
+ owner.userId = new ObjectID(userId);
122
+ owner.isOwnerNotified = !notify;
123
+ await DockerSwarmClusterOwnerUserService.create({
124
+ data: owner,
125
+ props: { isRoot: true },
126
+ });
127
+ }
128
+
129
+ for (const teamId of teamIds) {
130
+ const owner: DockerSwarmClusterOwnerTeam =
131
+ new DockerSwarmClusterOwnerTeam();
132
+ owner.dockerSwarmClusterId = dockerSwarmCluster.id;
133
+ owner.projectId = dockerSwarmCluster.projectId;
134
+ owner.teamId = new ObjectID(teamId);
135
+ owner.isOwnerNotified = !notify;
136
+ await DockerSwarmClusterOwnerTeamService.create({
137
+ data: owner,
138
+ props: { isRoot: true },
139
+ });
140
+ }
141
+ }
142
+
143
+ logger.debug(
144
+ `DockerSwarmClusterOwnerRuleEngine added owners to DockerSwarm cluster ${dockerSwarmCluster.id}`,
145
+ { projectId: dockerSwarmCluster.projectId.toString() } as LogAttributes,
146
+ );
147
+ } catch (error) {
148
+ logger.error(`Error applying DockerSwarm cluster owner rules: ${error}`, {
149
+ projectId: dockerSwarmCluster.projectId?.toString(),
150
+ dockerSwarmClusterId: dockerSwarmCluster.id?.toString(),
151
+ } as LogAttributes);
152
+ }
153
+ }
154
+
155
+ private doesDockerSwarmClusterMatchRule(
156
+ dockerSwarmCluster: DockerSwarmCluster,
157
+ rule: DockerSwarmClusterOwnerRule,
158
+ ): boolean {
159
+ if (
160
+ rule.dockerSwarmClusterLabels &&
161
+ rule.dockerSwarmClusterLabels.length > 0
162
+ ) {
163
+ if (
164
+ !dockerSwarmCluster.labels ||
165
+ dockerSwarmCluster.labels.length === 0
166
+ ) {
167
+ return false;
168
+ }
169
+ const ruleLabelIds: Array<string> = rule.dockerSwarmClusterLabels.map(
170
+ (l: Label) => {
171
+ return l.id?.toString() || "";
172
+ },
173
+ );
174
+ const labelIds: Array<string> = dockerSwarmCluster.labels.map(
175
+ (l: Label) => {
176
+ return l.id?.toString() || "";
177
+ },
178
+ );
179
+ if (
180
+ !ruleLabelIds.some((id: string) => {
181
+ return labelIds.includes(id);
182
+ })
183
+ ) {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ if (
189
+ rule.dockerSwarmClusterNamePattern &&
190
+ (!dockerSwarmCluster.name ||
191
+ !this.testRegex(
192
+ rule.dockerSwarmClusterNamePattern,
193
+ dockerSwarmCluster.name,
194
+ rule,
195
+ ))
196
+ ) {
197
+ return false;
198
+ }
199
+
200
+ if (
201
+ rule.dockerSwarmClusterDescriptionPattern &&
202
+ (!dockerSwarmCluster.description ||
203
+ !this.testRegex(
204
+ rule.dockerSwarmClusterDescriptionPattern,
205
+ dockerSwarmCluster.description,
206
+ rule,
207
+ ))
208
+ ) {
209
+ return false;
210
+ }
211
+
212
+ return true;
213
+ }
214
+
215
+ private testRegex(
216
+ pattern: string,
217
+ value: string,
218
+ rule: DockerSwarmClusterOwnerRule,
219
+ ): boolean {
220
+ try {
221
+ const regex: RegExp = new RegExp(pattern, "i");
222
+ return regex.test(value);
223
+ } catch {
224
+ logger.warn(
225
+ `Invalid regex in DockerSwarm cluster owner rule ${rule.id}: ${pattern}`,
226
+ );
227
+ return false;
228
+ }
229
+ }
230
+ }
231
+
232
+ export default new DockerSwarmClusterOwnerRuleEngineServiceClass();
@@ -0,0 +1,14 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/DockerSwarmClusterOwnerRule";
3
+ import { IsBillingEnabled } from "../EnvironmentConfig";
4
+
5
+ export class Service extends DatabaseService<Model> {
6
+ public constructor() {
7
+ super(Model);
8
+ if (IsBillingEnabled) {
9
+ this.hardDeleteItemsOlderThanInDays("createdAt", 3 * 365);
10
+ }
11
+ }
12
+ }
13
+
14
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/DockerSwarmClusterOwnerTeam";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();
@@ -0,0 +1,10 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import Model from "../../Models/DatabaseModels/DockerSwarmClusterOwnerUser";
3
+
4
+ export class Service extends DatabaseService<Model> {
5
+ public constructor() {
6
+ super(Model);
7
+ }
8
+ }
9
+
10
+ export default new Service();
@@ -0,0 +1,404 @@
1
+ import DatabaseService from "./DatabaseService";
2
+ import DockerSwarmClusterLabelRuleEngineService from "./DockerSwarmClusterLabelRuleEngineService";
3
+ import DockerSwarmClusterOwnerRuleEngineService from "./DockerSwarmClusterOwnerRuleEngineService";
4
+ import Model from "../../Models/DatabaseModels/DockerSwarmCluster";
5
+ import Label from "../../Models/DatabaseModels/Label";
6
+ import { OnCreate } from "../Types/Database/Hooks";
7
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
8
+ import ObjectID from "../../Types/ObjectID";
9
+ import QueryHelper from "../Types/Database/QueryHelper";
10
+ import OneUptimeDate from "../../Types/Date";
11
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
12
+ import GlobalCache from "../Infrastructure/GlobalCache";
13
+ import logger, { LogAttributes } from "../Utils/Logger";
14
+ import crypto from "crypto";
15
+
16
+ const LAST_SEEN_CACHE_NAMESPACE: string = "docker-swarm-cluster-last-seen";
17
+ const LAST_SEEN_THROTTLE_SECONDS: number = 60;
18
+
19
+ const LABELS_APPLIED_CACHE_NAMESPACE: string =
20
+ "docker-swarm-cluster-labels-applied";
21
+ const LABELS_APPLIED_CACHE_TTL_SECONDS: number = 60;
22
+
23
+ export class Service extends DatabaseService<Model> {
24
+ public constructor() {
25
+ super(Model);
26
+ }
27
+
28
+ @CaptureSpan()
29
+ protected override async onCreateSuccess(
30
+ _onCreate: OnCreate<Model>,
31
+ createdItem: Model,
32
+ ): Promise<Model> {
33
+ /*
34
+ * Rules run once, on creation only — exact parity with
35
+ * KubernetesClusterService. Label engine first: it syncs the
36
+ * in-memory labels so the owner engine can match rule-added labels.
37
+ */
38
+ if (createdItem.projectId && createdItem.id) {
39
+ Promise.resolve()
40
+ .then(async () => {
41
+ await DockerSwarmClusterLabelRuleEngineService.applyRulesToDockerSwarmCluster(
42
+ createdItem,
43
+ );
44
+ })
45
+ .then(async () => {
46
+ await DockerSwarmClusterOwnerRuleEngineService.applyRulesToDockerSwarmCluster(
47
+ createdItem,
48
+ );
49
+ })
50
+ .catch((error: Error) => {
51
+ logger.error(
52
+ `Error applying dockerSwarm cluster rules in DockerSwarmClusterService.onCreateSuccess: ${error}`,
53
+ {
54
+ projectId: createdItem.projectId?.toString(),
55
+ dockerSwarmClusterId: createdItem.id?.toString(),
56
+ } as LogAttributes,
57
+ );
58
+ });
59
+ }
60
+ return createdItem;
61
+ }
62
+
63
+ @CaptureSpan()
64
+ public async findOrCreateByName(data: {
65
+ projectId: ObjectID;
66
+ name: string;
67
+ }): Promise<Model> {
68
+ /*
69
+ * A DockerSwarm cluster is keyed by the `docker.swarm.cluster.name` OTel resource
70
+ * attribute, which the user configures on the agent. Look it up
71
+ * case-insensitively: the unique guard (checkUniqueColumnBy ->
72
+ * findWithSameText) compares case-insensitively, so a case-sensitive
73
+ * lookup would miss an existing row that differs only by case, then
74
+ * fail to create it — wedging ingest for that cluster. Unlike
75
+ * DockerHost.hostIdentifier (host.name casing is unstable on Windows)
76
+ * the configured cluster name's casing is stable, so we preserve the
77
+ * user's casing on create instead of canonicalizing to lowercase.
78
+ */
79
+ const name: string = data.name.trim();
80
+
81
+ const existingCluster: Model | null = await this.findOneBy({
82
+ query: {
83
+ projectId: data.projectId,
84
+ name: QueryHelper.findWithSameText(name),
85
+ },
86
+ select: {
87
+ _id: true,
88
+ projectId: true,
89
+ name: true,
90
+ },
91
+ props: {
92
+ isRoot: true,
93
+ },
94
+ });
95
+
96
+ if (existingCluster) {
97
+ return existingCluster;
98
+ }
99
+
100
+ try {
101
+ // Create new cluster
102
+ const newCluster: Model = new Model();
103
+ newCluster.projectId = data.projectId;
104
+ newCluster.name = name;
105
+ newCluster.otelCollectorStatus = "connected";
106
+ newCluster.lastSeenAt = OneUptimeDate.getCurrentDate();
107
+
108
+ const createdCluster: Model = await this.create({
109
+ data: newCluster,
110
+ props: {
111
+ isRoot: true,
112
+ },
113
+ });
114
+
115
+ return createdCluster;
116
+ } catch {
117
+ /*
118
+ * Either two ingest workers raced to create the same cluster, or a
119
+ * cluster with this name in a different case already existed and the
120
+ * unique guard rejected the insert. Re-resolve case-insensitively so
121
+ * the caller still gets the existing row instead of throwing.
122
+ */
123
+ const reFetchedCluster: Model | null = await this.findOneBy({
124
+ query: {
125
+ projectId: data.projectId,
126
+ name: QueryHelper.findWithSameText(name),
127
+ },
128
+ select: {
129
+ _id: true,
130
+ projectId: true,
131
+ name: true,
132
+ },
133
+ props: {
134
+ isRoot: true,
135
+ },
136
+ });
137
+
138
+ if (reFetchedCluster) {
139
+ return reFetchedCluster;
140
+ }
141
+
142
+ throw new Error("Failed to create or find DockerSwarm cluster: " + name);
143
+ }
144
+ }
145
+
146
+ /*
147
+ * Refresh lastSeenAt / connection status and (optionally) the
148
+ * snapshot columns the list page renders. Count columns ride this
149
+ * extras path with COALESCE-per-column semantics: a key that is
150
+ * undefined is simply not written, so a partial batch (one that
151
+ * lacked the matching *_info series) never zeroes a count. The
152
+ * 60-second extras fingerprint cache is the write throttle — the
153
+ * steady state (identical snapshot every scrape) costs one Redis
154
+ * read per batch and at most one Postgres UPDATE per minute.
155
+ *
156
+ * Two callers share this throttle with DISJOINT extras shapes: the
157
+ * metrics snapshot flush (pveVersion + counts, every batch) and the
158
+ * fenced autoDiscoverDockerSwarmCluster maintenance path (agentVersion
159
+ * only — and usually an all-null fingerprint, since the shipped
160
+ * agent config does not stamp oneuptime.agent.version). The single
161
+ * fingerprint covers the whole extras object, so each alternation
162
+ * between the two shapes busts the throttle: at most one extra
163
+ * Postgres UPDATE per maintenance-fence window (~5 min), which is
164
+ * accepted. Do NOT key the cache per-caller — that would let two
165
+ * callers each refresh lastSeenAt under their own throttle and is
166
+ * not worth the complexity for one UPDATE per 5 minutes.
167
+ */
168
+ @CaptureSpan()
169
+ public async updateLastSeen(
170
+ clusterId: ObjectID,
171
+ extra?: {
172
+ dockerVersion?: string | undefined;
173
+ swarmId?: string | undefined;
174
+ agentVersion?: string | undefined;
175
+ nodeCount?: number | undefined;
176
+ readyNodeCount?: number | undefined;
177
+ managerNodeCount?: number | undefined;
178
+ serviceCount?: number | undefined;
179
+ taskCount?: number | undefined;
180
+ runningTaskCount?: number | undefined;
181
+ stackCount?: number | undefined;
182
+ networkCount?: number | undefined;
183
+ },
184
+ ): Promise<void> {
185
+ const cacheKey: string = clusterId.toString();
186
+ const extrasFingerprint: string = crypto
187
+ .createHash("sha1")
188
+ .update(
189
+ JSON.stringify({
190
+ dockerVersion: extra?.dockerVersion ?? null,
191
+ swarmId: extra?.swarmId ?? null,
192
+ agentVersion: extra?.agentVersion ?? null,
193
+ nodeCount: extra?.nodeCount ?? null,
194
+ readyNodeCount: extra?.readyNodeCount ?? null,
195
+ managerNodeCount: extra?.managerNodeCount ?? null,
196
+ serviceCount: extra?.serviceCount ?? null,
197
+ taskCount: extra?.taskCount ?? null,
198
+ runningTaskCount: extra?.runningTaskCount ?? null,
199
+ stackCount: extra?.stackCount ?? null,
200
+ networkCount: extra?.networkCount ?? null,
201
+ }),
202
+ )
203
+ .digest("hex");
204
+
205
+ const cached: string | null = await GlobalCache.getString(
206
+ LAST_SEEN_CACHE_NAMESPACE,
207
+ cacheKey,
208
+ );
209
+
210
+ if (cached === extrasFingerprint) {
211
+ return; // same data was written recently
212
+ }
213
+
214
+ await GlobalCache.setString(
215
+ LAST_SEEN_CACHE_NAMESPACE,
216
+ cacheKey,
217
+ extrasFingerprint,
218
+ { expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
219
+ );
220
+
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ const data: any = {
223
+ lastSeenAt: OneUptimeDate.getCurrentDate(),
224
+ otelCollectorStatus: "connected",
225
+ };
226
+
227
+ if (extra?.dockerVersion) {
228
+ data.dockerVersion = extra.dockerVersion;
229
+ }
230
+ if (extra?.swarmId) {
231
+ data.swarmId = extra.swarmId;
232
+ }
233
+ if (extra?.agentVersion) {
234
+ data.agentVersion = extra.agentVersion;
235
+ }
236
+ // Counts: 0 is a legitimate value — gate on undefined, not falsiness.
237
+ if (extra?.nodeCount !== undefined) {
238
+ data.nodeCount = extra.nodeCount;
239
+ }
240
+ if (extra?.readyNodeCount !== undefined) {
241
+ data.readyNodeCount = extra.readyNodeCount;
242
+ }
243
+ if (extra?.managerNodeCount !== undefined) {
244
+ data.managerNodeCount = extra.managerNodeCount;
245
+ }
246
+ if (extra?.serviceCount !== undefined) {
247
+ data.serviceCount = extra.serviceCount;
248
+ }
249
+ if (extra?.taskCount !== undefined) {
250
+ data.taskCount = extra.taskCount;
251
+ }
252
+ if (extra?.runningTaskCount !== undefined) {
253
+ data.runningTaskCount = extra.runningTaskCount;
254
+ }
255
+ if (extra?.stackCount !== undefined) {
256
+ data.stackCount = extra.stackCount;
257
+ }
258
+ if (extra?.networkCount !== undefined) {
259
+ data.networkCount = extra.networkCount;
260
+ }
261
+
262
+ await this.updateOneById({
263
+ id: clusterId,
264
+ data: data,
265
+ props: {
266
+ isRoot: true,
267
+ },
268
+ });
269
+ }
270
+
271
+ /**
272
+ * Additively attach labels to a DockerSwarm cluster. Existing labels are
273
+ * never removed — manual labels set via the UI survive ingest. The
274
+ * set of labelIds passed in is fingerprinted and cached for 60s so
275
+ * the common case (steady-state collector pushing the same label
276
+ * set every batch) costs one in-memory lookup, not a join-table
277
+ * scan.
278
+ */
279
+ @CaptureSpan()
280
+ public async attachLabels(data: {
281
+ dockerSwarmClusterId: ObjectID;
282
+ labelIds: Array<ObjectID>;
283
+ }): Promise<void> {
284
+ if (!data.labelIds || data.labelIds.length === 0) {
285
+ return;
286
+ }
287
+
288
+ const cacheKey: string = data.dockerSwarmClusterId.toString();
289
+ const fingerprint: string = fingerprintLabelIds(data.labelIds);
290
+ const cached: string | null = await GlobalCache.getString(
291
+ LABELS_APPLIED_CACHE_NAMESPACE,
292
+ cacheKey,
293
+ );
294
+ if (cached === fingerprint) {
295
+ return;
296
+ }
297
+
298
+ try {
299
+ const dockerSwarmClusterIdStr: string =
300
+ data.dockerSwarmClusterId.toString();
301
+ const existingLabels: Array<Label> = await this.getRepository()
302
+ .createQueryBuilder()
303
+ .relation(Model, "labels")
304
+ .of(dockerSwarmClusterIdStr)
305
+ .loadMany();
306
+
307
+ const existingIds: Set<string> = new Set();
308
+ for (const lbl of existingLabels) {
309
+ const idStr: string | undefined = lbl._id?.toString();
310
+ if (idStr) {
311
+ existingIds.add(idStr);
312
+ }
313
+ }
314
+
315
+ const toAddIds: Array<string> = [];
316
+ const seen: Set<string> = new Set();
317
+ for (const id of data.labelIds) {
318
+ const idStr: string = id.toString();
319
+ if (existingIds.has(idStr) || seen.has(idStr)) {
320
+ continue;
321
+ }
322
+ seen.add(idStr);
323
+ toAddIds.push(idStr);
324
+ }
325
+
326
+ if (toAddIds.length > 0) {
327
+ await this.getRepository()
328
+ .createQueryBuilder()
329
+ .relation(Model, "labels")
330
+ .of(dockerSwarmClusterIdStr)
331
+ .add(toAddIds);
332
+ }
333
+
334
+ await GlobalCache.setString(
335
+ LABELS_APPLIED_CACHE_NAMESPACE,
336
+ cacheKey,
337
+ fingerprint,
338
+ { expiresInSeconds: LABELS_APPLIED_CACHE_TTL_SECONDS },
339
+ );
340
+ } catch (err) {
341
+ logger.warn(
342
+ `DockerSwarmClusterService.attachLabels failed for dockerSwarm cluster ${data.dockerSwarmClusterId.toString()}: ${
343
+ err instanceof Error ? err.message : String(err)
344
+ }`,
345
+ );
346
+ }
347
+ }
348
+
349
+ @CaptureSpan()
350
+ public async markDisconnectedClusters(): Promise<void> {
351
+ /*
352
+ * Threshold must stay well above the 5-minute OTel ingest
353
+ * maintenance fence (MAINTENANCE_FENCE_TTL_SECONDS in
354
+ * OtelIngestBaseService) — lastSeenAt is legitimately up to
355
+ * ~5 minutes stale during continuous telemetry, so a threshold
356
+ * equal to the fence TTL flaps healthy resources. 15 minutes
357
+ * gives 3x headroom.
358
+ */
359
+ const fifteenMinutesAgo: Date = OneUptimeDate.addRemoveMinutes(
360
+ OneUptimeDate.getCurrentDate(),
361
+ -15,
362
+ );
363
+
364
+ const connectedClusters: Array<Model> = await this.findBy({
365
+ query: {
366
+ otelCollectorStatus: "connected",
367
+ lastSeenAt: QueryHelper.lessThan(fifteenMinutesAgo),
368
+ },
369
+ select: {
370
+ _id: true,
371
+ },
372
+ limit: LIMIT_MAX,
373
+ skip: 0,
374
+ props: {
375
+ isRoot: true,
376
+ },
377
+ });
378
+
379
+ for (const cluster of connectedClusters) {
380
+ if (cluster._id) {
381
+ await this.updateOneById({
382
+ id: new ObjectID(cluster._id.toString()),
383
+ data: {
384
+ otelCollectorStatus: "disconnected",
385
+ },
386
+ props: {
387
+ isRoot: true,
388
+ },
389
+ });
390
+ }
391
+ }
392
+ }
393
+ }
394
+
395
+ function fingerprintLabelIds(labelIds: Array<ObjectID>): string {
396
+ const sorted: Array<string> = labelIds
397
+ .map((id: ObjectID) => {
398
+ return id.toString();
399
+ })
400
+ .sort();
401
+ return crypto.createHash("sha1").update(sorted.join(",")).digest("hex");
402
+ }
403
+
404
+ export default new Service();