@oneuptime/common 11.5.9 → 11.5.10

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 (376) hide show
  1. package/Models/AnalyticsModels/Index.ts +13 -0
  2. package/Models/AnalyticsModels/MetricItemAggMV1mByContainer.ts +178 -0
  3. package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +179 -0
  4. package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +179 -0
  5. package/Models/AnalyticsModels/NetworkFlow.ts +397 -0
  6. package/Models/DatabaseModels/EnterpriseLicenseInstance.ts +18 -0
  7. package/Models/DatabaseModels/GlobalConfig.ts +36 -0
  8. package/Models/DatabaseModels/Index.ts +2 -0
  9. package/Models/DatabaseModels/MarketingConversion.ts +198 -0
  10. package/Models/DatabaseModels/MetricSavedView.ts +34 -0
  11. package/Models/DatabaseModels/MetricType.ts +74 -0
  12. package/Models/DatabaseModels/NetworkDevice.ts +332 -0
  13. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +113 -0
  14. package/Models/DatabaseModels/NetworkInterface.ts +58 -0
  15. package/Models/DatabaseModels/Project.ts +37 -0
  16. package/Models/DatabaseModels/User.ts +37 -0
  17. package/Server/API/BaseAnalyticsAPI.ts +23 -0
  18. package/Server/API/EnterpriseLicenseAPI.ts +14 -0
  19. package/Server/EnvironmentConfig.ts +84 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1784191414522-AddCounterSemanticsToMetricType.ts +38 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1784191414600-AddViewTypeToMetricSavedView.ts +28 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1784211212164-AddNetworkDeviceInventoryAndDiscoverySchedule.ts +108 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1784218257664-AddEnterpriseLicenseNotificationColumns.ts +31 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1784293516000-AddAttributionColumnsToUserAndProject.ts +29 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1784298000000-AddMarketingConversionTable.ts +35 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  27. package/Server/Services/AnalyticsDatabaseService.ts +70 -1
  28. package/Server/Services/IncidentService.ts +13 -0
  29. package/Server/Services/Index.ts +10 -0
  30. package/Server/Services/MarketingConversionService.ts +10 -0
  31. package/Server/Services/MetricItemAggMV1mByContainerService.ts +31 -0
  32. package/Server/Services/MetricItemAggMV1mByK8sClusterService.ts +31 -0
  33. package/Server/Services/MetricItemAggMV1mByServiceService.ts +31 -0
  34. package/Server/Services/MetricService.ts +970 -122
  35. package/Server/Services/MonitorService.ts +14 -0
  36. package/Server/Services/NetworkDeviceOwnerTeamService.ts +42 -0
  37. package/Server/Services/NetworkDeviceOwnerUserService.ts +106 -0
  38. package/Server/Services/NetworkFlowService.ts +11 -0
  39. package/Server/Services/OnCallDutyPolicyService.ts +11 -1
  40. package/Server/Services/ProjectService.ts +136 -0
  41. package/Server/Services/SpanService.ts +13 -9
  42. package/Server/Services/StatusPageService.ts +10 -0
  43. package/Server/Services/TeamMemberService.ts +11 -0
  44. package/Server/Services/UserService.ts +59 -0
  45. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +37 -7
  46. package/Server/Utils/Attribution.ts +99 -0
  47. package/Server/Utils/Marketing/ConversionUploadProvider.ts +103 -0
  48. package/Server/Utils/Marketing/ConversionUploadProviders.ts +22 -0
  49. package/Server/Utils/Marketing/Providers/GoogleAds.ts +270 -0
  50. package/Server/Utils/Marketing/Providers/LinkedIn.ts +147 -0
  51. package/Server/Utils/Marketing/Providers/Meta.ts +148 -0
  52. package/Server/Utils/Marketing/Providers/MicrosoftAds.ts +196 -0
  53. package/Server/Utils/Marketing/Providers/Reddit.ts +178 -0
  54. package/Server/Utils/Monitor/MonitorAlert.ts +71 -7
  55. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +31 -19
  56. package/Server/Utils/Monitor/MonitorIncident.ts +71 -7
  57. package/Server/Utils/Monitor/MonitorMetricUtil.ts +57 -0
  58. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +94 -0
  59. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +15 -0
  60. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +125 -14
  61. package/Server/Utils/ProductAnalytics.ts +133 -0
  62. package/Server/Utils/Telemetry/Telemetry.ts +39 -0
  63. package/Server/Utils/Telemetry/TelemetryEntity.ts +21 -0
  64. package/Tests/Server/API/BaseAnalyticsAPI.test.ts +72 -0
  65. package/Tests/Server/Infrastructure/SemaphorePermit.test.ts +9 -1
  66. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +21 -2
  67. package/Tests/Server/Services/MetricEntityMVKeyParity.test.ts +173 -0
  68. package/Tests/Server/Services/MetricServiceAggregate.test.ts +1391 -0
  69. package/Tests/Server/Services/NetworkDeviceOwnerServices.test.ts +260 -0
  70. package/Tests/Server/Utils/Monitor/MonitorTemplateUtilNetworkDevice.test.ts +389 -0
  71. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +764 -0
  72. package/Tests/Types/BaseDatabase/AggregationIntervalUtil.test.ts +111 -2
  73. package/Tests/Types/Database/EndsWith.test.ts +64 -0
  74. package/Tests/Types/Database/GreaterThan.test.ts +62 -0
  75. package/Tests/Types/Database/GreaterThanOrEqual.test.ts +65 -0
  76. package/Tests/Types/Database/GreaterThanOrNull.test.ts +63 -0
  77. package/Tests/Types/Database/Includes.test.ts +65 -0
  78. package/Tests/Types/Database/IncludesAll.test.ts +65 -0
  79. package/Tests/Types/Database/IncludesNone.test.ts +65 -0
  80. package/Tests/Types/Database/IsNull.test.ts +44 -0
  81. package/Tests/Types/Database/LessThan.test.ts +62 -0
  82. package/Tests/Types/Database/LessThanOrEqual.test.ts +62 -0
  83. package/Tests/Types/Database/LessThanOrNull.test.ts +62 -0
  84. package/Tests/Types/Database/MultiSearch.test.ts +81 -0
  85. package/Tests/Types/Database/NotContains.test.ts +64 -0
  86. package/Tests/Types/Database/NotNull.test.ts +44 -0
  87. package/Tests/Types/Database/StartsWith.test.ts +64 -0
  88. package/Tests/Types/Monitor/MonitorStepSqlMonitor.test.ts +83 -1
  89. package/Tests/Types/Monitor/SnmpV3EnumParsing.test.ts +247 -0
  90. package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +263 -0
  91. package/Tests/UI/Components/XAxis.test.ts +5 -3
  92. package/Tests/Utils/EnterpriseLicenseUsage.test.ts +76 -0
  93. package/Tests/Utils/Metrics/MetricExplorerUrl.test.ts +622 -0
  94. package/Tests/Utils/Metrics/MetricFormulaEvaluator.test.ts +474 -0
  95. package/Tests/Utils/Telemetry/HeartbeatAvailability.test.ts +52 -4
  96. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +11 -0
  97. package/Types/BaseDatabase/AggregateBy.ts +31 -2
  98. package/Types/BaseDatabase/AggregatedResult.ts +22 -0
  99. package/Types/BaseDatabase/AggregationInterval.ts +11 -0
  100. package/Types/BaseDatabase/AggregationIntervalUtil.ts +30 -5
  101. package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +16 -0
  102. package/Types/Email/EmailTemplateType.ts +3 -0
  103. package/Types/Marketing/MarketingConversion.ts +11 -0
  104. package/Types/Metrics/MetricQueryConfigData.ts +21 -0
  105. package/Types/Metrics/MetricQueryData.ts +8 -0
  106. package/Types/Metrics/MetricViewData.ts +8 -0
  107. package/Types/Monitor/MonitorMetricType.ts +8 -0
  108. package/Types/Monitor/MonitorStep.ts +9 -0
  109. package/Types/Monitor/MonitorStepSqlMonitor.ts +12 -0
  110. package/Types/Monitor/MonitorType.ts +2 -1
  111. package/Types/Monitor/SSLMonitor/SslMonitorResponse.ts +17 -12
  112. package/Types/Monitor/SnmpMonitor/CdpNeighbor.ts +13 -0
  113. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +37 -3
  114. package/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.ts +46 -0
  115. package/Types/Monitor/SnmpMonitor/SnmpEntityInfo.ts +15 -0
  116. package/Types/Monitor/SnmpMonitor/SnmpInterface.ts +8 -0
  117. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +17 -8
  118. package/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.ts +53 -0
  119. package/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.ts +43 -0
  120. package/Types/Monitor/SnmpMonitor/SnmpSystemInfo.ts +16 -0
  121. package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +119 -3
  122. package/Types/NetFlow/NetworkFlowRecord.ts +25 -0
  123. package/Types/Syslog/SyslogMessage.ts +18 -0
  124. package/Types/Telemetry/TelemetrySavedViewState.ts +9 -0
  125. package/Types/Telemetry/TelemetrySavedViewType.ts +12 -0
  126. package/UI/Components/Charts/Area/AreaChart.tsx +51 -0
  127. package/UI/Components/Charts/Bar/BarChart.tsx +51 -1
  128. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +97 -26
  129. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +328 -1
  130. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +115 -0
  131. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +328 -1
  132. package/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.ts +7 -0
  133. package/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.ts +15 -0
  134. package/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.ts +13 -0
  135. package/UI/Components/Charts/Line/LineChart.tsx +51 -0
  136. package/UI/Components/Charts/Types/ReferenceRegionProps.ts +12 -0
  137. package/UI/Components/Charts/Types/TimeReferenceLineProps.ts +12 -0
  138. package/UI/Components/Charts/Types/XAxis/XAxisPrecision.ts +1 -0
  139. package/UI/Components/Charts/Utils/DataPoint.ts +0 -0
  140. package/UI/Components/Charts/Utils/TimeAnnotation.ts +169 -0
  141. package/UI/Components/Charts/Utils/XAxis.ts +28 -4
  142. package/UI/Components/Icon/Icon.tsx +33 -13
  143. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +9 -0
  144. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +67 -0
  145. package/UI/Components/Page/ModelPage.tsx +6 -1
  146. package/UI/Components/TelemetryViewer/components/SavedViewsDropdown.tsx +33 -4
  147. package/UI/Styles/Theme.css +10 -0
  148. package/UI/Utils/User.ts +41 -2
  149. package/Utils/Analytics.ts +8 -6
  150. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +74 -0
  151. package/Utils/Metrics/MetricExplorerUrl.ts +771 -0
  152. package/Utils/Metrics/MetricFormulaEvaluator.ts +410 -46
  153. package/Utils/Monitor/NetworkTopologyUtil.ts +261 -49
  154. package/Utils/ValueFormatter.ts +22 -1
  155. package/build/dist/Models/AnalyticsModels/Index.js +13 -0
  156. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  157. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js +159 -0
  158. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js.map +1 -0
  159. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +158 -0
  160. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js.map +1 -0
  161. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +160 -0
  162. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js.map +1 -0
  163. package/build/dist/Models/AnalyticsModels/NetworkFlow.js +351 -0
  164. package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -0
  165. package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js +19 -0
  166. package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js.map +1 -1
  167. package/build/dist/Models/DatabaseModels/GlobalConfig.js +38 -0
  168. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  169. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  170. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  171. package/build/dist/Models/DatabaseModels/MarketingConversion.js +219 -0
  172. package/build/dist/Models/DatabaseModels/MarketingConversion.js.map +1 -0
  173. package/build/dist/Models/DatabaseModels/MetricSavedView.js +35 -0
  174. package/build/dist/Models/DatabaseModels/MetricSavedView.js.map +1 -1
  175. package/build/dist/Models/DatabaseModels/MetricType.js +76 -0
  176. package/build/dist/Models/DatabaseModels/MetricType.js.map +1 -1
  177. package/build/dist/Models/DatabaseModels/NetworkDevice.js +341 -0
  178. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  179. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +116 -0
  180. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  181. package/build/dist/Models/DatabaseModels/NetworkInterface.js +60 -0
  182. package/build/dist/Models/DatabaseModels/NetworkInterface.js.map +1 -1
  183. package/build/dist/Models/DatabaseModels/Project.js +38 -0
  184. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  185. package/build/dist/Models/DatabaseModels/User.js +38 -0
  186. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  187. package/build/dist/Server/API/BaseAnalyticsAPI.js +19 -0
  188. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  189. package/build/dist/Server/API/EnterpriseLicenseAPI.js +8 -0
  190. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
  191. package/build/dist/Server/EnvironmentConfig.js +51 -0
  192. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  193. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784191414522-AddCounterSemanticsToMetricType.js +27 -0
  194. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784191414522-AddCounterSemanticsToMetricType.js.map +1 -0
  195. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784191414600-AddViewTypeToMetricSavedView.js +21 -0
  196. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784191414600-AddViewTypeToMetricSavedView.js.map +1 -0
  197. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784211212164-AddNetworkDeviceInventoryAndDiscoverySchedule.js +47 -0
  198. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784211212164-AddNetworkDeviceInventoryAndDiscoverySchedule.js.map +1 -0
  199. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784218257664-AddEnterpriseLicenseNotificationColumns.js +16 -0
  200. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784218257664-AddEnterpriseLicenseNotificationColumns.js.map +1 -0
  201. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784293516000-AddAttributionColumnsToUserAndProject.js +18 -0
  202. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784293516000-AddAttributionColumnsToUserAndProject.js.map +1 -0
  203. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784298000000-AddMarketingConversionTable.js +20 -0
  204. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784298000000-AddMarketingConversionTable.js.map +1 -0
  205. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  206. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  207. package/build/dist/Server/Services/AnalyticsDatabaseService.js +58 -4
  208. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  209. package/build/dist/Server/Services/IncidentService.js +12 -0
  210. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  211. package/build/dist/Server/Services/Index.js +10 -0
  212. package/build/dist/Server/Services/Index.js.map +1 -1
  213. package/build/dist/Server/Services/MarketingConversionService.js +9 -0
  214. package/build/dist/Server/Services/MarketingConversionService.js.map +1 -0
  215. package/build/dist/Server/Services/MetricItemAggMV1mByContainerService.js +29 -0
  216. package/build/dist/Server/Services/MetricItemAggMV1mByContainerService.js.map +1 -0
  217. package/build/dist/Server/Services/MetricItemAggMV1mByK8sClusterService.js +29 -0
  218. package/build/dist/Server/Services/MetricItemAggMV1mByK8sClusterService.js.map +1 -0
  219. package/build/dist/Server/Services/MetricItemAggMV1mByServiceService.js +29 -0
  220. package/build/dist/Server/Services/MetricItemAggMV1mByServiceService.js.map +1 -0
  221. package/build/dist/Server/Services/MetricService.js +761 -125
  222. package/build/dist/Server/Services/MetricService.js.map +1 -1
  223. package/build/dist/Server/Services/MonitorService.js +18 -5
  224. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  225. package/build/dist/Server/Services/NetworkDeviceOwnerTeamService.js +44 -0
  226. package/build/dist/Server/Services/NetworkDeviceOwnerTeamService.js.map +1 -1
  227. package/build/dist/Server/Services/NetworkDeviceOwnerUserService.js +88 -0
  228. package/build/dist/Server/Services/NetworkDeviceOwnerUserService.js.map +1 -1
  229. package/build/dist/Server/Services/NetworkFlowService.js +9 -0
  230. package/build/dist/Server/Services/NetworkFlowService.js.map +1 -0
  231. package/build/dist/Server/Services/OnCallDutyPolicyService.js +15 -6
  232. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  233. package/build/dist/Server/Services/ProjectService.js +107 -6
  234. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  235. package/build/dist/Server/Services/SpanService.js +8 -6
  236. package/build/dist/Server/Services/SpanService.js.map +1 -1
  237. package/build/dist/Server/Services/StatusPageService.js +10 -0
  238. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  239. package/build/dist/Server/Services/TeamMemberService.js +11 -0
  240. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  241. package/build/dist/Server/Services/UserService.js +52 -0
  242. package/build/dist/Server/Services/UserService.js.map +1 -1
  243. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +33 -7
  244. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  245. package/build/dist/Server/Utils/Attribution.js +74 -0
  246. package/build/dist/Server/Utils/Attribution.js.map +1 -0
  247. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js +40 -0
  248. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js.map +1 -0
  249. package/build/dist/Server/Utils/Marketing/ConversionUploadProviders.js +20 -0
  250. package/build/dist/Server/Utils/Marketing/ConversionUploadProviders.js.map +1 -0
  251. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js +177 -0
  252. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js.map +1 -0
  253. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js +113 -0
  254. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js.map +1 -0
  255. package/build/dist/Server/Utils/Marketing/Providers/Meta.js +109 -0
  256. package/build/dist/Server/Utils/Marketing/Providers/Meta.js.map +1 -0
  257. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js +130 -0
  258. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js.map +1 -0
  259. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js +126 -0
  260. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js.map +1 -0
  261. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +53 -9
  262. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  263. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +21 -10
  264. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  265. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +54 -11
  266. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  267. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +43 -3
  268. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  269. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +68 -0
  270. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  271. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +15 -0
  272. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  273. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +100 -15
  274. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  275. package/build/dist/Server/Utils/ProductAnalytics.js +111 -0
  276. package/build/dist/Server/Utils/ProductAnalytics.js.map +1 -0
  277. package/build/dist/Server/Utils/Telemetry/Telemetry.js +32 -5
  278. package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
  279. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +17 -0
  280. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  281. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +11 -0
  282. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  283. package/build/dist/Types/BaseDatabase/AggregationInterval.js +11 -0
  284. package/build/dist/Types/BaseDatabase/AggregationInterval.js.map +1 -1
  285. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +33 -5
  286. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -1
  287. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  288. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  289. package/build/dist/Types/Marketing/MarketingConversion.js +13 -0
  290. package/build/dist/Types/Marketing/MarketingConversion.js.map +1 -0
  291. package/build/dist/Types/Monitor/MonitorMetricType.js +7 -0
  292. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  293. package/build/dist/Types/Monitor/MonitorStep.js +6 -0
  294. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  295. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js +3 -0
  296. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
  297. package/build/dist/Types/Monitor/MonitorType.js +2 -1
  298. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  299. package/build/dist/Types/Monitor/SnmpMonitor/CdpNeighbor.js +2 -0
  300. package/build/dist/Types/Monitor/SnmpMonitor/CdpNeighbor.js.map +1 -0
  301. package/build/dist/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.js +41 -0
  302. package/build/dist/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.js.map +1 -1
  303. package/build/dist/Types/Monitor/SnmpMonitor/SnmpEntityInfo.js +2 -0
  304. package/build/dist/Types/Monitor/SnmpMonitor/SnmpEntityInfo.js.map +1 -0
  305. package/build/dist/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.js +48 -0
  306. package/build/dist/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.js.map +1 -1
  307. package/build/dist/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.js +38 -0
  308. package/build/dist/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.js.map +1 -1
  309. package/build/dist/Types/Monitor/SnmpMonitor/SnmpSystemInfo.js +2 -0
  310. package/build/dist/Types/Monitor/SnmpMonitor/SnmpSystemInfo.js.map +1 -0
  311. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +96 -3
  312. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
  313. package/build/dist/Types/NetFlow/NetworkFlowRecord.js +2 -0
  314. package/build/dist/Types/NetFlow/NetworkFlowRecord.js.map +1 -0
  315. package/build/dist/Types/Syslog/SyslogMessage.js +2 -0
  316. package/build/dist/Types/Syslog/SyslogMessage.js.map +1 -0
  317. package/build/dist/Types/Telemetry/TelemetrySavedViewState.js +0 -7
  318. package/build/dist/Types/Telemetry/TelemetrySavedViewState.js.map +1 -1
  319. package/build/dist/Types/Telemetry/TelemetrySavedViewType.js +13 -0
  320. package/build/dist/Types/Telemetry/TelemetrySavedViewType.js.map +1 -0
  321. package/build/dist/UI/Components/Charts/Area/AreaChart.js +25 -1
  322. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  323. package/build/dist/UI/Components/Charts/Bar/BarChart.js +26 -2
  324. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  325. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +36 -12
  326. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  327. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +208 -6
  328. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  329. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +52 -3
  330. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  331. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +208 -6
  332. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  333. package/build/dist/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.js +6 -1
  334. package/build/dist/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.js.map +1 -1
  335. package/build/dist/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.js +2 -0
  336. package/build/dist/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.js.map +1 -0
  337. package/build/dist/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.js +2 -0
  338. package/build/dist/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.js.map +1 -0
  339. package/build/dist/UI/Components/Charts/Line/LineChart.js +25 -1
  340. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  341. package/build/dist/UI/Components/Charts/Types/ReferenceRegionProps.js +2 -0
  342. package/build/dist/UI/Components/Charts/Types/ReferenceRegionProps.js.map +1 -0
  343. package/build/dist/UI/Components/Charts/Types/TimeReferenceLineProps.js +2 -0
  344. package/build/dist/UI/Components/Charts/Types/TimeReferenceLineProps.js.map +1 -0
  345. package/build/dist/UI/Components/Charts/Types/XAxis/XAxisPrecision.js +1 -0
  346. package/build/dist/UI/Components/Charts/Types/XAxis/XAxisPrecision.js.map +1 -1
  347. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +0 -0
  348. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  349. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +121 -0
  350. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -0
  351. package/build/dist/UI/Components/Charts/Utils/XAxis.js +27 -4
  352. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  353. package/build/dist/UI/Components/Icon/Icon.js +15 -8
  354. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  355. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  356. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +58 -0
  357. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  358. package/build/dist/UI/Components/Page/ModelPage.js +7 -1
  359. package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
  360. package/build/dist/UI/Components/TelemetryViewer/components/SavedViewsDropdown.js +10 -4
  361. package/build/dist/UI/Components/TelemetryViewer/components/SavedViewsDropdown.js.map +1 -1
  362. package/build/dist/UI/Utils/User.js +35 -2
  363. package/build/dist/UI/Utils/User.js.map +1 -1
  364. package/build/dist/Utils/Analytics.js +8 -5
  365. package/build/dist/Utils/Analytics.js.map +1 -1
  366. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +57 -0
  367. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  368. package/build/dist/Utils/Metrics/MetricExplorerUrl.js +418 -0
  369. package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -0
  370. package/build/dist/Utils/Metrics/MetricFormulaEvaluator.js +296 -37
  371. package/build/dist/Utils/Metrics/MetricFormulaEvaluator.js.map +1 -1
  372. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +176 -40
  373. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  374. package/build/dist/Utils/ValueFormatter.js +20 -1
  375. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  376. package/package.json +2 -2
@@ -0,0 +1,148 @@
1
+ import axios, { AxiosResponse } from "axios";
2
+ import crypto from "crypto";
3
+ import {
4
+ MetaConversionsAccessToken,
5
+ MetaConversionsPixelId,
6
+ MetaGraphApiVersion,
7
+ } from "../../../EnvironmentConfig";
8
+ import ConversionUploadProvider, {
9
+ ConversionSkip,
10
+ ConversionUploadBatchResult,
11
+ } from "../ConversionUploadProvider";
12
+ import { JSONObject } from "../../../../Types/JSON";
13
+ import MarketingConversion from "../../../../Models/DatabaseModels/MarketingConversion";
14
+
15
+ const REQUEST_TIMEOUT_MS: number = 30000;
16
+
17
+ // Meta rejects website events older than 7 days at upload time.
18
+ const META_MAX_EVENT_AGE_IN_DAYS: number = 7;
19
+
20
+ /*
21
+ * Meta (Facebook) Conversions API
22
+ * (graph.facebook.com/{version}/{pixelId}/events). Emails are SHA-256 hashed
23
+ * per Meta's customer-information matching spec; the raw email never leaves
24
+ * OneUptime. event_id is the conversion row id, so Meta deduplicates
25
+ * retried uploads (and browser-pixel duplicates) server-side.
26
+ */
27
+ export default class MetaProvider extends ConversionUploadProvider {
28
+ public override readonly key: string = "meta";
29
+ public override readonly displayName: string = "Meta";
30
+
31
+ public override isConfigured(): boolean {
32
+ return Boolean(MetaConversionsPixelId && MetaConversionsAccessToken);
33
+ }
34
+
35
+ public override getSkipReason(
36
+ conversion: MarketingConversion,
37
+ ): ConversionSkip | null {
38
+ if (!this.getClickId(conversion, "fbclid")) {
39
+ return {
40
+ reason: "No Meta click id (fbclid)",
41
+ isPermanent: true,
42
+ };
43
+ }
44
+
45
+ if (this.isOlderThanDays(conversion, META_MAX_EVENT_AGE_IN_DAYS)) {
46
+ return {
47
+ reason: "Conversion older than Meta's 7-day upload window",
48
+ isPermanent: true,
49
+ };
50
+ }
51
+
52
+ return null;
53
+ }
54
+
55
+ private hashEmail(email: string): string {
56
+ return crypto
57
+ .createHash("sha256")
58
+ .update(email.trim().toLowerCase())
59
+ .digest("hex");
60
+ }
61
+
62
+ /*
63
+ * fbc format per Meta spec: fb.1.{creationTimeMs}.{fbclid}. We use the
64
+ * conversion time as creation time since the original click timestamp is
65
+ * not stored.
66
+ */
67
+ private buildFbc(fbclid: string, eventAt: Date): string {
68
+ return `fb.1.${eventAt.getTime()}.${fbclid}`;
69
+ }
70
+
71
+ public override async upload(
72
+ conversions: Array<MarketingConversion>,
73
+ ): Promise<ConversionUploadBatchResult> {
74
+ const data: Array<JSONObject> = conversions.map(
75
+ (conversion: MarketingConversion) => {
76
+ const eventAt: Date = conversion.conversionAt || new Date();
77
+ const fbclid: string = this.getClickId(conversion, "fbclid") || "";
78
+
79
+ const userData: JSONObject = {
80
+ fbc: this.buildFbc(fbclid, eventAt),
81
+ };
82
+
83
+ if (conversion.email) {
84
+ userData["em"] = [this.hashEmail(conversion.email)];
85
+ }
86
+
87
+ const isSignUp: boolean = this.isSignUp(conversion);
88
+
89
+ const payload: JSONObject = {
90
+ event_name: isSignUp ? "CompleteRegistration" : "Purchase",
91
+ event_time: Math.floor(eventAt.getTime() / 1000),
92
+ event_id: conversion.id!.toString(),
93
+ /*
94
+ * Not "website": website events REQUIRE client_user_agent and
95
+ * event_source_url, which a server-side backfill does not have —
96
+ * Meta rejects the whole batch without them.
97
+ */
98
+ action_source: "other",
99
+ user_data: userData,
100
+ };
101
+
102
+ const valueInUSD: number | undefined = this.getValueInUSD(conversion);
103
+
104
+ /*
105
+ * Purchase events REQUIRE custom_data.value and currency — one
106
+ * valueless Purchase (custom-pricing plan) would 400 the entire
107
+ * batch. Send 0 when the value is unknown.
108
+ */
109
+ if (!isSignUp || valueInUSD !== undefined) {
110
+ payload["custom_data"] = {
111
+ value: valueInUSD ?? 0,
112
+ currency: "USD",
113
+ };
114
+ }
115
+
116
+ return payload;
117
+ },
118
+ );
119
+
120
+ const url: string = `https://graph.facebook.com/${MetaGraphApiVersion}/${MetaConversionsPixelId}/events`;
121
+
122
+ const response: AxiosResponse<JSONObject> = await axios.post(
123
+ url,
124
+ {
125
+ data: data,
126
+ access_token: MetaConversionsAccessToken,
127
+ },
128
+ {
129
+ timeout: REQUEST_TIMEOUT_MS,
130
+ },
131
+ );
132
+
133
+ const eventsReceived: number =
134
+ (response.data?.["events_received"] as number) || 0;
135
+
136
+ if (eventsReceived !== conversions.length) {
137
+ /*
138
+ * Retrying the whole batch is safe: event_id makes redelivery
139
+ * idempotent on Meta's side.
140
+ */
141
+ throw new Error(
142
+ `Meta accepted ${eventsReceived} of ${conversions.length} events`,
143
+ );
144
+ }
145
+
146
+ return { permanentFailures: new Map<number, string>() };
147
+ }
148
+ }
@@ -0,0 +1,196 @@
1
+ import axios, { AxiosResponse } from "axios";
2
+ import {
3
+ MicrosoftAdsAccountId,
4
+ MicrosoftAdsCustomerId,
5
+ MicrosoftAdsDeveloperToken,
6
+ MicrosoftAdsOAuthClientId,
7
+ MicrosoftAdsOAuthClientSecret,
8
+ MicrosoftAdsOAuthRefreshToken,
9
+ MicrosoftAdsPaidSubscriptionConversionName,
10
+ MicrosoftAdsSignUpConversionName,
11
+ } from "../../../EnvironmentConfig";
12
+ import ConversionUploadProvider, {
13
+ ConversionSkip,
14
+ ConversionUploadBatchResult,
15
+ } from "../ConversionUploadProvider";
16
+ import { JSONObject } from "../../../../Types/JSON";
17
+ import MarketingConversion from "../../../../Models/DatabaseModels/MarketingConversion";
18
+
19
+ const REQUEST_TIMEOUT_MS: number = 30000;
20
+
21
+ // Microsoft accepts offline conversions up to 90 days after the click.
22
+ const MICROSOFT_MAX_CONVERSION_AGE_IN_DAYS: number = 90;
23
+
24
+ /*
25
+ * Microsoft Advertising (Bing Ads) offline conversions via the Campaign
26
+ * Management v13 REST surface (OfflineConversions/Apply) using msclkid.
27
+ * Offline conversion goals are matched by conversion NAME configured in the
28
+ * Microsoft Advertising UI. OAuth2 refresh-token flow against Microsoft
29
+ * identity platform with the msads.manage scope.
30
+ */
31
+ export default class MicrosoftAdsProvider extends ConversionUploadProvider {
32
+ public override readonly key: string = "microsoft";
33
+ public override readonly displayName: string = "Microsoft Advertising";
34
+
35
+ private cachedAccessToken: string | null = null;
36
+ private cachedAccessTokenExpiresAt: number = 0;
37
+
38
+ public override isConfigured(): boolean {
39
+ return Boolean(
40
+ MicrosoftAdsDeveloperToken &&
41
+ MicrosoftAdsOAuthClientId &&
42
+ MicrosoftAdsOAuthRefreshToken &&
43
+ MicrosoftAdsCustomerId &&
44
+ MicrosoftAdsAccountId,
45
+ );
46
+ }
47
+
48
+ public override getSkipReason(
49
+ conversion: MarketingConversion,
50
+ ): ConversionSkip | null {
51
+ if (!this.getClickId(conversion, "msclkid")) {
52
+ return {
53
+ reason: "No Microsoft click id (msclkid)",
54
+ isPermanent: true,
55
+ };
56
+ }
57
+
58
+ if (!this.getConversionName(conversion)) {
59
+ // Config gap — leave pending so it uploads once the name is configured.
60
+ return {
61
+ reason:
62
+ "No Microsoft Advertising conversion name configured for this conversion type",
63
+ isPermanent: false,
64
+ };
65
+ }
66
+
67
+ if (
68
+ this.isOlderThanDays(conversion, MICROSOFT_MAX_CONVERSION_AGE_IN_DAYS)
69
+ ) {
70
+ return {
71
+ reason: "Conversion older than Microsoft's 90-day click window",
72
+ isPermanent: true,
73
+ };
74
+ }
75
+
76
+ return null;
77
+ }
78
+
79
+ private getConversionName(conversion: MarketingConversion): string {
80
+ return this.isSignUp(conversion)
81
+ ? MicrosoftAdsSignUpConversionName
82
+ : MicrosoftAdsPaidSubscriptionConversionName;
83
+ }
84
+
85
+ private async getAccessToken(): Promise<string> {
86
+ if (
87
+ this.cachedAccessToken &&
88
+ Date.now() < this.cachedAccessTokenExpiresAt
89
+ ) {
90
+ return this.cachedAccessToken;
91
+ }
92
+
93
+ const params: URLSearchParams = new URLSearchParams();
94
+ params.append("client_id", MicrosoftAdsOAuthClientId);
95
+ if (MicrosoftAdsOAuthClientSecret) {
96
+ params.append("client_secret", MicrosoftAdsOAuthClientSecret);
97
+ }
98
+ params.append("refresh_token", MicrosoftAdsOAuthRefreshToken);
99
+ params.append("grant_type", "refresh_token");
100
+ params.append(
101
+ "scope",
102
+ "https://ads.microsoft.com/msads.manage offline_access",
103
+ );
104
+
105
+ const response: AxiosResponse<{
106
+ access_token?: string;
107
+ expires_in?: number;
108
+ }> = await axios.post(
109
+ "https://login.microsoftonline.com/common/oauth2/v2.0/token",
110
+ params.toString(),
111
+ {
112
+ headers: {
113
+ "content-type": "application/x-www-form-urlencoded",
114
+ },
115
+ timeout: REQUEST_TIMEOUT_MS,
116
+ },
117
+ );
118
+
119
+ const accessToken: string | undefined = response.data?.access_token;
120
+
121
+ if (!accessToken) {
122
+ throw new Error("Microsoft OAuth token response had no access_token");
123
+ }
124
+
125
+ this.cachedAccessToken = accessToken;
126
+ this.cachedAccessTokenExpiresAt =
127
+ Date.now() + ((response.data?.expires_in || 3600) - 60) * 1000;
128
+
129
+ return accessToken;
130
+ }
131
+
132
+ public override async upload(
133
+ conversions: Array<MarketingConversion>,
134
+ ): Promise<ConversionUploadBatchResult> {
135
+ const accessToken: string = await this.getAccessToken();
136
+
137
+ const body: JSONObject = {
138
+ OfflineConversions: conversions.map((conversion: MarketingConversion) => {
139
+ const payload: JSONObject = {
140
+ MicrosoftClickId: this.getClickId(conversion, "msclkid") || "",
141
+ ConversionName: this.getConversionName(conversion),
142
+ // ISO 8601 UTC, e.g. 2026-07-18T12:34:56Z.
143
+ ConversionTime: (conversion.conversionAt || new Date())
144
+ .toISOString()
145
+ .replace(/\.\d{3}Z$/, "Z"),
146
+ };
147
+
148
+ const valueInUSD: number | undefined = this.getValueInUSD(conversion);
149
+
150
+ if (valueInUSD !== undefined) {
151
+ payload["ConversionValue"] = valueInUSD;
152
+ payload["ConversionCurrencyCode"] = "USD";
153
+ }
154
+
155
+ return payload;
156
+ }),
157
+ };
158
+
159
+ const response: AxiosResponse<JSONObject> = await axios.post(
160
+ "https://campaign.api.bingads.microsoft.com/CampaignManagement/v13/OfflineConversions/Apply",
161
+ body,
162
+ {
163
+ headers: {
164
+ Authorization: `Bearer ${accessToken}`,
165
+ DeveloperToken: MicrosoftAdsDeveloperToken,
166
+ CustomerId: MicrosoftAdsCustomerId,
167
+ CustomerAccountId: MicrosoftAdsAccountId,
168
+ "Content-Type": "application/json",
169
+ },
170
+ timeout: REQUEST_TIMEOUT_MS,
171
+ },
172
+ );
173
+
174
+ /*
175
+ * The Apply response reports per-item failures in PartialErrors, each
176
+ * carrying the Index of the failing item in the submitted array.
177
+ */
178
+ const permanentFailures: Map<number, string> = new Map<number, string>();
179
+
180
+ const partialErrors: Array<JSONObject> =
181
+ (response.data?.["PartialErrors"] as Array<JSONObject>) || [];
182
+
183
+ for (const partialError of partialErrors) {
184
+ if (typeof partialError?.["Index"] === "number") {
185
+ permanentFailures.set(
186
+ partialError["Index"] as number,
187
+ `${partialError["ErrorCode"] || ""} ${
188
+ partialError["Message"] || "Unknown Microsoft Advertising error"
189
+ }`.trim(),
190
+ );
191
+ }
192
+ }
193
+
194
+ return { permanentFailures };
195
+ }
196
+ }
@@ -0,0 +1,178 @@
1
+ import axios, { AxiosResponse } from "axios";
2
+ import crypto from "crypto";
3
+ import {
4
+ RedditAdsAccountId,
5
+ RedditAdsOAuthClientId,
6
+ RedditAdsOAuthClientSecret,
7
+ RedditAdsOAuthRefreshToken,
8
+ } from "../../../EnvironmentConfig";
9
+ import ConversionUploadProvider, {
10
+ ConversionSkip,
11
+ ConversionUploadBatchResult,
12
+ } from "../ConversionUploadProvider";
13
+ import { JSONObject } from "../../../../Types/JSON";
14
+ import MarketingConversion from "../../../../Models/DatabaseModels/MarketingConversion";
15
+
16
+ const REQUEST_TIMEOUT_MS: number = 30000;
17
+
18
+ // Reddit accepts conversion events up to 7 days old.
19
+ const REDDIT_MAX_EVENT_AGE_IN_DAYS: number = 7;
20
+
21
+ /*
22
+ * Reddit Conversions API
23
+ * (ads-api.reddit.com/api/v2.0/conversions/events/{accountId}) using the
24
+ * rdt_cid click id. conversion_id (the conversion row id) makes retried
25
+ * uploads idempotent on Reddit's side. OAuth2 refresh-token flow with HTTP
26
+ * basic auth against reddit.com.
27
+ */
28
+ export default class RedditProvider extends ConversionUploadProvider {
29
+ public override readonly key: string = "reddit";
30
+ public override readonly displayName: string = "Reddit";
31
+
32
+ private cachedAccessToken: string | null = null;
33
+ private cachedAccessTokenExpiresAt: number = 0;
34
+
35
+ public override isConfigured(): boolean {
36
+ return Boolean(
37
+ RedditAdsOAuthClientId &&
38
+ RedditAdsOAuthClientSecret &&
39
+ RedditAdsOAuthRefreshToken &&
40
+ RedditAdsAccountId,
41
+ );
42
+ }
43
+
44
+ public override getSkipReason(
45
+ conversion: MarketingConversion,
46
+ ): ConversionSkip | null {
47
+ if (!this.getClickId(conversion, "rdt_cid")) {
48
+ return {
49
+ reason: "No Reddit click id (rdt_cid)",
50
+ isPermanent: true,
51
+ };
52
+ }
53
+
54
+ if (this.isOlderThanDays(conversion, REDDIT_MAX_EVENT_AGE_IN_DAYS)) {
55
+ return {
56
+ reason: "Conversion older than Reddit's 7-day upload window",
57
+ isPermanent: true,
58
+ };
59
+ }
60
+
61
+ return null;
62
+ }
63
+
64
+ private hashEmail(email: string): string {
65
+ return crypto
66
+ .createHash("sha256")
67
+ .update(email.trim().toLowerCase())
68
+ .digest("hex");
69
+ }
70
+
71
+ private async getAccessToken(): Promise<string> {
72
+ if (
73
+ this.cachedAccessToken &&
74
+ Date.now() < this.cachedAccessTokenExpiresAt
75
+ ) {
76
+ return this.cachedAccessToken;
77
+ }
78
+
79
+ const params: URLSearchParams = new URLSearchParams();
80
+ params.append("grant_type", "refresh_token");
81
+ params.append("refresh_token", RedditAdsOAuthRefreshToken);
82
+
83
+ const response: AxiosResponse<{
84
+ access_token?: string;
85
+ expires_in?: number;
86
+ }> = await axios.post(
87
+ "https://www.reddit.com/api/v1/access_token",
88
+ params.toString(),
89
+ {
90
+ auth: {
91
+ username: RedditAdsOAuthClientId,
92
+ password: RedditAdsOAuthClientSecret,
93
+ },
94
+ headers: {
95
+ "content-type": "application/x-www-form-urlencoded",
96
+ // Reddit throttles/blocks requests without a descriptive User-Agent.
97
+ "User-Agent": "OneUptime-ConversionsUpload/1.0",
98
+ },
99
+ timeout: REQUEST_TIMEOUT_MS,
100
+ },
101
+ );
102
+
103
+ const accessToken: string | undefined = response.data?.access_token;
104
+
105
+ if (!accessToken) {
106
+ throw new Error("Reddit OAuth token response had no access_token");
107
+ }
108
+
109
+ this.cachedAccessToken = accessToken;
110
+ this.cachedAccessTokenExpiresAt =
111
+ Date.now() + ((response.data?.expires_in || 3600) - 60) * 1000;
112
+
113
+ return accessToken;
114
+ }
115
+
116
+ public override async upload(
117
+ conversions: Array<MarketingConversion>,
118
+ ): Promise<ConversionUploadBatchResult> {
119
+ const accessToken: string = await this.getAccessToken();
120
+
121
+ const events: Array<JSONObject> = conversions.map(
122
+ (conversion: MarketingConversion) => {
123
+ const eventAt: Date = conversion.conversionAt || new Date();
124
+
125
+ const eventMetadata: JSONObject = {
126
+ // Dedup key: retried uploads are idempotent on Reddit's side.
127
+ conversion_id: conversion.id!.toString(),
128
+ };
129
+
130
+ const valueInUSD: number | undefined = this.getValueInUSD(conversion);
131
+
132
+ if (valueInUSD !== undefined) {
133
+ eventMetadata["value_decimal"] = valueInUSD;
134
+ eventMetadata["currency"] = "USD";
135
+ }
136
+
137
+ const payload: JSONObject = {
138
+ event_at: eventAt.toISOString(),
139
+ click_id: this.getClickId(conversion, "rdt_cid") || "",
140
+ event_type: {
141
+ tracking_type: this.isSignUp(conversion) ? "SignUp" : "Purchase",
142
+ },
143
+ event_metadata: eventMetadata,
144
+ };
145
+
146
+ if (conversion.email) {
147
+ payload["user"] = {
148
+ email: this.hashEmail(conversion.email),
149
+ };
150
+ }
151
+
152
+ return payload;
153
+ },
154
+ );
155
+
156
+ await axios.post(
157
+ `https://ads-api.reddit.com/api/v2.0/conversions/events/${RedditAdsAccountId}`,
158
+ {
159
+ test_mode: false,
160
+ events: events,
161
+ },
162
+ {
163
+ headers: {
164
+ Authorization: `Bearer ${accessToken}`,
165
+ "Content-Type": "application/json",
166
+ },
167
+ timeout: REQUEST_TIMEOUT_MS,
168
+ },
169
+ );
170
+
171
+ /*
172
+ * Reddit accepts or rejects the request as a whole; request-level
173
+ * failures throw and the batch is retried (idempotent via
174
+ * conversion_id).
175
+ */
176
+ return { permanentFailures: new Map<number, string>() };
177
+ }
178
+ }
@@ -24,6 +24,9 @@ import AlertService from "../../Services/AlertService";
24
24
  import AlertSeverityService from "../../Services/AlertSeverityService";
25
25
  import AlertStateTimelineService from "../../Services/AlertStateTimelineService";
26
26
  import HostService from "../../Services/HostService";
27
+ import NetworkDeviceOwnerUserService, {
28
+ NetworkDeviceOwners,
29
+ } from "../../Services/NetworkDeviceOwnerUserService";
27
30
  import ServiceService from "../../Services/ServiceService";
28
31
  import logger, { LogAttributes } from "../Logger";
29
32
  import CaptureSpan from "../Telemetry/CaptureSpan";
@@ -300,6 +303,15 @@ export default class MonitorAlert {
300
303
  ? input.matchesPerSeries
301
304
  : [undefined];
302
305
 
306
+ /*
307
+ * Owners of the network device this monitor watches (if any), resolved
308
+ * lazily on first alert creation and reused for the rest of the
309
+ * evaluation — the device is configured per monitor step, so it is
310
+ * constant across the criteria/series loops below. Merged into every
311
+ * created alert's owners alongside the criteria-configured ones.
312
+ */
313
+ let networkDeviceOwners: NetworkDeviceOwners | null = null;
314
+
303
315
  for (const criteriaAlert of input.criteriaInstance.data?.alerts || []) {
304
316
  for (const seriesMatch of seriesToProcess) {
305
317
  const seriesFingerprint: string | undefined = seriesMatch?.fingerprint;
@@ -627,16 +639,38 @@ export default class MonitorAlert {
627
639
  },
628
640
  });
629
641
 
630
- // Add owner teams and users after alert creation
631
- if (
632
- criteriaAlert.ownerTeamIds?.length ||
633
- criteriaAlert.ownerUserIds?.length
634
- ) {
642
+ /*
643
+ * Add owner teams and users after alert creation. Owners configured
644
+ * on the criteria template are merged (deduped) with the owners of
645
+ * the network device this monitor watches, so device ownership flows
646
+ * into the alerts its monitor raises.
647
+ */
648
+ if (networkDeviceOwners === null) {
649
+ networkDeviceOwners =
650
+ await NetworkDeviceOwnerUserService.getDeviceOwnersForMonitor({
651
+ monitor: input.monitor,
652
+ monitorStepId: (
653
+ input.dataToProcess as ProbeMonitorResponse
654
+ ).monitorStepId?.toString(),
655
+ });
656
+ }
657
+
658
+ const ownerUserIds: Array<ObjectID> = this.mergeOwnerIds(
659
+ criteriaAlert.ownerUserIds || [],
660
+ networkDeviceOwners.ownerUserIds,
661
+ );
662
+
663
+ const ownerTeamIds: Array<ObjectID> = this.mergeOwnerIds(
664
+ criteriaAlert.ownerTeamIds || [],
665
+ networkDeviceOwners.ownerTeamIds,
666
+ );
667
+
668
+ if (ownerTeamIds.length || ownerUserIds.length) {
635
669
  await AlertService.addOwners(
636
670
  input.monitor.projectId!,
637
671
  createdAlert.id!,
638
- criteriaAlert.ownerUserIds || [],
639
- criteriaAlert.ownerTeamIds || [],
672
+ ownerUserIds,
673
+ ownerTeamIds,
640
674
  true, // notify owners
641
675
  {
642
676
  isRoot: true,
@@ -658,6 +692,36 @@ export default class MonitorAlert {
658
692
  }
659
693
  }
660
694
 
695
+ /*
696
+ * Merges two owner id lists, deduping by string value. Criteria-authored
697
+ * ids can arrive as plain strings from stored JSON, so normalise through
698
+ * toString() for both the comparison and the returned ObjectIDs.
699
+ */
700
+ private static mergeOwnerIds(
701
+ primary: Array<ObjectID>,
702
+ additional: Array<ObjectID>,
703
+ ): Array<ObjectID> {
704
+ const seenIds: Set<string> = new Set<string>();
705
+ const mergedIds: Array<ObjectID> = [];
706
+
707
+ for (const ownerId of [...primary, ...additional]) {
708
+ if (!ownerId) {
709
+ continue;
710
+ }
711
+
712
+ const ownerIdAsString: string = ownerId.toString();
713
+
714
+ if (!ownerIdAsString || seenIds.has(ownerIdAsString)) {
715
+ continue;
716
+ }
717
+
718
+ seenIds.add(ownerIdAsString);
719
+ mergedIds.push(new ObjectID(ownerIdAsString));
720
+ }
721
+
722
+ return mergedIds;
723
+ }
724
+
661
725
  private static async resolveOpenAlert(input: {
662
726
  openAlert: Alert;
663
727
  rootCause: string;