@oneuptime/common 12.0.2 → 12.0.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.
- package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +14 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/LogDropFilter.ts +9 -20
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +911 -0
- package/Models/DatabaseModels/StatusPageResource.ts +73 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +9 -20
- package/Server/API/BaseAPI.ts +13 -2
- package/Server/API/DashboardAPI.ts +39 -0
- package/Server/EnvironmentConfig.ts +31 -1
- package/Server/Infrastructure/GlobalCache.ts +115 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +16 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.ts +123 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/AlertStateTimelineService.ts +20 -0
- package/Server/Services/CephClusterService.ts +26 -86
- package/Server/Services/CloudResourceService.ts +23 -83
- package/Server/Services/DatabaseService.ts +111 -0
- package/Server/Services/DockerHostService.ts +19 -79
- package/Server/Services/DockerSwarmClusterService.ts +27 -88
- package/Server/Services/HostService.ts +46 -99
- package/Server/Services/IncidentStateTimelineService.ts +20 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTFleetService.ts +19 -79
- package/Server/Services/KubernetesClusterService.ts +17 -78
- package/Server/Services/LabelService.ts +57 -10
- package/Server/Services/MetricTypeService.ts +84 -0
- package/Server/Services/MonitorService.ts +89 -14
- package/Server/Services/MonitorStatusTimelineService.ts +29 -0
- package/Server/Services/MonitorTemplateService.ts +65 -0
- package/Server/Services/PodmanHostService.ts +19 -79
- package/Server/Services/ProxmoxClusterService.ts +23 -83
- package/Server/Services/RumApplicationService.ts +19 -80
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +21 -0
- package/Server/Services/ServerlessFunctionService.ts +24 -85
- package/Server/Services/ServiceService.ts +299 -73
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +752 -0
- package/Server/Services/StatusPageMonitorRuleService.ts +471 -0
- package/Server/Services/TelemetryEntityRelationshipService.ts +1 -0
- package/Server/Services/TelemetryEntityService.ts +1 -0
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +170 -39
- package/Server/Utils/Monitor/MonitorResource.ts +63 -36
- package/Server/Utils/Monitor/MonitorStatusTimeline.ts +36 -0
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +148 -127
- package/Server/Utils/Monitor/MonitorStepsReferenceExtractor.ts +434 -0
- package/Server/Utils/SingleFlight.ts +83 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +46 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +107 -26
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +314 -0
- package/Server/Utils/Telemetry/Telemetry.ts +351 -122
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +2 -0
- package/Tests/Models/DatabaseModels/ColumnTransformerInvariants.test.ts +306 -0
- package/Tests/Models/DatabaseModels/NumberColumnDeserialization.test.ts +333 -0
- package/Tests/Models/DatabaseModels/StatusPageMonitorRuleModel.test.ts +190 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +26 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +226 -0
- package/Tests/Server/Infrastructure/PostgresLockTimeoutOptions.test.ts +181 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlocked.test.ts +342 -0
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +245 -0
- package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +163 -15
- package/Tests/Server/Services/MetricTypeAttachServices.test.ts +222 -0
- package/Tests/Server/Services/MissingReferenceWriteGuard.test.ts +614 -0
- package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +23 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +305 -56
- package/Tests/Server/Services/ServiceUpdateLastSeenSplitGates.test.ts +705 -0
- package/Tests/Server/Services/StatusPageMonitorRuleEngineService.test.ts +1719 -0
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +1212 -0
- package/Tests/Server/Services/StatusPageMonitorRuleMonitorCreateHook.test.ts +228 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +267 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +260 -13
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +302 -0
- package/Tests/Server/Utils/MetricTypeIndexConvergence.test.ts +598 -0
- package/Tests/Server/Utils/Monitor/MonitorStatusTimelineUnusableStatus.test.ts +154 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +638 -92
- package/Tests/Server/Utils/Monitor/MonitorStepsReferenceExtractor.test.ts +724 -0
- package/Tests/Server/Utils/SingleFlight.test.ts +221 -0
- package/Tests/Types/Dashboard/NetworkDashboardTemplate.test.ts +793 -0
- package/Tests/Types/Database/BigIntColumnTransformer.test.ts +147 -0
- package/Tests/Types/Database/DatabasePropertyTransformer.test.ts +140 -0
- package/Tests/Types/Database/NumericColumnValue.test.ts +127 -0
- package/Tests/Types/Decimal.test.ts +37 -0
- package/Tests/Types/Monitor/SnmpVersionParsing.test.ts +152 -0
- package/Tests/Types/Port.test.ts +38 -0
- package/Tests/UI/Components/LogsHistogram.test.tsx +276 -0
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +489 -0
- package/Tests/UI/Components/UseLogsHistogram.test.tsx +500 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentsUtil.test.ts +120 -0
- package/Tests/Utils/Dashboard/DashboardNetworkMapComponent.test.ts +327 -0
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.ts +40 -0
- package/Types/Dashboard/DashboardTemplates.ts +397 -0
- package/Types/Database/BigIntColumnTransformer.ts +74 -0
- package/Types/Database/DatabaseProperty.ts +26 -0
- package/Types/Database/NumericColumnValue.ts +128 -0
- package/Types/Decimal.ts +16 -4
- package/Types/Permission.ts +48 -0
- package/Types/Port.ts +16 -4
- package/UI/Components/LogsViewer/useLiveLogsRefresh.ts +86 -0
- package/UI/Components/LogsViewer/useLogsHistogram.ts +113 -0
- package/Utils/Dashboard/Components/DashboardNetworkMapComponent.ts +136 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js +925 -0
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageResource.js +72 -0
- package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +11 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +39 -0
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +27 -1
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +91 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +5 -3
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertStateTimelineService.js +19 -0
- package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +26 -76
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +23 -73
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +86 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +19 -69
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +27 -78
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +58 -102
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetService.js +19 -69
- package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +17 -68
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +42 -7
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MetricTypeService.js +74 -0
- package/build/dist/Server/Services/MetricTypeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +81 -9
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +28 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +60 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +19 -69
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +23 -73
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationService.js +19 -70
- package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +20 -0
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionService.js +24 -75
- package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +236 -61
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +603 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js +401 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js.map +1 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityService.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +105 -29
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +56 -32
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +30 -3
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +110 -98
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js +312 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js.map +1 -0
- package/build/dist/Server/Utils/SingleFlight.js +76 -0
- package/build/dist/Server/Utils/SingleFlight.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +29 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +78 -19
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +160 -0
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +279 -104
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +368 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Database/BigIntColumnTransformer.js +66 -0
- package/build/dist/Types/Database/BigIntColumnTransformer.js.map +1 -0
- package/build/dist/Types/Database/DatabaseProperty.js +25 -0
- package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
- package/build/dist/Types/Database/NumericColumnValue.js +97 -0
- package/build/dist/Types/Database/NumericColumnValue.js.map +1 -0
- package/build/dist/Types/Decimal.js +14 -3
- package/build/dist/Types/Decimal.js.map +1 -1
- package/build/dist/Types/Permission.js +42 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Port.js +15 -5
- package/build/dist/Types/Port.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js +44 -0
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js +75 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js +114 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import Model from "../../Models/DatabaseModels/DockerSwarmCluster";
|
|
|
5
5
|
import Label from "../../Models/DatabaseModels/Label";
|
|
6
6
|
import { OnCreate } from "../Types/Database/Hooks";
|
|
7
7
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
8
|
+
import ResourceHeartbeat from "../Utils/Telemetry/ResourceHeartbeat";
|
|
8
9
|
import ObjectID from "../../Types/ObjectID";
|
|
9
10
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
10
11
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -182,7 +183,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
182
183
|
networkCount?: number | undefined;
|
|
183
184
|
},
|
|
184
185
|
): Promise<void> {
|
|
185
|
-
const cacheKey: string = clusterId.toString();
|
|
186
186
|
const extrasFingerprint: string = crypto
|
|
187
187
|
.createHash("sha1")
|
|
188
188
|
.update(
|
|
@@ -202,34 +202,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
202
202
|
)
|
|
203
203
|
.digest("hex");
|
|
204
204
|
|
|
205
|
-
let cached: string | null = null;
|
|
206
|
-
try {
|
|
207
|
-
cached = await GlobalCache.getString(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
208
|
-
} catch {
|
|
209
|
-
/*
|
|
210
|
-
* Cache unavailable — fail open and refresh lastSeenAt anyway. A
|
|
211
|
-
* cache error must never skip the DB write below, otherwise the
|
|
212
|
-
* resource is wrongly marked "disconnected" while telemetry is
|
|
213
|
-
* still flowing. Mirrors shouldRunMaintenance's fail-open stance.
|
|
214
|
-
*/
|
|
215
|
-
cached = null;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (cached === extrasFingerprint) {
|
|
219
|
-
return; // same data was written recently
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
try {
|
|
223
|
-
await GlobalCache.setString(
|
|
224
|
-
LAST_SEEN_CACHE_NAMESPACE,
|
|
225
|
-
cacheKey,
|
|
226
|
-
extrasFingerprint,
|
|
227
|
-
{ expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
|
|
228
|
-
);
|
|
229
|
-
} catch {
|
|
230
|
-
// Best-effort throttle write; proceed with the DB update regardless.
|
|
231
|
-
}
|
|
232
|
-
|
|
233
205
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
234
206
|
const liveness: any = {
|
|
235
207
|
lastSeenAt: OneUptimeDate.getCurrentDate(),
|
|
@@ -237,92 +209,59 @@ export class Service extends DatabaseService<Model> {
|
|
|
237
209
|
};
|
|
238
210
|
|
|
239
211
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
240
|
-
const
|
|
212
|
+
const metadata: any = {};
|
|
241
213
|
|
|
242
214
|
if (extra?.dockerVersion) {
|
|
243
|
-
|
|
215
|
+
metadata.dockerVersion = extra.dockerVersion;
|
|
244
216
|
}
|
|
245
217
|
if (extra?.swarmId) {
|
|
246
|
-
|
|
218
|
+
metadata.swarmId = extra.swarmId;
|
|
247
219
|
}
|
|
248
220
|
if (extra?.agentVersion) {
|
|
249
|
-
|
|
221
|
+
metadata.agentVersion = extra.agentVersion;
|
|
250
222
|
}
|
|
251
223
|
// Counts: 0 is a legitimate value — gate on undefined, not falsiness.
|
|
252
224
|
if (extra?.nodeCount !== undefined) {
|
|
253
|
-
|
|
225
|
+
metadata.nodeCount = extra.nodeCount;
|
|
254
226
|
}
|
|
255
227
|
if (extra?.readyNodeCount !== undefined) {
|
|
256
|
-
|
|
228
|
+
metadata.readyNodeCount = extra.readyNodeCount;
|
|
257
229
|
}
|
|
258
230
|
if (extra?.managerNodeCount !== undefined) {
|
|
259
|
-
|
|
231
|
+
metadata.managerNodeCount = extra.managerNodeCount;
|
|
260
232
|
}
|
|
261
233
|
if (extra?.serviceCount !== undefined) {
|
|
262
|
-
|
|
234
|
+
metadata.serviceCount = extra.serviceCount;
|
|
263
235
|
}
|
|
264
236
|
if (extra?.taskCount !== undefined) {
|
|
265
|
-
|
|
237
|
+
metadata.taskCount = extra.taskCount;
|
|
266
238
|
}
|
|
267
239
|
if (extra?.runningTaskCount !== undefined) {
|
|
268
|
-
|
|
240
|
+
metadata.runningTaskCount = extra.runningTaskCount;
|
|
269
241
|
}
|
|
270
242
|
if (extra?.stackCount !== undefined) {
|
|
271
|
-
|
|
243
|
+
metadata.stackCount = extra.stackCount;
|
|
272
244
|
}
|
|
273
245
|
if (extra?.networkCount !== undefined) {
|
|
274
|
-
|
|
246
|
+
metadata.networkCount = extra.networkCount;
|
|
275
247
|
}
|
|
276
248
|
|
|
277
249
|
/*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
* Collector-supplied strings are clamped to their declared column
|
|
283
|
-
* widths inside updateColumnsByIdWithoutHooks — see
|
|
284
|
-
* DatabaseService.truncateStringColumnsToMaxLength.
|
|
250
|
+
* One gated, non-blocking heartbeat write. The gates, the fail-open /
|
|
251
|
+
* fail-closed split and the liveness-only fallback all live in
|
|
252
|
+
* ResourceHeartbeat — see there for why this row's throttle used to
|
|
253
|
+
* provide no throttling at all.
|
|
285
254
|
*/
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
* reject the statement, lastSeenAt silently stops advancing and
|
|
297
|
-
* markDisconnectedClusters flips a perfectly healthy Docker Swarm
|
|
298
|
-
* cluster to "disconnected" 15 minutes later — with telemetry still
|
|
299
|
-
* arriving the whole time. That was issue #3006 on the Host path (a
|
|
300
|
-
* host.ip list longer than the then-varchar(500) column). Retry with
|
|
301
|
-
* liveness only so the enrichment is what gets dropped, never the
|
|
302
|
-
* heartbeat.
|
|
303
|
-
*/
|
|
304
|
-
logger.warn(
|
|
305
|
-
`DockerSwarmClusterService.updateLastSeen: metadata write failed for Docker Swarm cluster ${clusterId.toString()}, falling back to a liveness-only update: ${
|
|
306
|
-
err instanceof Error ? err.message : String(err)
|
|
307
|
-
}`,
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
/*
|
|
311
|
-
* The throttle fingerprint was already stored, so without this the
|
|
312
|
-
* next batch would short-circuit on a cache hit and skip the retry
|
|
313
|
-
* for the rest of the window.
|
|
314
|
-
*/
|
|
315
|
-
try {
|
|
316
|
-
await GlobalCache.deleteKey(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
317
|
-
} catch {
|
|
318
|
-
// Best-effort; the fallback write below is what actually matters.
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
322
|
-
id: clusterId,
|
|
323
|
-
data: liveness,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
255
|
+
await ResourceHeartbeat.write({
|
|
256
|
+
service: this,
|
|
257
|
+
id: clusterId,
|
|
258
|
+
cacheNamespace: LAST_SEEN_CACHE_NAMESPACE,
|
|
259
|
+
throttleInSeconds: LAST_SEEN_THROTTLE_SECONDS,
|
|
260
|
+
liveness: liveness,
|
|
261
|
+
metadata: metadata,
|
|
262
|
+
fingerprint: extrasFingerprint,
|
|
263
|
+
describe: `docker swarm cluster ${clusterId.toString()}`,
|
|
264
|
+
});
|
|
326
265
|
}
|
|
327
266
|
|
|
328
267
|
/**
|
|
@@ -5,6 +5,7 @@ import Model from "../../Models/DatabaseModels/Host";
|
|
|
5
5
|
import Label from "../../Models/DatabaseModels/Label";
|
|
6
6
|
import { OnCreate } from "../Types/Database/Hooks";
|
|
7
7
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
8
|
+
import ResourceHeartbeat from "../Utils/Telemetry/ResourceHeartbeat";
|
|
8
9
|
import ObjectID from "../../Types/ObjectID";
|
|
9
10
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
10
11
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -212,35 +213,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
212
213
|
* once per throttle window. If any extra value changed (e.g. cpuCores
|
|
213
214
|
* updated, IP address changed), bust the cache and write immediately.
|
|
214
215
|
*/
|
|
215
|
-
const cacheKey: string = hostId.toString();
|
|
216
216
|
const extrasFingerprint: string = this.fingerprintExtras(extra);
|
|
217
|
-
let cached: string | null = null;
|
|
218
|
-
try {
|
|
219
|
-
cached = await GlobalCache.getString(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
220
|
-
} catch {
|
|
221
|
-
/*
|
|
222
|
-
* Cache unavailable — fail open and refresh lastSeenAt anyway. A
|
|
223
|
-
* cache error must never skip the DB write below, otherwise the
|
|
224
|
-
* resource is wrongly marked "disconnected" while telemetry is
|
|
225
|
-
* still flowing. Mirrors shouldRunMaintenance's fail-open stance.
|
|
226
|
-
*/
|
|
227
|
-
cached = null;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (cached === extrasFingerprint) {
|
|
231
|
-
return; // same data was written recently
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
await GlobalCache.setString(
|
|
236
|
-
LAST_SEEN_CACHE_NAMESPACE,
|
|
237
|
-
cacheKey,
|
|
238
|
-
extrasFingerprint,
|
|
239
|
-
{ expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
|
|
240
|
-
);
|
|
241
|
-
} catch {
|
|
242
|
-
// Best-effort throttle write; proceed with the DB update regardless.
|
|
243
|
-
}
|
|
244
217
|
|
|
245
218
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
219
|
const liveness: any = {
|
|
@@ -249,118 +222,85 @@ export class Service extends DatabaseService<Model> {
|
|
|
249
222
|
};
|
|
250
223
|
|
|
251
224
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
252
|
-
const
|
|
225
|
+
const metadata: any = {};
|
|
253
226
|
|
|
254
227
|
if (extra?.osType) {
|
|
255
|
-
|
|
228
|
+
metadata.osType = extra.osType;
|
|
256
229
|
}
|
|
257
230
|
if (extra?.osVersion) {
|
|
258
|
-
|
|
231
|
+
metadata.osVersion = extra.osVersion;
|
|
259
232
|
}
|
|
260
233
|
if (extra?.hostId) {
|
|
261
|
-
|
|
234
|
+
metadata.hostId = extra.hostId;
|
|
262
235
|
}
|
|
263
236
|
if (extra?.hostArch) {
|
|
264
|
-
|
|
237
|
+
metadata.hostArch = extra.hostArch;
|
|
265
238
|
}
|
|
266
239
|
if (extra?.hostType) {
|
|
267
|
-
|
|
240
|
+
metadata.hostType = extra.hostType;
|
|
268
241
|
}
|
|
269
242
|
if (extra?.hostIpAddresses) {
|
|
270
|
-
|
|
243
|
+
metadata.hostIpAddresses = extra.hostIpAddresses;
|
|
271
244
|
}
|
|
272
245
|
if (extra?.cpuCores !== undefined) {
|
|
273
|
-
|
|
246
|
+
metadata.cpuCores = extra.cpuCores;
|
|
274
247
|
}
|
|
275
248
|
if (extra?.totalMemoryBytes !== undefined) {
|
|
276
|
-
|
|
249
|
+
metadata.totalMemoryBytes = extra.totalMemoryBytes;
|
|
277
250
|
}
|
|
278
251
|
if (extra?.processCount !== undefined) {
|
|
279
|
-
|
|
252
|
+
metadata.processCount = extra.processCount;
|
|
280
253
|
}
|
|
281
254
|
if (extra?.containerRuntime) {
|
|
282
|
-
|
|
255
|
+
metadata.containerRuntime = extra.containerRuntime;
|
|
283
256
|
}
|
|
284
257
|
if (extra?.dockerHostId) {
|
|
285
|
-
|
|
258
|
+
metadata.dockerHostId = extra.dockerHostId;
|
|
286
259
|
}
|
|
287
260
|
if (extra?.kubernetesClusterId) {
|
|
288
|
-
|
|
261
|
+
metadata.kubernetesClusterId = extra.kubernetesClusterId;
|
|
289
262
|
}
|
|
290
263
|
if (extra?.agentVersion) {
|
|
291
|
-
|
|
264
|
+
metadata.agentVersion = extra.agentVersion;
|
|
292
265
|
}
|
|
293
266
|
if (extra?.deploymentEnvironment) {
|
|
294
|
-
|
|
267
|
+
metadata.deploymentEnvironment = extra.deploymentEnvironment;
|
|
295
268
|
}
|
|
296
269
|
if (extra?.runtimeName) {
|
|
297
|
-
|
|
270
|
+
metadata.runtimeName = extra.runtimeName;
|
|
298
271
|
}
|
|
299
272
|
if (extra?.runtimeVersion) {
|
|
300
|
-
|
|
273
|
+
metadata.runtimeVersion = extra.runtimeVersion;
|
|
301
274
|
}
|
|
302
275
|
if (extra?.cloudProvider) {
|
|
303
|
-
|
|
276
|
+
metadata.cloudProvider = extra.cloudProvider;
|
|
304
277
|
}
|
|
305
278
|
if (extra?.cloudPlatform) {
|
|
306
|
-
|
|
279
|
+
metadata.cloudPlatform = extra.cloudPlatform;
|
|
307
280
|
}
|
|
308
281
|
if (extra?.cloudRegion) {
|
|
309
|
-
|
|
282
|
+
metadata.cloudRegion = extra.cloudRegion;
|
|
310
283
|
}
|
|
311
284
|
if (extra?.cloudAccountId) {
|
|
312
|
-
|
|
285
|
+
metadata.cloudAccountId = extra.cloudAccountId;
|
|
313
286
|
}
|
|
314
287
|
|
|
315
288
|
/*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
* Every optional value above comes from an OpenTelemetry resource
|
|
321
|
-
* attribute, so its length is whatever the collector felt like sending.
|
|
322
|
-
* updateColumnsByIdWithoutHooks clamps them to their declared column
|
|
323
|
-
* widths for us — see truncateStringColumnsToMaxLength.
|
|
289
|
+
* One gated, non-blocking heartbeat write. The gates, the fail-open /
|
|
290
|
+
* fail-closed split and the liveness-only fallback all live in
|
|
291
|
+
* ResourceHeartbeat — see there for why this row's throttle used to
|
|
292
|
+
* provide no throttling at all.
|
|
324
293
|
*/
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
* reject the statement, the host silently stops advancing
|
|
336
|
-
* lastSeenAt and MarkDisconnectedHosts flips a perfectly healthy
|
|
337
|
-
* host to "disconnected" 15 minutes later — with telemetry still
|
|
338
|
-
* arriving the whole time. That was issue #3006 (a host.ip list
|
|
339
|
-
* longer than the then-varchar(500) column). Retry with liveness
|
|
340
|
-
* only so the enrichment is what gets dropped, never the heartbeat.
|
|
341
|
-
*/
|
|
342
|
-
logger.warn(
|
|
343
|
-
`HostService.updateLastSeen: metadata write failed for host ${hostId.toString()}, falling back to a liveness-only update: ${
|
|
344
|
-
err instanceof Error ? err.message : String(err)
|
|
345
|
-
}`,
|
|
346
|
-
);
|
|
347
|
-
|
|
348
|
-
/*
|
|
349
|
-
* The throttle fingerprint was already stored, so without this the
|
|
350
|
-
* next batch would short-circuit on a cache hit and skip the retry
|
|
351
|
-
* for the rest of the window.
|
|
352
|
-
*/
|
|
353
|
-
try {
|
|
354
|
-
await GlobalCache.deleteKey(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
355
|
-
} catch {
|
|
356
|
-
// Best-effort; the fallback write below is what actually matters.
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
360
|
-
id: hostId,
|
|
361
|
-
data: liveness,
|
|
362
|
-
});
|
|
363
|
-
}
|
|
294
|
+
await ResourceHeartbeat.write({
|
|
295
|
+
service: this,
|
|
296
|
+
id: hostId,
|
|
297
|
+
cacheNamespace: LAST_SEEN_CACHE_NAMESPACE,
|
|
298
|
+
throttleInSeconds: LAST_SEEN_THROTTLE_SECONDS,
|
|
299
|
+
liveness: liveness,
|
|
300
|
+
metadata: metadata,
|
|
301
|
+
fingerprint: extrasFingerprint,
|
|
302
|
+
describe: `host ${hostId.toString()}`,
|
|
303
|
+
});
|
|
364
304
|
}
|
|
365
305
|
|
|
366
306
|
private fingerprintExtras(extra?: {
|
|
@@ -392,9 +332,16 @@ export class Service extends DatabaseService<Model> {
|
|
|
392
332
|
hostArch: extra?.hostArch ?? null,
|
|
393
333
|
hostType: extra?.hostType ?? null,
|
|
394
334
|
hostIpAddresses: extra?.hostIpAddresses ?? null,
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
335
|
+
/*
|
|
336
|
+
* cpuCores / totalMemoryBytes / processCount are DELIBERATELY not
|
|
337
|
+
* hashed. They are per-scrape gauges, and `system.processes.count` in
|
|
338
|
+
* particular is partitioned by process.status and summed, so it changes
|
|
339
|
+
* on essentially every scrape. Hashing them made the throttle key differ
|
|
340
|
+
* every time and the 60s window never engaged — for exactly the hosts
|
|
341
|
+
* producing the most batches, which is the worst possible place to lose
|
|
342
|
+
* a throttle. The columns are still written; they simply ride along on
|
|
343
|
+
* whatever write the throttle admits rather than forcing one.
|
|
344
|
+
*/
|
|
398
345
|
containerRuntime: extra?.containerRuntime ?? null,
|
|
399
346
|
dockerHostId: extra?.dockerHostId?.toString() ?? null,
|
|
400
347
|
kubernetesClusterId: extra?.kubernetesClusterId?.toString() ?? null,
|
|
@@ -25,6 +25,7 @@ import IncidentStateTimeline from "../../Models/DatabaseModels/IncidentStateTime
|
|
|
25
25
|
import IncidentMember from "../../Models/DatabaseModels/IncidentMember";
|
|
26
26
|
import IncidentRole from "../../Models/DatabaseModels/IncidentRole";
|
|
27
27
|
import { IsBillingEnabled } from "../EnvironmentConfig";
|
|
28
|
+
import ProjectScopedReferenceValidator from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
28
29
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
29
30
|
import IncidentFeedService from "./IncidentFeedService";
|
|
30
31
|
import AIIncidentPostmortemRunner from "../Utils/AI/SRE/IncidentPostmortemRunner";
|
|
@@ -128,6 +129,25 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
|
|
|
128
129
|
throw new BadDataException("incidentStateId is null");
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
/*
|
|
133
|
+
* Same guard, same reason, as MonitorStatusTimelineService: an id that
|
|
134
|
+
* exists nowhere (or belongs to another project) used to reach Postgres
|
|
135
|
+
* and come back as a raw foreign key violation. The ordering check below
|
|
136
|
+
* does look the state up, but only when there IS a preceding row with an
|
|
137
|
+
* order, so the first timeline row for an incident went through unchecked.
|
|
138
|
+
*/
|
|
139
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
140
|
+
projectId: createBy.props.tenantId || createBy.data.projectId,
|
|
141
|
+
subject: "incident state timeline",
|
|
142
|
+
references: [
|
|
143
|
+
{
|
|
144
|
+
modelName: "Incident State",
|
|
145
|
+
id: incidentStateId,
|
|
146
|
+
service: IncidentStateService,
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
});
|
|
150
|
+
|
|
131
151
|
// Execute queries for before and after states in parallel for better performance
|
|
132
152
|
const [stateBeforeThis, stateAfterThis] = await Promise.all([
|
|
133
153
|
this.findOneBy({
|
package/Server/Services/Index.ts
CHANGED
|
@@ -177,6 +177,7 @@ import StatusPageOwnerUserService from "./StatusPageOwnerUserService";
|
|
|
177
177
|
import StatusPagePrivateUserService from "./StatusPagePrivateUserService";
|
|
178
178
|
import StatusPagePrivateUserSessionService from "./StatusPagePrivateUserSessionService";
|
|
179
179
|
import StatusPageResourceService from "./StatusPageResourceService";
|
|
180
|
+
import StatusPageMonitorRuleService from "./StatusPageMonitorRuleService";
|
|
180
181
|
// Status Page
|
|
181
182
|
import StatusPageService from "./StatusPageService";
|
|
182
183
|
import StatusPageSsoService from "./StatusPageSsoService";
|
|
@@ -438,6 +439,7 @@ const services: Array<BaseService> = [
|
|
|
438
439
|
StatusPagePrivateUserService,
|
|
439
440
|
StatusPagePrivateUserSessionService,
|
|
440
441
|
StatusPageResourceService,
|
|
442
|
+
StatusPageMonitorRuleService,
|
|
441
443
|
StatusPageService,
|
|
442
444
|
StatusPageSsoService,
|
|
443
445
|
StatusPageOidcService,
|
|
@@ -5,6 +5,7 @@ import Model from "../../Models/DatabaseModels/IoTFleet";
|
|
|
5
5
|
import Label from "../../Models/DatabaseModels/Label";
|
|
6
6
|
import { OnCreate } from "../Types/Database/Hooks";
|
|
7
7
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
8
|
+
import ResourceHeartbeat from "../Utils/Telemetry/ResourceHeartbeat";
|
|
8
9
|
import ObjectID from "../../Types/ObjectID";
|
|
9
10
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
10
11
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -173,7 +174,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
173
174
|
onlineDeviceCount?: number | undefined;
|
|
174
175
|
},
|
|
175
176
|
): Promise<void> {
|
|
176
|
-
const cacheKey: string = fleetId.toString();
|
|
177
177
|
const extrasFingerprint: string = crypto
|
|
178
178
|
.createHash("sha1")
|
|
179
179
|
.update(
|
|
@@ -185,34 +185,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
185
185
|
)
|
|
186
186
|
.digest("hex");
|
|
187
187
|
|
|
188
|
-
let cached: string | null = null;
|
|
189
|
-
try {
|
|
190
|
-
cached = await GlobalCache.getString(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
191
|
-
} catch {
|
|
192
|
-
/*
|
|
193
|
-
* Cache unavailable — fail open and refresh lastSeenAt anyway. A
|
|
194
|
-
* cache error must never skip the DB write below, otherwise the
|
|
195
|
-
* resource is wrongly marked "disconnected" while telemetry is
|
|
196
|
-
* still flowing. Mirrors shouldRunMaintenance's fail-open stance.
|
|
197
|
-
*/
|
|
198
|
-
cached = null;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (cached === extrasFingerprint) {
|
|
202
|
-
return; // same data was written recently
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
try {
|
|
206
|
-
await GlobalCache.setString(
|
|
207
|
-
LAST_SEEN_CACHE_NAMESPACE,
|
|
208
|
-
cacheKey,
|
|
209
|
-
extrasFingerprint,
|
|
210
|
-
{ expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
|
|
211
|
-
);
|
|
212
|
-
} catch {
|
|
213
|
-
// Best-effort throttle write; proceed with the DB update regardless.
|
|
214
|
-
}
|
|
215
|
-
|
|
216
188
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
217
189
|
const liveness: any = {
|
|
218
190
|
lastSeenAt: OneUptimeDate.getCurrentDate(),
|
|
@@ -220,67 +192,35 @@ export class Service extends DatabaseService<Model> {
|
|
|
220
192
|
};
|
|
221
193
|
|
|
222
194
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
223
|
-
const
|
|
195
|
+
const metadata: any = {};
|
|
224
196
|
|
|
225
197
|
if (extra?.agentVersion) {
|
|
226
|
-
|
|
198
|
+
metadata.agentVersion = extra.agentVersion;
|
|
227
199
|
}
|
|
228
200
|
// Counts: 0 is a legitimate value — gate on undefined, not falsiness.
|
|
229
201
|
if (extra?.deviceCount !== undefined) {
|
|
230
|
-
|
|
202
|
+
metadata.deviceCount = extra.deviceCount;
|
|
231
203
|
}
|
|
232
204
|
if (extra?.onlineDeviceCount !== undefined) {
|
|
233
|
-
|
|
205
|
+
metadata.onlineDeviceCount = extra.onlineDeviceCount;
|
|
234
206
|
}
|
|
235
207
|
|
|
236
208
|
/*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
* Collector-supplied strings are clamped to their declared column
|
|
242
|
-
* widths inside updateColumnsByIdWithoutHooks — see
|
|
243
|
-
* DatabaseService.truncateStringColumnsToMaxLength.
|
|
209
|
+
* One gated, non-blocking heartbeat write. The gates, the fail-open /
|
|
210
|
+
* fail-closed split and the liveness-only fallback all live in
|
|
211
|
+
* ResourceHeartbeat — see there for why this row's throttle used to
|
|
212
|
+
* provide no throttling at all.
|
|
244
213
|
*/
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
* reject the statement, lastSeenAt silently stops advancing and
|
|
256
|
-
* markDisconnectedFleets flips a perfectly healthy IoT fleet to
|
|
257
|
-
* "disconnected" 15 minutes later — with telemetry still arriving the
|
|
258
|
-
* whole time. That was issue #3006 on the Host path (a host.ip list
|
|
259
|
-
* longer than the then-varchar(500) column). Retry with liveness only
|
|
260
|
-
* so the enrichment is what gets dropped, never the heartbeat.
|
|
261
|
-
*/
|
|
262
|
-
logger.warn(
|
|
263
|
-
`IoTFleetService.updateLastSeen: metadata write failed for IoT fleet ${fleetId.toString()}, falling back to a liveness-only update: ${
|
|
264
|
-
err instanceof Error ? err.message : String(err)
|
|
265
|
-
}`,
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
/*
|
|
269
|
-
* The throttle fingerprint was already stored, so without this the
|
|
270
|
-
* next batch would short-circuit on a cache hit and skip the retry
|
|
271
|
-
* for the rest of the window.
|
|
272
|
-
*/
|
|
273
|
-
try {
|
|
274
|
-
await GlobalCache.deleteKey(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
275
|
-
} catch {
|
|
276
|
-
// Best-effort; the fallback write below is what actually matters.
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
280
|
-
id: fleetId,
|
|
281
|
-
data: liveness,
|
|
282
|
-
});
|
|
283
|
-
}
|
|
214
|
+
await ResourceHeartbeat.write({
|
|
215
|
+
service: this,
|
|
216
|
+
id: fleetId,
|
|
217
|
+
cacheNamespace: LAST_SEEN_CACHE_NAMESPACE,
|
|
218
|
+
throttleInSeconds: LAST_SEEN_THROTTLE_SECONDS,
|
|
219
|
+
liveness: liveness,
|
|
220
|
+
metadata: metadata,
|
|
221
|
+
fingerprint: extrasFingerprint,
|
|
222
|
+
describe: `iot fleet ${fleetId.toString()}`,
|
|
223
|
+
});
|
|
284
224
|
}
|
|
285
225
|
|
|
286
226
|
/**
|