@oneuptime/common 10.4.13 → 10.4.15

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 (248) hide show
  1. package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +49 -0
  2. package/Models/AnalyticsModels/AuditLog.ts +8 -0
  3. package/Models/AnalyticsModels/ExceptionInstance.ts +1 -0
  4. package/Models/AnalyticsModels/Log.ts +1 -0
  5. package/Models/AnalyticsModels/Metric.ts +10 -0
  6. package/Models/AnalyticsModels/MonitorLog.ts +1 -0
  7. package/Models/AnalyticsModels/Profile.ts +1 -0
  8. package/Models/AnalyticsModels/ProfileSample.ts +1 -0
  9. package/Models/AnalyticsModels/Span.ts +1 -0
  10. package/Models/DatabaseModels/Alert.ts +2 -0
  11. package/Models/DatabaseModels/AlertCustomField.ts +37 -0
  12. package/Models/DatabaseModels/AlertFeed.ts +1 -0
  13. package/Models/DatabaseModels/CallLog.ts +2 -0
  14. package/Models/DatabaseModels/DockerHost.ts +34 -0
  15. package/Models/DatabaseModels/EmailLog.ts +2 -0
  16. package/Models/DatabaseModels/Host.ts +34 -0
  17. package/Models/DatabaseModels/Incident.ts +1 -0
  18. package/Models/DatabaseModels/IncidentCustomField.ts +37 -0
  19. package/Models/DatabaseModels/IncidentFeed.ts +1 -0
  20. package/Models/DatabaseModels/IncidentMember.ts +9 -0
  21. package/Models/DatabaseModels/KubernetesCluster.ts +34 -0
  22. package/Models/DatabaseModels/MonitorCustomField.ts +37 -0
  23. package/Models/DatabaseModels/MonitorFeed.ts +1 -0
  24. package/Models/DatabaseModels/MonitorProbe.ts +1 -0
  25. package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +37 -0
  26. package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +3 -0
  27. package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +37 -0
  28. package/Models/DatabaseModels/SmsLog.ts +2 -0
  29. package/Models/DatabaseModels/StatusPageCustomField.ts +37 -0
  30. package/Models/DatabaseModels/StatusPageSubscriber.ts +2 -0
  31. package/Models/DatabaseModels/TableView.ts +40 -0
  32. package/Models/DatabaseModels/TeamMemberCustomField.ts +37 -0
  33. package/Models/DatabaseModels/TelemetryException.ts +2 -0
  34. package/Models/DatabaseModels/UserOnCallLog.ts +1 -0
  35. package/Models/DatabaseModels/WorkflowLog.ts +1 -0
  36. package/Server/API/BaseAnalyticsAPI.ts +128 -20
  37. package/Server/API/MetricAPI.ts +5 -138
  38. package/Server/API/ProjectAPI.ts +52 -15
  39. package/Server/API/StatusAPI.ts +103 -7
  40. package/Server/EnvironmentConfig.ts +69 -0
  41. package/Server/Infrastructure/Postgres/DataSourceOptions.ts +26 -1
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.ts +29 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.ts +160 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.ts +13 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.ts +34 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.ts +67 -0
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  48. package/Server/Infrastructure/PostgresDatabase.ts +2 -5
  49. package/Server/Middleware/ProjectAuthorization.ts +31 -53
  50. package/Server/Middleware/UserAuthorization.ts +106 -64
  51. package/Server/Services/AccessTokenService.ts +1 -1
  52. package/Server/Services/AnalyticsDatabaseService.ts +24 -4
  53. package/Server/Services/ApiKeyService.ts +100 -1
  54. package/Server/Services/DockerHostService.ts +5 -0
  55. package/Server/Services/HostService.ts +6 -0
  56. package/Server/Services/KubernetesClusterService.ts +33 -10
  57. package/Server/Services/MetricService.ts +113 -0
  58. package/Server/Services/MonitorService.ts +10 -3
  59. package/Server/Services/ProjectService.ts +93 -2
  60. package/Server/Services/TeamMemberService.ts +36 -0
  61. package/Server/Services/UserService.ts +38 -0
  62. package/Server/Utils/Response.ts +4 -1
  63. package/Server/Utils/UserPermission/UserPermission.ts +17 -1
  64. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +2 -2
  65. package/Types/API/HTTPResponse.ts +16 -0
  66. package/Types/BaseDatabase/ListResult.ts +6 -0
  67. package/Types/CustomField/CustomFieldType.ts +2 -0
  68. package/Types/Date.ts +9 -1
  69. package/Types/ListData.ts +14 -0
  70. package/Types/Monitor/DnsMonitor/DnsMonitorResponse.ts +3 -0
  71. package/Types/Monitor/DnssecMonitor/DnssecMonitorResponse.ts +5 -0
  72. package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +4 -0
  73. package/Types/Monitor/ExternalStatusPageMonitor/ExternalStatusPageMonitorResponse.ts +4 -0
  74. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +3 -0
  75. package/Types/Probe/ProbeAttempt.ts +9 -0
  76. package/Types/Probe/ProbeMonitorResponse.ts +3 -0
  77. package/UI/Components/BulkUpdate/BulkOwnerActions.tsx +504 -0
  78. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +64 -54
  79. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +38 -0
  80. package/UI/Components/CustomFields/DropdownOptionsInput.tsx +150 -0
  81. package/UI/Components/Detail/Detail.tsx +78 -11
  82. package/UI/Components/List/List.tsx +6 -0
  83. package/UI/Components/ModelTable/BaseModelTable.tsx +74 -2
  84. package/UI/Components/ModelTable/TableView.tsx +70 -30
  85. package/UI/Components/Pagination/Pagination.tsx +75 -33
  86. package/UI/Components/Table/Table.tsx +6 -0
  87. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +1 -0
  88. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +33 -0
  89. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
  90. package/build/dist/Models/AnalyticsModels/AuditLog.js +8 -0
  91. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  92. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +1 -0
  93. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
  94. package/build/dist/Models/AnalyticsModels/Log.js +1 -0
  95. package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
  96. package/build/dist/Models/AnalyticsModels/Metric.js +10 -0
  97. package/build/dist/Models/AnalyticsModels/Metric.js.map +1 -1
  98. package/build/dist/Models/AnalyticsModels/MonitorLog.js +1 -0
  99. package/build/dist/Models/AnalyticsModels/MonitorLog.js.map +1 -1
  100. package/build/dist/Models/AnalyticsModels/Profile.js +1 -0
  101. package/build/dist/Models/AnalyticsModels/Profile.js.map +1 -1
  102. package/build/dist/Models/AnalyticsModels/ProfileSample.js +1 -0
  103. package/build/dist/Models/AnalyticsModels/ProfileSample.js.map +1 -1
  104. package/build/dist/Models/AnalyticsModels/Span.js +1 -0
  105. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  106. package/build/dist/Models/DatabaseModels/Alert.js +3 -1
  107. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  108. package/build/dist/Models/DatabaseModels/AlertCustomField.js +38 -0
  109. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
  110. package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -1
  111. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  112. package/build/dist/Models/DatabaseModels/CallLog.js +4 -1
  113. package/build/dist/Models/DatabaseModels/CallLog.js.map +1 -1
  114. package/build/dist/Models/DatabaseModels/DockerHost.js +35 -0
  115. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  116. package/build/dist/Models/DatabaseModels/EmailLog.js +4 -1
  117. package/build/dist/Models/DatabaseModels/EmailLog.js.map +1 -1
  118. package/build/dist/Models/DatabaseModels/Host.js +35 -0
  119. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  120. package/build/dist/Models/DatabaseModels/Incident.js +2 -1
  121. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  122. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +38 -0
  123. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  124. package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -1
  125. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  126. package/build/dist/Models/DatabaseModels/IncidentMember.js +11 -1
  127. package/build/dist/Models/DatabaseModels/IncidentMember.js.map +1 -1
  128. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +35 -0
  129. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  130. package/build/dist/Models/DatabaseModels/MonitorCustomField.js +38 -0
  131. package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
  132. package/build/dist/Models/DatabaseModels/MonitorFeed.js +2 -1
  133. package/build/dist/Models/DatabaseModels/MonitorFeed.js.map +1 -1
  134. package/build/dist/Models/DatabaseModels/MonitorProbe.js +2 -0
  135. package/build/dist/Models/DatabaseModels/MonitorProbe.js.map +1 -1
  136. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +38 -0
  137. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
  138. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +3 -0
  139. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
  140. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +38 -0
  141. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
  142. package/build/dist/Models/DatabaseModels/SmsLog.js +4 -1
  143. package/build/dist/Models/DatabaseModels/SmsLog.js.map +1 -1
  144. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +38 -0
  145. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
  146. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +4 -1
  147. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
  148. package/build/dist/Models/DatabaseModels/TableView.js +40 -0
  149. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
  150. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +38 -0
  151. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
  152. package/build/dist/Models/DatabaseModels/TelemetryException.js +3 -1
  153. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  154. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +1 -0
  155. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  156. package/build/dist/Models/DatabaseModels/WorkflowLog.js +2 -1
  157. package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
  158. package/build/dist/Server/API/BaseAnalyticsAPI.js +105 -18
  159. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  160. package/build/dist/Server/API/MetricAPI.js +5 -113
  161. package/build/dist/Server/API/MetricAPI.js.map +1 -1
  162. package/build/dist/Server/API/ProjectAPI.js +42 -14
  163. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  164. package/build/dist/Server/API/StatusAPI.js +75 -8
  165. package/build/dist/Server/API/StatusAPI.js.map +1 -1
  166. package/build/dist/Server/EnvironmentConfig.js +41 -0
  167. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  168. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +20 -2
  169. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
  170. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.js +16 -0
  171. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392865146-AddAgentVersionToKubernetesDockerHost.js.map +1 -0
  172. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.js +63 -0
  173. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779392970424-AddPerformanceIndexes.js.map +1 -0
  174. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js +12 -0
  175. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779536271671-AddFacetsToTableView.js.map +1 -0
  176. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js +27 -0
  177. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779540427366-AddIsMemberNotifiedIndex.js.map +1 -0
  178. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js +28 -0
  179. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1779619108628-AddDropdownOptionsToCustomFields.js.map +1 -0
  180. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  181. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  182. package/build/dist/Server/Infrastructure/PostgresDatabase.js +2 -2
  183. package/build/dist/Server/Infrastructure/PostgresDatabase.js.map +1 -1
  184. package/build/dist/Server/Middleware/ProjectAuthorization.js +21 -39
  185. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  186. package/build/dist/Server/Middleware/UserAuthorization.js +83 -50
  187. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  188. package/build/dist/Server/Services/AccessTokenService.js +1 -1
  189. package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
  190. package/build/dist/Server/Services/AnalyticsDatabaseService.js +22 -3
  191. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  192. package/build/dist/Server/Services/ApiKeyService.js +86 -0
  193. package/build/dist/Server/Services/ApiKeyService.js.map +1 -1
  194. package/build/dist/Server/Services/DockerHostService.js +5 -1
  195. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  196. package/build/dist/Server/Services/HostService.js +5 -1
  197. package/build/dist/Server/Services/HostService.js.map +1 -1
  198. package/build/dist/Server/Services/KubernetesClusterService.js +21 -11
  199. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  200. package/build/dist/Server/Services/MetricService.js +89 -0
  201. package/build/dist/Server/Services/MetricService.js.map +1 -1
  202. package/build/dist/Server/Services/MonitorService.js +8 -3
  203. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  204. package/build/dist/Server/Services/ProjectService.js +84 -2
  205. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  206. package/build/dist/Server/Services/TeamMemberService.js +24 -0
  207. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  208. package/build/dist/Server/Services/UserService.js +36 -0
  209. package/build/dist/Server/Services/UserService.js.map +1 -1
  210. package/build/dist/Server/Utils/Response.js +6 -5
  211. package/build/dist/Server/Utils/Response.js.map +1 -1
  212. package/build/dist/Server/Utils/UserPermission/UserPermission.js +13 -1
  213. package/build/dist/Server/Utils/UserPermission/UserPermission.js.map +1 -1
  214. package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js +2 -2
  215. package/build/dist/Tests/Server/Services/AnalyticsDatabaseService.test.js.map +1 -1
  216. package/build/dist/Types/API/HTTPResponse.js +15 -0
  217. package/build/dist/Types/API/HTTPResponse.js.map +1 -1
  218. package/build/dist/Types/CustomField/CustomFieldType.js +2 -0
  219. package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
  220. package/build/dist/Types/Date.js +10 -1
  221. package/build/dist/Types/Date.js.map +1 -1
  222. package/build/dist/Types/ListData.js +4 -0
  223. package/build/dist/Types/ListData.js.map +1 -1
  224. package/build/dist/Types/Probe/ProbeAttempt.js +2 -0
  225. package/build/dist/Types/Probe/ProbeAttempt.js.map +1 -0
  226. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js +376 -0
  227. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js.map +1 -0
  228. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +32 -25
  229. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  230. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +32 -0
  231. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  232. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js +84 -0
  233. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js.map +1 -0
  234. package/build/dist/UI/Components/Detail/Detail.js +34 -3
  235. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  236. package/build/dist/UI/Components/List/List.js +1 -1
  237. package/build/dist/UI/Components/List/List.js.map +1 -1
  238. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +45 -5
  239. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  240. package/build/dist/UI/Components/ModelTable/TableView.js +40 -19
  241. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  242. package/build/dist/UI/Components/Pagination/Pagination.js +62 -36
  243. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  244. package/build/dist/UI/Components/Table/Table.js +1 -1
  245. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  246. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +1 -0
  247. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  248. package/package.json +1 -1
@@ -52,6 +52,16 @@ export default class AnalyticsBaseModel extends CommonModel {
52
52
  materializedViews?: Array<MaterializedView> | undefined;
53
53
  enableMCP?: boolean | undefined;
54
54
  ttlExpression?: string | undefined; // e.g. "retentionDate DELETE"
55
+ /*
56
+ * Column that `findBy` falls back to when the caller doesn't
57
+ * specify a `sort`. Defaults to `createdAt` (matching the legacy
58
+ * behavior), but heavy analytics tables should override this to
59
+ * a column that participates in their ClickHouse sort key so the
60
+ * default list query streams from the index instead of doing a
61
+ * full sort. Examples: Log/MonitorLog/ExceptionInstance => "time",
62
+ * Span/Profile => "startTime", AuditLog => "createdAt".
63
+ */
64
+ defaultSortColumn?: string | undefined;
55
65
  }) {
56
66
  super({
57
67
  tableColumns: data.tableColumns,
@@ -156,6 +166,29 @@ export default class AnalyticsBaseModel extends CommonModel {
156
166
  this.materializedViews = data.materializedViews || [];
157
167
  this.enableMCP = data.enableMCP || false;
158
168
  this.ttlExpression = data.ttlExpression || "";
169
+
170
+ /*
171
+ * Validate the override matches the schema. We deliberately do
172
+ * NOT require the column to be in `sortKeys` — it must just
173
+ * exist on the table; the caller picks a column they know is
174
+ * indexed (typically the timestamp column at position 2 of the
175
+ * sort key, after `projectId`).
176
+ */
177
+ if (data.defaultSortColumn) {
178
+ const column: AnalyticsTableColumn | undefined = columns.find(
179
+ (column: AnalyticsTableColumn) => {
180
+ return column.key === data.defaultSortColumn;
181
+ },
182
+ );
183
+ if (!column) {
184
+ throw new BadDataException(
185
+ "defaultSortColumn " +
186
+ data.defaultSortColumn +
187
+ " is not part of tableColumns",
188
+ );
189
+ }
190
+ this.defaultSortColumn = data.defaultSortColumn;
191
+ }
159
192
  }
160
193
 
161
194
  private _enableWorkflowOn: EnableWorkflowOn | undefined;
@@ -214,6 +247,22 @@ export default class AnalyticsBaseModel extends CommonModel {
214
247
  this._sortKeys = v;
215
248
  }
216
249
 
250
+ /*
251
+ * Column that `AnalyticsDatabaseService._findBy` falls back to
252
+ * when the caller didn't pass a `sort`. `createdAt` (the historical
253
+ * default) is not part of the ClickHouse sort key on heavy
254
+ * analytics tables (Log/Span/Metric/...), so a default list query
255
+ * over those tables triggers a full sort. Per-model overrides
256
+ * point at a column that participates in the sort key.
257
+ */
258
+ private _defaultSortColumn: string = "createdAt";
259
+ public get defaultSortColumn(): string {
260
+ return this._defaultSortColumn;
261
+ }
262
+ public set defaultSortColumn(v: string) {
263
+ this._defaultSortColumn = v;
264
+ }
265
+
217
266
  private _singularName: string = "";
218
267
  public get singularName(): string {
219
268
  return this._singularName;
@@ -287,6 +287,14 @@ export default class AuditLog extends AnalyticsBaseModel {
287
287
  primaryKeys: ["projectId", "createdAt"],
288
288
  partitionKey: "sipHash64(projectId) % 16",
289
289
  ttlExpression: "retentionDate DELETE",
290
+ /*
291
+ * `createdAt` already participates in the AuditLog sort key
292
+ * (position 2 after `projectId`), so the legacy `createdAt
293
+ * DESC` default was already efficient here. Set it explicitly
294
+ * so the choice is intentional rather than inherited from the
295
+ * base class.
296
+ */
297
+ defaultSortColumn: "createdAt",
290
298
  });
291
299
  }
292
300
 
@@ -667,6 +667,7 @@ export default class ExceptionInstance extends AnalyticsBaseModel {
667
667
  primaryKeys: ["projectId", "time", "serviceId", "fingerprint"],
668
668
  partitionKey: "sipHash64(projectId) % 16",
669
669
  ttlExpression: "retentionDate DELETE",
670
+ defaultSortColumn: "time",
670
671
  });
671
672
  }
672
673
 
@@ -569,6 +569,7 @@ export default class Log extends AnalyticsBaseModel {
569
569
  primaryKeys: ["projectId", "time", "serviceId"],
570
570
  partitionKey: "sipHash64(projectId) % 16",
571
571
  ttlExpression: "retentionDate DELETE",
572
+ defaultSortColumn: "time",
572
573
  });
573
574
  }
574
575
 
@@ -1046,6 +1046,16 @@ export default class Metric extends AnalyticsBaseModel {
1046
1046
  primaryKeys: ["projectId", "name", "serviceId", "time"],
1047
1047
  partitionKey: "sipHash64(projectId) % 16",
1048
1048
  ttlExpression: "retentionDate DELETE",
1049
+ /*
1050
+ * `time` is the 4th column of the Metric sort key (after
1051
+ * projectId + name + serviceId). A list query that filters
1052
+ * by name (the typical "metric detail" drilldown) can still
1053
+ * stream from the index when sorting by `time DESC`. With
1054
+ * no name filter the sort is less efficient but still far
1055
+ * better than the legacy `createdAt DESC` fallback, which
1056
+ * isn't in the sort key at all.
1057
+ */
1058
+ defaultSortColumn: "time",
1049
1059
  });
1050
1060
  }
1051
1061
 
@@ -188,6 +188,7 @@ export default class MonitorLog extends AnalyticsBaseModel {
188
188
  primaryKeys: ["projectId", "time", "monitorId"],
189
189
  partitionKey: "sipHash64(projectId) % 16",
190
190
  ttlExpression: "retentionDate DELETE",
191
+ defaultSortColumn: "time",
191
192
  });
192
193
  }
193
194
 
@@ -673,6 +673,7 @@ export default class Profile extends AnalyticsBaseModel {
673
673
  primaryKeys: ["projectId", "startTime", "serviceId", "profileType"],
674
674
  partitionKey: "sipHash64(projectId) % 16",
675
675
  ttlExpression: "retentionDate DELETE",
676
+ defaultSortColumn: "startTime",
676
677
  });
677
678
  }
678
679
 
@@ -542,6 +542,7 @@ export default class ProfileSample extends AnalyticsBaseModel {
542
542
  ],
543
543
  partitionKey: "sipHash64(projectId) % 16",
544
544
  ttlExpression: "retentionDate DELETE",
545
+ defaultSortColumn: "time",
545
546
  });
546
547
  }
547
548
 
@@ -846,6 +846,7 @@ export default class Span extends AnalyticsBaseModel {
846
846
  primaryKeys: ["projectId", "startTime", "serviceId", "traceId"],
847
847
  partitionKey: "sipHash64(projectId) % 16",
848
848
  ttlExpression: "retentionDate DELETE",
849
+ defaultSortColumn: "startTime",
849
850
  });
850
851
  }
851
852
 
@@ -114,6 +114,7 @@ import NotificationRuleWorkspaceChannel from "../../Types/Workspace/Notification
114
114
  delete: true,
115
115
  },
116
116
  })
117
+ @Index(["projectId", "currentAlertStateId"]) // Active-alert counters on dashboard
117
118
  export default class Alert extends BaseModel {
118
119
  @ColumnAccessControl({
119
120
  create: [
@@ -484,6 +485,7 @@ export default class Alert extends BaseModel {
484
485
  Permission.EditAlert,
485
486
  ],
486
487
  })
488
+ @Index()
487
489
  @TableColumn({
488
490
  type: TableColumnType.ObjectID,
489
491
  title: "Monitor ID",
@@ -249,6 +249,43 @@ export default class AlertCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateAlertCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.AlertAdmin,
264
+ Permission.AlertMember,
265
+ Permission.AlertViewer,
266
+ Permission.ReadAlertCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditAlertCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -91,6 +91,7 @@ export enum AlertFeedEventType {
91
91
  tableDescription:
92
92
  "Log of the entire alert state change. This is a log of all the alert state changes, public notes, more etc.",
93
93
  })
94
+ @Index(["alertId", "postedAt"]) // Alert detail page: feed sorted by postedAt
94
95
  export default class AlertFeed extends BaseModel {
95
96
  @ColumnAccessControl({
96
97
  create: [
@@ -61,6 +61,8 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
61
61
  tableDescription:
62
62
  "Logs of all the Call sent out to all users and subscribers for this project.",
63
63
  })
64
+ @Index(["projectId", "createdAt"]) // Notification logs table: time-range filter per project
65
+ @Index(["projectId", "status"]) // Notification logs table: status filter per project
64
66
  export default class CallLog extends BaseModel {
65
67
  @ColumnAccessControl({
66
68
  create: [],
@@ -358,6 +358,40 @@ export default class DockerHost extends BaseModel {
358
358
  })
359
359
  public otelCollectorStatus?: string = undefined;
360
360
 
361
+ @ColumnAccessControl({
362
+ create: [],
363
+ read: [
364
+ Permission.ProjectOwner,
365
+ Permission.ProjectAdmin,
366
+ Permission.ProjectMember,
367
+ Permission.Viewer,
368
+ Permission.SettingsAdmin,
369
+ Permission.SettingsMember,
370
+ Permission.SettingsViewer,
371
+ Permission.ReadDockerHost,
372
+ ],
373
+ update: [
374
+ Permission.ProjectOwner,
375
+ Permission.ProjectAdmin,
376
+ Permission.EditDockerHost,
377
+ ],
378
+ })
379
+ @TableColumn({
380
+ required: false,
381
+ type: TableColumnType.ShortText,
382
+ canReadOnRelationQuery: true,
383
+ title: "Agent Version",
384
+ description:
385
+ "Version of the OneUptime Docker agent reporting telemetry, as self-reported via the oneuptime.agent.version resource attribute",
386
+ example: "1.0.0",
387
+ })
388
+ @Column({
389
+ nullable: true,
390
+ type: ColumnType.ShortText,
391
+ length: ColumnLength.ShortText,
392
+ })
393
+ public agentVersion?: string = undefined;
394
+
361
395
  @ColumnAccessControl({
362
396
  create: [],
363
397
  read: [
@@ -62,6 +62,8 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
62
62
  tableDescription:
63
63
  "Logs of all the Email sent out to all users and subscribers for this project.",
64
64
  })
65
+ @Index(["projectId", "createdAt"]) // Notification logs table: time-range filter per project
66
+ @Index(["projectId", "status"]) // Notification logs table: status filter per project
65
67
  export default class EmailLog extends BaseModel {
66
68
  @ColumnAccessControl({
67
69
  create: [],
@@ -360,6 +360,40 @@ export default class Host extends BaseModel {
360
360
  })
361
361
  public otelCollectorStatus?: string = undefined;
362
362
 
363
+ @ColumnAccessControl({
364
+ create: [],
365
+ read: [
366
+ Permission.ProjectOwner,
367
+ Permission.ProjectAdmin,
368
+ Permission.ProjectMember,
369
+ Permission.Viewer,
370
+ Permission.SettingsAdmin,
371
+ Permission.SettingsMember,
372
+ Permission.SettingsViewer,
373
+ Permission.ReadHost,
374
+ ],
375
+ update: [
376
+ Permission.ProjectOwner,
377
+ Permission.ProjectAdmin,
378
+ Permission.EditHost,
379
+ ],
380
+ })
381
+ @TableColumn({
382
+ required: false,
383
+ type: TableColumnType.ShortText,
384
+ canReadOnRelationQuery: true,
385
+ title: "Agent Version",
386
+ description:
387
+ "Version of the OneUptime agent reporting telemetry on this host, as self-reported via the oneuptime.agent.version resource attribute",
388
+ example: "1.0.0",
389
+ })
390
+ @Column({
391
+ nullable: true,
392
+ type: ColumnType.ShortText,
393
+ length: ColumnLength.ShortText,
394
+ })
395
+ public agentVersion?: string = undefined;
396
+
363
397
  @ColumnAccessControl({
364
398
  create: [],
365
399
  read: [
@@ -118,6 +118,7 @@ import NotificationRuleWorkspaceChannel from "../../Types/Workspace/Notification
118
118
  delete: true,
119
119
  },
120
120
  })
121
+ @Index(["projectId", "currentIncidentStateId"]) // Active-incident counters on dashboard
121
122
  export default class Incident extends BaseModel {
122
123
  @ColumnAccessControl({
123
124
  create: [
@@ -249,6 +249,43 @@ export default class IncidentCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateIncidentCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.IncidentAdmin,
264
+ Permission.IncidentMember,
265
+ Permission.IncidentViewer,
266
+ Permission.ReadIncidentCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditIncidentCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -91,6 +91,7 @@ export enum IncidentFeedEventType {
91
91
  tableDescription:
92
92
  "Log of the entire incident state change. This is a log of all the incident state changes, public notes, more etc.",
93
93
  })
94
+ @Index(["incidentId", "postedAt"]) // Incident detail page: feed sorted by postedAt
94
95
  export default class IncidentFeed extends BaseModel {
95
96
  @ColumnAccessControl({
96
97
  create: [
@@ -605,6 +605,15 @@ export default class IncidentMember extends BaseModel {
605
605
  read: [],
606
606
  update: [],
607
607
  })
608
+ /*
609
+ * Indexed because `IncidentMembers/SendMemberAddedNotification`
610
+ * cron polls `WHERE isMemberNotified = false` every minute. Without
611
+ * the index the cron does a full table scan that grows with every
612
+ * incident-member assignment ever made. Matches the indexing
613
+ * pattern used by the sibling `isOwnerNotified` flag on state
614
+ * timeline tables.
615
+ */
616
+ @Index()
608
617
  @TableColumn({
609
618
  isDefaultValueColumn: true,
610
619
  type: TableColumnType.Boolean,
@@ -410,6 +410,40 @@ export default class KubernetesCluster extends BaseModel {
410
410
  })
411
411
  public otelCollectorStatus?: string = undefined;
412
412
 
413
+ @ColumnAccessControl({
414
+ create: [],
415
+ read: [
416
+ Permission.ProjectOwner,
417
+ Permission.ProjectAdmin,
418
+ Permission.ProjectMember,
419
+ Permission.Viewer,
420
+ Permission.SettingsAdmin,
421
+ Permission.SettingsMember,
422
+ Permission.SettingsViewer,
423
+ Permission.ReadKubernetesCluster,
424
+ ],
425
+ update: [
426
+ Permission.ProjectOwner,
427
+ Permission.ProjectAdmin,
428
+ Permission.EditKubernetesCluster,
429
+ ],
430
+ })
431
+ @TableColumn({
432
+ required: false,
433
+ type: TableColumnType.ShortText,
434
+ canReadOnRelationQuery: true,
435
+ title: "Agent Version",
436
+ description:
437
+ "Version of the OneUptime Kubernetes agent reporting telemetry, as self-reported via the oneuptime.agent.version resource attribute",
438
+ example: "1.0.0",
439
+ })
440
+ @Column({
441
+ nullable: true,
442
+ type: ColumnType.ShortText,
443
+ length: ColumnLength.ShortText,
444
+ })
445
+ public agentVersion?: string = undefined;
446
+
413
447
  @ColumnAccessControl({
414
448
  create: [],
415
449
  read: [
@@ -249,6 +249,43 @@ export default class MonitorCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateMonitorCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.MonitorAdmin,
264
+ Permission.MonitorMember,
265
+ Permission.MonitorViewer,
266
+ Permission.ReadMonitorCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditMonitorCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -80,6 +80,7 @@ export enum MonitorFeedEventType {
80
80
  tableDescription:
81
81
  "Log of the entire monitor state change. This is a log of all the monitor state changes, public notes, more etc.",
82
82
  })
83
+ @Index(["monitorId", "postedAt"]) // Monitor detail page: feed sorted by postedAt
83
84
  export default class MonitorFeed extends BaseModel {
84
85
  @ColumnAccessControl({
85
86
  create: [
@@ -27,6 +27,7 @@ export type MonitorStepProbeResponse = Dictionary<ProbeMonitorResponse>;
27
27
  @TenantColumn("projectId")
28
28
  @Index(["monitorId", "probeId"]) // Composite index for efficient monitor-probe relationship queries
29
29
  @Index(["monitorId", "projectId"]) // Alternative index for monitor queries within project
30
+ @Index(["probeId", "isEnabled", "nextPingAt"]) // Scheduler hot path: pick due probes per probeId
30
31
  @TableAccessControl({
31
32
  create: [
32
33
  Permission.ProjectOwner,
@@ -244,6 +244,43 @@ export default class OnCallDutyPolicyCustomField extends BaseModel {
244
244
  })
245
245
  public customFieldType?: CustomFieldType = undefined;
246
246
 
247
+ @ColumnAccessControl({
248
+ create: [
249
+ Permission.ProjectOwner,
250
+ Permission.ProjectAdmin,
251
+ Permission.CreateOnCallDutyPolicyCustomField,
252
+ ],
253
+ read: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.ProjectMember,
257
+ Permission.Viewer,
258
+ Permission.OnCallAdmin,
259
+ Permission.OnCallMember,
260
+ Permission.OnCallViewer,
261
+ Permission.ReadOnCallDutyPolicyCustomField,
262
+ ],
263
+ update: [
264
+ Permission.ProjectOwner,
265
+ Permission.ProjectAdmin,
266
+ Permission.EditOnCallDutyPolicyCustomField,
267
+ ],
268
+ })
269
+ @TableColumn({
270
+ required: false,
271
+ type: TableColumnType.LongText,
272
+ title: "Dropdown Options",
273
+ description:
274
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
275
+ example: "Option 1\nOption 2\nOption 3",
276
+ })
277
+ @Column({
278
+ nullable: true,
279
+ type: ColumnType.LongText,
280
+ length: ColumnLength.LongText,
281
+ })
282
+ public dropdownOptions?: string = undefined;
283
+
247
284
  @ColumnAccessControl({
248
285
  create: [
249
286
  Permission.ProjectOwner,
@@ -483,6 +483,7 @@ export default class OnCallDutyPolicyTimeLog extends BaseModel {
483
483
  ],
484
484
  update: [],
485
485
  })
486
+ @Index()
486
487
  @TableColumn({
487
488
  type: TableColumnType.ObjectID,
488
489
  required: true,
@@ -497,6 +498,7 @@ export default class OnCallDutyPolicyTimeLog extends BaseModel {
497
498
  })
498
499
  public userId?: ObjectID = undefined;
499
500
 
501
+ @Index()
500
502
  @TableColumn({
501
503
  title: "Start At",
502
504
  type: TableColumnType.Date,
@@ -530,6 +532,7 @@ export default class OnCallDutyPolicyTimeLog extends BaseModel {
530
532
  })
531
533
  public startsAt?: Date = undefined;
532
534
 
535
+ @Index()
533
536
  @TableColumn({
534
537
  title: "Ends At",
535
538
  type: TableColumnType.Date,
@@ -249,6 +249,43 @@ export default class ScheduledMaintenanceCustomField extends BaseModel {
249
249
  })
250
250
  public customFieldType?: CustomFieldType = undefined;
251
251
 
252
+ @ColumnAccessControl({
253
+ create: [
254
+ Permission.ProjectOwner,
255
+ Permission.ProjectAdmin,
256
+ Permission.CreateScheduledMaintenanceCustomField,
257
+ ],
258
+ read: [
259
+ Permission.ProjectOwner,
260
+ Permission.ProjectAdmin,
261
+ Permission.ProjectMember,
262
+ Permission.Viewer,
263
+ Permission.ScheduledMaintenanceAdmin,
264
+ Permission.ScheduledMaintenanceMember,
265
+ Permission.ScheduledMaintenanceViewer,
266
+ Permission.ReadScheduledMaintenanceCustomField,
267
+ ],
268
+ update: [
269
+ Permission.ProjectOwner,
270
+ Permission.ProjectAdmin,
271
+ Permission.EditScheduledMaintenanceCustomField,
272
+ ],
273
+ })
274
+ @TableColumn({
275
+ required: false,
276
+ type: TableColumnType.LongText,
277
+ title: "Dropdown Options",
278
+ description:
279
+ "Options for the dropdown field, one per line. Only used when Custom Field Type is Dropdown.",
280
+ example: "Option 1\nOption 2\nOption 3",
281
+ })
282
+ @Column({
283
+ nullable: true,
284
+ type: ColumnType.LongText,
285
+ length: ColumnLength.LongText,
286
+ })
287
+ public dropdownOptions?: string = undefined;
288
+
252
289
  @ColumnAccessControl({
253
290
  create: [
254
291
  Permission.ProjectOwner,
@@ -61,6 +61,8 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
61
61
  tableDescription:
62
62
  "Logs of all the SMS sent out to all users and subscribers for this project.",
63
63
  })
64
+ @Index(["projectId", "createdAt"]) // Notification logs table: time-range filter per project
65
+ @Index(["projectId", "status"]) // Notification logs table: status filter per project
64
66
  export default class SmsLog extends BaseModel {
65
67
  @ColumnAccessControl({
66
68
  create: [],