@oneuptime/common 10.7.2 → 10.8.1

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 (256) hide show
  1. package/Models/DatabaseModels/CloudResource.ts +846 -0
  2. package/Models/DatabaseModels/CloudResourceInstance.ts +276 -0
  3. package/Models/DatabaseModels/CloudResourceLabelRule.ts +510 -0
  4. package/Models/DatabaseModels/CloudResourceOwnerRule.ts +592 -0
  5. package/Models/DatabaseModels/CloudResourceOwnerTeam.ts +487 -0
  6. package/Models/DatabaseModels/CloudResourceOwnerUser.ts +486 -0
  7. package/Models/DatabaseModels/Host.ts +209 -0
  8. package/Models/DatabaseModels/Index.ts +36 -0
  9. package/Models/DatabaseModels/RumApplication.ts +731 -0
  10. package/Models/DatabaseModels/RumApplicationClient.ts +229 -0
  11. package/Models/DatabaseModels/RumApplicationLabelRule.ts +510 -0
  12. package/Models/DatabaseModels/RumApplicationOwnerRule.ts +592 -0
  13. package/Models/DatabaseModels/RumApplicationOwnerTeam.ts +486 -0
  14. package/Models/DatabaseModels/RumApplicationOwnerUser.ts +485 -0
  15. package/Models/DatabaseModels/ServerlessFunction.ts +881 -0
  16. package/Models/DatabaseModels/ServerlessFunctionInstance.ts +212 -0
  17. package/Models/DatabaseModels/ServerlessFunctionLabelRule.ts +510 -0
  18. package/Models/DatabaseModels/ServerlessFunctionOwnerRule.ts +592 -0
  19. package/Models/DatabaseModels/ServerlessFunctionOwnerTeam.ts +487 -0
  20. package/Models/DatabaseModels/ServerlessFunctionOwnerUser.ts +486 -0
  21. package/Models/DatabaseModels/Service.ts +268 -0
  22. package/Models/DatabaseModels/TelemetryException.ts +15 -1
  23. package/Models/DatabaseModels/WorkflowLog.ts +52 -0
  24. package/Server/API/TelemetryAPI.ts +78 -25
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1780931746908-AddResumeStateToWorkflowLog.ts +21 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1780931863719-AddTelemetryResourceMetadataColumns.ts +108 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1780933132562-AddServerlessFunctionTables.ts +205 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1780935387827-AddCloudResourceTables.ts +195 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1780936579718-AddRumApplicationTables.ts +202 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1780938407319-AddServerlessFunctionRuleTables.ts +156 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1780940721814-AddCloudResourceRuleTables.ts +149 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1780940998002-AddRumApplicationRuleTables.ts +149 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/1780941762204-AddTelemetryResourceInventoryTables.ts +95 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1780985763463-AddRumApplicationSdkLanguage.ts +25 -0
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1780987192743-RecastCloudResourcesByEnvironment.ts +30 -0
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +22 -0
  37. package/Server/Infrastructure/Queue.ts +11 -0
  38. package/Server/Services/CloudResourceInstanceService.ts +76 -0
  39. package/Server/Services/CloudResourceLabelRuleEngineService.ts +175 -0
  40. package/Server/Services/CloudResourceLabelRuleService.ts +14 -0
  41. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +192 -0
  42. package/Server/Services/CloudResourceOwnerRuleService.ts +14 -0
  43. package/Server/Services/CloudResourceOwnerTeamService.ts +10 -0
  44. package/Server/Services/CloudResourceOwnerUserService.ts +10 -0
  45. package/Server/Services/CloudResourceService.ts +342 -0
  46. package/Server/Services/ExceptionAggregationService.ts +3 -0
  47. package/Server/Services/HostService.ts +42 -0
  48. package/Server/Services/LogAggregationService.ts +44 -16
  49. package/Server/Services/MetricAggregationService.ts +3 -0
  50. package/Server/Services/OpenTelemetryIngestService.ts +148 -1
  51. package/Server/Services/RumApplicationClientService.ts +69 -0
  52. package/Server/Services/RumApplicationLabelRuleEngineService.ts +175 -0
  53. package/Server/Services/RumApplicationLabelRuleService.ts +14 -0
  54. package/Server/Services/RumApplicationOwnerRuleEngineService.ts +192 -0
  55. package/Server/Services/RumApplicationOwnerRuleService.ts +14 -0
  56. package/Server/Services/RumApplicationOwnerTeamService.ts +10 -0
  57. package/Server/Services/RumApplicationOwnerUserService.ts +10 -0
  58. package/Server/Services/RumApplicationService.ts +301 -0
  59. package/Server/Services/ServerlessFunctionInstanceService.ts +61 -0
  60. package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +182 -0
  61. package/Server/Services/ServerlessFunctionLabelRuleService.ts +14 -0
  62. package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +199 -0
  63. package/Server/Services/ServerlessFunctionOwnerRuleService.ts +14 -0
  64. package/Server/Services/ServerlessFunctionOwnerTeamService.ts +10 -0
  65. package/Server/Services/ServerlessFunctionOwnerUserService.ts +10 -0
  66. package/Server/Services/ServerlessFunctionService.ts +351 -0
  67. package/Server/Services/ServiceService.ts +95 -8
  68. package/Server/Services/TraceAggregationService.ts +131 -4
  69. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +39 -0
  70. package/Server/Types/Workflow/ComponentCode.ts +9 -0
  71. package/Server/Types/Workflow/Components/Index.ts +2 -0
  72. package/Server/Types/Workflow/Components/Sleep.ts +105 -0
  73. package/Server/Types/Workflow/Workflow.ts +6 -0
  74. package/Server/Utils/Telemetry/ResourceFacetResolver.ts +150 -0
  75. package/Types/Permission.ts +692 -1
  76. package/Types/Telemetry/ServiceType.ts +3 -0
  77. package/Types/Workflow/ComponentID.ts +1 -0
  78. package/Types/Workflow/Components/Sleep.ts +71 -0
  79. package/Types/Workflow/Components.ts +2 -0
  80. package/Types/Workflow/WorkflowStatus.ts +1 -0
  81. package/UI/Components/BulkUpdate/BulkLabelActions.tsx +159 -32
  82. package/UI/Components/Navbar/NavBar.tsx +72 -123
  83. package/UI/Components/Navbar/NavBarMenuModal.tsx +642 -0
  84. package/UI/Components/Workflow/WorkflowStatus.tsx +3 -0
  85. package/build/dist/Models/DatabaseModels/CloudResource.js +871 -0
  86. package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -0
  87. package/build/dist/Models/DatabaseModels/CloudResourceInstance.js +300 -0
  88. package/build/dist/Models/DatabaseModels/CloudResourceInstance.js.map +1 -0
  89. package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js +520 -0
  90. package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js.map +1 -0
  91. package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js +601 -0
  92. package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js.map +1 -0
  93. package/build/dist/Models/DatabaseModels/CloudResourceOwnerTeam.js +503 -0
  94. package/build/dist/Models/DatabaseModels/CloudResourceOwnerTeam.js.map +1 -0
  95. package/build/dist/Models/DatabaseModels/CloudResourceOwnerUser.js +502 -0
  96. package/build/dist/Models/DatabaseModels/CloudResourceOwnerUser.js.map +1 -0
  97. package/build/dist/Models/DatabaseModels/Host.js +215 -0
  98. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  99. package/build/dist/Models/DatabaseModels/Index.js +36 -0
  100. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  101. package/build/dist/Models/DatabaseModels/RumApplication.js +751 -0
  102. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -0
  103. package/build/dist/Models/DatabaseModels/RumApplicationClient.js +252 -0
  104. package/build/dist/Models/DatabaseModels/RumApplicationClient.js.map +1 -0
  105. package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js +520 -0
  106. package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js.map +1 -0
  107. package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js +601 -0
  108. package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js.map +1 -0
  109. package/build/dist/Models/DatabaseModels/RumApplicationOwnerTeam.js +503 -0
  110. package/build/dist/Models/DatabaseModels/RumApplicationOwnerTeam.js.map +1 -0
  111. package/build/dist/Models/DatabaseModels/RumApplicationOwnerUser.js +502 -0
  112. package/build/dist/Models/DatabaseModels/RumApplicationOwnerUser.js.map +1 -0
  113. package/build/dist/Models/DatabaseModels/ServerlessFunction.js +908 -0
  114. package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -0
  115. package/build/dist/Models/DatabaseModels/ServerlessFunctionInstance.js +234 -0
  116. package/build/dist/Models/DatabaseModels/ServerlessFunctionInstance.js.map +1 -0
  117. package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js +520 -0
  118. package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js.map +1 -0
  119. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js +601 -0
  120. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js.map +1 -0
  121. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerTeam.js +503 -0
  122. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerTeam.js.map +1 -0
  123. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerUser.js +502 -0
  124. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerUser.js.map +1 -0
  125. package/build/dist/Models/DatabaseModels/Service.js +276 -0
  126. package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
  127. package/build/dist/Models/DatabaseModels/TelemetryException.js +12 -1
  128. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  129. package/build/dist/Models/DatabaseModels/WorkflowLog.js +53 -0
  130. package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
  131. package/build/dist/Server/API/TelemetryAPI.js +61 -23
  132. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  133. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780931746908-AddResumeStateToWorkflowLog.js +14 -0
  134. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780931746908-AddResumeStateToWorkflowLog.js.map +1 -0
  135. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780931863719-AddTelemetryResourceMetadataColumns.js +53 -0
  136. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780931863719-AddTelemetryResourceMetadataColumns.js.map +1 -0
  137. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780933132562-AddServerlessFunctionTables.js +82 -0
  138. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780933132562-AddServerlessFunctionTables.js.map +1 -0
  139. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780935387827-AddCloudResourceTables.js +82 -0
  140. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780935387827-AddCloudResourceTables.js.map +1 -0
  141. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780936579718-AddRumApplicationTables.js +83 -0
  142. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780936579718-AddRumApplicationTables.js.map +1 -0
  143. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780938407319-AddServerlessFunctionRuleTables.js +67 -0
  144. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780938407319-AddServerlessFunctionRuleTables.js.map +1 -0
  145. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780940721814-AddCloudResourceRuleTables.js +60 -0
  146. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780940721814-AddCloudResourceRuleTables.js.map +1 -0
  147. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780940998002-AddRumApplicationRuleTables.js +60 -0
  148. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780940998002-AddRumApplicationRuleTables.js.map +1 -0
  149. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780941762204-AddTelemetryResourceInventoryTables.js +45 -0
  150. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780941762204-AddTelemetryResourceInventoryTables.js.map +1 -0
  151. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780985763463-AddRumApplicationSdkLanguage.js +18 -0
  152. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780985763463-AddRumApplicationSdkLanguage.js.map +1 -0
  153. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780987192743-RecastCloudResourcesByEnvironment.js +27 -0
  154. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1780987192743-RecastCloudResourcesByEnvironment.js.map +1 -0
  155. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +22 -0
  156. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  157. package/build/dist/Server/Infrastructure/Queue.js +3 -0
  158. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  159. package/build/dist/Server/Services/CloudResourceInstanceService.js +76 -0
  160. package/build/dist/Server/Services/CloudResourceInstanceService.js.map +1 -0
  161. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +160 -0
  162. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -0
  163. package/build/dist/Server/Services/CloudResourceLabelRuleService.js +13 -0
  164. package/build/dist/Server/Services/CloudResourceLabelRuleService.js.map +1 -0
  165. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +179 -0
  166. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -0
  167. package/build/dist/Server/Services/CloudResourceOwnerRuleService.js +13 -0
  168. package/build/dist/Server/Services/CloudResourceOwnerRuleService.js.map +1 -0
  169. package/build/dist/Server/Services/CloudResourceOwnerTeamService.js +9 -0
  170. package/build/dist/Server/Services/CloudResourceOwnerTeamService.js.map +1 -0
  171. package/build/dist/Server/Services/CloudResourceOwnerUserService.js +9 -0
  172. package/build/dist/Server/Services/CloudResourceOwnerUserService.js.map +1 -0
  173. package/build/dist/Server/Services/CloudResourceService.js +287 -0
  174. package/build/dist/Server/Services/CloudResourceService.js.map +1 -0
  175. package/build/dist/Server/Services/ExceptionAggregationService.js +3 -0
  176. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  177. package/build/dist/Server/Services/HostService.js +29 -1
  178. package/build/dist/Server/Services/HostService.js.map +1 -1
  179. package/build/dist/Server/Services/LogAggregationService.js +36 -10
  180. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  181. package/build/dist/Server/Services/MetricAggregationService.js +3 -0
  182. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  183. package/build/dist/Server/Services/OpenTelemetryIngestService.js +98 -2
  184. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  185. package/build/dist/Server/Services/RumApplicationClientService.js +70 -0
  186. package/build/dist/Server/Services/RumApplicationClientService.js.map +1 -0
  187. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +160 -0
  188. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -0
  189. package/build/dist/Server/Services/RumApplicationLabelRuleService.js +13 -0
  190. package/build/dist/Server/Services/RumApplicationLabelRuleService.js.map +1 -0
  191. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +179 -0
  192. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -0
  193. package/build/dist/Server/Services/RumApplicationOwnerRuleService.js +13 -0
  194. package/build/dist/Server/Services/RumApplicationOwnerRuleService.js.map +1 -0
  195. package/build/dist/Server/Services/RumApplicationOwnerTeamService.js +9 -0
  196. package/build/dist/Server/Services/RumApplicationOwnerTeamService.js.map +1 -0
  197. package/build/dist/Server/Services/RumApplicationOwnerUserService.js +9 -0
  198. package/build/dist/Server/Services/RumApplicationOwnerUserService.js.map +1 -0
  199. package/build/dist/Server/Services/RumApplicationService.js +259 -0
  200. package/build/dist/Server/Services/RumApplicationService.js.map +1 -0
  201. package/build/dist/Server/Services/ServerlessFunctionInstanceService.js +64 -0
  202. package/build/dist/Server/Services/ServerlessFunctionInstanceService.js.map +1 -0
  203. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +160 -0
  204. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -0
  205. package/build/dist/Server/Services/ServerlessFunctionLabelRuleService.js +13 -0
  206. package/build/dist/Server/Services/ServerlessFunctionLabelRuleService.js.map +1 -0
  207. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +179 -0
  208. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -0
  209. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleService.js +13 -0
  210. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleService.js.map +1 -0
  211. package/build/dist/Server/Services/ServerlessFunctionOwnerTeamService.js +9 -0
  212. package/build/dist/Server/Services/ServerlessFunctionOwnerTeamService.js.map +1 -0
  213. package/build/dist/Server/Services/ServerlessFunctionOwnerUserService.js +9 -0
  214. package/build/dist/Server/Services/ServerlessFunctionOwnerUserService.js.map +1 -0
  215. package/build/dist/Server/Services/ServerlessFunctionService.js +299 -0
  216. package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -0
  217. package/build/dist/Server/Services/ServiceService.js +63 -7
  218. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  219. package/build/dist/Server/Services/TraceAggregationService.js +108 -4
  220. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  221. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +39 -0
  222. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  223. package/build/dist/Server/Types/Workflow/ComponentCode.js.map +1 -1
  224. package/build/dist/Server/Types/Workflow/Components/Index.js +2 -0
  225. package/build/dist/Server/Types/Workflow/Components/Index.js.map +1 -1
  226. package/build/dist/Server/Types/Workflow/Components/Sleep.js +85 -0
  227. package/build/dist/Server/Types/Workflow/Components/Sleep.js.map +1 -0
  228. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +90 -0
  229. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
  230. package/build/dist/Types/Permission.js +609 -1
  231. package/build/dist/Types/Permission.js.map +1 -1
  232. package/build/dist/Types/Telemetry/ServiceType.js +3 -0
  233. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  234. package/build/dist/Types/Workflow/ComponentID.js +1 -0
  235. package/build/dist/Types/Workflow/ComponentID.js.map +1 -1
  236. package/build/dist/Types/Workflow/Components/Sleep.js +64 -0
  237. package/build/dist/Types/Workflow/Components/Sleep.js.map +1 -0
  238. package/build/dist/Types/Workflow/Components.js +2 -0
  239. package/build/dist/Types/Workflow/Components.js.map +1 -1
  240. package/build/dist/Types/Workflow/WorkflowStatus.js +1 -0
  241. package/build/dist/Types/Workflow/WorkflowStatus.js.map +1 -1
  242. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +113 -19
  243. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
  244. package/build/dist/UI/Components/Navbar/NavBar.js +34 -66
  245. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  246. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +412 -0
  247. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -0
  248. package/build/dist/UI/Components/Workflow/WorkflowStatus.js +3 -0
  249. package/build/dist/UI/Components/Workflow/WorkflowStatus.js.map +1 -1
  250. package/package.json +1 -1
  251. package/UI/Components/Navbar/NavBarMenu.tsx +0 -183
  252. package/UI/Components/Navbar/NavBarMenuItem.tsx +0 -146
  253. package/build/dist/UI/Components/Navbar/NavBarMenu.js +0 -82
  254. package/build/dist/UI/Components/Navbar/NavBarMenu.js.map +0 -1
  255. package/build/dist/UI/Components/Navbar/NavBarMenuItem.js +0 -109
  256. package/build/dist/UI/Components/Navbar/NavBarMenuItem.js.map +0 -1
@@ -863,4 +863,272 @@ export default class Service extends BaseModel {
863
863
  type: ColumnType.Date,
864
864
  })
865
865
  public lastSeenAt?: Date = undefined;
866
+
867
+ /*
868
+ * The columns below are auto-populated from OpenTelemetry resource
869
+ * attributes at ingest time (see OTelIngestService.telemetryServiceFromName).
870
+ * They are system-managed — not user-editable — so create/update access
871
+ * control is empty and writes only happen via the root ingest path.
872
+ */
873
+
874
+ @ColumnAccessControl({
875
+ create: [],
876
+ read: [
877
+ Permission.ProjectOwner,
878
+ Permission.ProjectAdmin,
879
+ Permission.ProjectMember,
880
+ Permission.Viewer,
881
+ Permission.SettingsAdmin,
882
+ Permission.SettingsMember,
883
+ Permission.SettingsViewer,
884
+ Permission.ReadService,
885
+ ],
886
+ update: [],
887
+ })
888
+ @TableColumn({
889
+ required: false,
890
+ type: TableColumnType.ShortText,
891
+ canReadOnRelationQuery: true,
892
+ title: "Service Version",
893
+ description:
894
+ "Last-seen value of the service.version OpenTelemetry resource attribute.",
895
+ })
896
+ @Column({
897
+ nullable: true,
898
+ type: ColumnType.ShortText,
899
+ length: ColumnLength.ShortText,
900
+ })
901
+ public serviceVersion?: string = undefined;
902
+
903
+ @ColumnAccessControl({
904
+ create: [],
905
+ read: [
906
+ Permission.ProjectOwner,
907
+ Permission.ProjectAdmin,
908
+ Permission.ProjectMember,
909
+ Permission.Viewer,
910
+ Permission.SettingsAdmin,
911
+ Permission.SettingsMember,
912
+ Permission.SettingsViewer,
913
+ Permission.ReadService,
914
+ ],
915
+ update: [],
916
+ })
917
+ @TableColumn({
918
+ required: false,
919
+ type: TableColumnType.ShortText,
920
+ canReadOnRelationQuery: true,
921
+ title: "Deployment Environment",
922
+ description:
923
+ "Last-seen value of the deployment.environment.name (or deployment.environment) OpenTelemetry resource attribute, e.g. production, staging.",
924
+ })
925
+ @Column({
926
+ nullable: true,
927
+ type: ColumnType.ShortText,
928
+ length: ColumnLength.ShortText,
929
+ })
930
+ public deploymentEnvironment?: string = undefined;
931
+
932
+ @ColumnAccessControl({
933
+ create: [],
934
+ read: [
935
+ Permission.ProjectOwner,
936
+ Permission.ProjectAdmin,
937
+ Permission.ProjectMember,
938
+ Permission.Viewer,
939
+ Permission.SettingsAdmin,
940
+ Permission.SettingsMember,
941
+ Permission.SettingsViewer,
942
+ Permission.ReadService,
943
+ ],
944
+ update: [],
945
+ })
946
+ @TableColumn({
947
+ required: false,
948
+ type: TableColumnType.ShortText,
949
+ canReadOnRelationQuery: true,
950
+ title: "Service Namespace",
951
+ description:
952
+ "Last-seen value of the service.namespace OpenTelemetry resource attribute.",
953
+ })
954
+ @Column({
955
+ nullable: true,
956
+ type: ColumnType.ShortText,
957
+ length: ColumnLength.ShortText,
958
+ })
959
+ public serviceNamespace?: string = undefined;
960
+
961
+ @ColumnAccessControl({
962
+ create: [],
963
+ read: [
964
+ Permission.ProjectOwner,
965
+ Permission.ProjectAdmin,
966
+ Permission.ProjectMember,
967
+ Permission.Viewer,
968
+ Permission.SettingsAdmin,
969
+ Permission.SettingsMember,
970
+ Permission.SettingsViewer,
971
+ Permission.ReadService,
972
+ ],
973
+ update: [],
974
+ })
975
+ @TableColumn({
976
+ required: false,
977
+ type: TableColumnType.ShortText,
978
+ canReadOnRelationQuery: true,
979
+ title: "Runtime Name",
980
+ description:
981
+ "Last-seen value of the process.runtime.name OpenTelemetry resource attribute, e.g. nodejs, go, OpenJDK Runtime Environment.",
982
+ })
983
+ @Column({
984
+ nullable: true,
985
+ type: ColumnType.ShortText,
986
+ length: ColumnLength.ShortText,
987
+ })
988
+ public runtimeName?: string = undefined;
989
+
990
+ @ColumnAccessControl({
991
+ create: [],
992
+ read: [
993
+ Permission.ProjectOwner,
994
+ Permission.ProjectAdmin,
995
+ Permission.ProjectMember,
996
+ Permission.Viewer,
997
+ Permission.SettingsAdmin,
998
+ Permission.SettingsMember,
999
+ Permission.SettingsViewer,
1000
+ Permission.ReadService,
1001
+ ],
1002
+ update: [],
1003
+ })
1004
+ @TableColumn({
1005
+ required: false,
1006
+ type: TableColumnType.ShortText,
1007
+ canReadOnRelationQuery: true,
1008
+ title: "Runtime Version",
1009
+ description:
1010
+ "Last-seen value of the process.runtime.version OpenTelemetry resource attribute.",
1011
+ })
1012
+ @Column({
1013
+ nullable: true,
1014
+ type: ColumnType.ShortText,
1015
+ length: ColumnLength.ShortText,
1016
+ })
1017
+ public runtimeVersion?: string = undefined;
1018
+
1019
+ @ColumnAccessControl({
1020
+ create: [],
1021
+ read: [
1022
+ Permission.ProjectOwner,
1023
+ Permission.ProjectAdmin,
1024
+ Permission.ProjectMember,
1025
+ Permission.Viewer,
1026
+ Permission.SettingsAdmin,
1027
+ Permission.SettingsMember,
1028
+ Permission.SettingsViewer,
1029
+ Permission.ReadService,
1030
+ ],
1031
+ update: [],
1032
+ })
1033
+ @TableColumn({
1034
+ required: false,
1035
+ type: TableColumnType.ShortText,
1036
+ canReadOnRelationQuery: true,
1037
+ title: "Cloud Provider",
1038
+ description:
1039
+ "Last-seen value of the cloud.provider OpenTelemetry resource attribute, e.g. aws, gcp, azure.",
1040
+ })
1041
+ @Column({
1042
+ nullable: true,
1043
+ type: ColumnType.ShortText,
1044
+ length: ColumnLength.ShortText,
1045
+ })
1046
+ public cloudProvider?: string = undefined;
1047
+
1048
+ @ColumnAccessControl({
1049
+ create: [],
1050
+ read: [
1051
+ Permission.ProjectOwner,
1052
+ Permission.ProjectAdmin,
1053
+ Permission.ProjectMember,
1054
+ Permission.Viewer,
1055
+ Permission.SettingsAdmin,
1056
+ Permission.SettingsMember,
1057
+ Permission.SettingsViewer,
1058
+ Permission.ReadService,
1059
+ ],
1060
+ update: [],
1061
+ })
1062
+ @TableColumn({
1063
+ required: false,
1064
+ type: TableColumnType.ShortText,
1065
+ canReadOnRelationQuery: true,
1066
+ title: "Cloud Platform",
1067
+ description:
1068
+ "Last-seen value of the cloud.platform OpenTelemetry resource attribute, e.g. aws_ecs, gcp_cloud_run, aws_lambda.",
1069
+ })
1070
+ @Column({
1071
+ nullable: true,
1072
+ type: ColumnType.ShortText,
1073
+ length: ColumnLength.ShortText,
1074
+ })
1075
+ public cloudPlatform?: string = undefined;
1076
+
1077
+ @ColumnAccessControl({
1078
+ create: [],
1079
+ read: [
1080
+ Permission.ProjectOwner,
1081
+ Permission.ProjectAdmin,
1082
+ Permission.ProjectMember,
1083
+ Permission.Viewer,
1084
+ Permission.SettingsAdmin,
1085
+ Permission.SettingsMember,
1086
+ Permission.SettingsViewer,
1087
+ Permission.ReadService,
1088
+ ],
1089
+ update: [],
1090
+ })
1091
+ @TableColumn({
1092
+ required: false,
1093
+ type: TableColumnType.ShortText,
1094
+ canReadOnRelationQuery: true,
1095
+ title: "Cloud Region",
1096
+ description:
1097
+ "Last-seen value of the cloud.region OpenTelemetry resource attribute, e.g. us-east-1.",
1098
+ })
1099
+ @Column({
1100
+ nullable: true,
1101
+ type: ColumnType.ShortText,
1102
+ length: ColumnLength.ShortText,
1103
+ })
1104
+ public cloudRegion?: string = undefined;
1105
+
1106
+ @ColumnAccessControl({
1107
+ create: [],
1108
+ read: [
1109
+ Permission.ProjectOwner,
1110
+ Permission.ProjectAdmin,
1111
+ Permission.ProjectMember,
1112
+ Permission.Viewer,
1113
+ Permission.SettingsAdmin,
1114
+ Permission.SettingsMember,
1115
+ Permission.SettingsViewer,
1116
+ Permission.ReadService,
1117
+ ],
1118
+ update: [],
1119
+ })
1120
+ @TableColumn({
1121
+ required: false,
1122
+ type: TableColumnType.ShortText,
1123
+ canReadOnRelationQuery: true,
1124
+ title: "Cloud Account ID",
1125
+ description:
1126
+ "Last-seen value of the cloud.account.id OpenTelemetry resource attribute.",
1127
+ })
1128
+ @Column({
1129
+ nullable: true,
1130
+ type: ColumnType.ShortText,
1131
+ length: ColumnLength.ShortText,
1132
+ })
1133
+ public cloudAccountId?: string = undefined;
866
1134
  }
@@ -24,6 +24,9 @@ import Service from "./Service";
24
24
  import Host from "./Host";
25
25
  import DockerHost from "./DockerHost";
26
26
  import KubernetesCluster from "./KubernetesCluster";
27
+ import ServerlessFunction from "./ServerlessFunction";
28
+ import CloudResource from "./CloudResource";
29
+ import RumApplication from "./RumApplication";
27
30
 
28
31
  @EnableDocumentation()
29
32
  @CanAccessIfCanReadOn("service")
@@ -71,7 +74,18 @@ import KubernetesCluster from "./KubernetesCluster";
71
74
  * of those resource types, and includeProjectScope lets in-project users
72
75
  * see the unattributed bucket (which has no owner resource).
73
76
  */
74
- @OwnedThrough("serviceId", [Service, Host, DockerHost, KubernetesCluster], {
77
+ @OwnedThrough(
78
+ "serviceId",
79
+ [
80
+ Service,
81
+ Host,
82
+ DockerHost,
83
+ KubernetesCluster,
84
+ ServerlessFunction,
85
+ CloudResource,
86
+ RumApplication,
87
+ ],
88
+ {
75
89
  includeProjectScope: true,
76
90
  })
77
91
  @Entity({
@@ -15,6 +15,7 @@ import TableColumnType from "../../Types/Database/TableColumnType";
15
15
  import TableMetadata from "../../Types/Database/TableMetadata";
16
16
  import TenantColumn from "../../Types/Database/TenantColumn";
17
17
  import IconProp from "../../Types/Icon/IconProp";
18
+ import { JSONObject } from "../../Types/JSON";
18
19
  import ObjectID from "../../Types/ObjectID";
19
20
  import Permission from "../../Types/Permission";
20
21
  import WorkflowStatus from "../../Types/Workflow/WorkflowStatus";
@@ -296,6 +297,57 @@ export default class WorkflowLog extends BaseModel {
296
297
  })
297
298
  public completedAt?: Date = undefined;
298
299
 
300
+ @ColumnAccessControl({
301
+ create: [],
302
+ read: [
303
+ Permission.ProjectOwner,
304
+ Permission.ProjectAdmin,
305
+ Permission.ProjectMember,
306
+ Permission.Viewer,
307
+ Permission.WorkflowAdmin,
308
+ Permission.WorkflowMember,
309
+ Permission.WorkflowViewer,
310
+ Permission.ReadWorkflowLog,
311
+ ],
312
+ update: [],
313
+ })
314
+ @TableColumn({
315
+ type: TableColumnType.Date,
316
+ title: "Resume At",
317
+ description:
318
+ "When this workflow run is scheduled to resume after a Sleep step (only set while the run is Waiting).",
319
+ })
320
+ @Column({
321
+ type: ColumnType.Date,
322
+ nullable: true,
323
+ unique: false,
324
+ })
325
+ public resumeAt?: Date = undefined;
326
+
327
+ /*
328
+ * Internal. Serialized execution state (pending steps, executed steps and
329
+ * accumulated component return values) used to resume a workflow run after a
330
+ * Sleep step. Never exposed via the API.
331
+ */
332
+ @ColumnAccessControl({
333
+ create: [],
334
+ read: [],
335
+ update: [],
336
+ })
337
+ @TableColumn({
338
+ required: false,
339
+ isDefaultValueColumn: false,
340
+ type: TableColumnType.JSON,
341
+ title: "Resume Data",
342
+ description:
343
+ "Internal serialized execution state used to resume a workflow run after a Sleep step.",
344
+ })
345
+ @Column({
346
+ type: ColumnType.JSON,
347
+ nullable: true,
348
+ })
349
+ public resumeData?: JSONObject = undefined;
350
+
299
351
  @ColumnAccessControl({
300
352
  create: [],
301
353
  read: [],
@@ -688,11 +688,10 @@ router.post(
688
688
  : undefined;
689
689
 
690
690
  /*
691
- * Compute all facets from a single sort-key-aligned sample query
692
- * (ORDER BY startTime DESC LIMIT N) and count top-K in Node. This
693
- * avoids ClickHouse GROUP BY aggregations that can't return partial
694
- * results under max_execution_time 'break' mode, and returns in
695
- * <1s even over 14-day windows.
691
+ * Shared window + active filters for both facet-counting paths below:
692
+ * the exact projection-backed GROUP BY (resource facets + statusCode)
693
+ * and the recent-N sample (kind + attribute facets, which have no cheap
694
+ * exact path).
696
695
  */
697
696
  const multiRequest: TraceMultiFacetRequest = {
698
697
  projectId: databaseProps.tenantId,
@@ -710,38 +709,92 @@ router.post(
710
709
  attributes,
711
710
  };
712
711
 
713
- let facets: Record<string, Array<TraceFacetValue>>;
714
- try {
715
- facets =
716
- await TraceAggregationService.getFacetValuesFromSample(multiRequest);
717
- } catch {
718
- facets = Object.fromEntries(
719
- facetKeys.map((key: string): [string, Array<TraceFacetValue>] => {
720
- return [key, []];
721
- }),
722
- );
712
+ /*
713
+ * Resource facets (serviceId / hostId / dockerHostId / k8s cluster ...)
714
+ * and statusCode are counted with an exact, projection-backed GROUP BY
715
+ * in getResourceFacetCounts(). The recent-N sample below saturates with
716
+ * whichever service is chattiest right now and reports 0 for every other
717
+ * service regardless of its true volume over the window — the "top 1000"
718
+ * symptom. Facets with no projection (kind, attribute keys) have no cheap
719
+ * exact path and stay on the sample.
720
+ */
721
+ const sampledKeys: Array<string> = facetKeys.filter(
722
+ (key: string): boolean => {
723
+ return (
724
+ !ResourceFacetResolver.isResourceFacet(key) && key !== "statusCode"
725
+ );
726
+ },
727
+ );
728
+
729
+ let facets: Record<string, Array<TraceFacetValue>> = {};
730
+ if (sampledKeys.length > 0) {
731
+ try {
732
+ facets = await TraceAggregationService.getFacetValuesFromSample({
733
+ ...multiRequest,
734
+ facetKeys: sampledKeys,
735
+ });
736
+ } catch {
737
+ facets = Object.fromEntries(
738
+ sampledKeys.map((key: string): [string, Array<TraceFacetValue>] => {
739
+ return [key, []];
740
+ }),
741
+ );
742
+ }
743
+ }
744
+
745
+ const needsAccurateCounts: boolean =
746
+ facetKeys.includes("statusCode") ||
747
+ facetKeys.some((key: string): boolean => {
748
+ return ResourceFacetResolver.isResourceFacet(key);
749
+ });
750
+
751
+ let serviceCounts: Map<string, number> = new Map<string, number>();
752
+ let statusCounts: Map<string, number> = new Map<string, number>();
753
+ if (needsAccurateCounts) {
754
+ try {
755
+ const accurate: {
756
+ serviceCounts: Map<string, number>;
757
+ statusCounts: Map<string, number>;
758
+ } =
759
+ await TraceAggregationService.getResourceFacetCounts(multiRequest);
760
+ serviceCounts = accurate.serviceCounts;
761
+ statusCounts = accurate.statusCounts;
762
+ } catch {
763
+ /*
764
+ * Degrade gracefully: resource facets still enumerate via Postgres
765
+ * (count 0), statusCode falls back to empty.
766
+ */
767
+ }
768
+ }
769
+
770
+ if (facetKeys.includes("statusCode")) {
771
+ facets["statusCode"] = Array.from(statusCounts.entries())
772
+ .map(([value, count]: [string, number]): TraceFacetValue => {
773
+ return { value, count };
774
+ })
775
+ .sort((a: TraceFacetValue, b: TraceFacetValue): number => {
776
+ return b.count - a.count;
777
+ })
778
+ .slice(0, limit);
723
779
  }
724
780
 
725
781
  /*
726
782
  * Replace resource-facet results with the Postgres source-of-truth list
727
- * (filtered by facetSearchText and enriched with displayName). Counts
728
- * come from the ClickHouse sample above entities with no recent
729
- * telemetry surface with count 0 instead of being hidden entirely. This
730
- * means low-volume services / hosts still appear in the sidebar and the
731
- * search box can find resources beyond the loaded subset.
783
+ * (filtered by facetSearchText and enriched with displayName). Every
784
+ * resource facet shares the same exact serviceId -> count map; resource
785
+ * ids are globally unique, so each facet only ever resolves its own
786
+ * entities. Entities with no telemetry in the window surface with count
787
+ * 0 instead of being hidden, and the search box can find resources
788
+ * beyond the loaded subset.
732
789
  */
733
790
  const resourceSpecs: Array<ResourceFacetSpec> = facetKeys
734
791
  .filter((key: string): boolean => {
735
792
  return ResourceFacetResolver.isResourceFacet(key);
736
793
  })
737
794
  .map((key: string): ResourceFacetSpec => {
738
- const counts: Map<string, number> = new Map();
739
- for (const fv of facets[key] || []) {
740
- counts.set(fv.value, fv.count);
741
- }
742
795
  return {
743
796
  facetKey: key,
744
- counts,
797
+ counts: serviceCounts,
745
798
  searchText: facetSearchText?.[key],
746
799
  limit,
747
800
  };
@@ -0,0 +1,21 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AddResumeStateToWorkflowLog1780931746908
4
+ implements MigrationInterface
5
+ {
6
+ public name = "AddResumeStateToWorkflowLog1780931746908";
7
+
8
+ public async up(queryRunner: QueryRunner): Promise<void> {
9
+ await queryRunner.query(
10
+ `ALTER TABLE "WorkflowLog" ADD "resumeAt" TIMESTAMP WITH TIME ZONE`,
11
+ );
12
+ await queryRunner.query(`ALTER TABLE "WorkflowLog" ADD "resumeData" jsonb`);
13
+ }
14
+
15
+ public async down(queryRunner: QueryRunner): Promise<void> {
16
+ await queryRunner.query(
17
+ `ALTER TABLE "WorkflowLog" DROP COLUMN "resumeData"`,
18
+ );
19
+ await queryRunner.query(`ALTER TABLE "WorkflowLog" DROP COLUMN "resumeAt"`);
20
+ }
21
+ }
@@ -0,0 +1,108 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ /*
4
+ * Phase 0 (capture dropped OTel attributes): add first-class columns to
5
+ * Service and Host for resource attributes that ingest previously dropped
6
+ * (they only lived as resource.* attributes on telemetry rows). These are
7
+ * auto-populated from OpenTelemetry resource attributes at ingest time and
8
+ * are system-managed (not user-editable).
9
+ */
10
+ export class AddTelemetryResourceMetadataColumns1780931863719
11
+ implements MigrationInterface
12
+ {
13
+ public name = "AddTelemetryResourceMetadataColumns1780931863719";
14
+
15
+ public async up(queryRunner: QueryRunner): Promise<void> {
16
+ // Service
17
+ await queryRunner.query(
18
+ `ALTER TABLE "Service" ADD "serviceVersion" character varying(100)`,
19
+ );
20
+ await queryRunner.query(
21
+ `ALTER TABLE "Service" ADD "deploymentEnvironment" character varying(100)`,
22
+ );
23
+ await queryRunner.query(
24
+ `ALTER TABLE "Service" ADD "serviceNamespace" character varying(100)`,
25
+ );
26
+ await queryRunner.query(
27
+ `ALTER TABLE "Service" ADD "runtimeName" character varying(100)`,
28
+ );
29
+ await queryRunner.query(
30
+ `ALTER TABLE "Service" ADD "runtimeVersion" character varying(100)`,
31
+ );
32
+ await queryRunner.query(
33
+ `ALTER TABLE "Service" ADD "cloudProvider" character varying(100)`,
34
+ );
35
+ await queryRunner.query(
36
+ `ALTER TABLE "Service" ADD "cloudPlatform" character varying(100)`,
37
+ );
38
+ await queryRunner.query(
39
+ `ALTER TABLE "Service" ADD "cloudRegion" character varying(100)`,
40
+ );
41
+ await queryRunner.query(
42
+ `ALTER TABLE "Service" ADD "cloudAccountId" character varying(100)`,
43
+ );
44
+
45
+ // Host
46
+ await queryRunner.query(
47
+ `ALTER TABLE "Host" ADD "deploymentEnvironment" character varying(100)`,
48
+ );
49
+ await queryRunner.query(
50
+ `ALTER TABLE "Host" ADD "runtimeName" character varying(100)`,
51
+ );
52
+ await queryRunner.query(
53
+ `ALTER TABLE "Host" ADD "runtimeVersion" character varying(100)`,
54
+ );
55
+ await queryRunner.query(
56
+ `ALTER TABLE "Host" ADD "cloudProvider" character varying(100)`,
57
+ );
58
+ await queryRunner.query(
59
+ `ALTER TABLE "Host" ADD "cloudPlatform" character varying(100)`,
60
+ );
61
+ await queryRunner.query(
62
+ `ALTER TABLE "Host" ADD "cloudRegion" character varying(100)`,
63
+ );
64
+ await queryRunner.query(
65
+ `ALTER TABLE "Host" ADD "cloudAccountId" character varying(100)`,
66
+ );
67
+ }
68
+
69
+ public async down(queryRunner: QueryRunner): Promise<void> {
70
+ // Host
71
+ await queryRunner.query(
72
+ `ALTER TABLE "Host" DROP COLUMN "cloudAccountId"`,
73
+ );
74
+ await queryRunner.query(`ALTER TABLE "Host" DROP COLUMN "cloudRegion"`);
75
+ await queryRunner.query(`ALTER TABLE "Host" DROP COLUMN "cloudPlatform"`);
76
+ await queryRunner.query(`ALTER TABLE "Host" DROP COLUMN "cloudProvider"`);
77
+ await queryRunner.query(`ALTER TABLE "Host" DROP COLUMN "runtimeVersion"`);
78
+ await queryRunner.query(`ALTER TABLE "Host" DROP COLUMN "runtimeName"`);
79
+ await queryRunner.query(
80
+ `ALTER TABLE "Host" DROP COLUMN "deploymentEnvironment"`,
81
+ );
82
+
83
+ // Service
84
+ await queryRunner.query(
85
+ `ALTER TABLE "Service" DROP COLUMN "cloudAccountId"`,
86
+ );
87
+ await queryRunner.query(`ALTER TABLE "Service" DROP COLUMN "cloudRegion"`);
88
+ await queryRunner.query(
89
+ `ALTER TABLE "Service" DROP COLUMN "cloudPlatform"`,
90
+ );
91
+ await queryRunner.query(
92
+ `ALTER TABLE "Service" DROP COLUMN "cloudProvider"`,
93
+ );
94
+ await queryRunner.query(
95
+ `ALTER TABLE "Service" DROP COLUMN "runtimeVersion"`,
96
+ );
97
+ await queryRunner.query(`ALTER TABLE "Service" DROP COLUMN "runtimeName"`);
98
+ await queryRunner.query(
99
+ `ALTER TABLE "Service" DROP COLUMN "serviceNamespace"`,
100
+ );
101
+ await queryRunner.query(
102
+ `ALTER TABLE "Service" DROP COLUMN "deploymentEnvironment"`,
103
+ );
104
+ await queryRunner.query(
105
+ `ALTER TABLE "Service" DROP COLUMN "serviceVersion"`,
106
+ );
107
+ }
108
+ }