Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/common/sessionsTelemetry.ts
13389 views
1
/*---------------------------------------------------------------------------------------------
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 { ITelemetryService } from '../../platform/telemetry/common/telemetry.js';
7
8
// --- Titlebar button interactions ---
9
10
export type SessionsInteractionButton =
11
| 'newSession'
12
| 'runPrimaryTask'
13
| 'addTask'
14
| 'generateNewTask'
15
| 'openTerminal'
16
| 'openInVSCode';
17
18
export type SessionsInteractionSource = 'menu' | 'actionWidget';
19
20
type SessionsInteractionEvent = {
21
button: string;
22
source?: string;
23
};
24
25
type SessionsInteractionClassification = {
26
owner: 'osortega';
27
comment: 'Tracks user interactions with buttons in the Agents window';
28
button: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The identifier of the button that was clicked' };
29
source?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The UI surface that triggered the interaction (menu or actionWidget)' };
30
};
31
32
/**
33
* Log a titlebar button interaction in the Agents window.
34
*/
35
export function logSessionsInteraction(telemetryService: ITelemetryService, button: SessionsInteractionButton, source?: SessionsInteractionSource): void {
36
telemetryService.publicLog2<SessionsInteractionEvent, SessionsInteractionClassification>('vscodeAgents.interaction', source ? { button, source } : { button });
37
}
38
39
// --- Changes panel interactions ---
40
41
type ChangesViewTogglePanelEvent = {
42
visible: boolean;
43
};
44
45
type ChangesViewTogglePanelClassification = {
46
owner: 'osortega';
47
comment: 'Tracks when the user toggles the Changes panel open or closed.';
48
visible: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the Changes panel is now visible.' };
49
};
50
51
export function logChangesViewToggle(telemetryService: ITelemetryService, visible: boolean): void {
52
telemetryService.publicLog2<ChangesViewTogglePanelEvent, ChangesViewTogglePanelClassification>('vscodeAgents.changesView/togglePanel', { visible });
53
}
54
55
type ChangesViewVersionModeChangeEvent = {
56
mode: string;
57
};
58
59
type ChangesViewVersionModeChangeClassification = {
60
owner: 'osortega';
61
comment: 'Tracks when the user switches the version mode in the Changes panel (Branch Changes, All Changes, Last Turn).';
62
mode: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The version mode selected by the user.' };
63
};
64
65
export function logChangesViewVersionModeChange(telemetryService: ITelemetryService, mode: string): void {
66
telemetryService.publicLog2<ChangesViewVersionModeChangeEvent, ChangesViewVersionModeChangeClassification>('vscodeAgents.changesView/versionModeChange', { mode });
67
}
68
69
type ChangesViewFileSelectEvent = {
70
changeType: string;
71
};
72
73
type ChangesViewFileSelectClassification = {
74
owner: 'osortega';
75
comment: 'Tracks when the user selects a changed file in the Changes panel.';
76
changeType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The type of change (added, modified, deleted).' };
77
};
78
79
export function logChangesViewFileSelect(telemetryService: ITelemetryService, changeType: string): void {
80
telemetryService.publicLog2<ChangesViewFileSelectEvent, ChangesViewFileSelectClassification>('vscodeAgents.changesView/fileSelect', { changeType });
81
}
82
83
type ChangesViewViewModeChangeEvent = {
84
mode: string;
85
};
86
87
type ChangesViewViewModeChangeClassification = {
88
owner: 'osortega';
89
comment: 'Tracks when the user switches between list and tree view modes in the Changes panel.';
90
mode: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The view mode selected by the user (list or tree).' };
91
};
92
93
export function logChangesViewViewModeChange(telemetryService: ITelemetryService, mode: string): void {
94
telemetryService.publicLog2<ChangesViewViewModeChangeEvent, ChangesViewViewModeChangeClassification>('vscodeAgents.changesView/viewModeChange', { mode });
95
}
96
97
type ChangesViewReviewCommentAddedEvent = {
98
hasExistingFeedback: boolean;
99
hasSuggestion: boolean;
100
isFromPRReview: boolean;
101
};
102
103
type ChangesViewReviewCommentAddedClassification = {
104
owner: 'osortega';
105
comment: 'Tracks when a user adds a review comment (feedback) to a file in the Changes panel.';
106
hasExistingFeedback: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether there was already feedback on this file.' };
107
hasSuggestion: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the feedback includes a code suggestion.' };
108
isFromPRReview: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the feedback was converted from a PR review comment.' };
109
};
110
111
export function logChangesViewReviewCommentAdded(telemetryService: ITelemetryService, data: { hasExistingFeedback: boolean; hasSuggestion: boolean; isFromPRReview: boolean }): void {
112
telemetryService.publicLog2<ChangesViewReviewCommentAddedEvent, ChangesViewReviewCommentAddedClassification>('vscodeAgents.changesView/reviewCommentAdded', data);
113
}
114
115
// --- Tunnel agent host connect ---
116
117
export type TunnelConnectErrorCategory =
118
| 'relayConnectionFailed'
119
| 'auth'
120
| 'authExpired'
121
| 'network'
122
| 'other';
123
124
export type TunnelConnectFailureReason =
125
| 'hostOffline'
126
| 'maxAttemptsReached'
127
| 'auth'
128
| 'authExpired';
129
130
type TunnelConnectAttemptEvent = {
131
isReconnect: boolean;
132
attempt: number;
133
durationMs: number;
134
success: boolean;
135
errorCategory: string;
136
};
137
138
type TunnelConnectAttemptClassification = {
139
owner: 'osortega';
140
comment: 'Tracks individual agent-host tunnel connect attempts for performance and reliability.';
141
isReconnect: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether this attempt was part of a reconnect cycle (true) or an initial connect (false).' };
142
attempt: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Attempt number within the current connect session (1-based).' };
143
durationMs: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Duration of this individual attempt in milliseconds.' };
144
success: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'Whether this individual attempt succeeded.' };
145
errorCategory: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'Category of error when the attempt failed (relayConnectionFailed, auth, authExpired, network, other); empty on success.' };
146
};
147
148
export function logTunnelConnectAttempt(telemetryService: ITelemetryService, data: { isReconnect: boolean; attempt: number; durationMs: number; success: boolean; errorCategory?: TunnelConnectErrorCategory }): void {
149
telemetryService.publicLog2<TunnelConnectAttemptEvent, TunnelConnectAttemptClassification>('vscodeAgents.tunnelConnect/attempt', {
150
isReconnect: data.isReconnect,
151
attempt: data.attempt,
152
durationMs: data.durationMs,
153
success: data.success,
154
errorCategory: data.errorCategory ?? '',
155
});
156
}
157
158
type TunnelConnectResolvedEvent = {
159
isReconnect: boolean;
160
totalAttempts: number;
161
totalDurationMs: number;
162
success: boolean;
163
failureReason: string;
164
};
165
166
type TunnelConnectResolvedClassification = {
167
owner: 'osortega';
168
comment: 'Tracks overall agent-host tunnel connect session outcomes for reliability.';
169
isReconnect: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the resolved session was a reconnect cycle (true) or an initial connect (false).' };
170
totalAttempts: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Total number of attempts made before resolution.' };
171
totalDurationMs: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Total elapsed time from session start to resolution in milliseconds.' };
172
success: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'Whether the connect session ultimately succeeded.' };
173
failureReason: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'Reason the session terminated without connecting (hostOffline, maxAttemptsReached, auth, authExpired); empty on success.' };
174
};
175
176
export function logTunnelConnectResolved(telemetryService: ITelemetryService, data: { isReconnect: boolean; totalAttempts: number; totalDurationMs: number; success: boolean; failureReason?: TunnelConnectFailureReason }): void {
177
telemetryService.publicLog2<TunnelConnectResolvedEvent, TunnelConnectResolvedClassification>('vscodeAgents.tunnelConnect/resolved', {
178
isReconnect: data.isReconnect,
179
totalAttempts: data.totalAttempts,
180
totalDurationMs: data.totalDurationMs,
181
success: data.success,
182
failureReason: data.failureReason ?? '',
183
});
184
}
185
186
// --- Socket lifecycle telemetry ---
187
188
export type SocketCloseTrigger =
189
| 'server'
190
| 'sendOnDeadSocket'
191
| 'visibility'
192
| 'offline'
193
| 'malformedFrames'
194
| 'disposed'
195
| 'error';
196
197
type SocketCloseEvent = {
198
closeCode: number;
199
wasClean: boolean;
200
lifetimeMs: number;
201
messagesSent: number;
202
messagesReceived: number;
203
messagesDropped: number;
204
trigger: string;
205
};
206
207
type SocketCloseClassification = {
208
owner: 'osortega';
209
comment: 'Tracks WebSocket close events for agent host connections to measure connection reliability.';
210
closeCode: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'WebSocket close code.' };
211
wasClean: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'Whether the close was clean.' };
212
lifetimeMs: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'How long the socket was alive in milliseconds.' };
213
messagesSent: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Total messages sent.' };
214
messagesReceived: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Total messages received.' };
215
messagesDropped: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Total messages dropped due to non-OPEN socket.' };
216
trigger: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'What triggered the close (server, sendOnDeadSocket, visibility, offline, malformedFrames, disposed, error).' };
217
};
218
219
export function logSocketClose(telemetryService: ITelemetryService, data: { closeCode: number; wasClean: boolean; lifetimeMs: number; messagesSent: number; messagesReceived: number; messagesDropped: number; trigger: SocketCloseTrigger }): void {
220
telemetryService.publicLog2<SocketCloseEvent, SocketCloseClassification>('vscodeAgents.socket/close', data);
221
}
222
223
// --- Send dropped telemetry ---
224
225
type SendDroppedEvent = {
226
readyState: number;
227
timeSinceLastReceiveMs: number;
228
timeSinceLastSendMs: number;
229
};
230
231
type SendDroppedClassification = {
232
owner: 'osortega';
233
comment: 'Tracks when a message is silently dropped due to a non-OPEN WebSocket, indicating a zombie socket.';
234
readyState: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'WebSocket readyState at drop time (0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED).' };
235
timeSinceLastReceiveMs: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Milliseconds since last received message.' };
236
timeSinceLastSendMs: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Milliseconds since last sent message.' };
237
};
238
239
export function logSendDropped(telemetryService: ITelemetryService, data: { readyState: number; timeSinceLastReceiveMs: number; timeSinceLastSendMs: number }): void {
240
telemetryService.publicLog2<SendDroppedEvent, SendDroppedClassification>('vscodeAgents.socket/sendDropped', data);
241
}
242
243
// --- Visibility resumed telemetry ---
244
245
type VisibilityResumedEvent = {
246
hiddenDurationMs: number;
247
socketAlive: boolean;
248
forceClosed: boolean;
249
};
250
251
type VisibilityResumedClassification = {
252
owner: 'osortega';
253
comment: 'Tracks tab visibility resume events to measure zombie socket detection effectiveness.';
254
hiddenDurationMs: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'How long the tab was hidden in milliseconds.' };
255
socketAlive: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'Whether the socket was alive after zombie detection check.' };
256
forceClosed: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'Whether the socket was force-closed on resume.' };
257
};
258
259
export function logVisibilityResumed(telemetryService: ITelemetryService, data: { hiddenDurationMs: number; socketAlive: boolean; forceClosed: boolean }): void {
260
telemetryService.publicLog2<VisibilityResumedEvent, VisibilityResumedClassification>('vscodeAgents.socket/visibilityResumed', data);
261
}
262
263
// --- Terminal recovery telemetry ---
264
265
type TerminalRecoveryEvent = {
266
recoveredCount: number;
267
totalCount: number;
268
};
269
270
type TerminalRecoveryClassification = {
271
owner: 'osortega';
272
comment: 'Tracks terminal reconnection outcomes after agent host disconnect.';
273
recoveredCount: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Number of terminals successfully reconnected.' };
274
totalCount: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Total number of active terminals at reconnect time.' };
275
};
276
277
export function logTerminalRecovery(telemetryService: ITelemetryService, data: { recoveredCount: number; totalCount: number }): void {
278
telemetryService.publicLog2<TerminalRecoveryEvent, TerminalRecoveryClassification>('vscodeAgents.terminal/recovery', data);
279
}
280
281