Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/conversation/vscode-node/test/interactiveSessionProvider.telemetry.test.ts
13405 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 assert from 'assert';
7
import * as vscode from 'vscode';
8
import { ICopilotTokenManager } from '../../../../platform/authentication/common/copilotTokenManager';
9
import { SimulationTestCopilotTokenManager } from '../../../../platform/authentication/test/node/simulationTestCopilotTokenManager';
10
import { allEvents, withTelemetryCapture } from '../../../../platform/test/node/telemetry';
11
import { SpyChatResponseStream } from '../../../../util/common/test/mockChatResponseStream';
12
import { SyncDescriptor } from '../../../../util/vs/platform/instantiation/common/descriptors';
13
import { IInstantiationService } from '../../../../util/vs/platform/instantiation/common/instantiation';
14
import { ChatParticipantRequestHandler } from '../../../prompt/node/chatParticipantRequestHandler';
15
import { TestChatRequest } from '../../../test/node/testHelpers';
16
import { createExtensionTestingServices } from '../../../test/vscode-node/services';
17
18
19
suite('Conversation telemetry tests - Integration tests', function () {
20
this.timeout(10000);
21
22
test.skip('Telemetry for user message', async function () {
23
const testingServiceCollection = createExtensionTestingServices();
24
testingServiceCollection.define(ICopilotTokenManager, new SyncDescriptor(SimulationTestCopilotTokenManager));
25
const messageText = 'Write me a function that returns the square root of a number.';
26
27
const [messages] = await withTelemetryCapture(testingServiceCollection, async (accessor) => {
28
const token = new vscode.CancellationTokenSource().token;
29
const request: vscode.ChatRequest = new TestChatRequest(messageText);
30
const stream = new SpyChatResponseStream();
31
const instantiationService = accessor.get(IInstantiationService);
32
const session = instantiationService.createInstance(ChatParticipantRequestHandler,
33
[],
34
request,
35
stream,
36
token,
37
{ agentName: '', agentId: '' },
38
() => false,
39
undefined);
40
await session.getResult(); // and throw away the result
41
});
42
assert.ok(allEvents(messages));
43
const names = messages
44
.map(message => message.data.baseData.name.split('/')[1])
45
// in case we need a new Copilot token, we don't care about the messages that triggers
46
.filter(name => !['auth.new_login', 'auth.new_token'].includes(name));
47
48
// Check client telemetry events
49
orderMatches(
50
[
51
'conversation.message',
52
'conversation.messageText',
53
'request.sent',
54
'request.response',
55
'engine.messages',
56
'engine.messages.length',
57
'model.request.added',
58
'model.message.added',
59
'model.modelCall.input',
60
'model.request.options.added',
61
'request.shownWarning',
62
].sort(),
63
names.filter(name => name !== 'log').sort()
64
);
65
66
// Check there exists a conversation.message event for the user with the correct properties and measurements
67
const userMessage = messages.find(
68
message =>
69
message.data.baseData.name.split('/')[1] === 'conversation.message' &&
70
message.data.baseData.properties.source === 'user'
71
);
72
const userMessageId = userMessage?.data.baseData.properties.messageId;
73
// conversation.message event exists
74
assert.ok(userMessage, 'conversation.message event for user message does not exist');
75
// Turn index is 0 because this is the first message in the conversation
76
assert.ok(
77
userMessage.data.baseData.properties.turnIndex === '0',
78
'conversation.message event for user message has turn index != 0'
79
);
80
// Message length equals the length of the message text
81
assert.ok(
82
userMessage.data.baseData.measurements.messageCharLen === messageText.length,
83
'conversation.message event for user message has incorrect message length'
84
);
85
// Check there exists a conversation.messageText event for the user with the correct properties and measurements
86
const userMessageText = messages.find(
87
message =>
88
message.data.baseData.name.split('/')[1] === 'conversation.messageText' &&
89
message.data.baseData.properties.messageId === userMessageId
90
);
91
// conversation.messageText event exists with matching messageId
92
assert.ok(userMessageText, 'conversation.messageText event for user message does not exist');
93
assert.ok(
94
userMessageText.data.baseData.properties.messageText === messageText,
95
'conversation.messageText event for user message has incorrect message text'
96
);
97
98
// Check there exists a request.sent event with matching messageId
99
const userMessageRequest = messages.find(
100
message =>
101
message.data.baseData.name.split('/')[1] === 'request.sent' &&
102
message.data.baseData.properties.messageId === userMessageId
103
);
104
// request.sent event exists with matching messageId
105
assert.ok(userMessageRequest, 'request.sent event for user message does not exist');
106
107
// Check there exists a request.response event with matching messageId
108
const userMessageResponse = messages.find(
109
message =>
110
message.data.baseData.name.split('/')[1] === 'request.response' &&
111
message.data.baseData.properties.messageId === userMessageId
112
);
113
// request.sent event exists with matching messageId
114
assert.ok(userMessageResponse, 'request.response event for user message does not exist');
115
116
// Check there exists a engine.messages event with matching messageId
117
const userMessageEngine = messages.find(
118
message =>
119
message.data.baseData.name.split('/')[1] === 'engine.messages' &&
120
message.data.baseData.properties.messageId === userMessageId
121
);
122
// engine.messages event exists with matching messageId
123
assert.ok(userMessageEngine, 'engine.messages event for user message does not exist');
124
// Check that the engine.messages event has a messagesJson property with length greater than or equal to message
125
assert.ok(
126
userMessageEngine.data.baseData.properties.messagesJson.length >= messageText.length,
127
'engine.messages event for user message has messagesJson property with length < message length'
128
);
129
130
// Check there exists a engine.messages.length event with matching messageId
131
const userMessageEngineLength = messages.find(
132
message =>
133
message.data.baseData.name.split('/')[1] === 'engine.messages.length' &&
134
message.data.baseData.properties.messageId === userMessageId
135
);
136
assert.ok(userMessageEngineLength, 'engine.messages.length event for user message does not exist');
137
138
// Check there exists a model.request.added event with matching headerRequestId
139
const modelRequestAdded = messages.find(
140
message =>
141
message.data.baseData.name.split('/')[1] === 'model.request.added' &&
142
message.data.baseData.properties.headerRequestId
143
);
144
assert.ok(modelRequestAdded, 'model.request.added event for user message does not exist');
145
146
// Check there exists a model.message.added event with messageUuid
147
const modelMessageAdded = messages.find(
148
message =>
149
message.data.baseData.name.split('/')[1] === 'model.message.added' &&
150
message.data.baseData.properties.messageUuid
151
);
152
assert.ok(modelMessageAdded, 'model.message.added event for user message does not exist');
153
154
// Check there exists a model.modelCall.input event with modelCallId
155
const modelCallInput = messages.find(
156
message =>
157
message.data.baseData.name.split('/')[1] === 'model.modelCall.input' &&
158
message.data.baseData.properties.modelCallId
159
);
160
assert.ok(modelCallInput, 'model.modelCall.input event for user message does not exist');
161
162
// Check there exists a model.request.options.added event with requestOptionsId
163
const modelRequestOptionsAdded = messages.find(
164
message =>
165
message.data.baseData.name.split('/')[1] === 'model.request.options.added' &&
166
message.data.baseData.properties.requestOptionsId
167
);
168
assert.ok(modelRequestOptionsAdded, 'model.request.options.added event for user message does not exist');
169
});
170
});
171
172
function orderMatches(list1: string[], list2: string[]) {
173
const filteredList2 = list2.filter(el => list1.includes(el));
174
const result = list1.every((el, index) => el === filteredList2[index]);
175
assert.ok(result, `Expected members\n[${list2.join(', ')}]\nto be in order\n[${list1.join(', ')}].`);
176
}
177
178