1
>
/*---------------------------------------------------------------------------------------------
chatServiceTelemetry.ts
2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
import { URI } from '../../../../../base/common/uri.js';
7
>
import { isLocation } from '../../../../../editor/common/languages.js';
8
>
import { escapeModelIdForTelemetry, ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
9
>
import { IChatAgentData } from '../participants/chatAgents.js';
10
>
import { ChatRequestModel, IChatRequestVariableData } from '../model/chatModel.js';
11
>
import { ChatRequestAgentSubcommandPart, ChatRequestSlashCommandPart } from '../requestParser/chatParserTypes.js';
12
>
import { ChatAgentVoteDirection, ChatCopyKind, IChatSendRequestOptions, IChatUserActionEvent } from './chatService.js';
13
>
import { isImageVariableEntry } from '../attachments/chatVariableEntries.js';
14
>
import { ChatAgentLocation, ChatModeKind, ChatPermissionLevel } from '../constants.js';
15
>
import { ILanguageModelsService } from '../languageModels.js';
16
>
import { chatSessionResourceToId, getChatSessionType } from '../model/chatUri.js';
17
>
import { isRemoteAgentHostSessionType, parseRemoteAgentHostHarness } from '../../../../../platform/agentHost/common/agentHostSessionType.js';
18
>
19
>
type ChatVoteEvent = {
20
>
direction: 'up' | 'down';
21
>
agentId: string;
22
>
command: string | undefined;
23
>
};
24
>
25
>
type ChatVoteClassification = {
26
>
direction: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the user voted up or down.' };
27
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the chat agent that this vote is for.' };
28
>
command: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the slash command that this vote is for.' };
29
>
owner: 'roblourens';
30
>
comment: 'Provides insight into the performance of Chat agents.';
31
>
};
32
>
33
>
type ChatCopyEvent = {
34
>
copyKind: 'action' | 'toolbar';
35
>
agentId: string;
36
>
command: string | undefined;
37
>
};
38
>
39
>
type ChatCopyClassification = {
40
>
copyKind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'How the copy was initiated.' };
41
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the chat agent that the copy acted on.' };
42
>
command: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the slash command the copy acted on.' };
43
>
owner: 'roblourens';
44
>
comment: 'Provides insight into the usage of Chat features.';
45
>
};
46
>
47
>
type ChatInsertEvent = {
48
>
newFile: boolean;
49
>
agentId: string;
50
>
command: string | undefined;
51
>
};
52
>
53
>
type ChatInsertClassification = {
54
>
newFile: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the code was inserted into a new untitled file.' };
55
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the chat agent that this insertion is for.' };
56
>
command: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the slash command that this insertion is for.' };
57
>
owner: 'roblourens';
58
>
comment: 'Provides insight into the usage of Chat features.';
59
>
};
60
>
61
>
type ChatApplyEvent = {
62
>
newFile: boolean;
63
>
agentId: string;
64
>
command: string | undefined;
65
>
codeMapper: string | undefined;
66
>
editsProposed: boolean;
67
>
};
68
>
69
>
type ChatApplyClassification = {
70
>
newFile: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the code was inserted into a new untitled file.' };
71
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the chat agent that this insertion is for.' };
72
>
command: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the slash command that this insertion is for.' };
73
>
codeMapper: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The code mapper that wa used to compute the edit.' };
74
>
editsProposed: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether there was a change proposed to the user.' };
75
>
owner: 'aeschli';
76
>
comment: 'Provides insight into the usage of Chat features.';
77
>
};
78
>
79
>
type ChatFollowupEvent = {
80
>
agentId: string;
81
>
command: string | undefined;
82
>
};
83
>
84
>
type ChatFollowupClassification = {
85
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the related chat agent.' };
86
>
command: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the related slash command.' };
87
>
owner: 'roblourens';
88
>
comment: 'Provides insight into the usage of Chat features.';
89
>
};
90
>
91
>
type ChatTerminalEvent = {
92
>
languageId: string;
93
>
agentId: string;
94
>
command: string | undefined;
95
>
};
96
>
97
>
type ChatTerminalClassification = {
98
>
languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The language of the code that was run in the terminal.' };
99
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the related chat agent.' };
100
>
command: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the related slash command.' };
101
>
owner: 'roblourens';
102
>
comment: 'Provides insight into the usage of Chat features.';
103
>
};
104
>
105
>
type ChatFollowupsRetrievedEvent = {
106
>
agentId: string;
107
>
command: string | undefined;
108
>
numFollowups: number;
109
>
};
110
>
111
>
type ChatFollowupsRetrievedClassification = {
112
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the related chat agent.' };
113
>
command: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the related slash command.' };
114
>
numFollowups: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The number of followup prompts returned by the agent.' };
115
>
owner: 'roblourens';
116
>
comment: 'Provides insight into the usage of Chat features.';
117
>
};
118
>
119
>
type ChatEditHunkEvent = {
120
>
agentId: string;
121
>
outcome: 'accepted' | 'rejected';
122
>
lineCount: number;
123
>
hasRemainingEdits: boolean;
124
>
requestId: string;
125
>
modelId: string;
126
>
modeId: string;
127
>
};
128
>
129
>
type ChatEditHunkClassification = {
130
>
agentId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the related chat agent.' };
131
>
outcome: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The outcome of the edit hunk action.' };
132
>
lineCount: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The number of lines in the relevant change.' };
133
>
hasRemainingEdits: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether there are remaining edits in the file after this action.' };
134
>
requestId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the chat request that produced the edit.' };
135
>
modelId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The AI model used to generate the edit.' };
136
>
modeId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The chat mode used for the request (e.g. ask, edit, agent).' };
137
>
owner: 'roblourens';
138
>
comment: 'Provides insight into the usage of Chat features.';
139
>
};
140
>
141
>
export type ChatProviderInvokedEvent = {
142
>
timeToFirstProgress: number | undefined;
143
>
totalTime: number | undefined;
144
>
result: 'success' | 'error' | 'errorWithOutput' | 'cancelled' | 'filtered';
145
>
requestType: 'string' | 'followup' | 'slashCommand';
146
>
chatSessionId: string;
147
>
requestId: string;
148
>
agent: string;
149
>
agentExtensionId: string | undefined;
150
>
slashCommand: string | undefined;
151
>
location: ChatAgentLocation;
152
>
citations: number;
153
>
numCodeBlocks: number;
154
>
isParticipantDetected: boolean;
155
>
enableCommandDetection: boolean;
156
>
attachmentKinds: string[];
157
>
model: string | undefined;
158
>
permissionLevel: ChatPermissionLevel | undefined;
159
>
chatMode: string | undefined;
160
>
sessionType: string | undefined;
161
>
harness: string | undefined;
162
>
};
163
>
164
>
export type ChatProviderInvokedClassification = {
165
>
timeToFirstProgress: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The time in milliseconds from invoking the provider to getting the first data.' };
166
>
totalTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The total time it took to run the provider\'s `provideResponseWithProgress`.' };
167
>
result: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether invoking the ChatProvider resulted in an error.' };
168
>
requestType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The type of request that the user made.' };
169
>
chatSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A random ID for the session.' };
170
>
requestId: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The identifier of the chat request, used to correlate workbench and agent host telemetry.' };
171
>
agent: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The type of agent used.' };
172
>
agentExtensionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The extension that contributed the agent.' };
173
>
slashCommand?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The type of slashCommand used.' };
174
>
location: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The location at which chat request was made.' };
175
>
citations: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The number of public code citations that were returned with the response.' };
176
>
numCodeBlocks: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The number of code blocks in the response.' };
177
>
isParticipantDetected: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the participant was automatically detected.' };
178
>
enableCommandDetection: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether participation detection was disabled for this invocation.' };
179
>
attachmentKinds: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The types of variables/attachments that the user included with their query.' };
180
>
model: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The model used to generate the response.' };
181
>
permissionLevel: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The tool auto-approval permission level selected in the permission picker (default, assisted, autoApprove, or autopilot). Undefined when the picker is not applicable (e.g. ask mode or API-driven requests).' };
182
>
chatMode: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The chat mode used for the request. Built-in modes (ask, agent, edit), extension-contributed names (e.g. Plan), or a hashed identifier for user-created custom agents.' };
183
>
sessionType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The session type scheme (e.g. vscodeLocalChatSession for local, or remote session scheme).' };
184
>
harness: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'For remote agent host sessions, the underlying harness/provider (e.g. copilotcli, claude, codex) so remote activity can be split by harness. Undefined for non-remote sessions.' };
185
>
owner: 'roblourens';
186
>
comment: 'Provides insight into the performance of Chat agents.';
187
>
};
188
>
189
>
export class ChatServiceTelemetry {
190
>
constructor(
191
@ITelemetryService private readonly telemetryService: ITelemetryService,
192
) { }
194
>
notifyUserAction(action: IChatUserActionEvent): void {
195
if (action.action.kind === 'vote') {
196
this.telemetryService.publicLog2<ChatVoteEvent, ChatVoteClassification>('interactiveSessionVote', {