@oneuptime/common 11.5.13 → 11.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +41 -24
- package/Models/AnalyticsModels/MetricBaselineHourly.ts +2 -0
- package/Models/AnalyticsModels/MetricItemAggMV1m.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByContainer.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +5 -2
- package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +5 -2
- package/Models/DatabaseModels/EnterpriseLicense.ts +21 -0
- package/Models/DatabaseModels/EnterpriseLicenseInstance.ts +25 -0
- package/Models/DatabaseModels/GlobalConfig.ts +76 -0
- package/Server/API/EnterpriseLicenseAPI.ts +57 -0
- package/Server/API/GlobalConfigAPI.ts +62 -1
- package/Server/EnvironmentConfig.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.ts +38 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/AnalyticsDatabaseService.ts +61 -46
- package/Server/Services/DatabaseService.ts +66 -1
- package/Server/Services/WorkflowService.ts +100 -39
- package/Server/Types/Workflow/Components/Schedule.ts +57 -32
- package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +59 -0
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +41 -4
- package/Server/Utils/Express.ts +13 -0
- package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +799 -0
- package/Server/Utils/Telemetry/TelemetryWriterClient.ts +263 -0
- package/Server/Utils/Telemetry/TelemetryWriterServer.ts +240 -0
- package/Server/Utils/Telemetry/TelemetryWriterShedMetrics.ts +93 -0
- package/Tests/Models/AnalyticsModels/AnalyticsBaseModel.test.ts +122 -0
- package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +232 -0
- package/Tests/Server/Services/UpdateOneByIdKeepsRowId.test.ts +107 -0
- package/Tests/Server/Services/WorkflowService.test.ts +308 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +164 -3
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +99 -0
- package/Tests/Server/Utils/Attribution.test.ts +203 -0
- package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +183 -0
- package/Tests/Server/Utils/Marketing/GoogleAds.test.ts +340 -0
- package/Tests/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.test.ts +87 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +165 -0
- package/Tests/Server/Utils/Monitor/Criteria/TraceMonitorCriteria.test.ts +86 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +1565 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterClient.test.ts +313 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterServer.test.ts +270 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterShedMetrics.test.ts +127 -0
- package/Tests/Types/AI/CodeFixTaskType.test.ts +3 -0
- package/Tests/Types/HashCode.test.ts +41 -0
- package/Tests/Types/Log/LogQueryParser.test.ts +186 -0
- package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +228 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +169 -0
- package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +289 -0
- package/Tests/Types/Monitor/MonitorStepLogMonitor.test.ts +231 -0
- package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +245 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +155 -0
- package/Tests/Types/Monitor/MonitorStepTelemetrySerialization.test.ts +141 -0
- package/Tests/Types/Monitor/MonitorStepTraceMonitor.test.ts +137 -0
- package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +311 -0
- package/Tests/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.test.ts +461 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +2852 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +758 -0
- package/Tests/UI/Utils/NotificationMethodUtil.test.ts +564 -0
- package/Tests/Utils/Array.test.ts +156 -0
- package/Tests/Utils/CronTab.test.ts +199 -0
- package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +197 -0
- package/Tests/Utils/ModelImportExport.test.ts +101 -0
- package/Tests/Utils/Number.test.ts +179 -0
- package/Tests/Utils/ValueFormatter.test.ts +305 -0
- package/Tests/Utils/VersionUtil.test.ts +348 -0
- package/Tests/jest.setup.ts +1 -0
- package/Types/AnalyticsDatabase/TableColumn.ts +23 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +6 -0
- package/Types/Monitor/MonitorStep.ts +24 -4
- package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +105 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +445 -12
- package/UI/Components/Workflow/ArgumentsForm.tsx +68 -30
- package/UI/Components/Workflow/CronScheduleField.tsx +411 -0
- package/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.ts +176 -0
- package/UI/Utils/NotificationMethodUtil.ts +310 -0
- package/Utils/CronTab.ts +823 -0
- package/Utils/ModelImportExport.ts +21 -6
- package/Utils/VersionUtil.ts +260 -0
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +25 -20
- package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js +2 -0
- package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +5 -2
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +22 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js +26 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +81 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +47 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +52 -1
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +17 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +53 -17
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +53 -1
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowService.js +80 -30
- package/build/dist/Server/Services/WorkflowService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Schedule.js +44 -19
- package/build/dist/Server/Types/Workflow/Components/Schedule.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js +24 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +29 -4
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Express.js +12 -0
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +496 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js +165 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js +136 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js +76 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js.map +1 -0
- package/build/dist/Types/AnalyticsDatabase/TableColumn.js +7 -0
- package/build/dist/Types/AnalyticsDatabase/TableColumn.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +20 -4
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +73 -0
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +261 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +30 -6
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/CronScheduleField.js +209 -0
- package/build/dist/UI/Components/Workflow/CronScheduleField.js.map +1 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js +129 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js.map +1 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js +189 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js.map +1 -0
- package/build/dist/Utils/CronTab.js +609 -0
- package/build/dist/Utils/CronTab.js.map +1 -0
- package/build/dist/Utils/ModelImportExport.js +20 -6
- package/build/dist/Utils/ModelImportExport.js.map +1 -1
- package/build/dist/Utils/VersionUtil.js +193 -0
- package/build/dist/Utils/VersionUtil.js.map +1 -0
- package/package.json +1 -1
|
@@ -77,6 +77,15 @@ export default class AnalyticsBaseModel extends CommonModel {
|
|
|
77
77
|
materializedViews?: Array<MaterializedView> | undefined;
|
|
78
78
|
enableMCP?: boolean | undefined;
|
|
79
79
|
ttlExpression?: string | undefined; // e.g. "retentionDate DELETE"
|
|
80
|
+
/*
|
|
81
|
+
* Generic event/entity tables carry `_id` and `createdAt`. Derived
|
|
82
|
+
* AggregatingMergeTree targets do not represent independently-addressable
|
|
83
|
+
* rows: their identity is exactly their aggregation key, and an arbitrary
|
|
84
|
+
* creation timestamp has no stable meaning after merges. Those models set
|
|
85
|
+
* this false so ClickHouse can enforce that every non-key column is an
|
|
86
|
+
* aggregate measure. Defaults true for backward compatibility.
|
|
87
|
+
*/
|
|
88
|
+
includeBaseColumns?: boolean | undefined;
|
|
80
89
|
/*
|
|
81
90
|
* Column that `findBy` falls back to when the caller doesn't
|
|
82
91
|
* specify a `sort`. Defaults to `createdAt` (matching the legacy
|
|
@@ -100,31 +109,39 @@ export default class AnalyticsBaseModel extends CommonModel {
|
|
|
100
109
|
this.tableEngine = data.tableEngine;
|
|
101
110
|
}
|
|
102
111
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
if (data.includeBaseColumns !== false) {
|
|
113
|
+
columns.push(
|
|
114
|
+
new AnalyticsTableColumn({
|
|
115
|
+
key: "_id",
|
|
116
|
+
title: "ID",
|
|
117
|
+
description: "ID of this object",
|
|
118
|
+
required: true,
|
|
119
|
+
type: TableColumnType.ObjectID,
|
|
120
|
+
/*
|
|
121
|
+
* Ids are UUIDv7 (time-ordered — see ObjectID.generateTimeOrdered),
|
|
122
|
+
* so consecutive rows share their 48-bit timestamp prefix and ZSTD
|
|
123
|
+
* compresses them well; random v4 ids were incompressible.
|
|
124
|
+
*/
|
|
125
|
+
codec: { codec: "ZSTD", level: 1 },
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
118
128
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
columns.push(
|
|
130
|
+
new AnalyticsTableColumn({
|
|
131
|
+
key: "createdAt",
|
|
132
|
+
title: "Created",
|
|
133
|
+
description: "Date and Time when the object was created.",
|
|
134
|
+
required: true,
|
|
135
|
+
type: TableColumnType.Date,
|
|
136
|
+
}),
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (data.includeBaseColumns === false && !data.defaultSortColumn) {
|
|
141
|
+
throw new BadDataException(
|
|
142
|
+
"defaultSortColumn is required when includeBaseColumns is false because createdAt is not part of the table schema",
|
|
143
|
+
);
|
|
144
|
+
}
|
|
128
145
|
|
|
129
146
|
if (!data.primaryKeys || data.primaryKeys.length === 0) {
|
|
130
147
|
throw new BadDataException("Primary keys are required");
|
|
@@ -234,6 +234,8 @@ GROUP BY projectId, name, primaryEntityId, day, hourOfWeek`,
|
|
|
234
234
|
tableSettings:
|
|
235
235
|
"ttl_only_drop_parts = 1, non_replicated_deduplication_window = 10000",
|
|
236
236
|
ttlExpression: "day + INTERVAL 90 DAY",
|
|
237
|
+
includeBaseColumns: false,
|
|
238
|
+
defaultSortColumn: "day",
|
|
237
239
|
});
|
|
238
240
|
}
|
|
239
241
|
}
|
|
@@ -110,9 +110,10 @@ export default class MetricItemAggMV1m extends AnalyticsBaseModel {
|
|
|
110
110
|
key: "retentionDate",
|
|
111
111
|
title: "Retention Date",
|
|
112
112
|
description:
|
|
113
|
-
"
|
|
113
|
+
"Latest date after which this aggregate bucket is eligible for TTL deletion. Stored as SimpleAggregateFunction(max, DateTime) so partial rows keep the maximum expiry when AggregatingMergeTree merges them.",
|
|
114
114
|
required: true,
|
|
115
115
|
type: TableColumnType.Date,
|
|
116
|
+
simpleAggregateFunction: "max",
|
|
116
117
|
});
|
|
117
118
|
|
|
118
119
|
super({
|
|
@@ -156,7 +157,7 @@ SELECT
|
|
|
156
157
|
countState(toFloat64(coalesce(value, sum, 0))) AS valueCountState,
|
|
157
158
|
minState(toFloat64(coalesce(value, sum, 0))) AS valueMinState,
|
|
158
159
|
maxState(toFloat64(coalesce(value, sum, 0))) AS valueMaxState,
|
|
159
|
-
|
|
160
|
+
maxSimpleState(retentionDate) AS retentionDate
|
|
160
161
|
FROM MetricItemV3
|
|
161
162
|
GROUP BY projectId, name, primaryEntityId, bucketTime`,
|
|
162
163
|
},
|
|
@@ -172,6 +173,8 @@ GROUP BY projectId, name, primaryEntityId, bucketTime`,
|
|
|
172
173
|
tableSettings:
|
|
173
174
|
"ttl_only_drop_parts = 1, non_replicated_deduplication_window = 10000",
|
|
174
175
|
ttlExpression: "retentionDate DELETE",
|
|
176
|
+
includeBaseColumns: false,
|
|
177
|
+
defaultSortColumn: "bucketTime",
|
|
175
178
|
});
|
|
176
179
|
}
|
|
177
180
|
}
|
|
@@ -111,9 +111,10 @@ export default class MetricItemAggMV1mByContainer extends AnalyticsBaseModel {
|
|
|
111
111
|
key: "retentionDate",
|
|
112
112
|
title: "Retention Date",
|
|
113
113
|
description:
|
|
114
|
-
"
|
|
114
|
+
"Latest date after which this aggregate bucket is eligible for TTL deletion. Stored as SimpleAggregateFunction(max, DateTime) so partial rows keep the maximum expiry when AggregatingMergeTree merges them.",
|
|
115
115
|
required: true,
|
|
116
116
|
type: TableColumnType.Date,
|
|
117
|
+
simpleAggregateFunction: "max",
|
|
117
118
|
});
|
|
118
119
|
|
|
119
120
|
super({
|
|
@@ -159,7 +160,7 @@ SELECT
|
|
|
159
160
|
countState(toFloat64(coalesce(value, sum, 0))) AS valueCountState,
|
|
160
161
|
minState(toFloat64(coalesce(value, sum, 0))) AS valueMinState,
|
|
161
162
|
maxState(toFloat64(coalesce(value, sum, 0))) AS valueMaxState,
|
|
162
|
-
|
|
163
|
+
maxSimpleState(retentionDate) AS retentionDate
|
|
163
164
|
FROM MetricItemV3
|
|
164
165
|
WHERE containerEntityKey != ''
|
|
165
166
|
GROUP BY projectId, name, containerEntityKey, bucketTime`,
|
|
@@ -173,6 +174,8 @@ GROUP BY projectId, name, containerEntityKey, bucketTime`,
|
|
|
173
174
|
tableSettings:
|
|
174
175
|
"ttl_only_drop_parts = 1, non_replicated_deduplication_window = 10000",
|
|
175
176
|
ttlExpression: "retentionDate DELETE",
|
|
177
|
+
includeBaseColumns: false,
|
|
178
|
+
defaultSortColumn: "bucketTime",
|
|
176
179
|
});
|
|
177
180
|
}
|
|
178
181
|
}
|
|
@@ -114,9 +114,10 @@ export default class MetricItemAggMV1mByHostV2 extends AnalyticsBaseModel {
|
|
|
114
114
|
key: "retentionDate",
|
|
115
115
|
title: "Retention Date",
|
|
116
116
|
description:
|
|
117
|
-
"
|
|
117
|
+
"Latest date after which this aggregate bucket is eligible for TTL deletion. Stored as SimpleAggregateFunction(max, DateTime) so partial rows keep the maximum expiry when AggregatingMergeTree merges them.",
|
|
118
118
|
required: true,
|
|
119
119
|
type: TableColumnType.Date,
|
|
120
|
+
simpleAggregateFunction: "max",
|
|
120
121
|
});
|
|
121
122
|
|
|
122
123
|
super({
|
|
@@ -162,7 +163,7 @@ SELECT
|
|
|
162
163
|
countState(toFloat64(coalesce(value, sum, 0))) AS valueCountState,
|
|
163
164
|
minState(toFloat64(coalesce(value, sum, 0))) AS valueMinState,
|
|
164
165
|
maxState(toFloat64(coalesce(value, sum, 0))) AS valueMaxState,
|
|
165
|
-
|
|
166
|
+
maxSimpleState(retentionDate) AS retentionDate
|
|
166
167
|
FROM MetricItemV3
|
|
167
168
|
WHERE hostEntityKey != ''
|
|
168
169
|
GROUP BY projectId, name, hostEntityKey, bucketTime`,
|
|
@@ -176,6 +177,8 @@ GROUP BY projectId, name, hostEntityKey, bucketTime`,
|
|
|
176
177
|
tableSettings:
|
|
177
178
|
"ttl_only_drop_parts = 1, non_replicated_deduplication_window = 10000",
|
|
178
179
|
ttlExpression: "retentionDate DELETE",
|
|
180
|
+
includeBaseColumns: false,
|
|
181
|
+
defaultSortColumn: "bucketTime",
|
|
179
182
|
});
|
|
180
183
|
}
|
|
181
184
|
}
|
|
@@ -110,9 +110,10 @@ export default class MetricItemAggMV1mByK8sCluster extends AnalyticsBaseModel {
|
|
|
110
110
|
key: "retentionDate",
|
|
111
111
|
title: "Retention Date",
|
|
112
112
|
description:
|
|
113
|
-
"
|
|
113
|
+
"Latest date after which this aggregate bucket is eligible for TTL deletion. Stored as SimpleAggregateFunction(max, DateTime) so partial rows keep the maximum expiry when AggregatingMergeTree merges them.",
|
|
114
114
|
required: true,
|
|
115
115
|
type: TableColumnType.Date,
|
|
116
|
+
simpleAggregateFunction: "max",
|
|
116
117
|
});
|
|
117
118
|
|
|
118
119
|
super({
|
|
@@ -160,7 +161,7 @@ SELECT
|
|
|
160
161
|
countState(toFloat64(coalesce(value, sum, 0))) AS valueCountState,
|
|
161
162
|
minState(toFloat64(coalesce(value, sum, 0))) AS valueMinState,
|
|
162
163
|
maxState(toFloat64(coalesce(value, sum, 0))) AS valueMaxState,
|
|
163
|
-
|
|
164
|
+
maxSimpleState(retentionDate) AS retentionDate
|
|
164
165
|
FROM MetricItemV3
|
|
165
166
|
WHERE k8sClusterEntityKey != ''
|
|
166
167
|
GROUP BY projectId, name, k8sClusterEntityKey, bucketTime`,
|
|
@@ -174,6 +175,8 @@ GROUP BY projectId, name, k8sClusterEntityKey, bucketTime`,
|
|
|
174
175
|
tableSettings:
|
|
175
176
|
"ttl_only_drop_parts = 1, non_replicated_deduplication_window = 10000",
|
|
176
177
|
ttlExpression: "retentionDate DELETE",
|
|
178
|
+
includeBaseColumns: false,
|
|
179
|
+
defaultSortColumn: "bucketTime",
|
|
177
180
|
});
|
|
178
181
|
}
|
|
179
182
|
}
|
|
@@ -112,9 +112,10 @@ export default class MetricItemAggMV1mByService extends AnalyticsBaseModel {
|
|
|
112
112
|
key: "retentionDate",
|
|
113
113
|
title: "Retention Date",
|
|
114
114
|
description:
|
|
115
|
-
"
|
|
115
|
+
"Latest date after which this aggregate bucket is eligible for TTL deletion. Stored as SimpleAggregateFunction(max, DateTime) so partial rows keep the maximum expiry when AggregatingMergeTree merges them.",
|
|
116
116
|
required: true,
|
|
117
117
|
type: TableColumnType.Date,
|
|
118
|
+
simpleAggregateFunction: "max",
|
|
118
119
|
});
|
|
119
120
|
|
|
120
121
|
super({
|
|
@@ -160,7 +161,7 @@ SELECT
|
|
|
160
161
|
countState(toFloat64(coalesce(value, sum, 0))) AS valueCountState,
|
|
161
162
|
minState(toFloat64(coalesce(value, sum, 0))) AS valueMinState,
|
|
162
163
|
maxState(toFloat64(coalesce(value, sum, 0))) AS valueMaxState,
|
|
163
|
-
|
|
164
|
+
maxSimpleState(retentionDate) AS retentionDate
|
|
164
165
|
FROM MetricItemV3
|
|
165
166
|
WHERE serviceEntityKey != ''
|
|
166
167
|
GROUP BY projectId, name, serviceEntityKey, bucketTime`,
|
|
@@ -174,6 +175,8 @@ GROUP BY projectId, name, serviceEntityKey, bucketTime`,
|
|
|
174
175
|
tableSettings:
|
|
175
176
|
"ttl_only_drop_parts = 1, non_replicated_deduplication_window = 10000",
|
|
176
177
|
ttlExpression: "retentionDate DELETE",
|
|
178
|
+
includeBaseColumns: false,
|
|
179
|
+
defaultSortColumn: "bucketTime",
|
|
177
180
|
});
|
|
178
181
|
}
|
|
179
182
|
}
|
|
@@ -102,6 +102,27 @@ export default class EnterpriseLicense extends BaseModel {
|
|
|
102
102
|
})
|
|
103
103
|
public annualContractValue?: number = undefined;
|
|
104
104
|
|
|
105
|
+
@ColumnAccessControl({
|
|
106
|
+
create: [],
|
|
107
|
+
read: [],
|
|
108
|
+
update: [],
|
|
109
|
+
})
|
|
110
|
+
@TableColumn({
|
|
111
|
+
required: true,
|
|
112
|
+
isDefaultValueColumn: true,
|
|
113
|
+
type: TableColumnType.Boolean,
|
|
114
|
+
title: "Evaluation License",
|
|
115
|
+
description:
|
|
116
|
+
"When enabled, this key is for evaluation and testing only — the customer's installation shows an evaluation notice and it is not meant for production use.",
|
|
117
|
+
defaultValue: false,
|
|
118
|
+
})
|
|
119
|
+
@Column({
|
|
120
|
+
nullable: false,
|
|
121
|
+
type: ColumnType.Boolean,
|
|
122
|
+
default: false,
|
|
123
|
+
})
|
|
124
|
+
public isEvaluationLicense?: boolean = undefined;
|
|
125
|
+
|
|
105
126
|
@ColumnAccessControl({
|
|
106
127
|
create: [],
|
|
107
128
|
read: [],
|
|
@@ -188,4 +188,29 @@ export default class EnterpriseLicenseInstance extends BaseModel {
|
|
|
188
188
|
nullable: true,
|
|
189
189
|
})
|
|
190
190
|
public masterAdminEmails?: Array<string> = undefined;
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
* Named oneuptimeVersion, not version: DatabaseBaseModel already declares a
|
|
194
|
+
* `version` @VersionColumn() (the optimistic-locking row revision) on every
|
|
195
|
+
* model, so a second `version` property would collide in the TypeORM entity
|
|
196
|
+
* metadata.
|
|
197
|
+
*/
|
|
198
|
+
@ColumnAccessControl({
|
|
199
|
+
create: [],
|
|
200
|
+
read: [],
|
|
201
|
+
update: [],
|
|
202
|
+
})
|
|
203
|
+
@TableColumn({
|
|
204
|
+
required: false,
|
|
205
|
+
type: TableColumnType.ShortText,
|
|
206
|
+
title: "OneUptime Version",
|
|
207
|
+
description:
|
|
208
|
+
"OneUptime version this instance last reported, for example 11.5.13. Lets support see which instances are running an outdated build.",
|
|
209
|
+
})
|
|
210
|
+
@Column({
|
|
211
|
+
nullable: true,
|
|
212
|
+
type: ColumnType.ShortText,
|
|
213
|
+
length: ColumnLength.ShortText,
|
|
214
|
+
})
|
|
215
|
+
public oneuptimeVersion?: string = undefined;
|
|
191
216
|
}
|
|
@@ -824,6 +824,25 @@ export default class GlobalConfig extends GlobalConfigModel {
|
|
|
824
824
|
})
|
|
825
825
|
public enterpriseLicenseToken?: string = undefined;
|
|
826
826
|
|
|
827
|
+
@ColumnAccessControl({
|
|
828
|
+
create: [],
|
|
829
|
+
read: [],
|
|
830
|
+
update: [],
|
|
831
|
+
})
|
|
832
|
+
@TableColumn({
|
|
833
|
+
type: TableColumnType.Boolean,
|
|
834
|
+
title: "Enterprise License Is Evaluation",
|
|
835
|
+
description:
|
|
836
|
+
"True when the validated enterprise license is an evaluation/testing license. Drives the evaluation notice shown in the edition modal.",
|
|
837
|
+
defaultValue: false,
|
|
838
|
+
})
|
|
839
|
+
@Column({
|
|
840
|
+
type: ColumnType.Boolean,
|
|
841
|
+
nullable: true,
|
|
842
|
+
default: false,
|
|
843
|
+
})
|
|
844
|
+
public enterpriseLicenseIsEvaluation?: boolean = undefined;
|
|
845
|
+
|
|
827
846
|
@ColumnAccessControl({
|
|
828
847
|
create: [],
|
|
829
848
|
read: [],
|
|
@@ -929,6 +948,63 @@ export default class GlobalConfig extends GlobalConfigModel {
|
|
|
929
948
|
})
|
|
930
949
|
public enterpriseLicenseExpiryReminderDays?: number = undefined;
|
|
931
950
|
|
|
951
|
+
/*
|
|
952
|
+
* The four latestRelease* columns cache the daily GitHub release check
|
|
953
|
+
* (Workers/Jobs/InstanceUpdate/CheckForNewVersion). They are a cache, not
|
|
954
|
+
* configuration: an air-gapped installation simply leaves them null and no
|
|
955
|
+
* update prompt is ever shown.
|
|
956
|
+
*/
|
|
957
|
+
@ColumnAccessControl({
|
|
958
|
+
create: [],
|
|
959
|
+
read: [],
|
|
960
|
+
update: [],
|
|
961
|
+
})
|
|
962
|
+
@TableColumn({
|
|
963
|
+
type: TableColumnType.ShortText,
|
|
964
|
+
title: "Latest Release Version",
|
|
965
|
+
description:
|
|
966
|
+
"Latest OneUptime version published on GitHub, for example 11.6.0, as of the last update check. Null until the first successful check.",
|
|
967
|
+
})
|
|
968
|
+
@Column({
|
|
969
|
+
type: ColumnType.ShortText,
|
|
970
|
+
length: ColumnLength.ShortText,
|
|
971
|
+
nullable: true,
|
|
972
|
+
})
|
|
973
|
+
public latestReleaseVersion?: string = undefined;
|
|
974
|
+
|
|
975
|
+
@ColumnAccessControl({
|
|
976
|
+
create: [],
|
|
977
|
+
read: [],
|
|
978
|
+
update: [],
|
|
979
|
+
})
|
|
980
|
+
@TableColumn({
|
|
981
|
+
type: TableColumnType.Date,
|
|
982
|
+
title: "Latest Release Published At",
|
|
983
|
+
description: "When the latest OneUptime version was published on GitHub.",
|
|
984
|
+
})
|
|
985
|
+
@Column({
|
|
986
|
+
type: ColumnType.Date,
|
|
987
|
+
nullable: true,
|
|
988
|
+
})
|
|
989
|
+
public latestReleasePublishedAt?: Date = undefined;
|
|
990
|
+
|
|
991
|
+
@ColumnAccessControl({
|
|
992
|
+
create: [],
|
|
993
|
+
read: [],
|
|
994
|
+
update: [],
|
|
995
|
+
})
|
|
996
|
+
@TableColumn({
|
|
997
|
+
type: TableColumnType.Date,
|
|
998
|
+
title: "Latest Release Checked At",
|
|
999
|
+
description:
|
|
1000
|
+
"When this installation last successfully checked GitHub for a newer OneUptime release.",
|
|
1001
|
+
})
|
|
1002
|
+
@Column({
|
|
1003
|
+
type: ColumnType.Date,
|
|
1004
|
+
nullable: true,
|
|
1005
|
+
})
|
|
1006
|
+
public latestReleaseCheckedAt?: Date = undefined;
|
|
1007
|
+
|
|
932
1008
|
@ColumnAccessControl({
|
|
933
1009
|
create: [],
|
|
934
1010
|
read: [],
|
|
@@ -5,6 +5,7 @@ import { JSONObject } from "../../Types/JSON";
|
|
|
5
5
|
import PartialEntity from "../../Types/Database/PartialEntity";
|
|
6
6
|
import EnterpriseLicenseInstanceSummary from "../../Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary";
|
|
7
7
|
import EnterpriseLicenseUsageUtil from "../../Utils/EnterpriseLicense/EnterpriseLicenseUsage";
|
|
8
|
+
import VersionUtil from "../../Utils/VersionUtil";
|
|
8
9
|
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
9
10
|
import ObjectID from "../../Types/ObjectID";
|
|
10
11
|
import PositiveNumber from "../../Types/PositiveNumber";
|
|
@@ -29,6 +30,8 @@ export interface LicenseInstanceUpsert {
|
|
|
29
30
|
licenseId: ObjectID;
|
|
30
31
|
instanceId: string;
|
|
31
32
|
host: string | undefined;
|
|
33
|
+
// OneUptime version the instance is running. Absent on instances too old to report it.
|
|
34
|
+
oneuptimeVersion?: string | null | undefined;
|
|
32
35
|
// Usage fields are only set on report-user-count, not on validate.
|
|
33
36
|
userCount?: number | undefined;
|
|
34
37
|
userEmailHashes?: Array<string> | undefined;
|
|
@@ -84,6 +87,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
84
87
|
userLimit: true,
|
|
85
88
|
currentUserCount: true,
|
|
86
89
|
userCountUpdatedAt: true,
|
|
90
|
+
isEvaluationLicense: true,
|
|
87
91
|
},
|
|
88
92
|
props: {
|
|
89
93
|
isRoot: true,
|
|
@@ -117,12 +121,16 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
117
121
|
req.body["instanceId"],
|
|
118
122
|
);
|
|
119
123
|
const instanceHost: string = this.parseShortText(req.body["host"]);
|
|
124
|
+
const instanceVersion: string | null | undefined = this.parseVersion(
|
|
125
|
+
req.body["version"],
|
|
126
|
+
);
|
|
120
127
|
|
|
121
128
|
if (instanceId) {
|
|
122
129
|
await this.upsertLicenseInstance({
|
|
123
130
|
licenseId: license.id!,
|
|
124
131
|
instanceId: instanceId,
|
|
125
132
|
host: instanceHost || undefined,
|
|
133
|
+
oneuptimeVersion: instanceVersion,
|
|
126
134
|
});
|
|
127
135
|
}
|
|
128
136
|
|
|
@@ -154,6 +162,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
154
162
|
userCountUpdatedAt: license.userCountUpdatedAt
|
|
155
163
|
? license.userCountUpdatedAt.toISOString()
|
|
156
164
|
: null,
|
|
165
|
+
isEvaluationLicense: Boolean(license.isEvaluationLicense),
|
|
157
166
|
instances: this.getInstanceSummaries(instances),
|
|
158
167
|
token,
|
|
159
168
|
});
|
|
@@ -196,6 +205,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
196
205
|
select: {
|
|
197
206
|
_id: true,
|
|
198
207
|
userLimit: true,
|
|
208
|
+
isEvaluationLicense: true,
|
|
199
209
|
},
|
|
200
210
|
props: {
|
|
201
211
|
isRoot: true,
|
|
@@ -212,6 +222,9 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
212
222
|
req.body["instanceId"],
|
|
213
223
|
);
|
|
214
224
|
const instanceHost: string = this.parseShortText(req.body["host"]);
|
|
225
|
+
const instanceVersion: string | null | undefined = this.parseVersion(
|
|
226
|
+
req.body["version"],
|
|
227
|
+
);
|
|
215
228
|
const userEmailHashes: Array<string> =
|
|
216
229
|
EnterpriseLicenseUsageUtil.sanitizeUserEmailHashes(
|
|
217
230
|
req.body["userEmailHashes"],
|
|
@@ -230,6 +243,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
230
243
|
licenseId: license.id!,
|
|
231
244
|
instanceId: instanceId,
|
|
232
245
|
host: instanceHost || undefined,
|
|
246
|
+
oneuptimeVersion: instanceVersion,
|
|
233
247
|
userCount: userCount,
|
|
234
248
|
userEmailHashes: userEmailHashes,
|
|
235
249
|
masterAdminEmails: masterAdminEmails,
|
|
@@ -273,6 +287,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
273
287
|
userCountUpdatedAt: reportedAt.toISOString(),
|
|
274
288
|
userLimit:
|
|
275
289
|
typeof license.userLimit === "number" ? license.userLimit : null,
|
|
290
|
+
isEvaluationLicense: Boolean(license.isEvaluationLicense),
|
|
276
291
|
instances: this.getInstanceSummaries(instances),
|
|
277
292
|
});
|
|
278
293
|
} catch (err) {
|
|
@@ -290,6 +305,31 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
290
305
|
return value.trim().substring(0, 100);
|
|
291
306
|
}
|
|
292
307
|
|
|
308
|
+
/*
|
|
309
|
+
* report-user-count is unauthenticated, so the reported version is only
|
|
310
|
+
* stored when it is a version we could actually compare against a release —
|
|
311
|
+
* garbage never reaches the admin dashboard or the customer's modal.
|
|
312
|
+
*
|
|
313
|
+
* Three outcomes, and the callers depend on the distinction:
|
|
314
|
+
* undefined — the instance sent no version at all (it predates this
|
|
315
|
+
* field). Leave whatever is stored alone.
|
|
316
|
+
* null — it sent something, but not a version. Clear the stored
|
|
317
|
+
* value, so an instance rolled back to a build with no
|
|
318
|
+
* APP_VERSION stops advertising the version it used to run.
|
|
319
|
+
* string — a valid, canonical version to store.
|
|
320
|
+
*/
|
|
321
|
+
private parseVersion(value: unknown): string | null | undefined {
|
|
322
|
+
if (value === undefined || value === null) {
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/*
|
|
327
|
+
* Canonicalized rather than passed through, so the stored string is never
|
|
328
|
+
* something the UIs would render with a doubled "v".
|
|
329
|
+
*/
|
|
330
|
+
return VersionUtil.canonicalize(value);
|
|
331
|
+
}
|
|
332
|
+
|
|
293
333
|
private async findLicenseInstances(
|
|
294
334
|
licenseId: ObjectID,
|
|
295
335
|
): Promise<Array<EnterpriseLicenseInstance>> {
|
|
@@ -304,6 +344,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
304
344
|
userCount: true,
|
|
305
345
|
userEmailHashes: true,
|
|
306
346
|
lastReportedAt: true,
|
|
347
|
+
oneuptimeVersion: true,
|
|
307
348
|
},
|
|
308
349
|
sort: {
|
|
309
350
|
createdAt: SortOrder.Ascending,
|
|
@@ -331,6 +372,7 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
331
372
|
lastReportedAt: instance.lastReportedAt
|
|
332
373
|
? instance.lastReportedAt.toISOString()
|
|
333
374
|
: null,
|
|
375
|
+
version: instance.oneuptimeVersion || null,
|
|
334
376
|
};
|
|
335
377
|
},
|
|
336
378
|
);
|
|
@@ -370,6 +412,11 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
370
412
|
newInstance.host = data.host;
|
|
371
413
|
}
|
|
372
414
|
|
|
415
|
+
// Null means "reported something that is not a version" — nothing to store.
|
|
416
|
+
if (data.oneuptimeVersion) {
|
|
417
|
+
newInstance.oneuptimeVersion = data.oneuptimeVersion;
|
|
418
|
+
}
|
|
419
|
+
|
|
373
420
|
if (data.userCount !== undefined) {
|
|
374
421
|
newInstance.userCount = data.userCount;
|
|
375
422
|
}
|
|
@@ -434,6 +481,16 @@ export default class EnterpriseLicenseAPI extends BaseAPI<
|
|
|
434
481
|
updateData.host = data.host;
|
|
435
482
|
}
|
|
436
483
|
|
|
484
|
+
/*
|
|
485
|
+
* Null clears the column: an instance rebuilt onto a build with no
|
|
486
|
+
* APP_VERSION must stop advertising the version it used to run, because
|
|
487
|
+
* lastReportedAt is refreshed on the same request and would otherwise
|
|
488
|
+
* read as "confirmed running v11.5.13 as of today".
|
|
489
|
+
*/
|
|
490
|
+
if (data.oneuptimeVersion !== undefined) {
|
|
491
|
+
updateData.oneuptimeVersion = data.oneuptimeVersion;
|
|
492
|
+
}
|
|
493
|
+
|
|
437
494
|
if (data.userCount !== undefined) {
|
|
438
495
|
updateData.userCount = data.userCount;
|
|
439
496
|
}
|