-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: add OTel events and metrics for agentic edit quality signals #4794
Changes from all commits
6ffaa40
292b7d5
717a6c1
32ff490
857935c
8a59a7d
a6be15a
e066eed
5493cca
9bd44fe
bb49464
7f0b9ca
66f66d9
ed254c9
c57e4ae
b0c2c5e
5bb5fcb
8ea0262
de00d09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,6 +15,8 @@ import { GithubRepoId, IGitService } from '../../../platform/git/common/gitServi | |||||||
| import { derivePullRequestState, PullRequestSearchItem, SessionInfo } from '../../../platform/github/common/githubAPI'; | ||||||||
| import { AuthOptions, CCAEnabledResult, IGithubRepositoryService, IOctoKitService, JobInfo, RemoteAgentJobResponse } from '../../../platform/github/common/githubService'; | ||||||||
| import { ILogService } from '../../../platform/log/common/logService'; | ||||||||
| import { GenAiMetrics } from '../../../platform/otel/common/genAiMetrics'; | ||||||||
| import { IOTelService } from '../../../platform/otel/common/otelService'; | ||||||||
| import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService'; | ||||||||
| import { ITelemetryService } from '../../../platform/telemetry/common/telemetry'; | ||||||||
| import { DeferredPromise, retry, RunOnceScheduler } from '../../../util/vs/base/common/async'; | ||||||||
|
|
@@ -307,6 +309,7 @@ export class CopilotCloudSessionsProvider extends Disposable implements vscode.C | |||||||
| @IChatDelegationSummaryService private readonly _chatDelegationSummaryService: IChatDelegationSummaryService, | ||||||||
| @IExperimentationService private readonly _experimentationService: IExperimentationService, | ||||||||
| @IDomainService private readonly _domainService: IDomainService, | ||||||||
| @IOTelService private readonly _otelService: IOTelService, | ||||||||
| ) { | ||||||||
| super(); | ||||||||
| this.registerCommands(); | ||||||||
|
|
@@ -1962,6 +1965,7 @@ export class CopilotCloudSessionsProvider extends Disposable implements vscode.C | |||||||
| partnerAgent: partnerAgent?.name ?? 'unknown', | ||||||||
| model: modelId ?? 'unknown' | ||||||||
| }); | ||||||||
|
||||||||
| }); | |
| }); | |
| GenAiMetrics.emitCloudSessionInvokeEvent(this._otelService, request.id, modelId ?? 'unknown', partnerAgent?.name ?? 'unknown'); |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,8 +10,9 @@ import { EditSurvivalResult } from '../../../platform/editSurvivalTracking/commo | |||||||
| import { ILanguageDiagnosticsService } from '../../../platform/languages/common/languageDiagnosticsService'; | ||||||||
| import { IMultiFileEditInternalTelemetryService } from '../../../platform/multiFileEdit/common/multiFileEditQualityTelemetry'; | ||||||||
| import { INotebookService } from '../../../platform/notebook/common/notebookService'; | ||||||||
| import { GenAiMetrics } from '../../../platform/otel/common/genAiMetrics'; | ||||||||
| import type { EditOutcome } from '../../../platform/otel/common/genAiAttributes'; | ||||||||
| import { emitEditFeedbackEvent, emitEditHunkActionEvent, emitEditSurvivalEvent, emitInlineDoneEvent, emitUserFeedbackEvent } from '../../../platform/otel/common/genAiEvents'; | ||||||||
| import { GenAiMetrics } from '../../../platform/otel/common/genAiMetrics'; | ||||||||
| import { IOTelService } from '../../../platform/otel/common/otelService'; | ||||||||
| import { ISurveyService } from '../../../platform/survey/common/surveyService'; | ||||||||
| import { ITelemetryService, TelemetryEventMeasurements, TelemetryEventProperties } from '../../../platform/telemetry/common/telemetry'; | ||||||||
|
|
@@ -91,6 +92,7 @@ export class UserFeedbackService implements IUserFeedbackService { | |||||||
| characterCount: e.action.copiedCharacters, | ||||||||
| lineCount: e.action.copiedText.split('\n').length, | ||||||||
| }); | ||||||||
| GenAiMetrics.incrementUserActionCount(this.otelService, 'copy'); | ||||||||
| break; | ||||||||
| case 'insert': | ||||||||
| /* __GDPR__ | ||||||||
|
|
@@ -116,6 +118,7 @@ export class UserFeedbackService implements IUserFeedbackService { | |||||||
| characterCount: e.action.totalCharacters, | ||||||||
| newFile: e.action.newFile ? 1 : 0 | ||||||||
| }); | ||||||||
| GenAiMetrics.incrementUserActionCount(this.otelService, 'insert'); | ||||||||
| break; | ||||||||
| case 'followUp': | ||||||||
| /* __GDPR__ | ||||||||
|
|
@@ -134,6 +137,7 @@ export class UserFeedbackService implements IUserFeedbackService { | |||||||
| participant: agentId, | ||||||||
| command: result.metadata?.command, | ||||||||
| }); | ||||||||
| GenAiMetrics.incrementUserActionCount(this.otelService, 'followup'); | ||||||||
| break; | ||||||||
| case 'bug': | ||||||||
| if (conversation) { | ||||||||
|
|
@@ -204,7 +208,11 @@ export class UserFeedbackService implements IUserFeedbackService { | |||||||
| isNotebookCell: e.action.uri.scheme === Schemas.vscodeNotebookCell ? 1 : 0 | ||||||||
| }); | ||||||||
|
|
||||||||
| GenAiMetrics.recordChatEditOutcome(this.otelService, 'chat_editing', outcomes.get(e.action.outcome) ?? 'unknown', document?.languageId, e.action.hasRemainingEdits); | ||||||||
| { | ||||||||
| const otelOutcome = outcomes.get(e.action.outcome) ?? 'unknown'; | ||||||||
| emitEditFeedbackEvent(this.otelService, otelOutcome, document?.languageId ?? '', agentId, result.metadata?.responseId ?? '', 'agent', e.action.hasRemainingEdits, this.notebookService.hasSupportedNotebooks(e.action.uri)); | ||||||||
| GenAiMetrics.recordEditAcceptance(this.otelService, 'chat_editing', otelOutcome, document?.languageId); | ||||||||
|
||||||||
| GenAiMetrics.recordEditAcceptance(this.otelService, 'chat_editing', otelOutcome, document?.languageId); | |
| GenAiMetrics.recordEditAcceptance(this.otelService, 'chat_editing', otelOutcome, document?.languageId); | |
| GenAiMetrics.recordChatEditOutcome(this.otelService, 'chat_editing', otelOutcome as EditOutcome, document?.languageId); |
Copilot
AI
Mar 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline.done is still sent to MSFT + internal telemetry, but the GitHub telemetry forwarding (sendGHTelemetryEvent('inline.done', ...)) was removed. This looks like a regression from the previous behavior where GH telemetry parity existed for inline chat completion signals; please re-add GH telemetry (or document/justify the intentional removal).
Copilot
AI
Mar 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline.trackEditSurvival is now only sent to MSFT telemetry (plus OTel), but the GitHub telemetry forwarding call was removed. If GH telemetry is still expected for edit survival (as it is for other edit-survival signals like applyPatch/replaceString), please restore the GH event here to avoid losing that signal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new “Agent Activity & Outcome Metrics” section documents metric names (
copilot_chat.edit.accept.count,copilot_chat.edit.hunk.count,copilot_chat.edit.survival_rate) that don’t exist in the implementation. The code emitscopilot_chat.edit.acceptance.count(withcopilot_chat.edit.sourcedistinguishing file vs hunk) and survival histogramscopilot_chat.edit.survival.four_gram/copilot_chat.edit.survival.no_revert. Please align the doc table with the actual instrument names (or rename the instruments to match the doc).This issue also appears on line 246 of the same file.