Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/chat/vscode-node/chatHookTelemetry.ts
13399 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 type * as vscode from 'vscode';
7
import { IPostToolUseHookResult, IPreToolUseHookResult } from '../../../platform/chat/common/chatHookService';
8
import { ITelemetryService } from '../../../platform/telemetry/common/telemetry';
9
10
export class ChatHookTelemetry {
11
constructor(
12
private readonly _telemetryService: ITelemetryService,
13
) { }
14
15
logConfiguredHooks(hooks: vscode.ChatRequestHooks): void {
16
const hookTypeCounts: Record<string, number> = {};
17
let totalHookCount = 0;
18
for (const hookType of Object.keys(hooks)) {
19
const commands = hooks[hookType];
20
if (commands && commands.length > 0) {
21
hookTypeCounts[hookType] = commands.length;
22
totalHookCount += commands.length;
23
}
24
}
25
26
if (totalHookCount === 0) {
27
return;
28
}
29
30
/* __GDPR__
31
"hooks.configured" : {
32
"owner": "roblourens",
33
"comment": "Reports which hook types are configured for a chat request",
34
"hookTypes": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "JSON map of hook type names to their command counts" },
35
"totalHookCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Total number of hook commands configured across all types" }
36
}
37
*/
38
this._telemetryService.sendMSFTTelemetryEvent('hooks.configured', {
39
hookTypes: JSON.stringify(hookTypeCounts),
40
}, {
41
totalHookCount,
42
});
43
}
44
45
logHookExecuted(hookType: string, hookCount: number, durationMs: number, hasError: boolean, hasCaughtException: boolean): void {
46
/* __GDPR__
47
"hooks.executed" : {
48
"owner": "roblourens",
49
"comment": "Reports the execution of hooks including duration and outcome",
50
"hookType": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The type of hook that was executed (e.g., PreToolUse, PostToolUse, Stop)" },
51
"hookCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Number of hook commands executed for this hook type" },
52
"hasError": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Whether any hook command returned an error exit code" },
53
"hasCaughtException": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Whether an unexpected exception was caught during hook execution" },
54
"durationMs": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true, "comment": "Total duration of all hook executions in milliseconds" }
55
}
56
*/
57
this._telemetryService.sendMSFTTelemetryEvent('hooks.executed', {
58
hookType,
59
hasError: String(hasError),
60
hasCaughtException: String(hasCaughtException),
61
}, {
62
hookCount,
63
durationMs,
64
});
65
}
66
67
logPreToolUseResult(result: IPreToolUseHookResult): void {
68
/* __GDPR__
69
"hooks.preToolUse.result" : {
70
"owner": "roblourens",
71
"comment": "Reports the collapsed result of PreToolUse hooks including whether the tool was blocked",
72
"permissionDecision": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The most restrictive permission decision: allow, deny, or ask" },
73
"hasUpdatedInput": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Whether a hook modified the tool input" },
74
"hasAdditionalContext": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Whether hooks provided additional context" }
75
}
76
*/
77
this._telemetryService.sendMSFTTelemetryEvent('hooks.preToolUse.result', {
78
permissionDecision: result.permissionDecision,
79
hasUpdatedInput: result.updatedInput ? 'true' : undefined,
80
hasAdditionalContext: result.additionalContext ? 'true' : undefined,
81
});
82
}
83
84
logPostToolUseResult(result: IPostToolUseHookResult): void {
85
/* __GDPR__
86
"hooks.postToolUse.result" : {
87
"owner": "roblourens",
88
"comment": "Reports the collapsed result of PostToolUse hooks including whether the tool result was blocked",
89
"didBlock": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Whether any hook blocked the tool result" },
90
"hasAdditionalContext": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Whether hooks provided additional context" }
91
}
92
*/
93
this._telemetryService.sendMSFTTelemetryEvent('hooks.postToolUse.result', {
94
didBlock: result.decision === 'block' ? 'true' : undefined,
95
hasAdditionalContext: result.additionalContext ? 'true' : undefined,
96
});
97
}
98
}
99
100