@oneuptime/common 11.5.11 → 11.5.13
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/NetworkFlow.ts +12 -1
- package/Models/DatabaseModels/AIInsight.ts +30 -0
- package/Models/DatabaseModels/Project.ts +30 -0
- package/Models/DatabaseModels/TelemetryException.ts +128 -0
- package/Server/API/AIAgentDataAPI.ts +129 -5
- package/Server/API/AIInvestigationAPI.ts +87 -0
- package/Server/API/StatusPageAPI.ts +14 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784640000000-AddExceptionTriageAndPrivacyColumns.ts +56 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -2
- package/Server/Services/AIRunService.ts +8 -0
- package/Server/Services/IncidentService.ts +62 -67
- package/Server/Services/MonitorGroupService.ts +15 -2
- package/Server/Services/MonitorService.ts +91 -3
- package/Server/Services/MonitorStatusTimelineService.ts +285 -100
- package/Server/Services/StatusPageService.ts +59 -34
- package/Server/Services/TelemetryExceptionService.ts +320 -24
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +15 -4
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +15 -4
- package/Server/Utils/AI/SRE/Insights/InsightScanner.ts +222 -24
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +225 -9
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +39 -0
- package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +114 -0
- package/Server/Utils/Monitor/MonitorResource.ts +43 -14
- package/Server/Utils/Monitor/MonitorStatusTimeline.ts +32 -7
- package/Server/Utils/Monitor/MonitorStatusTimelineReconciler.ts +362 -0
- package/Server/Utils/Telemetry/ExceptionSanitizer.ts +222 -0
- package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +235 -0
- package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +205 -1
- package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +150 -141
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +277 -1
- package/Tests/Server/Utils/ExceptionSanitizer.test.ts +70 -0
- package/Tests/Server/Utils/InsightTriageClassification.test.ts +57 -0
- package/Tests/Server/Utils/Monitor/MonitorStatusTimelineReconciler.test.ts +555 -0
- package/Tests/Server/Utils/TelemetryImprovementTaskTrigger.test.ts +141 -0
- package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +216 -0
- package/Tests/Types/Database/GreaterThan.test.ts +5 -1
- package/Tests/Types/Database/GreaterThanOrEqual.test.ts +5 -1
- package/Tests/Types/Database/GreaterThanOrNull.test.ts +24 -1
- package/Tests/Types/Database/LessThan.test.ts +5 -1
- package/Tests/Types/Database/LessThanOrEqual.test.ts +24 -1
- package/Tests/Types/Database/LessThanOrNull.test.ts +5 -1
- package/Tests/UI/Components/ModelTableSelectFromColumns.test.ts +259 -0
- package/Tests/Utils/Uptime/UptimeUtil.test.ts +726 -0
- package/Types/AI/CodeFixTaskContext.ts +6 -0
- package/Types/AI/CodeFixTaskType.ts +38 -1
- package/Types/AI/ExceptionAIClassification.ts +27 -0
- package/Types/BaseDatabase/GreaterThan.ts +8 -1
- package/Types/BaseDatabase/GreaterThanOrEqual.ts +8 -1
- package/Types/BaseDatabase/GreaterThanOrNull.ts +9 -1
- package/Types/BaseDatabase/LessThan.ts +8 -1
- package/Types/BaseDatabase/LessThanOrEqual.ts +9 -1
- package/Types/BaseDatabase/LessThanOrNull.ts +8 -1
- package/Types/Log/LogScrubPatternType.ts +7 -0
- package/Types/Trace/TraceScrubPatternType.ts +7 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +15 -46
- package/UI/Components/ModelTable/SelectFromColumns.ts +129 -0
- package/Utils/StatusPage/ResourceUptime.ts +11 -1
- package/Utils/Uptime/UptimeUtil.ts +142 -36
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js +12 -1
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AIInsight.js +31 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +31 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +134 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +97 -8
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +55 -0
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +12 -2
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784640000000-AddExceptionTriageAndPrivacyColumns.js +33 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784640000000-AddExceptionTriageAndPrivacyColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -2
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +9 -2
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +47 -56
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/MonitorGroupService.js +15 -2
- package/build/dist/Server/Services/MonitorGroupService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +66 -3
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +244 -102
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +57 -33
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryExceptionService.js +263 -22
- package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +12 -4
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +12 -4
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js +193 -22
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightScanner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +178 -9
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +37 -0
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +98 -0
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +34 -12
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +25 -8
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimelineReconciler.js +268 -0
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimelineReconciler.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js +149 -0
- package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskType.js +38 -1
- package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -1
- package/build/dist/Types/AI/ExceptionAIClassification.js +28 -0
- package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -0
- package/build/dist/Types/BaseDatabase/GreaterThan.js +8 -1
- package/build/dist/Types/BaseDatabase/GreaterThan.js.map +1 -1
- package/build/dist/Types/BaseDatabase/GreaterThanOrEqual.js +8 -1
- package/build/dist/Types/BaseDatabase/GreaterThanOrEqual.js.map +1 -1
- package/build/dist/Types/BaseDatabase/GreaterThanOrNull.js +9 -1
- package/build/dist/Types/BaseDatabase/GreaterThanOrNull.js.map +1 -1
- package/build/dist/Types/BaseDatabase/LessThan.js +8 -1
- package/build/dist/Types/BaseDatabase/LessThan.js.map +1 -1
- package/build/dist/Types/BaseDatabase/LessThanOrEqual.js +9 -1
- package/build/dist/Types/BaseDatabase/LessThanOrEqual.js.map +1 -1
- package/build/dist/Types/BaseDatabase/LessThanOrNull.js +8 -1
- package/build/dist/Types/BaseDatabase/LessThanOrNull.js.map +1 -1
- package/build/dist/Types/Log/LogScrubPatternType.js +7 -0
- package/build/dist/Types/Log/LogScrubPatternType.js.map +1 -1
- package/build/dist/Types/Trace/TraceScrubPatternType.js +7 -0
- package/build/dist/Types/Trace/TraceScrubPatternType.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +12 -37
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/SelectFromColumns.js +82 -0
- package/build/dist/UI/Components/ModelTable/SelectFromColumns.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceUptime.js +4 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/Uptime/UptimeUtil.js +86 -33
- package/build/dist/Utils/Uptime/UptimeUtil.js.map +1 -1
- package/package.json +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784401962564-MigrationName.ts +0 -101
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784401962564-MigrationName.js +0 -40
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784401962564-MigrationName.js.map +0 -1
|
@@ -285,8 +285,19 @@ export default class NetworkFlow extends AnalyticsBaseModel {
|
|
|
285
285
|
* (a retentionDate column computed at ingest, like Log/Metric) is
|
|
286
286
|
* the phase-2 follow-up. Keyed on server-assigned ingestedAt so a
|
|
287
287
|
* device with a wrong clock cannot make rows expire early.
|
|
288
|
+
*
|
|
289
|
+
* toDateTime() is NOT redundant: ingestedAt is DateTime64(9), so
|
|
290
|
+
* `ingestedAt + INTERVAL 30 DAY` stays DateTime64(9), and a TTL
|
|
291
|
+
* expression must evaluate to Date or DateTime. ClickHouse only began
|
|
292
|
+
* accepting DateTime64 there in 25.x; on 24.x it fails the CREATE with
|
|
293
|
+
* BAD_TTL_EXPRESSION, which aborts the whole boot schema-sync (it has
|
|
294
|
+
* no per-table error handling) and takes every table registered after
|
|
295
|
+
* this one down with it. The Helm chart ships `tag: latest` but tells
|
|
296
|
+
* operators to pin for production, so older servers are supported and
|
|
297
|
+
* this must stay version-portable. Narrowing to second precision is
|
|
298
|
+
* lossless for a 30-day retention window.
|
|
288
299
|
*/
|
|
289
|
-
ttlExpression: "ingestedAt + INTERVAL 30 DAY DELETE",
|
|
300
|
+
ttlExpression: "toDateTime(ingestedAt) + INTERVAL 30 DAY DELETE",
|
|
290
301
|
defaultSortColumn: "flowStartAt",
|
|
291
302
|
});
|
|
292
303
|
}
|
|
@@ -205,6 +205,36 @@ export default class AIInsight extends BaseModel {
|
|
|
205
205
|
})
|
|
206
206
|
public severity?: AIInsightSeverity = undefined;
|
|
207
207
|
|
|
208
|
+
/*
|
|
209
|
+
* Triage verdict (ExceptionAIClassification values) written by the
|
|
210
|
+
* insight triage runner. Null until triage completes. The automatic
|
|
211
|
+
* fix lane only opens pull requests for insights triaged as
|
|
212
|
+
* code-fault — see InsightScanner / InsightFixRouting.
|
|
213
|
+
*/
|
|
214
|
+
@ColumnAccessControl({
|
|
215
|
+
create: [],
|
|
216
|
+
read: [
|
|
217
|
+
Permission.ProjectOwner,
|
|
218
|
+
Permission.ProjectAdmin,
|
|
219
|
+
Permission.ProjectMember,
|
|
220
|
+
],
|
|
221
|
+
update: [],
|
|
222
|
+
})
|
|
223
|
+
@TableColumn({
|
|
224
|
+
required: false,
|
|
225
|
+
type: TableColumnType.ShortText,
|
|
226
|
+
title: "Classification",
|
|
227
|
+
description:
|
|
228
|
+
"AI triage verdict: code-fault, user-error, expected-denial, infrastructure or unknown. Automatic fix pull requests are only opened for code-fault.",
|
|
229
|
+
canReadOnRelationQuery: true,
|
|
230
|
+
})
|
|
231
|
+
@Column({
|
|
232
|
+
nullable: true,
|
|
233
|
+
type: ColumnType.ShortText,
|
|
234
|
+
length: ColumnLength.ShortText,
|
|
235
|
+
})
|
|
236
|
+
public classification?: string = undefined;
|
|
237
|
+
|
|
208
238
|
/*
|
|
209
239
|
* The detector's stable dedupe key for this finding (e.g.
|
|
210
240
|
* "new-exception:<telemetryExceptionId>"). The scanner refreshes the
|
|
@@ -1599,6 +1599,36 @@ export default class Project extends TenantModel {
|
|
|
1599
1599
|
})
|
|
1600
1600
|
public enableInsightFixTasks?: boolean = undefined;
|
|
1601
1601
|
|
|
1602
|
+
@ColumnAccessControl({
|
|
1603
|
+
create: [],
|
|
1604
|
+
read: [
|
|
1605
|
+
Permission.ProjectOwner,
|
|
1606
|
+
Permission.ProjectAdmin,
|
|
1607
|
+
Permission.ProjectMember,
|
|
1608
|
+
Permission.Viewer,
|
|
1609
|
+
Permission.ReadProject,
|
|
1610
|
+
Permission.UnAuthorizedSsoUser,
|
|
1611
|
+
Permission.ProjectUser,
|
|
1612
|
+
],
|
|
1613
|
+
update: [Permission.ProjectOwner, Permission.ProjectAdmin],
|
|
1614
|
+
})
|
|
1615
|
+
@TableColumn({
|
|
1616
|
+
required: true,
|
|
1617
|
+
isDefaultValueColumn: true,
|
|
1618
|
+
type: TableColumnType.Boolean,
|
|
1619
|
+
title: "Auto Archive Non-Actionable Exceptions",
|
|
1620
|
+
description:
|
|
1621
|
+
"When enabled, exception groups the AI triage classifies as expected denials (auth failures, plan/paywall rejections, scanner probes tripping intentional validation) are automatically archived so they stop surfacing in the unresolved list and never queue AI fix tasks. Groups classified as user errors or infrastructure conditions are NOT auto-archived — only clear expected denials are. Archiving is reversible from the Archived tab.",
|
|
1622
|
+
defaultValue: false,
|
|
1623
|
+
example: true,
|
|
1624
|
+
})
|
|
1625
|
+
@Column({
|
|
1626
|
+
nullable: false,
|
|
1627
|
+
default: false,
|
|
1628
|
+
type: ColumnType.Boolean,
|
|
1629
|
+
})
|
|
1630
|
+
public autoArchiveNonActionableExceptions?: boolean = undefined;
|
|
1631
|
+
|
|
1602
1632
|
@ColumnAccessControl({
|
|
1603
1633
|
create: [],
|
|
1604
1634
|
read: [
|
|
@@ -1281,4 +1281,132 @@ export default class TelemetryException extends DatabaseBaseModel {
|
|
|
1281
1281
|
length: ColumnLength.LongText,
|
|
1282
1282
|
})
|
|
1283
1283
|
public environment?: string = undefined;
|
|
1284
|
+
|
|
1285
|
+
@ColumnAccessControl({
|
|
1286
|
+
/*
|
|
1287
|
+
* Server-written only (isRoot bypasses column ACL): this is derived
|
|
1288
|
+
* state maintained by ingest / triage / the PR-state sync — a client
|
|
1289
|
+
* PATCH must not be able to set it (the value flows into LLM prompts
|
|
1290
|
+
* and public PR text, and it gates the automatic fix lane).
|
|
1291
|
+
*/
|
|
1292
|
+
create: [],
|
|
1293
|
+
read: [
|
|
1294
|
+
Permission.ProjectOwner,
|
|
1295
|
+
Permission.ProjectAdmin,
|
|
1296
|
+
Permission.ProjectMember,
|
|
1297
|
+
Permission.Viewer,
|
|
1298
|
+
Permission.TelemetryAdmin,
|
|
1299
|
+
Permission.TelemetryMember,
|
|
1300
|
+
Permission.TelemetryViewer,
|
|
1301
|
+
Permission.ReadTelemetryException,
|
|
1302
|
+
],
|
|
1303
|
+
update: [],
|
|
1304
|
+
})
|
|
1305
|
+
/*
|
|
1306
|
+
* Sticky rollup of the OTel exception.escaped flag: true once ANY
|
|
1307
|
+
* occurrence of this group escaped its span scope (was unhandled).
|
|
1308
|
+
* Maintained by the ingest upsert with `unhandled OR EXCLUDED.unhandled`
|
|
1309
|
+
* — a group never flips back to handled. Handled exceptions are usually
|
|
1310
|
+
* expected/operational errors, which is a key signal for deciding
|
|
1311
|
+
* whether an AI fix PR is warranted.
|
|
1312
|
+
*/
|
|
1313
|
+
@TableColumn({
|
|
1314
|
+
title: "Unhandled",
|
|
1315
|
+
description:
|
|
1316
|
+
"True when at least one occurrence of this exception escaped its span scope (was unhandled, per OTel exception.escaped)",
|
|
1317
|
+
isDefaultValueColumn: true,
|
|
1318
|
+
required: true,
|
|
1319
|
+
type: TableColumnType.Boolean,
|
|
1320
|
+
defaultValue: false,
|
|
1321
|
+
example: true,
|
|
1322
|
+
})
|
|
1323
|
+
@Column({
|
|
1324
|
+
type: ColumnType.Boolean,
|
|
1325
|
+
nullable: false,
|
|
1326
|
+
unique: false,
|
|
1327
|
+
default: false,
|
|
1328
|
+
})
|
|
1329
|
+
public unhandled?: boolean = undefined;
|
|
1330
|
+
|
|
1331
|
+
@ColumnAccessControl({
|
|
1332
|
+
/*
|
|
1333
|
+
* Server-written only (isRoot bypasses column ACL): this is derived
|
|
1334
|
+
* state maintained by ingest / triage / the PR-state sync — a client
|
|
1335
|
+
* PATCH must not be able to set it (the value flows into LLM prompts
|
|
1336
|
+
* and public PR text, and it gates the automatic fix lane).
|
|
1337
|
+
*/
|
|
1338
|
+
create: [],
|
|
1339
|
+
read: [
|
|
1340
|
+
Permission.ProjectOwner,
|
|
1341
|
+
Permission.ProjectAdmin,
|
|
1342
|
+
Permission.ProjectMember,
|
|
1343
|
+
Permission.Viewer,
|
|
1344
|
+
Permission.TelemetryAdmin,
|
|
1345
|
+
Permission.TelemetryMember,
|
|
1346
|
+
Permission.TelemetryViewer,
|
|
1347
|
+
Permission.ReadTelemetryException,
|
|
1348
|
+
],
|
|
1349
|
+
update: [],
|
|
1350
|
+
})
|
|
1351
|
+
/*
|
|
1352
|
+
* Verdict of the AI insight triage for this exception group: is this a
|
|
1353
|
+
* code defect the AI should try to fix, an expected end-user error, an
|
|
1354
|
+
* expected denial (auth/paywall/probe), or an infrastructure condition?
|
|
1355
|
+
* Values come from ExceptionAIClassification. Written by the triage
|
|
1356
|
+
* runner; the automatic fix lane only opens PRs for CodeFault groups.
|
|
1357
|
+
*/
|
|
1358
|
+
@TableColumn({
|
|
1359
|
+
title: "AI Classification",
|
|
1360
|
+
description:
|
|
1361
|
+
"AI triage verdict for this exception group (code-fault, user-error, expected-denial, infrastructure)",
|
|
1362
|
+
required: false,
|
|
1363
|
+
type: TableColumnType.ShortText,
|
|
1364
|
+
example: "code-fault",
|
|
1365
|
+
})
|
|
1366
|
+
@Column({
|
|
1367
|
+
nullable: true,
|
|
1368
|
+
type: ColumnType.ShortText,
|
|
1369
|
+
length: ColumnLength.ShortText,
|
|
1370
|
+
})
|
|
1371
|
+
public aiClassification?: string = undefined;
|
|
1372
|
+
|
|
1373
|
+
@ColumnAccessControl({
|
|
1374
|
+
/*
|
|
1375
|
+
* Server-written only (isRoot bypasses column ACL): this is derived
|
|
1376
|
+
* state maintained by ingest / triage / the PR-state sync — a client
|
|
1377
|
+
* PATCH must not be able to set it (the value flows into LLM prompts
|
|
1378
|
+
* and public PR text, and it gates the automatic fix lane).
|
|
1379
|
+
*/
|
|
1380
|
+
create: [],
|
|
1381
|
+
read: [
|
|
1382
|
+
Permission.ProjectOwner,
|
|
1383
|
+
Permission.ProjectAdmin,
|
|
1384
|
+
Permission.ProjectMember,
|
|
1385
|
+
Permission.Viewer,
|
|
1386
|
+
Permission.TelemetryAdmin,
|
|
1387
|
+
Permission.TelemetryMember,
|
|
1388
|
+
Permission.TelemetryViewer,
|
|
1389
|
+
Permission.ReadTelemetryException,
|
|
1390
|
+
],
|
|
1391
|
+
update: [],
|
|
1392
|
+
})
|
|
1393
|
+
/*
|
|
1394
|
+
* Stamped when a human closes an AI-authored fix PR for this exception
|
|
1395
|
+
* without merging it — the strongest "the AI fix was not wanted" signal.
|
|
1396
|
+
* The automatic fix lane skips groups carrying this stamp; a human
|
|
1397
|
+
* clicking "Fix with AI" on the exception page clears it and retries.
|
|
1398
|
+
*/
|
|
1399
|
+
@TableColumn({
|
|
1400
|
+
title: "AI Fix Declined At",
|
|
1401
|
+
description:
|
|
1402
|
+
"Set when an AI-authored fix pull request for this exception was closed without merging; suppresses further automatic fix attempts",
|
|
1403
|
+
required: false,
|
|
1404
|
+
type: TableColumnType.Date,
|
|
1405
|
+
example: "2026-01-01T00:00:00.000Z",
|
|
1406
|
+
})
|
|
1407
|
+
@Column({
|
|
1408
|
+
nullable: true,
|
|
1409
|
+
type: ColumnType.Date,
|
|
1410
|
+
})
|
|
1411
|
+
public aiFixDeclinedAt?: Date = undefined;
|
|
1284
1412
|
}
|
|
@@ -43,6 +43,11 @@ import CodeFixTaskContext, {
|
|
|
43
43
|
PerformanceFinding,
|
|
44
44
|
} from "../../Types/AI/CodeFixTaskContext";
|
|
45
45
|
import SpanTreeAnalyzer from "../Utils/AI/PerfEvidence/SpanTreeAnalyzer";
|
|
46
|
+
import {
|
|
47
|
+
sanitizeExceptionMessage,
|
|
48
|
+
sanitizeStackTrace,
|
|
49
|
+
} from "../Utils/Telemetry/ExceptionSanitizer";
|
|
50
|
+
import ToolResultSerializer from "../Utils/AI/Toolbox/Serializer";
|
|
46
51
|
import OpenPullRequestCap, {
|
|
47
52
|
OpenPullRequestCapDecision,
|
|
48
53
|
} from "../Utils/AI/CodeFix/OpenPullRequestCap";
|
|
@@ -204,6 +209,7 @@ export default class AIAgentDataAPI {
|
|
|
204
209
|
stackTrace: true,
|
|
205
210
|
exceptionType: true,
|
|
206
211
|
fingerprint: true,
|
|
212
|
+
aiClassification: true,
|
|
207
213
|
primaryEntityId: true,
|
|
208
214
|
primaryEntityType: true,
|
|
209
215
|
},
|
|
@@ -221,7 +227,7 @@ export default class AIAgentDataAPI {
|
|
|
221
227
|
}
|
|
222
228
|
|
|
223
229
|
logger.debug(
|
|
224
|
-
`Exception details fetched: ${exception._id}
|
|
230
|
+
`Exception details fetched: ${exception._id}`,
|
|
225
231
|
getLogAttributesFromRequest(req as any),
|
|
226
232
|
);
|
|
227
233
|
|
|
@@ -245,13 +251,24 @@ export default class AIAgentDataAPI {
|
|
|
245
251
|
})
|
|
246
252
|
: null;
|
|
247
253
|
|
|
254
|
+
/*
|
|
255
|
+
* Sanitize at the choke point: everything the AI agent worker
|
|
256
|
+
* sees — and therefore everything that can end up in an LLM
|
|
257
|
+
* prompt, a public pull-request title/body, or a commit
|
|
258
|
+
* message — flows through this response. The message gets
|
|
259
|
+
* dynamic-token normalization + secret redaction; the stack
|
|
260
|
+
* trace gets redaction only, so file:line frames stay intact
|
|
261
|
+
* for the code agent.
|
|
262
|
+
*/
|
|
248
263
|
return Response.sendJsonObjectResponse(req, res, {
|
|
249
264
|
exception: {
|
|
250
265
|
id: exception._id?.toString(),
|
|
251
|
-
message: exception.message,
|
|
252
|
-
stackTrace: exception.stackTrace,
|
|
253
|
-
|
|
266
|
+
message: sanitizeExceptionMessage(exception.message || ""),
|
|
267
|
+
stackTrace: sanitizeStackTrace(exception.stackTrace || ""),
|
|
268
|
+
// Legacy pre-batch-upsert rows can carry NULL here.
|
|
269
|
+
exceptionType: exception.exceptionType || "",
|
|
254
270
|
fingerprint: exception.fingerprint,
|
|
271
|
+
aiClassification: exception.aiClassification || null,
|
|
255
272
|
},
|
|
256
273
|
service: exception.primaryEntityId
|
|
257
274
|
? {
|
|
@@ -518,6 +535,103 @@ export default class AIAgentDataAPI {
|
|
|
518
535
|
);
|
|
519
536
|
}
|
|
520
537
|
|
|
538
|
+
/*
|
|
539
|
+
* Service-scoped instrumentation recipes (ImproveLogging /
|
|
540
|
+
* ImproveTracing): the context is just the service — resolve the
|
|
541
|
+
* repository by service name (no stack trace) and hand the
|
|
542
|
+
* worker a short brief; the recipe's checklist lives in the
|
|
543
|
+
* worker's prompt.
|
|
544
|
+
*/
|
|
545
|
+
if (
|
|
546
|
+
taskType === CodeFixTaskType.ImproveLogging ||
|
|
547
|
+
taskType === CodeFixTaskType.ImproveTracing
|
|
548
|
+
) {
|
|
549
|
+
const taskContext: CodeFixTaskContext | undefined = run.taskContext;
|
|
550
|
+
const improvementServiceName: string =
|
|
551
|
+
taskContext?.serviceName || "";
|
|
552
|
+
|
|
553
|
+
if (!taskContext?.telemetryServiceId) {
|
|
554
|
+
return Response.sendErrorResponse(
|
|
555
|
+
req,
|
|
556
|
+
res,
|
|
557
|
+
new BadDataException(
|
|
558
|
+
"This telemetry-improvement task has no stored service context — the task has nothing to work from.",
|
|
559
|
+
),
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const pillar: string =
|
|
564
|
+
taskType === CodeFixTaskType.ImproveLogging
|
|
565
|
+
? "logging"
|
|
566
|
+
: "tracing";
|
|
567
|
+
const subjectTitle: string = improvementServiceName
|
|
568
|
+
? `Improve ${pillar} for ${improvementServiceName}`
|
|
569
|
+
: `Improve ${pillar}`;
|
|
570
|
+
|
|
571
|
+
const resolution: RepoResolution | null =
|
|
572
|
+
await CodeRepositoryService.resolveRepositoryForException({
|
|
573
|
+
projectId: run.projectId,
|
|
574
|
+
stackTrace: null,
|
|
575
|
+
serviceName: improvementServiceName || null,
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
const repository: CodeRepository | null = resolution
|
|
579
|
+
? await CodeRepositoryService.findOneById({
|
|
580
|
+
id: new ObjectID(resolution.codeRepositoryId),
|
|
581
|
+
select: {
|
|
582
|
+
_id: true,
|
|
583
|
+
name: true,
|
|
584
|
+
repositoryHostedAt: true,
|
|
585
|
+
organizationName: true,
|
|
586
|
+
repositoryName: true,
|
|
587
|
+
mainBranchName: true,
|
|
588
|
+
gitHubAppInstallationId: true,
|
|
589
|
+
},
|
|
590
|
+
props: { isRoot: true },
|
|
591
|
+
})
|
|
592
|
+
: null;
|
|
593
|
+
|
|
594
|
+
const basePayload: JSONObject = {
|
|
595
|
+
subjectType: "service",
|
|
596
|
+
subjectTitle,
|
|
597
|
+
analysisMarkdown: `OneUptime observes the telemetry of the service ${
|
|
598
|
+
improvementServiceName
|
|
599
|
+
? `"${improvementServiceName}"`
|
|
600
|
+
: "in this repository"
|
|
601
|
+
}. A user asked for its ${pillar} instrumentation to be improved — follow the task checklist in your instructions.`,
|
|
602
|
+
serviceName: improvementServiceName,
|
|
603
|
+
projectId: run.projectId.toString(),
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
if (!resolution || !repository) {
|
|
607
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
608
|
+
...basePayload,
|
|
609
|
+
repositories: [],
|
|
610
|
+
resolutionError:
|
|
611
|
+
"Could not resolve a repository for this task: no connected repository name matches the service and the project has more than one repository. Connect the right repository via the GitHub App, or rename one to match the service.",
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
616
|
+
...basePayload,
|
|
617
|
+
repositories: [
|
|
618
|
+
{
|
|
619
|
+
id: repository.id!.toString(),
|
|
620
|
+
name: repository.name || "",
|
|
621
|
+
repositoryHostedAt: repository.repositoryHostedAt || "",
|
|
622
|
+
organizationName: repository.organizationName || "",
|
|
623
|
+
repositoryName: repository.repositoryName || "",
|
|
624
|
+
mainBranchName: repository.mainBranchName || "main",
|
|
625
|
+
servicePathInRepository: resolution.servicePathInRepository,
|
|
626
|
+
gitHubAppInstallationId:
|
|
627
|
+
repository.gitHubAppInstallationId || null,
|
|
628
|
+
resolutionMethod: resolution.method,
|
|
629
|
+
resolutionEvidence: resolution.evidence,
|
|
630
|
+
},
|
|
631
|
+
],
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
|
|
521
635
|
/*
|
|
522
636
|
* Trace-evidence recipes (FixPerformance): everything the worker
|
|
523
637
|
* needs was captured into taskContext at trigger time — the spans
|
|
@@ -607,8 +721,10 @@ export default class AIAgentDataAPI {
|
|
|
607
721
|
const basePayload: JSONObject = {
|
|
608
722
|
subjectType: "trace",
|
|
609
723
|
subjectTitle: findings[0]!.headline,
|
|
610
|
-
|
|
724
|
+
// Redact before it can reach a prompt or PR body.
|
|
725
|
+
analysisMarkdown: ToolResultSerializer.redact(
|
|
611
726
|
SpanTreeAnalyzer.renderFindingsMarkdown(findings),
|
|
727
|
+
).text,
|
|
612
728
|
serviceName,
|
|
613
729
|
projectId: run.projectId.toString(),
|
|
614
730
|
traceId: taskContext.traceId,
|
|
@@ -788,6 +904,14 @@ export default class AIAgentDataAPI {
|
|
|
788
904
|
);
|
|
789
905
|
}
|
|
790
906
|
|
|
907
|
+
/*
|
|
908
|
+
* The analysis was written by the investigation LLM over
|
|
909
|
+
* redacted tool results, but quoted exception text can still
|
|
910
|
+
* carry secrets — sweep it again before it reaches the worker's
|
|
911
|
+
* prompt and the pull-request body.
|
|
912
|
+
*/
|
|
913
|
+
analysisMarkdown = ToolResultSerializer.redact(analysisMarkdown).text;
|
|
914
|
+
|
|
791
915
|
/*
|
|
792
916
|
* Resolve the repository WITHOUT a stack trace — these tasks have
|
|
793
917
|
* no exception, so only the name-match (against the subject's
|
|
@@ -31,6 +31,8 @@ import ServiceService from "../Services/ServiceService";
|
|
|
31
31
|
import SpanService from "../Services/SpanService";
|
|
32
32
|
import FixFromIncidentTaskTrigger from "../Utils/AI/SRE/FixFromIncidentTaskTrigger";
|
|
33
33
|
import FixPerformanceTaskTrigger from "../Utils/AI/SRE/FixPerformanceTaskTrigger";
|
|
34
|
+
import TelemetryImprovementTaskTrigger from "../Utils/AI/SRE/TelemetryImprovementTaskTrigger";
|
|
35
|
+
import CodeFixTaskType from "../../Types/AI/CodeFixTaskType";
|
|
34
36
|
import { AnalyzableSpan } from "../Utils/AI/PerfEvidence/SpanTreeAnalyzer";
|
|
35
37
|
|
|
36
38
|
const router: ExpressRouter = Express.getRouter();
|
|
@@ -575,4 +577,89 @@ router.post(
|
|
|
575
577
|
},
|
|
576
578
|
);
|
|
577
579
|
|
|
580
|
+
/*
|
|
581
|
+
* "Improve logging / tracing with AI" from a telemetry service's Logs or
|
|
582
|
+
* Traces page: gate and enqueue a service-scoped instrumentation-
|
|
583
|
+
* improvement CodeFix run (ImproveLogging / ImproveTracing). Human-
|
|
584
|
+
* triggered — the click is the gate; budget, repository and per-service
|
|
585
|
+
* dedupe are enforced in the trigger. Returns { aiRunId }.
|
|
586
|
+
*/
|
|
587
|
+
router.post(
|
|
588
|
+
"/ai-investigation/create-telemetry-improvement-task",
|
|
589
|
+
UserMiddleware.getUserMiddleware,
|
|
590
|
+
async (
|
|
591
|
+
req: ExpressRequest,
|
|
592
|
+
res: ExpressResponse,
|
|
593
|
+
next: NextFunction,
|
|
594
|
+
): Promise<void> => {
|
|
595
|
+
try {
|
|
596
|
+
const props: DatabaseCommonInteractionProps = await getLoggedInProps(req);
|
|
597
|
+
|
|
598
|
+
const projectId: ObjectID | undefined = props.tenantId;
|
|
599
|
+
|
|
600
|
+
if (!projectId) {
|
|
601
|
+
throw new BadDataException("A project scope is required.");
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const telemetryServiceIdParam: string | undefined = req.body[
|
|
605
|
+
"telemetryServiceId"
|
|
606
|
+
] as string | undefined;
|
|
607
|
+
|
|
608
|
+
if (!telemetryServiceIdParam) {
|
|
609
|
+
throw new BadDataException("telemetryServiceId is required.");
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
const rawTaskType: string | undefined = req.body["taskType"] as
|
|
613
|
+
| string
|
|
614
|
+
| undefined;
|
|
615
|
+
|
|
616
|
+
if (
|
|
617
|
+
rawTaskType !== CodeFixTaskType.ImproveLogging &&
|
|
618
|
+
rawTaskType !== CodeFixTaskType.ImproveTracing
|
|
619
|
+
) {
|
|
620
|
+
throw new BadDataException(
|
|
621
|
+
`taskType must be ${CodeFixTaskType.ImproveLogging} or ${CodeFixTaskType.ImproveTracing}.`,
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const telemetryServiceId: ObjectID = new ObjectID(
|
|
626
|
+
telemetryServiceIdParam,
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
/*
|
|
630
|
+
* Access check under the USER's permissions: the caller must be able
|
|
631
|
+
* to read the service they are asking the agent to instrument. The
|
|
632
|
+
* trigger re-reads as root afterwards.
|
|
633
|
+
*/
|
|
634
|
+
const service: Service | null = await ServiceService.findOneById({
|
|
635
|
+
id: telemetryServiceId,
|
|
636
|
+
select: { _id: true },
|
|
637
|
+
props: props,
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
if (!service) {
|
|
641
|
+
throw new BadDataException(
|
|
642
|
+
"Telemetry service not found (or you do not have access to it).",
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const run: AIRun =
|
|
647
|
+
await TelemetryImprovementTaskTrigger.createTelemetryImprovementTask({
|
|
648
|
+
projectId,
|
|
649
|
+
telemetryServiceId,
|
|
650
|
+
taskType: rawTaskType,
|
|
651
|
+
userId: props.userId!,
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
Response.sendJsonObjectResponse(req, res, {
|
|
655
|
+
aiRunId: run.id!.toString(),
|
|
656
|
+
});
|
|
657
|
+
return;
|
|
658
|
+
} catch (err) {
|
|
659
|
+
next(err);
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
},
|
|
663
|
+
);
|
|
664
|
+
|
|
578
665
|
export default router;
|
|
@@ -88,7 +88,7 @@ import StatusPageEventType from "../../Types/StatusPage/StatusPageEventType";
|
|
|
88
88
|
import StatusPageResourceUptimeUtil from "../../Utils/StatusPage/ResourceUptime";
|
|
89
89
|
import UptimePrecision from "../../Types/StatusPage/UptimePrecision";
|
|
90
90
|
import { Green } from "../../Types/BrandColors";
|
|
91
|
-
import UptimeUtil from "../../Utils/Uptime/UptimeUtil";
|
|
91
|
+
import UptimeUtil, { UptimeWindow } from "../../Utils/Uptime/UptimeUtil";
|
|
92
92
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
93
93
|
import URL from "../../Types/API/URL";
|
|
94
94
|
import SMS from "../../Types/SMS/SMS";
|
|
@@ -1265,6 +1265,17 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
1265
1265
|
const downtimeMonitorStatuses: Array<MonitorStatus> =
|
|
1266
1266
|
statusPage.downtimeMonitorStatuses || [];
|
|
1267
1267
|
|
|
1268
|
+
/*
|
|
1269
|
+
* this endpoint reports uptime over an explicit [startDate, endDate] range, so events
|
|
1270
|
+
* have to be clipped to it and the denominator has to be the range itself. Without
|
|
1271
|
+
* this an open (endsAt = null) row that started before the range contributes its
|
|
1272
|
+
* entire duration to the downtime total.
|
|
1273
|
+
*/
|
|
1274
|
+
const uptimeWindow: UptimeWindow = {
|
|
1275
|
+
startDate: startDate,
|
|
1276
|
+
endDate: endDate,
|
|
1277
|
+
};
|
|
1278
|
+
|
|
1268
1279
|
type ResourceUptime = {
|
|
1269
1280
|
statusPageResourceId: ObjectID;
|
|
1270
1281
|
uptimePercent: number | null;
|
|
@@ -1369,6 +1380,7 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
1369
1380
|
resourceStatusTimelines,
|
|
1370
1381
|
precision,
|
|
1371
1382
|
downtimeMonitorStatuses,
|
|
1383
|
+
uptimeWindow,
|
|
1372
1384
|
);
|
|
1373
1385
|
|
|
1374
1386
|
resourceUptime.uptimePercent = uptimePercent;
|
|
@@ -1419,6 +1431,7 @@ export default class StatusPageAPI extends BaseAPI<
|
|
|
1419
1431
|
resourceStatusTimelines,
|
|
1420
1432
|
precision,
|
|
1421
1433
|
downtimeMonitorStatuses,
|
|
1434
|
+
uptimeWindow,
|
|
1422
1435
|
);
|
|
1423
1436
|
|
|
1424
1437
|
resourceUptime.uptimePercent = uptimePercent;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* AI exception triage + privacy columns:
|
|
5
|
+
*
|
|
6
|
+
* - TelemetryException.unhandled: sticky rollup of OTel exception.escaped
|
|
7
|
+
* (maintained by the ingest upsert with OR semantics).
|
|
8
|
+
* - TelemetryException.aiClassification: triage verdict (code-fault,
|
|
9
|
+
* user-error, expected-denial, infrastructure, unknown).
|
|
10
|
+
* - TelemetryException.aiFixDeclinedAt: stamped when a human closes an
|
|
11
|
+
* AI fix PR without merging; suppresses further automatic fix attempts.
|
|
12
|
+
* - AIInsight.classification: the same triage verdict on the insight row.
|
|
13
|
+
* - Project.autoArchiveNonActionableExceptions: opt-in auto-archive of
|
|
14
|
+
* expected-denial exception groups.
|
|
15
|
+
*/
|
|
16
|
+
export class AddExceptionTriageAndPrivacyColumns1784640000000
|
|
17
|
+
implements MigrationInterface
|
|
18
|
+
{
|
|
19
|
+
public name: string = "AddExceptionTriageAndPrivacyColumns1784640000000";
|
|
20
|
+
|
|
21
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "TelemetryException" ADD "unhandled" boolean NOT NULL DEFAULT false`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`ALTER TABLE "TelemetryException" ADD "aiClassification" character varying(100)`,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`ALTER TABLE "TelemetryException" ADD "aiFixDeclinedAt" TIMESTAMP WITH TIME ZONE`,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`ALTER TABLE "AIInsight" ADD "classification" character varying(100)`,
|
|
33
|
+
);
|
|
34
|
+
await queryRunner.query(
|
|
35
|
+
`ALTER TABLE "Project" ADD "autoArchiveNonActionableExceptions" boolean NOT NULL DEFAULT false`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
40
|
+
await queryRunner.query(
|
|
41
|
+
`ALTER TABLE "Project" DROP COLUMN "autoArchiveNonActionableExceptions"`,
|
|
42
|
+
);
|
|
43
|
+
await queryRunner.query(
|
|
44
|
+
`ALTER TABLE "AIInsight" DROP COLUMN "classification"`,
|
|
45
|
+
);
|
|
46
|
+
await queryRunner.query(
|
|
47
|
+
`ALTER TABLE "TelemetryException" DROP COLUMN "aiFixDeclinedAt"`,
|
|
48
|
+
);
|
|
49
|
+
await queryRunner.query(
|
|
50
|
+
`ALTER TABLE "TelemetryException" DROP COLUMN "aiClassification"`,
|
|
51
|
+
);
|
|
52
|
+
await queryRunner.query(
|
|
53
|
+
`ALTER TABLE "TelemetryException" DROP COLUMN "unhandled"`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -461,7 +461,7 @@ import { AddNetworkDeviceInventoryAndDiscoverySchedule1784211212164 } from "./17
|
|
|
461
461
|
import { AddEnterpriseLicenseNotificationColumns1784218257664 } from "./1784218257664-AddEnterpriseLicenseNotificationColumns";
|
|
462
462
|
import { AddAttributionColumnsToUserAndProject1784293516000 } from "./1784293516000-AddAttributionColumnsToUserAndProject";
|
|
463
463
|
import { AddMarketingConversionTable1784298000000 } from "./1784298000000-AddMarketingConversionTable";
|
|
464
|
-
import {
|
|
464
|
+
import { AddExceptionTriageAndPrivacyColumns1784640000000 } from "./1784640000000-AddExceptionTriageAndPrivacyColumns";
|
|
465
465
|
|
|
466
466
|
export default [
|
|
467
467
|
InitialMigration,
|
|
@@ -927,5 +927,5 @@ export default [
|
|
|
927
927
|
AddEnterpriseLicenseNotificationColumns1784218257664,
|
|
928
928
|
AddAttributionColumnsToUserAndProject1784293516000,
|
|
929
929
|
AddMarketingConversionTable1784298000000,
|
|
930
|
-
|
|
930
|
+
AddExceptionTriageAndPrivacyColumns1784640000000,
|
|
931
931
|
];
|
|
@@ -187,6 +187,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
187
187
|
run.triggeredByIncidentId || run.triggeredByAlertId
|
|
188
188
|
? null
|
|
189
189
|
: "Queued code-fix run has no incident or alert subject.";
|
|
190
|
+
} else if (
|
|
191
|
+
run.codeFixTaskType === CodeFixTaskType.ImproveLogging ||
|
|
192
|
+
run.codeFixTaskType === CodeFixTaskType.ImproveTracing
|
|
193
|
+
) {
|
|
194
|
+
// Service-scoped instrumentation recipes carry the service instead.
|
|
195
|
+
missingContextMessage = run.taskContext?.telemetryServiceId
|
|
196
|
+
? null
|
|
197
|
+
: "Queued code-fix run has no telemetry service in its task context.";
|
|
190
198
|
} else {
|
|
191
199
|
missingContextMessage = run.taskContext?.traceId
|
|
192
200
|
? null
|