@oneuptime/common 10.0.96 → 10.0.98

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 (131) hide show
  1. package/Models/AnalyticsModels/Log.ts +6 -0
  2. package/Models/AnalyticsModels/Metric.ts +6 -0
  3. package/Models/AnalyticsModels/Profile.ts +6 -0
  4. package/Models/AnalyticsModels/Span.ts +6 -0
  5. package/Models/DatabaseModels/Alert.ts +52 -0
  6. package/Models/DatabaseModels/DockerHost.ts +3 -10
  7. package/Models/DatabaseModels/Host.ts +1015 -0
  8. package/Models/DatabaseModels/HostOwnerTeam.ts +462 -0
  9. package/Models/DatabaseModels/HostOwnerUser.ts +461 -0
  10. package/Models/DatabaseModels/Incident.ts +52 -0
  11. package/Models/DatabaseModels/Index.ts +6 -0
  12. package/Models/DatabaseModels/KubernetesCluster.ts +0 -7
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1778006035712-AddHostTables.ts +201 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1778013317872-AddHostIpAddresses.ts +15 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1778066346303-WidenHostOsVersionToLongText.ts +42 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1778070278986-MigrationName.ts +79 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  18. package/Server/Services/DockerHostService.ts +18 -5
  19. package/Server/Services/HostOwnerTeamService.ts +10 -0
  20. package/Server/Services/HostOwnerUserService.ts +10 -0
  21. package/Server/Services/HostService.ts +251 -0
  22. package/Server/Services/LogAggregationService.ts +10 -3
  23. package/Server/Services/MetricService.ts +200 -0
  24. package/Server/Services/TraceAggregationService.ts +8 -3
  25. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +46 -18
  26. package/Server/Utils/Monitor/MonitorAlert.ts +37 -0
  27. package/Server/Utils/Monitor/MonitorIncident.ts +37 -0
  28. package/Tests/Server/Services/LogAggregationService.test.ts +25 -0
  29. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +145 -0
  30. package/Types/Metrics/MetricQueryConfigData.ts +9 -0
  31. package/Types/Permission.ts +134 -0
  32. package/UI/Components/Charts/Area/AreaChart.tsx +1 -1
  33. package/UI/Components/Charts/Bar/BarChart.tsx +1 -1
  34. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +17 -8
  35. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +11 -6
  36. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +17 -8
  37. package/UI/Components/Charts/Line/LineChart.tsx +1 -1
  38. package/UI/Components/ExpandableText/ExpandableText.tsx +29 -7
  39. package/UI/Components/JSONTable/JSONTable.tsx +27 -1
  40. package/UI/Components/LogsViewer/LogsViewer.tsx +3 -0
  41. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +109 -23
  42. package/UI/Components/LogsViewer/components/LogSearchBar.tsx +11 -4
  43. package/UI/Components/Navbar/NavBarMenu.tsx +17 -2
  44. package/UI/Components/TelemetryViewer/components/TelemetrySearchBar.tsx +10 -3
  45. package/Utils/ValueFormatter.ts +57 -3
  46. package/build/dist/Models/AnalyticsModels/Log.js +6 -0
  47. package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
  48. package/build/dist/Models/AnalyticsModels/Metric.js +6 -0
  49. package/build/dist/Models/AnalyticsModels/Metric.js.map +1 -1
  50. package/build/dist/Models/AnalyticsModels/Profile.js +6 -0
  51. package/build/dist/Models/AnalyticsModels/Profile.js.map +1 -1
  52. package/build/dist/Models/AnalyticsModels/Span.js +6 -0
  53. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  54. package/build/dist/Models/DatabaseModels/Alert.js +51 -0
  55. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  56. package/build/dist/Models/DatabaseModels/DockerHost.js +3 -10
  57. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  58. package/build/dist/Models/DatabaseModels/Host.js +1041 -0
  59. package/build/dist/Models/DatabaseModels/Host.js.map +1 -0
  60. package/build/dist/Models/DatabaseModels/HostOwnerTeam.js +480 -0
  61. package/build/dist/Models/DatabaseModels/HostOwnerTeam.js.map +1 -0
  62. package/build/dist/Models/DatabaseModels/HostOwnerUser.js +479 -0
  63. package/build/dist/Models/DatabaseModels/HostOwnerUser.js.map +1 -0
  64. package/build/dist/Models/DatabaseModels/Incident.js +51 -0
  65. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  66. package/build/dist/Models/DatabaseModels/Index.js +6 -0
  67. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  68. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +0 -7
  69. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  70. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778006035712-AddHostTables.js +76 -0
  71. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778006035712-AddHostTables.js.map +1 -0
  72. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778013317872-AddHostIpAddresses.js +12 -0
  73. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778013317872-AddHostIpAddresses.js.map +1 -0
  74. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778066346303-WidenHostOsVersionToLongText.js +31 -0
  75. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778066346303-WidenHostOsVersionToLongText.js.map +1 -0
  76. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778070278986-MigrationName.js +34 -0
  77. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778070278986-MigrationName.js.map +1 -0
  78. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  80. package/build/dist/Server/Services/DockerHostService.js +12 -5
  81. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  82. package/build/dist/Server/Services/HostOwnerTeamService.js +9 -0
  83. package/build/dist/Server/Services/HostOwnerTeamService.js.map +1 -0
  84. package/build/dist/Server/Services/HostOwnerUserService.js +9 -0
  85. package/build/dist/Server/Services/HostOwnerUserService.js.map +1 -0
  86. package/build/dist/Server/Services/HostService.js +214 -0
  87. package/build/dist/Server/Services/HostService.js.map +1 -0
  88. package/build/dist/Server/Services/LogAggregationService.js +10 -3
  89. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  90. package/build/dist/Server/Services/MetricService.js +160 -0
  91. package/build/dist/Server/Services/MetricService.js.map +1 -1
  92. package/build/dist/Server/Services/TraceAggregationService.js +8 -3
  93. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  94. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +46 -18
  95. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  96. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +32 -0
  97. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  98. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +32 -0
  99. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  100. package/build/dist/Tests/Server/Services/LogAggregationService.test.js +13 -0
  101. package/build/dist/Tests/Server/Services/LogAggregationService.test.js.map +1 -1
  102. package/build/dist/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.js +123 -0
  103. package/build/dist/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.js.map +1 -1
  104. package/build/dist/Types/Permission.js +120 -0
  105. package/build/dist/Types/Permission.js.map +1 -1
  106. package/build/dist/UI/Components/Charts/Area/AreaChart.js +1 -1
  107. package/build/dist/UI/Components/Charts/Bar/BarChart.js +1 -1
  108. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +15 -7
  109. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  110. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +10 -6
  111. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  112. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +16 -8
  113. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  114. package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
  115. package/build/dist/UI/Components/ExpandableText/ExpandableText.js +10 -5
  116. package/build/dist/UI/Components/ExpandableText/ExpandableText.js.map +1 -1
  117. package/build/dist/UI/Components/JSONTable/JSONTable.js +8 -1
  118. package/build/dist/UI/Components/JSONTable/JSONTable.js.map +1 -1
  119. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +1 -1
  120. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  121. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +40 -14
  122. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  123. package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js +10 -4
  124. package/build/dist/UI/Components/LogsViewer/components/LogSearchBar.js.map +1 -1
  125. package/build/dist/UI/Components/Navbar/NavBarMenu.js +15 -2
  126. package/build/dist/UI/Components/Navbar/NavBarMenu.js.map +1 -1
  127. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js +10 -3
  128. package/build/dist/UI/Components/TelemetryViewer/components/TelemetrySearchBar.js.map +1 -1
  129. package/build/dist/Utils/ValueFormatter.js +47 -3
  130. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  131. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
+ import Host from "../../../Models/DatabaseModels/Host";
1
2
  import Incident from "../../../Models/DatabaseModels/Incident";
2
3
  import IncidentSeverity from "../../../Models/DatabaseModels/IncidentSeverity";
3
4
  import IncidentStateTimeline from "../../../Models/DatabaseModels/IncidentStateTimeline";
@@ -15,6 +16,7 @@ import ObjectID from "../../../Types/ObjectID";
15
16
  import ProbeMonitorResponse from "../../../Types/Probe/ProbeMonitorResponse";
16
17
  import { TelemetryQuery } from "../../../Types/Telemetry/TelemetryQuery";
17
18
  import { DisableAutomaticIncidentCreation } from "../../EnvironmentConfig";
19
+ import HostService from "../../Services/HostService";
18
20
  import IncidentService from "../../Services/IncidentService";
19
21
  import IncidentSeverityService from "../../Services/IncidentSeverityService";
20
22
  import IncidentStateTimelineService from "../../Services/IncidentStateTimelineService";
@@ -313,6 +315,41 @@ export default class MonitorIncident {
313
315
  }
314
316
  if (seriesLabels && Object.keys(seriesLabels).length > 0) {
315
317
  incident.seriesLabels = seriesLabels;
318
+
319
+ /*
320
+ * Link the incident to the Host that emitted this series, if
321
+ * the metric carried a `host.name` resource attribute. The
322
+ * Host record was auto-discovered during OTel ingestion.
323
+ * Metric attributes are stored with the `resource.` prefix in
324
+ * ClickHouse, so the group-by dropdown surfaces
325
+ * `resource.host.name` — but accept the bare `host.name` too
326
+ * for any non-OTel ingest paths.
327
+ */
328
+ const hostName: string | undefined =
329
+ typeof seriesLabels["resource.host.name"] === "string"
330
+ ? (seriesLabels["resource.host.name"] as string)
331
+ : typeof seriesLabels["host.name"] === "string"
332
+ ? (seriesLabels["host.name"] as string)
333
+ : undefined;
334
+
335
+ if (hostName) {
336
+ const host: Host | null = await HostService.findOneBy({
337
+ query: {
338
+ projectId: input.monitor.projectId!,
339
+ hostIdentifier: hostName,
340
+ },
341
+ select: {
342
+ _id: true,
343
+ },
344
+ props: {
345
+ isRoot: true,
346
+ },
347
+ });
348
+
349
+ if (host) {
350
+ incident.hosts = [host];
351
+ }
352
+ }
316
353
  }
317
354
 
318
355
  incident.onCallDutyPolicies =
@@ -80,4 +80,29 @@ describe("LogAggregationService", () => {
80
80
  });
81
81
  }).toThrow("Invalid facetKey");
82
82
  });
83
+
84
+ test("histogram attribute filter matches attribute keys case-insensitively", () => {
85
+ /*
86
+ * Users typing `requestid` should still match data stored with the key
87
+ * `requestId` (camelCase). The histogram filter shares the same WHERE
88
+ * clause builder (`appendCommonFilters`) with the list/facet queries, so
89
+ * verifying it on histogram covers all three.
90
+ */
91
+ const statement: Statement = (
92
+ LogAggregationService as any
93
+ ).buildHistogramStatement({
94
+ ...defaultRequest,
95
+ facetKey: undefined,
96
+ attributes: { requestid: "uuid-123" },
97
+ });
98
+
99
+ expect(statement.query).toContain(
100
+ "arrayExists((k, v) -> lowerUTF8(k) = lowerUTF8(",
101
+ );
102
+ expect(statement.query).toContain(
103
+ ", mapKeys(attributes), mapValues(attributes))",
104
+ );
105
+ expect(Object.values(statement.query_params)).toContain("requestid");
106
+ expect(Object.values(statement.query_params)).toContain("uuid-123");
107
+ });
83
108
  });
@@ -13,6 +13,13 @@ import AnalyticsTableEngine from "../../../../Types/AnalyticsDatabase/AnalyticsT
13
13
  import AnalyticsTableColumn from "../../../../Types/AnalyticsDatabase/TableColumn";
14
14
  import TableColumnType from "../../../../Types/AnalyticsDatabase/TableColumnType";
15
15
  import OneUptimeDate from "../../../../Types/Date";
16
+ import EqualTo from "../../../../Types/BaseDatabase/EqualTo";
17
+ import NotEqual from "../../../../Types/BaseDatabase/NotEqual";
18
+ import IsNull from "../../../../Types/BaseDatabase/IsNull";
19
+ import NotNull from "../../../../Types/BaseDatabase/NotNull";
20
+ import GreaterThan from "../../../../Types/BaseDatabase/GreaterThan";
21
+ import Search from "../../../../Types/BaseDatabase/Search";
22
+ import StartsWith from "../../../../Types/BaseDatabase/StartsWith";
16
23
 
17
24
  function expectStatement(actual: Statement, expected: Statement): void {
18
25
  expect(actual.query).toBe(expected.query);
@@ -179,6 +186,144 @@ describe("StatementGenerator", () => {
179
186
  p3: OneUptimeDate.toClickhouseDateTime(date),
180
187
  });
181
188
  });
189
+
190
+ describe("MapStringString columns", () => {
191
+ class MapModel extends AnalyticsBaseModel {
192
+ public constructor() {
193
+ super({
194
+ tableName: "<map-table>",
195
+ singularName: "<singular>",
196
+ pluralName: "<plural>",
197
+ tableColumns: [
198
+ new AnalyticsTableColumn({
199
+ key: "_id",
200
+ title: "<title>",
201
+ description: "<description>",
202
+ required: true,
203
+ type: TableColumnType.ObjectID,
204
+ }),
205
+ new AnalyticsTableColumn({
206
+ key: "attributes",
207
+ title: "<title>",
208
+ description: "<description>",
209
+ required: true,
210
+ defaultValue: {},
211
+ type: TableColumnType.MapStringString,
212
+ }),
213
+ ],
214
+ crudApiPath: new Route("route"),
215
+ primaryKeys: ["_id"],
216
+ sortKeys: ["_id"],
217
+ partitionKey: "_id",
218
+ tableEngine: AnalyticsTableEngine.MergeTree,
219
+ });
220
+ }
221
+ }
222
+
223
+ let mapGenerator: StatementGenerator<MapModel>;
224
+ beforeEach(() => {
225
+ mapGenerator = new StatementGenerator<MapModel>({
226
+ modelType: MapModel,
227
+ database: ClickhouseAppInstance,
228
+ });
229
+ });
230
+
231
+ test("uses direct map subscript for bare-value equality", () => {
232
+ const statement: Statement = mapGenerator.toWhereStatement({
233
+ attributes: { requestId: "uuid-123" },
234
+ } as any);
235
+ /*
236
+ * Programmatic callers pass canonical keys, so bare-value
237
+ * equality compiles to `attributes['k'] = v` — an O(1) Map
238
+ * subscript that the planner can push into PREWHERE. The
239
+ * slower case-insensitive arrayExists form is reserved for
240
+ * the user-typed Search/StartsWith/EndsWith/NotContains
241
+ * operators below.
242
+ */
243
+ expect(statement.query).toBe(
244
+ "AND {p0:Identifier}[{p1:String}] = {p2:String}",
245
+ );
246
+ expect(statement.query_params).toStrictEqual({
247
+ p0: "attributes",
248
+ p1: "requestId",
249
+ p2: "uuid-123",
250
+ });
251
+ });
252
+
253
+ test("uses direct map subscript for EqualTo wrapper", () => {
254
+ const statement: Statement = mapGenerator.toWhereStatement({
255
+ attributes: { requestId: new EqualTo("uuid-123") },
256
+ } as any);
257
+ expect(statement.query).toBe(
258
+ "AND {p0:Identifier}[{p1:String}] = {p2:String}",
259
+ );
260
+ expect(statement.query_params).toStrictEqual({
261
+ p0: "attributes",
262
+ p1: "requestId",
263
+ p2: "uuid-123",
264
+ });
265
+ });
266
+
267
+ test("uses direct map subscript for NotEqual wrapper", () => {
268
+ const statement: Statement = mapGenerator.toWhereStatement({
269
+ attributes: { requestId: new NotEqual("uuid-123") },
270
+ } as any);
271
+ expect(statement.query).toBe(
272
+ "AND {p0:Identifier}[{p1:String}] != {p2:String}",
273
+ );
274
+ });
275
+
276
+ test("uses mapContains+subscript for IsNull wrapper", () => {
277
+ const statement: Statement = mapGenerator.toWhereStatement({
278
+ attributes: { requestId: new IsNull() },
279
+ } as any);
280
+ expect(statement.query).toBe(
281
+ "AND ((NOT mapContains({p0:Identifier}, {p1:String})) OR {p2:Identifier}[{p3:String}] = '')",
282
+ );
283
+ });
284
+
285
+ test("uses mapContains+subscript for NotNull wrapper", () => {
286
+ const statement: Statement = mapGenerator.toWhereStatement({
287
+ attributes: { requestId: new NotNull() },
288
+ } as any);
289
+ expect(statement.query).toBe(
290
+ "AND mapContains({p0:Identifier}, {p1:String}) AND {p2:Identifier}[{p3:String}] != ''",
291
+ );
292
+ });
293
+
294
+ test("uses direct map subscript for numeric GreaterThan wrapper", () => {
295
+ const statement: Statement = mapGenerator.toWhereStatement({
296
+ attributes: { httpStatus: new GreaterThan(500) },
297
+ } as any);
298
+ expect(statement.query).toBe(
299
+ "AND toFloat64OrNull({p0:Identifier}[{p1:String}]) > {p2:Int32}",
300
+ );
301
+ });
302
+
303
+ test("keeps case-insensitive arrayExists for Search wrapper", () => {
304
+ const statement: Statement = mapGenerator.toWhereStatement({
305
+ attributes: { requestId: new Search("uuid") },
306
+ } as any);
307
+ /*
308
+ * Search comes from the user-typed search bar — keep the
309
+ * case-insensitive ILIKE form so the user doesn't have to
310
+ * remember whether the stored key is `requestId` or
311
+ * `requestid`.
312
+ */
313
+ expect(statement.query).toContain("arrayExists");
314
+ expect(statement.query).toContain("lowerUTF8");
315
+ expect(statement.query).toContain("ILIKE");
316
+ });
317
+
318
+ test("keeps case-insensitive arrayExists for StartsWith wrapper", () => {
319
+ const statement: Statement = mapGenerator.toWhereStatement({
320
+ attributes: { requestId: new StartsWith("uuid") },
321
+ } as any);
322
+ expect(statement.query).toContain("arrayExists");
323
+ expect(statement.query).toContain("lowerUTF8");
324
+ expect(statement.query).toContain("ILIKE");
325
+ });
326
+ });
182
327
  });
183
328
 
184
329
  describe("toSelectStatement", () => {
@@ -20,4 +20,13 @@ export default interface MetricQueryConfigData {
20
20
  yAxisValueFormatter?: ((value: number) => string) | undefined;
21
21
  warningThreshold?: number | undefined;
22
22
  criticalThreshold?: number | undefined;
23
+ /*
24
+ * When true, the post-aggregation series points are transformed into
25
+ * a per-second rate of change: `(value - previousValue) / Δt`. This is
26
+ * the right view for OTel cumulative counters (e.g. `system.disk.io`,
27
+ * `system.network.io`) — without it, the chart plots monotonically
28
+ * growing bytes-since-process-start. Negative deltas (counter resets
29
+ * on agent restart) are clamped to 0.
30
+ */
31
+ transformAsRate?: boolean | undefined;
23
32
  }
@@ -812,6 +812,21 @@ enum Permission {
812
812
  EditDockerHostOwnerUser = "EditDockerHostOwnerUser",
813
813
  ReadDockerHostOwnerUser = "ReadDockerHostOwnerUser",
814
814
 
815
+ CreateHost = "CreateHost",
816
+ DeleteHost = "DeleteHost",
817
+ EditHost = "EditHost",
818
+ ReadHost = "ReadHost",
819
+
820
+ CreateHostOwnerTeam = "CreateHostOwnerTeam",
821
+ DeleteHostOwnerTeam = "DeleteHostOwnerTeam",
822
+ EditHostOwnerTeam = "EditHostOwnerTeam",
823
+ ReadHostOwnerTeam = "ReadHostOwnerTeam",
824
+
825
+ CreateHostOwnerUser = "CreateHostOwnerUser",
826
+ DeleteHostOwnerUser = "DeleteHostOwnerUser",
827
+ EditHostOwnerUser = "EditHostOwnerUser",
828
+ ReadHostOwnerUser = "ReadHostOwnerUser",
829
+
815
830
  CreateService = "CreateService",
816
831
  DeleteService = "DeleteService",
817
832
  EditService = "EditService",
@@ -5602,6 +5617,125 @@ export class PermissionHelper {
5602
5617
  group: PermissionGroup.Telemetry,
5603
5618
  },
5604
5619
 
5620
+ {
5621
+ permission: Permission.CreateHost,
5622
+ title: "Create Host",
5623
+ description: "This permission can create Host in this project.",
5624
+ isAssignableToTenant: true,
5625
+ isAccessControlPermission: false,
5626
+ isRolePermission: false,
5627
+ group: PermissionGroup.Telemetry,
5628
+ },
5629
+ {
5630
+ permission: Permission.DeleteHost,
5631
+ title: "Delete Host",
5632
+ description: "This permission can delete Host of this project.",
5633
+ isAssignableToTenant: true,
5634
+ isAccessControlPermission: true,
5635
+ isRolePermission: false,
5636
+ group: PermissionGroup.Telemetry,
5637
+ },
5638
+ {
5639
+ permission: Permission.EditHost,
5640
+ title: "Edit Host",
5641
+ description: "This permission can edit Host of this project.",
5642
+ isAssignableToTenant: true,
5643
+ isAccessControlPermission: true,
5644
+ isRolePermission: false,
5645
+ group: PermissionGroup.Telemetry,
5646
+ },
5647
+ {
5648
+ permission: Permission.ReadHost,
5649
+ title: "Read Host",
5650
+ description: "This permission can read Host of this project.",
5651
+ isAssignableToTenant: true,
5652
+ isAccessControlPermission: true,
5653
+ isRolePermission: false,
5654
+ group: PermissionGroup.Telemetry,
5655
+ },
5656
+
5657
+ {
5658
+ permission: Permission.CreateHostOwnerTeam,
5659
+ title: "Create Host Team Owner",
5660
+ description:
5661
+ "This permission can create Host Team Owner of this project.",
5662
+ isAssignableToTenant: true,
5663
+ isAccessControlPermission: false,
5664
+ isRolePermission: false,
5665
+ group: PermissionGroup.Telemetry,
5666
+ },
5667
+ {
5668
+ permission: Permission.DeleteHostOwnerTeam,
5669
+ title: "Delete Host Team Owner",
5670
+ description:
5671
+ "This permission can delete Host Team Owner of this project.",
5672
+ isAssignableToTenant: true,
5673
+ isAccessControlPermission: false,
5674
+ isRolePermission: false,
5675
+ group: PermissionGroup.Telemetry,
5676
+ },
5677
+ {
5678
+ permission: Permission.EditHostOwnerTeam,
5679
+ title: "Edit Host Team Owner",
5680
+ description:
5681
+ "This permission can edit Host Team Owner of this project.",
5682
+ isAssignableToTenant: true,
5683
+ isAccessControlPermission: false,
5684
+ isRolePermission: false,
5685
+ group: PermissionGroup.Telemetry,
5686
+ },
5687
+ {
5688
+ permission: Permission.ReadHostOwnerTeam,
5689
+ title: "Read Host Team Owner",
5690
+ description:
5691
+ "This permission can read Host Team Owner of this project.",
5692
+ isAssignableToTenant: true,
5693
+ isAccessControlPermission: false,
5694
+ isRolePermission: false,
5695
+ group: PermissionGroup.Telemetry,
5696
+ },
5697
+
5698
+ {
5699
+ permission: Permission.CreateHostOwnerUser,
5700
+ title: "Create Host User Owner",
5701
+ description:
5702
+ "This permission can create Host User Owner of this project.",
5703
+ isAssignableToTenant: true,
5704
+ isAccessControlPermission: false,
5705
+ isRolePermission: false,
5706
+ group: PermissionGroup.Telemetry,
5707
+ },
5708
+ {
5709
+ permission: Permission.DeleteHostOwnerUser,
5710
+ title: "Delete Host User Owner",
5711
+ description:
5712
+ "This permission can delete Host User Owner of this project.",
5713
+ isAssignableToTenant: true,
5714
+ isAccessControlPermission: false,
5715
+ isRolePermission: false,
5716
+ group: PermissionGroup.Telemetry,
5717
+ },
5718
+ {
5719
+ permission: Permission.EditHostOwnerUser,
5720
+ title: "Edit Host User Owner",
5721
+ description:
5722
+ "This permission can edit Host User Owner of this project.",
5723
+ isAssignableToTenant: true,
5724
+ isAccessControlPermission: false,
5725
+ isRolePermission: false,
5726
+ group: PermissionGroup.Telemetry,
5727
+ },
5728
+ {
5729
+ permission: Permission.ReadHostOwnerUser,
5730
+ title: "Read Host User Owner",
5731
+ description:
5732
+ "This permission can read Host User Owner of this project.",
5733
+ isAssignableToTenant: true,
5734
+ isAccessControlPermission: false,
5735
+ isRolePermission: false,
5736
+ group: PermissionGroup.Telemetry,
5737
+ },
5738
+
5605
5739
  {
5606
5740
  permission: Permission.CreateService,
5607
5741
  title: "Create Service",
@@ -115,7 +115,7 @@ const AreaChartElement: FunctionComponent<AreaInternalProps> = (
115
115
  connectNulls={true}
116
116
  curve={props.curve || ChartCurve.MONOTONE}
117
117
  syncid={props.sync ? props.syncid : undefined}
118
- yAxisWidth={60}
118
+ yAxisWidth={64}
119
119
  onValueChange={() => {}}
120
120
  referenceLines={props.referenceLines}
121
121
  formattedExemplarPoints={
@@ -79,7 +79,7 @@ const BarChartElement: FunctionComponent<BarInternalProps> = (
79
79
  valueFormatter={props.yAxis.options.formatter || undefined}
80
80
  showTooltip={true}
81
81
  showLegend={props.showLegend !== false}
82
- yAxisWidth={60}
82
+ yAxisWidth={64}
83
83
  syncid={props.sync ? props.syncid : undefined}
84
84
  onValueChange={() => {}}
85
85
  referenceLines={props.referenceLines}
@@ -695,9 +695,9 @@ const AreaChart: React.ForwardRefExoticComponent<
695
695
  : () => {}
696
696
  }
697
697
  margin={{
698
- bottom: (xAxisLabel ? 30 : undefined) as unknown as number,
699
- left: (yAxisLabel ? 20 : undefined) as unknown as number,
700
- right: (yAxisLabel ? 5 : undefined) as unknown as number,
698
+ bottom: (xAxisLabel ? 30 : 8) as unknown as number,
699
+ left: (yAxisLabel ? 20 : 0) as unknown as number,
700
+ right: (yAxisLabel ? 5 : 8) as unknown as number,
701
701
  top: 5,
702
702
  }}
703
703
  >
@@ -724,7 +724,8 @@ const AreaChart: React.ForwardRefExoticComponent<
724
724
  </defs>
725
725
  {showGridLines ? (
726
726
  <CartesianGrid
727
- className={cx("stroke-gray-200 stroke-1")}
727
+ className={cx("stroke-gray-100")}
728
+ strokeDasharray="3 3"
728
729
  horizontal={true}
729
730
  vertical={false}
730
731
  />
@@ -734,7 +735,11 @@ const AreaChart: React.ForwardRefExoticComponent<
734
735
  hide={!showXAxis}
735
736
  dataKey={index}
736
737
  interval={startEndOnly ? "preserveStartEnd" : intervalType}
737
- tick={{ transform: "translate(0, 6)" }}
738
+ tick={{
739
+ transform: "translate(0, 6)",
740
+ fontSize: 10,
741
+ fontWeight: 500,
742
+ }}
738
743
  ticks={
739
744
  startEndOnly
740
745
  ? ([
@@ -748,7 +753,7 @@ const AreaChart: React.ForwardRefExoticComponent<
748
753
  }
749
754
  fill=""
750
755
  stroke=""
751
- className={cx("text-xs", "fill-gray-500")}
756
+ className={cx("tabular-nums", "fill-gray-500")}
752
757
  tickLine={false}
753
758
  axisLine={false}
754
759
  minTickGap={tickGap}
@@ -770,10 +775,14 @@ const AreaChart: React.ForwardRefExoticComponent<
770
775
  tickLine={false}
771
776
  type="number"
772
777
  domain={yAxisDomain as AxisDomain}
773
- tick={{ transform: "translate(-3, 0)" }}
778
+ tick={{
779
+ transform: "translate(-4, 0)",
780
+ fontSize: 10,
781
+ fontWeight: 500,
782
+ }}
774
783
  fill=""
775
784
  stroke=""
776
- className={cx("text-xs", "fill-gray-500")}
785
+ className={cx("tabular-nums", "fill-gray-500")}
777
786
  tickFormatter={valueFormatter}
778
787
  allowDecimals={allowDecimals}
779
788
  >
@@ -794,9 +794,9 @@ const BarChart: React.ForwardRefExoticComponent<
794
794
  }
795
795
  : {})}
796
796
  margin={{
797
- bottom: xAxisLabel ? 30 : 0,
797
+ bottom: xAxisLabel ? 30 : 8,
798
798
  left: yAxisLabel ? 20 : 0,
799
- right: yAxisLabel ? 5 : 0,
799
+ right: yAxisLabel ? 5 : 8,
800
800
  top: 5,
801
801
  }}
802
802
  stackOffset={type === "percent" ? "expand" : "none"}
@@ -805,7 +805,8 @@ const BarChart: React.ForwardRefExoticComponent<
805
805
  >
806
806
  {showGridLines ? (
807
807
  <CartesianGrid
808
- className={cx("stroke-gray-200 stroke-1")}
808
+ className={cx("stroke-gray-100")}
809
+ strokeDasharray="3 3"
809
810
  horizontal={layout !== "vertical"}
810
811
  vertical={layout === "vertical"}
811
812
  />
@@ -815,12 +816,14 @@ const BarChart: React.ForwardRefExoticComponent<
815
816
  tick={{
816
817
  transform:
817
818
  layout !== "vertical" ? "translate(0, 6)" : undefined,
819
+ fontSize: 10,
820
+ fontWeight: 500,
818
821
  }}
819
822
  fill=""
820
823
  stroke=""
821
824
  className={cx(
822
825
  // base
823
- "text-xs",
826
+ "tabular-nums",
824
827
  // text fill
825
828
  "fill-gray-500",
826
829
  { "mt-4": layout !== "vertical" },
@@ -872,15 +875,17 @@ const BarChart: React.ForwardRefExoticComponent<
872
875
  stroke=""
873
876
  className={cx(
874
877
  // base
875
- "text-xs",
878
+ "tabular-nums",
876
879
  // text fill
877
880
  "fill-gray-500",
878
881
  )}
879
882
  tick={{
880
883
  transform:
881
884
  layout !== "vertical"
882
- ? "translate(-3, 0)"
885
+ ? "translate(-4, 0)"
883
886
  : "translate(0, 0)",
887
+ fontSize: 10,
888
+ fontWeight: 500,
884
889
  }}
885
890
  {...(layout !== "vertical"
886
891
  ? {
@@ -710,15 +710,16 @@ const LineChart: React.ForwardRefExoticComponent<
710
710
  : () => {} // do nothing
711
711
  }
712
712
  margin={{
713
- bottom: (xAxisLabel ? 30 : undefined) as unknown as number,
714
- left: (yAxisLabel ? 20 : undefined) as unknown as number,
715
- right: (yAxisLabel ? 5 : undefined) as unknown as number,
713
+ bottom: (xAxisLabel ? 30 : 8) as unknown as number,
714
+ left: (yAxisLabel ? 20 : 0) as unknown as number,
715
+ right: (yAxisLabel ? 5 : 8) as unknown as number,
716
716
  top: 5,
717
717
  }}
718
718
  >
719
719
  {showGridLines ? (
720
720
  <CartesianGrid
721
- className={cx("stroke-gray-200 stroke-1")}
721
+ className={cx("stroke-gray-100")}
722
+ strokeDasharray="3 3"
722
723
  horizontal={true}
723
724
  vertical={false}
724
725
  />
@@ -728,7 +729,11 @@ const LineChart: React.ForwardRefExoticComponent<
728
729
  hide={!showXAxis}
729
730
  dataKey={index}
730
731
  interval={startEndOnly ? "preserveStartEnd" : intervalType}
731
- tick={{ transform: "translate(0, 6)" }}
732
+ tick={{
733
+ transform: "translate(0, 6)",
734
+ fontSize: 10,
735
+ fontWeight: 500,
736
+ }}
732
737
  ticks={
733
738
  startEndOnly
734
739
  ? ([
@@ -741,7 +746,7 @@ const LineChart: React.ForwardRefExoticComponent<
741
746
  stroke=""
742
747
  className={cx(
743
748
  // base
744
- "text-xs",
749
+ "tabular-nums",
745
750
  // text fill
746
751
  "fill-gray-500",
747
752
  )}
@@ -766,12 +771,16 @@ const LineChart: React.ForwardRefExoticComponent<
766
771
  tickLine={false}
767
772
  type="number"
768
773
  domain={yAxisDomain as AxisDomain}
769
- tick={{ transform: "translate(-3, 0)" }}
774
+ tick={{
775
+ transform: "translate(-4, 0)",
776
+ fontSize: 10,
777
+ fontWeight: 500,
778
+ }}
770
779
  fill=""
771
780
  stroke=""
772
781
  className={cx(
773
782
  // base
774
- "text-xs",
783
+ "tabular-nums",
775
784
  // text fill
776
785
  "fill-gray-500",
777
786
  )}
@@ -114,7 +114,7 @@ const LineChartElement: FunctionComponent<LineInternalProps> = (
114
114
  connectNulls={true}
115
115
  curve={props.curve}
116
116
  syncid={props.sync ? props.syncid : undefined}
117
- yAxisWidth={60}
117
+ yAxisWidth={64}
118
118
  onValueChange={() => {}}
119
119
  referenceLines={props.referenceLines}
120
120
  formattedExemplarPoints={
@@ -17,23 +17,45 @@ const ExpandableText: FunctionComponent<ComponentProps> = (
17
17
  }
18
18
 
19
19
  const isLong: boolean = props.text.length > maxLength;
20
+ const baseTextClass: string = props.className || "text-sm text-gray-900";
20
21
 
21
22
  if (!isLong) {
22
- return (
23
- <span className={props.className || "text-gray-600"}>{props.text}</span>
24
- );
23
+ return <span className={baseTextClass}>{props.text}</span>;
25
24
  }
26
25
 
26
+ const truncated: string =
27
+ props.text.substring(0, maxLength).replace(/\s+$/u, "") + "…";
28
+
27
29
  return (
28
- <span className={props.className || "text-gray-600"}>
29
- {isExpanded ? props.text : props.text.substring(0, maxLength) + "..."}
30
+ <span className="inline align-baseline">
31
+ <span className={`${baseTextClass} break-words align-baseline`}>
32
+ {isExpanded ? props.text : truncated}
33
+ </span>
30
34
  <button
35
+ type="button"
31
36
  onClick={() => {
32
37
  setIsExpanded(!isExpanded);
33
38
  }}
34
- className="ml-1.5 text-xs text-indigo-600 hover:text-indigo-800 font-medium"
39
+ aria-expanded={isExpanded}
40
+ className="ml-2 inline-flex items-center gap-1 align-baseline rounded text-xs font-medium text-indigo-600 hover:text-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-1 transition-colors"
35
41
  >
36
- {isExpanded ? "Less" : "More"}
42
+ <span>{isExpanded ? "Show less" : "Show more"}</span>
43
+ <svg
44
+ className={`w-3 h-3 transition-transform duration-200 ${
45
+ isExpanded ? "rotate-180" : ""
46
+ }`}
47
+ fill="none"
48
+ viewBox="0 0 24 24"
49
+ stroke="currentColor"
50
+ strokeWidth={2.25}
51
+ aria-hidden="true"
52
+ >
53
+ <path
54
+ strokeLinecap="round"
55
+ strokeLinejoin="round"
56
+ d="M19 9l-7 7-7-7"
57
+ />
58
+ </svg>
37
59
  </button>
38
60
  </span>
39
61
  );