@oneuptime/common 11.7.2 → 11.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +103 -0
  2. package/Models/DatabaseModels/TableView.ts +40 -0
  3. package/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.ts +13 -0
  4. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  5. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
  6. package/Tests/Types/JSONFunctions.test.ts +103 -1
  7. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
  8. package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +572 -0
  9. package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
  10. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -0
  11. package/Tests/Utils/UserPreferences.test.ts +563 -0
  12. package/Types/JSONFunctions.ts +7 -2
  13. package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
  14. package/UI/Components/MasterPage/MasterPage.tsx +65 -0
  15. package/UI/Components/ModelTable/BaseModelTable.tsx +387 -4
  16. package/UI/Components/ModelTable/Column.ts +17 -0
  17. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +420 -0
  18. package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
  19. package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
  20. package/UI/Components/ModelTable/TableView.tsx +24 -2
  21. package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
  22. package/UI/Components/SideMenu/SideMenu.tsx +24 -4
  23. package/UI/Components/Table/Table.tsx +14 -1
  24. package/UI/Components/Table/TableRow.tsx +180 -175
  25. package/UI/Components/Table/Types/Column.ts +2 -0
  26. package/Utils/UserPreferences.ts +53 -0
  27. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
  28. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
  29. package/build/dist/Models/DatabaseModels/TableView.js +40 -0
  30. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
  31. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js +12 -0
  32. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
  33. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  34. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  35. package/build/dist/Types/JSONFunctions.js +8 -3
  36. package/build/dist/Types/JSONFunctions.js.map +1 -1
  37. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -1
  38. package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
  39. package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
  40. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +239 -7
  41. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  42. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +189 -0
  43. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
  44. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
  45. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
  46. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
  47. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
  48. package/build/dist/UI/Components/ModelTable/TableView.js +13 -2
  49. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  50. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
  51. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -0
  52. package/build/dist/UI/Components/SideMenu/SideMenu.js +15 -5
  53. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  54. package/build/dist/UI/Components/Table/Table.js +15 -2
  55. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  56. package/build/dist/UI/Components/Table/TableRow.js +11 -6
  57. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  58. package/build/dist/Utils/UserPreferences.js +33 -0
  59. package/build/dist/Utils/UserPreferences.js.map +1 -1
  60. package/package.json +1 -1
@@ -77,6 +77,13 @@ const TableRow: TableRowFunction = <T extends GenericObject>(
77
77
  };
78
78
  }, []);
79
79
 
80
+ // The columns this row will actually put on screen.
81
+ const renderedColumns: Array<Column<T>> = (props.columns || []).filter(
82
+ (column: Column<T>) => {
83
+ return !(column.hideOnMobile && isMobile);
84
+ },
85
+ );
86
+
80
87
  type GetRowFunction = (provided?: DraggableProvided) => ReactElement;
81
88
 
82
89
  const getRow: GetRowFunction = (
@@ -339,186 +346,184 @@ const TableRow: TableRowFunction = <T extends GenericObject>(
339
346
  </td>
340
347
  )}
341
348
  {props.columns &&
342
- props.columns
343
- .filter((column: Column<T>) => {
344
- return !(column.hideOnMobile && isMobile);
345
- })
346
- .map((column: Column<T>, i: number) => {
347
- let className: string =
348
- "whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-500 sm:pl-6 align-top";
349
- if (i === props.columns.length - 1) {
350
- className =
351
- "whitespace-nowrap py-4 pl-4 pr-6 text-sm font-medium text-gray-500 sm:pl-6 align-top";
352
- }
353
-
354
- let columnContent: React.ReactNode = null;
355
-
356
- if (column.key && !column.getElement) {
357
- columnContent =
358
- column.type === FieldType.Date ? (
359
- props.item[column.key] ? (
360
- OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
361
- props.item[column.key] as string,
362
- true,
363
- )
364
- ) : (
365
- column.noValueMessage || ""
366
- )
367
- ) : column.type === FieldType.DateTime ? (
368
- props.item[column.key] ? (
369
- OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
370
- props.item[column.key] as string,
371
- false,
372
- )
373
- ) : (
374
- column.noValueMessage || ""
375
- )
376
- ) : column.type === FieldType.USDCents ? (
377
- props.item[column.key] ? (
378
- ((props.item[column.key] as number) || 0) / 100 + " USD"
379
- ) : (
380
- column.noValueMessage || "0 USD"
381
- )
382
- ) : column.type === FieldType.Percent ? (
383
- props.item[column.key] ? (
384
- props.item[column.key] + "%"
385
- ) : (
386
- column.noValueMessage || "0%"
349
+ renderedColumns.map((column: Column<T>, i: number) => {
350
+ let className: string =
351
+ "whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-500 sm:pl-6 align-top";
352
+ /*
353
+ * Compared against the rendered count, not the declared one:
354
+ * with any column filtered out the two differ, and the extra
355
+ * right padding would land on the wrong cell - or on none.
356
+ */
357
+ if (i === renderedColumns.length - 1) {
358
+ className =
359
+ "whitespace-nowrap py-4 pl-4 pr-6 text-sm font-medium text-gray-500 sm:pl-6 align-top";
360
+ }
361
+
362
+ let columnContent: React.ReactNode = null;
363
+
364
+ if (column.key && !column.getElement) {
365
+ columnContent =
366
+ column.type === FieldType.Date ? (
367
+ props.item[column.key] ? (
368
+ OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
369
+ props.item[column.key] as string,
370
+ true,
387
371
  )
388
- ) : column.type === FieldType.Color ? (
389
- props.item[column.key] ? (
390
- <ColorInput value={props.item[column.key] as Color} />
391
- ) : (
392
- column.noValueMessage || "0%"
393
- )
394
- ) : column.type === FieldType.LongText ? (
395
- props.item[column.key] ? (
396
- <LongTextViewer
397
- text={props.item[column.key] as string}
398
- />
399
- ) : (
400
- column.noValueMessage || ""
401
- )
402
- ) : column.type === FieldType.Boolean ? (
403
- props.item[column.key] ? (
404
- <Icon
405
- icon={IconProp.Check}
406
- className={"h-5 w-5 text-gray-500"}
407
- thick={ThickProp.Thick}
408
- />
409
- ) : (
410
- <Icon
411
- icon={IconProp.False}
412
- className={"h-5 w-5 text-gray-500"}
413
- thick={ThickProp.Thick}
414
- />
372
+ ) : (
373
+ column.noValueMessage || ""
374
+ )
375
+ ) : column.type === FieldType.DateTime ? (
376
+ props.item[column.key] ? (
377
+ OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
378
+ props.item[column.key] as string,
379
+ false,
415
380
  )
416
381
  ) : (
417
- getNestedValue(
418
- props.item,
419
- String(column.key),
420
- )?.toString() ||
421
- column.noValueMessage ||
422
- ""
423
- );
424
- } else if (column.key && column.getElement) {
425
- columnContent = column.getElement(props.item);
426
- }
427
-
428
- const contentWrapperClassName: string = column.contentClassName
429
- ? column.contentClassName
430
- : "";
431
-
432
- const actionsContainerClassName: string =
433
- column.contentClassName
434
- ? `flex justify-end ${column.contentClassName}`
435
- : "flex justify-end";
382
+ column.noValueMessage || ""
383
+ )
384
+ ) : column.type === FieldType.USDCents ? (
385
+ props.item[column.key] ? (
386
+ ((props.item[column.key] as number) || 0) / 100 + " USD"
387
+ ) : (
388
+ column.noValueMessage || "0 USD"
389
+ )
390
+ ) : column.type === FieldType.Percent ? (
391
+ props.item[column.key] ? (
392
+ props.item[column.key] + "%"
393
+ ) : (
394
+ column.noValueMessage || "0%"
395
+ )
396
+ ) : column.type === FieldType.Color ? (
397
+ props.item[column.key] ? (
398
+ <ColorInput value={props.item[column.key] as Color} />
399
+ ) : (
400
+ column.noValueMessage || "0%"
401
+ )
402
+ ) : column.type === FieldType.LongText ? (
403
+ props.item[column.key] ? (
404
+ <LongTextViewer text={props.item[column.key] as string} />
405
+ ) : (
406
+ column.noValueMessage || ""
407
+ )
408
+ ) : column.type === FieldType.Boolean ? (
409
+ props.item[column.key] ? (
410
+ <Icon
411
+ icon={IconProp.Check}
412
+ className={"h-5 w-5 text-gray-500"}
413
+ thick={ThickProp.Thick}
414
+ />
415
+ ) : (
416
+ <Icon
417
+ icon={IconProp.False}
418
+ className={"h-5 w-5 text-gray-500"}
419
+ thick={ThickProp.Thick}
420
+ />
421
+ )
422
+ ) : (
423
+ getNestedValue(
424
+ props.item,
425
+ String(column.key),
426
+ )?.toString() ||
427
+ column.noValueMessage ||
428
+ ""
429
+ );
430
+ } else if (column.key && column.getElement) {
431
+ columnContent = column.getElement(props.item);
432
+ }
433
+
434
+ const contentWrapperClassName: string = column.contentClassName
435
+ ? column.contentClassName
436
+ : "";
437
+
438
+ const actionsContainerClassName: string = column.contentClassName
439
+ ? `flex justify-end ${column.contentClassName}`
440
+ : "flex justify-end";
441
+
442
+ return (
443
+ <td
444
+ key={i}
445
+ className={className}
446
+ style={{
447
+ textAlign:
448
+ column.type === FieldType.Actions ? "right" : "left",
449
+ }}
450
+ onClick={() => {
451
+ if (column.tooltipText) {
452
+ setTooltipModalText(column.tooltipText(props.item));
453
+ }
454
+ }}
455
+ >
456
+ {columnContent !== null && columnContent !== undefined && (
457
+ <div className={contentWrapperClassName}>
458
+ {columnContent}
459
+ </div>
460
+ )}
461
+ {column.type === FieldType.Actions && (
462
+ <div className={actionsContainerClassName}>
463
+ {error && (
464
+ <div className="text-align-left">
465
+ <ConfirmModal
466
+ title={`Error`}
467
+ description={error}
468
+ submitButtonText={"Close"}
469
+ onSubmit={() => {
470
+ return setError("");
471
+ }}
472
+ />
473
+ </div>
474
+ )}
475
+ {props.actionButtons?.map(
476
+ (button: ActionButtonSchema<T>, i: number) => {
477
+ if (
478
+ button.isVisible &&
479
+ !button.isVisible(props.item)
480
+ ) {
481
+ return <div key={i}></div>;
482
+ }
436
483
 
437
- return (
438
- <td
439
- key={i}
440
- className={className}
441
- style={{
442
- textAlign:
443
- column.type === FieldType.Actions ? "right" : "left",
444
- }}
445
- onClick={() => {
446
- if (column.tooltipText) {
447
- setTooltipModalText(column.tooltipText(props.item));
448
- }
449
- }}
450
- >
451
- {columnContent !== null && columnContent !== undefined && (
452
- <div className={contentWrapperClassName}>
453
- {columnContent}
454
- </div>
455
- )}
456
- {column.type === FieldType.Actions && (
457
- <div className={actionsContainerClassName}>
458
- {error && (
459
- <div className="text-align-left">
460
- <ConfirmModal
461
- title={`Error`}
462
- description={error}
463
- submitButtonText={"Close"}
464
- onSubmit={() => {
465
- return setError("");
466
- }}
467
- />
468
- </div>
469
- )}
470
- {props.actionButtons?.map(
471
- (button: ActionButtonSchema<T>, i: number) => {
472
- if (
473
- button.isVisible &&
474
- !button.isVisible(props.item)
475
- ) {
476
- return <div key={i}></div>;
477
- }
478
-
479
- // Hide button on mobile if hideOnMobile is true
480
- if (button.hideOnMobile && isMobile) {
481
- return <div key={i}></div>;
482
- }
483
-
484
- return (
485
- <div key={i}>
486
- <Button
487
- buttonSize={ButtonSize.Small}
488
- title={button.title}
489
- icon={button.icon}
490
- buttonStyle={button.buttonStyleType}
491
- isLoading={isButtonLoading[i]}
492
- onClick={() => {
493
- if (button.onClick) {
494
- isButtonLoading[i] = true;
495
- setIsButtonLoading(isButtonLoading);
484
+ // Hide button on mobile if hideOnMobile is true
485
+ if (button.hideOnMobile && isMobile) {
486
+ return <div key={i}></div>;
487
+ }
496
488
 
497
- button.onClick(
498
- props.item,
499
- () => {
500
- // on action complete
501
- isButtonLoading[i] = false;
502
- setIsButtonLoading(isButtonLoading);
503
- },
504
- (err: Error) => {
505
- isButtonLoading[i] = false;
506
- setIsButtonLoading(isButtonLoading);
507
- setError((err as Error).message);
508
- },
509
- );
510
- }
511
- }}
512
- />
513
- </div>
514
- );
515
- },
516
- )}
517
- </div>
518
- )}
519
- </td>
520
- );
521
- })}
489
+ return (
490
+ <div key={i}>
491
+ <Button
492
+ buttonSize={ButtonSize.Small}
493
+ title={button.title}
494
+ icon={button.icon}
495
+ buttonStyle={button.buttonStyleType}
496
+ isLoading={isButtonLoading[i]}
497
+ onClick={() => {
498
+ if (button.onClick) {
499
+ isButtonLoading[i] = true;
500
+ setIsButtonLoading(isButtonLoading);
501
+
502
+ button.onClick(
503
+ props.item,
504
+ () => {
505
+ // on action complete
506
+ isButtonLoading[i] = false;
507
+ setIsButtonLoading(isButtonLoading);
508
+ },
509
+ (err: Error) => {
510
+ isButtonLoading[i] = false;
511
+ setIsButtonLoading(isButtonLoading);
512
+ setError((err as Error).message);
513
+ },
514
+ );
515
+ }
516
+ }}
517
+ />
518
+ </div>
519
+ );
520
+ },
521
+ )}
522
+ </div>
523
+ )}
524
+ </td>
525
+ );
526
+ })}
522
527
  </tr>
523
528
  {tooltipModalText && (
524
529
  <ConfirmModal
@@ -5,6 +5,8 @@ import { ReactElement } from "react";
5
5
 
6
6
  export default interface Column<T extends GenericObject> {
7
7
  title: string;
8
+ // Stable identity carried over from the ModelTable column, if it had one.
9
+ id?: string | undefined;
8
10
  description?: string | undefined;
9
11
  disableSort?: boolean | undefined;
10
12
  tooltipText?: ((item: T) => string) | undefined;
@@ -1,7 +1,9 @@
1
1
  import LocalStorage from "../UI/Utils/LocalStorage";
2
+ import { JSONObject } from "../Types/JSON";
2
3
 
3
4
  export enum UserPreferenceType {
4
5
  BaseModelTablePageSize = "BaseModelTablePageSize",
6
+ BaseModelTableColumns = "BaseModelTableColumns",
5
7
  }
6
8
 
7
9
  export default class UserPreferences {
@@ -30,4 +32,55 @@ export default class UserPreferences {
30
32
  const finalKey: string = `${userPreferenceType}.${key}`;
31
33
  LocalStorage.setItem(finalKey, value);
32
34
  }
35
+
36
+ /*
37
+ * Object-shaped preferences (e.g. a table's column layout). LocalStorage
38
+ * already JSON-serializes objects on the way in and parses them on the way
39
+ * out, so this only has to reject anything that came back as something other
40
+ * than a plain object - a half-written or hand-edited entry must degrade to
41
+ * "no preference" rather than reaching the caller as a string or an array.
42
+ */
43
+ public static getUserPreferenceByTypeAsJSON(data: {
44
+ key: string;
45
+ userPreferenceType: UserPreferenceType;
46
+ }): JSONObject | null {
47
+ const { key, userPreferenceType } = data;
48
+
49
+ const finalKey: string = `${userPreferenceType}.${key}`;
50
+
51
+ let value: unknown = null;
52
+
53
+ try {
54
+ value = LocalStorage.getItem(finalKey);
55
+ } catch {
56
+ return null;
57
+ }
58
+
59
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
60
+ return null;
61
+ }
62
+
63
+ return value as JSONObject;
64
+ }
65
+
66
+ public static saveUserPreferenceByTypeAsJSON(data: {
67
+ key: string;
68
+ userPreferenceType: UserPreferenceType;
69
+ value: JSONObject;
70
+ }): void {
71
+ const { key, userPreferenceType, value } = data;
72
+
73
+ const finalKey: string = `${userPreferenceType}.${key}`;
74
+ LocalStorage.setItem(finalKey, value);
75
+ }
76
+
77
+ public static removeUserPreferenceByType(data: {
78
+ key: string;
79
+ userPreferenceType: UserPreferenceType;
80
+ }): void {
81
+ const { key, userPreferenceType } = data;
82
+
83
+ const finalKey: string = `${userPreferenceType}.${key}`;
84
+ LocalStorage.removeItem(finalKey);
85
+ }
33
86
  }
@@ -305,6 +305,11 @@ export default class KubernetesCostAllocation extends AnalyticsBaseModel {
305
305
  title: "CPU Core Usage Average",
306
306
  description: "Average CPU cores actually used over the window.",
307
307
  },
308
+ {
309
+ key: "cpuCoreLimitAverage",
310
+ title: "CPU Core Limit Average",
311
+ description: "Average CPU core limit over the window. 0 when no limit is set — which is also what a row ingested before this column reads back.",
312
+ },
308
313
  {
309
314
  key: "cpuCost",
310
315
  title: "CPU Cost",
@@ -335,6 +340,16 @@ export default class KubernetesCostAllocation extends AnalyticsBaseModel {
335
340
  title: "RAM Bytes Usage Average",
336
341
  description: "Average RAM bytes actually used over the window.",
337
342
  },
343
+ {
344
+ key: "ramBytesLimitAverage",
345
+ title: "RAM Bytes Limit Average",
346
+ description: "Average RAM byte limit over the window. 0 when no limit is set — which is also what a row ingested before this column reads back.",
347
+ },
348
+ {
349
+ key: "ramBytesUsageMax",
350
+ title: "RAM Bytes Usage Max",
351
+ description: "Peak RAM bytes used during the window, from Prometheus rather than the cost engine — the engine only reports averages, and an hourly mean hides the burst that OOMKills a container. 0 when the agent has no Prometheus configured, when the scrape had no data, or on rows ingested before this column; treat 0 as 'unknown', never as a real peak.",
352
+ },
338
353
  {
339
354
  key: "ramCost",
340
355
  title: "RAM Cost",
@@ -420,6 +435,45 @@ export default class KubernetesCostAllocation extends AnalyticsBaseModel {
420
435
  update: [],
421
436
  },
422
437
  });
438
+ /*
439
+ * Delivery bookkeeping, not workload data. A window wider than the
440
+ * agent's batch size arrives as several independent ingest jobs, so the
441
+ * ingest service needs to tell "another chunk of the delivery I am
442
+ * already ingesting" (accept) from "a window a previous delivery already
443
+ * ingested" (drop, or a restarted agent double-counts spend). shipmentId
444
+ * is the agent's content hash of the window — identical across restarts,
445
+ * different when the engine's answer for that window changed.
446
+ *
447
+ * Empty / 0 on rows written before these columns existed and on rows
448
+ * from agents older than the shipment contract; the ingest service falls
449
+ * back to the whole-window guard for those.
450
+ */
451
+ const shipmentIdColumn = new AnalyticsTableColumn({
452
+ key: "shipmentId",
453
+ title: "Shipment ID",
454
+ description: "Content hash identifying the agent delivery this row arrived in. Used to deduplicate re-shipped windows; empty for rows ingested before the shipment contract.",
455
+ required: true,
456
+ defaultValue: "",
457
+ type: TableColumnType.Text,
458
+ accessControl: {
459
+ read: readPermissions,
460
+ create: createPermissions,
461
+ update: [],
462
+ },
463
+ });
464
+ const shipmentChunkColumn = new AnalyticsTableColumn({
465
+ key: "shipmentChunk",
466
+ title: "Shipment Chunk",
467
+ description: "Index of the request within its shipment that carried this row. 0 for single-request shipments and for rows ingested before the shipment contract.",
468
+ required: true,
469
+ defaultValue: 0,
470
+ type: TableColumnType.Number,
471
+ accessControl: {
472
+ read: readPermissions,
473
+ create: createPermissions,
474
+ update: [],
475
+ },
476
+ });
423
477
  const retentionDateColumn = new AnalyticsTableColumn({
424
478
  key: "retentionDate",
425
479
  codec: [{ codec: "DoubleDelta" }, { codec: "ZSTD", level: 1 }],
@@ -462,6 +516,8 @@ export default class KubernetesCostAllocation extends AnalyticsBaseModel {
462
516
  labelKeysColumn,
463
517
  ...measureColumns,
464
518
  currencyColumn,
519
+ shipmentIdColumn,
520
+ shipmentChunkColumn,
465
521
  retentionDateColumn,
466
522
  ],
467
523
  sortKeys: [
@@ -595,6 +651,12 @@ export default class KubernetesCostAllocation extends AnalyticsBaseModel {
595
651
  set cpuCoreUsageAverage(v) {
596
652
  this.setColumnValue("cpuCoreUsageAverage", v);
597
653
  }
654
+ get cpuCoreLimitAverage() {
655
+ return this.getColumnValue("cpuCoreLimitAverage");
656
+ }
657
+ set cpuCoreLimitAverage(v) {
658
+ this.setColumnValue("cpuCoreLimitAverage", v);
659
+ }
598
660
  get cpuCost() {
599
661
  return this.getColumnValue("cpuCost");
600
662
  }
@@ -631,6 +693,18 @@ export default class KubernetesCostAllocation extends AnalyticsBaseModel {
631
693
  set ramBytesUsageAverage(v) {
632
694
  this.setColumnValue("ramBytesUsageAverage", v);
633
695
  }
696
+ get ramBytesLimitAverage() {
697
+ return this.getColumnValue("ramBytesLimitAverage");
698
+ }
699
+ set ramBytesLimitAverage(v) {
700
+ this.setColumnValue("ramBytesLimitAverage", v);
701
+ }
702
+ get ramBytesUsageMax() {
703
+ return this.getColumnValue("ramBytesUsageMax");
704
+ }
705
+ set ramBytesUsageMax(v) {
706
+ this.setColumnValue("ramBytesUsageMax", v);
707
+ }
634
708
  get ramCost() {
635
709
  return this.getColumnValue("ramCost");
636
710
  }
@@ -703,6 +777,18 @@ export default class KubernetesCostAllocation extends AnalyticsBaseModel {
703
777
  set currency(v) {
704
778
  this.setColumnValue("currency", v);
705
779
  }
780
+ get shipmentId() {
781
+ return this.getColumnValue("shipmentId");
782
+ }
783
+ set shipmentId(v) {
784
+ this.setColumnValue("shipmentId", v);
785
+ }
786
+ get shipmentChunk() {
787
+ return this.getColumnValue("shipmentChunk");
788
+ }
789
+ set shipmentChunk(v) {
790
+ this.setColumnValue("shipmentChunk", v);
791
+ }
706
792
  get retentionDate() {
707
793
  return this.getColumnValue("retentionDate");
708
794
  }