Skip to content

Commit a2b7383

Browse files
Add instrumentation support to the typescript code (#12991)
* add instrumentation support to the typescript code * fix linter * missed file * update to a newer image? * merged * work around webpack * webpack! Arg! * cleanup * cleanups * remove spaces * must use eval to work around webpack * need vscode in here * fix line endings? * fix line endings? * Add comment * Added instrumentation to copilothoverprovider * inject instrumentation code via perfecto instead * Ensure that everything is instrumented where we can. * extra comma
1 parent 388a81c commit a2b7383

File tree

8 files changed

+140
-80
lines changed

8 files changed

+140
-80
lines changed

Extension/src/Debugger/extension.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { TargetLeafNode, setActiveSshTarget } from '../SSH/TargetsView/targetNod
1515
import { sshCommandToConfig } from '../SSH/sshCommandToConfig';
1616
import { getSshConfiguration, getSshConfigurationFiles, parseFailures, writeSshConfiguration } from '../SSH/sshHosts';
1717
import { pathAccessible } from '../common';
18+
import { instrument } from '../instrumentation';
1819
import { getSshChannel } from '../logger';
1920
import { AttachItemsProvider, AttachPicker, RemoteAttachPicker } from './attachToProcess';
2021
import { ConfigurationAssetProviderFactory, ConfigurationSnippetProvider, DebugConfigurationProvider, IConfigurationAssetProvider } from './configurationProvider';
@@ -46,10 +47,10 @@ export async function initialize(context: vscode.ExtensionContext): Promise<void
4647
let cppVsDebugProvider: DebugConfigurationProvider | null = null;
4748
if (os.platform() === 'win32') {
4849
cppVsDebugProvider = new DebugConfigurationProvider(assetProvider, DebuggerType.cppvsdbg);
49-
disposables.push(vscode.debug.registerDebugConfigurationProvider(DebuggerType.cppvsdbg, cppVsDebugProvider, vscode.DebugConfigurationProviderTriggerKind.Dynamic));
50+
disposables.push(vscode.debug.registerDebugConfigurationProvider(DebuggerType.cppvsdbg, instrument(cppVsDebugProvider), vscode.DebugConfigurationProviderTriggerKind.Dynamic));
5051
}
5152
const cppDebugProvider: DebugConfigurationProvider = new DebugConfigurationProvider(assetProvider, DebuggerType.cppdbg);
52-
disposables.push(vscode.debug.registerDebugConfigurationProvider(DebuggerType.cppdbg, cppDebugProvider, vscode.DebugConfigurationProviderTriggerKind.Dynamic));
53+
disposables.push(vscode.debug.registerDebugConfigurationProvider(DebuggerType.cppdbg, instrument(cppDebugProvider), vscode.DebugConfigurationProviderTriggerKind.Dynamic));
5354

5455
// Register DebugConfigurationProviders for "Run and Debug" play button.
5556
const debugProvider: DebugConfigurationProvider = new DebugConfigurationProvider(assetProvider, DebuggerType.all);
@@ -75,7 +76,7 @@ export async function initialize(context: vscode.ExtensionContext): Promise<void
7576
}];
7677

7778
// ConfigurationSnippetProvider needs to be initiallized after configurationProvider calls getConfigurationSnippets.
78-
disposables.push(vscode.languages.registerCompletionItemProvider(launchJsonDocumentSelector, new ConfigurationSnippetProvider(assetProvider)));
79+
disposables.push(vscode.languages.registerCompletionItemProvider(launchJsonDocumentSelector, instrument(new ConfigurationSnippetProvider(assetProvider))));
7980

8081
// Register Debug Adapters
8182
disposables.push(vscode.debug.registerDebugAdapterDescriptorFactory(DebuggerType.cppvsdbg, new CppvsdbgDebugAdapterDescriptorFactory(context)));
@@ -84,7 +85,7 @@ export async function initialize(context: vscode.ExtensionContext): Promise<void
8485
// SSH Targets View
8586
await initializeSshTargets();
8687
const sshTargetsProvider: SshTargetsProvider = new SshTargetsProvider();
87-
disposables.push(vscode.window.registerTreeDataProvider('CppSshTargetsView', sshTargetsProvider));
88+
disposables.push(vscode.window.registerTreeDataProvider('CppSshTargetsView', instrument(sshTargetsProvider)));
8889
disposables.push(vscode.commands.registerCommand(addSshTargetCmd, () => enableSshTargetsViewAndRun(addSshTargetImpl)));
8990
disposables.push(vscode.commands.registerCommand('C_Cpp.removeSshTarget', (node?: BaseNode) => enableSshTargetsViewAndRun(removeSshTargetImpl, node)));
9091
disposables.push(vscode.commands.registerCommand(refreshCppSshTargetsViewCmd, (node?: BaseNode) => enableSshTargetsViewAndRun((node?: BaseNode) => sshTargetsProvider.refresh(node), node)));

Extension/src/LanguageServer/client.ts

+33-35
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { logAndReturn } from '../Utility/Async/returns';
3838
import { is } from '../Utility/System/guards';
3939
import * as util from '../common';
4040
import { isWindows } from '../constants';
41+
import { instrument, isInstrumentationEnabled } from '../instrumentation';
4142
import { DebugProtocolParams, Logger, ShowWarningParams, getDiagnosticsChannel, getOutputChannelLogger, logDebugProtocol, logLocalized, showWarning } from '../logger';
4243
import { localizedStringCount, lookupString } from '../nativeStrings';
4344
import { SessionState } from '../sessionState';
@@ -840,6 +841,16 @@ export interface Client {
840841
}
841842

842843
export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client {
844+
if (isInstrumentationEnabled) {
845+
instrument(vscode.languages, { name: "languages" });
846+
instrument(vscode.window, { name: "window" });
847+
instrument(vscode.workspace, { name: "workspace" });
848+
instrument(vscode.commands, { name: "commands" });
849+
instrument(vscode.debug, { name: "debug" });
850+
instrument(vscode.env, { name: "env" });
851+
instrument(vscode.extensions, { name: "extensions" });
852+
return instrument(new DefaultClient(workspaceFolder), { ignore: ["enqueue", "onInterval", "logTelemetry"] });
853+
}
843854
return new DefaultClient(workspaceFolder);
844855
}
845856

@@ -1323,31 +1334,33 @@ export class DefaultClient implements Client {
13231334
this.currentCopilotHoverEnabled = new PersistentWorkspaceState<string>("cpp.copilotHover", settings.copilotHover);
13241335
if (settings.copilotHover !== "disabled") {
13251336
this.copilotHoverProvider = new CopilotHoverProvider(this);
1326-
this.disposables.push(vscode.languages.registerHoverProvider(util.documentSelector, this.copilotHoverProvider));
1337+
this.disposables.push(vscode.languages.registerHoverProvider(util.documentSelector, instrument(this.copilotHoverProvider)));
13271338
}
1339+
13281340
if (settings.copilotHover !== this.currentCopilotHoverEnabled.Value) {
13291341
this.currentCopilotHoverEnabled.Value = settings.copilotHover;
13301342
}
1331-
this.disposables.push(vscode.languages.registerHoverProvider(util.documentSelector, this.hoverProvider));
1332-
this.disposables.push(vscode.languages.registerInlayHintsProvider(util.documentSelector, this.inlayHintsProvider));
1333-
this.disposables.push(vscode.languages.registerRenameProvider(util.documentSelector, new RenameProvider(this)));
1334-
this.disposables.push(vscode.languages.registerReferenceProvider(util.documentSelector, new FindAllReferencesProvider(this)));
1335-
this.disposables.push(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(this)));
1336-
this.disposables.push(vscode.languages.registerDocumentSymbolProvider(util.documentSelector, new DocumentSymbolProvider(), undefined));
1337-
this.disposables.push(vscode.languages.registerCodeActionsProvider(util.documentSelector, new CodeActionProvider(this), undefined));
1338-
this.disposables.push(vscode.languages.registerCallHierarchyProvider(util.documentSelector, new CallHierarchyProvider(this)));
1343+
this.disposables.push(vscode.languages.registerHoverProvider(util.documentSelector, instrument(this.hoverProvider)));
1344+
this.disposables.push(vscode.languages.registerInlayHintsProvider(util.documentSelector, instrument(this.inlayHintsProvider)));
1345+
this.disposables.push(vscode.languages.registerRenameProvider(util.documentSelector, instrument(new RenameProvider(this))));
1346+
this.disposables.push(vscode.languages.registerReferenceProvider(util.documentSelector, instrument(new FindAllReferencesProvider(this))));
1347+
this.disposables.push(vscode.languages.registerWorkspaceSymbolProvider(instrument(new WorkspaceSymbolProvider(this))));
1348+
this.disposables.push(vscode.languages.registerDocumentSymbolProvider(util.documentSelector, instrument(new DocumentSymbolProvider()), undefined));
1349+
this.disposables.push(vscode.languages.registerCodeActionsProvider(util.documentSelector, instrument(new CodeActionProvider(this)), undefined));
1350+
this.disposables.push(vscode.languages.registerCallHierarchyProvider(util.documentSelector, instrument(new CallHierarchyProvider(this))));
1351+
13391352
// Because formatting and codeFolding can vary per folder, we need to register these providers once
13401353
// and leave them registered. The decision of whether to provide results needs to be made on a per folder basis,
13411354
// within the providers themselves.
1342-
this.documentFormattingProviderDisposable = vscode.languages.registerDocumentFormattingEditProvider(util.documentSelector, new DocumentFormattingEditProvider(this));
1343-
this.formattingRangeProviderDisposable = vscode.languages.registerDocumentRangeFormattingEditProvider(util.documentSelector, new DocumentRangeFormattingEditProvider(this));
1344-
this.onTypeFormattingProviderDisposable = vscode.languages.registerOnTypeFormattingEditProvider(util.documentSelector, new OnTypeFormattingEditProvider(this), ";", "}", "\n");
1355+
this.documentFormattingProviderDisposable = vscode.languages.registerDocumentFormattingEditProvider(util.documentSelector, instrument(new DocumentFormattingEditProvider(this)));
1356+
this.formattingRangeProviderDisposable = vscode.languages.registerDocumentRangeFormattingEditProvider(util.documentSelector, instrument(new DocumentRangeFormattingEditProvider(this)));
1357+
this.onTypeFormattingProviderDisposable = vscode.languages.registerOnTypeFormattingEditProvider(util.documentSelector, instrument(new OnTypeFormattingEditProvider(this)), ";", "}", "\n");
13451358

13461359
this.codeFoldingProvider = new FoldingRangeProvider(this);
1347-
this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(util.documentSelector, this.codeFoldingProvider);
1360+
this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(util.documentSelector, instrument(this.codeFoldingProvider));
13481361

13491362
if (settings.isEnhancedColorizationEnabled && semanticTokensLegend) {
1350-
this.semanticTokensProvider = new SemanticTokensProvider();
1363+
this.semanticTokensProvider = instrument(new SemanticTokensProvider());
13511364
this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend);
13521365
}
13531366

@@ -1730,8 +1743,7 @@ export class DefaultClient implements Client {
17301743
const oldLoggingLevelLogged: boolean = this.loggingLevel > 1;
17311744
this.loggingLevel = util.getNumericLoggingLevel(changedSettings.loggingLevel);
17321745
if (oldLoggingLevelLogged || this.loggingLevel > 1) {
1733-
const out: Logger = getOutputChannelLogger();
1734-
out.appendLine(localize({ key: "loggingLevel.changed", comment: ["{0} is the setting name 'loggingLevel', {1} is a string value such as 'Debug'"] }, "{0} has changed to: {1}", "loggingLevel", changedSettings.loggingLevel));
1746+
getOutputChannelLogger().appendLine(localize({ key: "loggingLevel.changed", comment: ["{0} is the setting name 'loggingLevel', {1} is a string value such as 'Debug'"] }, "{0} has changed to: {1}", "loggingLevel", changedSettings.loggingLevel));
17351747
}
17361748
}
17371749
const settings: CppSettings = new CppSettings();
@@ -2746,12 +2758,7 @@ export class DefaultClient implements Client {
27462758
const status: IntelliSenseStatus = { status: Status.IntelliSenseCompiling };
27472759
testHook.updateStatus(status);
27482760
} else if (message.endsWith("IntelliSense done")) {
2749-
const settings: CppSettings = new CppSettings();
2750-
if (util.getNumericLoggingLevel(settings.loggingLevel) >= 6) {
2751-
const out: Logger = getOutputChannelLogger();
2752-
const duration: number = Date.now() - timeStamp;
2753-
out.appendLine(localize("update.intellisense.time", "Update IntelliSense time (sec): {0}", duration / 1000));
2754-
}
2761+
getOutputChannelLogger().appendLineAtLevel(6, localize("update.intellisense.time", "Update IntelliSense time (sec): {0}", (Date.now() - timeStamp) / 1000));
27552762
this.model.isUpdatingIntelliSense.Value = false;
27562763
const status: IntelliSenseStatus = { status: Status.IntelliSenseReady };
27572764
testHook.updateStatus(status);
@@ -3183,11 +3190,8 @@ export class DefaultClient implements Client {
31833190
return;
31843191
}
31853192

3186-
const settings: CppSettings = new CppSettings();
31873193
const out: Logger = getOutputChannelLogger();
3188-
if (util.getNumericLoggingLevel(settings.loggingLevel) >= 6) {
3189-
out.appendLine(localize("configurations.received", "Custom configurations received:"));
3190-
}
3194+
out.appendLineAtLevel(6, localize("configurations.received", "Custom configurations received:"));
31913195
const sanitized: SourceFileConfigurationItemAdapter[] = [];
31923196
configs.forEach(item => {
31933197
if (this.isSourceFileConfigurationItem(item, providerVersion)) {
@@ -3199,10 +3203,8 @@ export class DefaultClient implements Client {
31993203
uri = item.uri.toString();
32003204
}
32013205
this.configurationLogging.set(uri, JSON.stringify(item.configuration, null, 4));
3202-
if (util.getNumericLoggingLevel(settings.loggingLevel) >= 6) {
3203-
out.appendLine(` uri: ${uri}`);
3204-
out.appendLine(` config: ${JSON.stringify(item.configuration, null, 2)}`);
3205-
}
3206+
out.appendLineAtLevel(6, ` uri: ${uri}`);
3207+
out.appendLineAtLevel(6, ` config: ${JSON.stringify(item.configuration, null, 2)}`);
32063208
if (item.configuration.includePath.some(path => path.endsWith('**'))) {
32073209
console.warn("custom include paths should not use recursive includes ('**')");
32083210
}
@@ -3306,11 +3308,7 @@ export class DefaultClient implements Client {
33063308
return;
33073309
}
33083310

3309-
const settings: CppSettings = new CppSettings();
3310-
if (util.getNumericLoggingLevel(settings.loggingLevel) >= 6) {
3311-
const out: Logger = getOutputChannelLogger();
3312-
out.appendLine(localize("browse.configuration.received", "Custom browse configuration received: {0}", JSON.stringify(sanitized, null, 2)));
3313-
}
3311+
getOutputChannelLogger().appendLineAtLevel(6, localize("browse.configuration.received", "Custom browse configuration received: {0}", JSON.stringify(sanitized, null, 2)));
33143312

33153313
// Separate compiler path and args before sending to language client
33163314
if (util.isString(sanitized.compilerPath)) {

Extension/src/LanguageServer/extension.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import * as which from 'which';
1818
import { logAndReturn } from '../Utility/Async/returns';
1919
import * as util from '../common';
2020
import { modelSelector } from '../constants';
21+
import { instrument } from '../instrumentation';
2122
import { getCrashCallStacksChannel } from '../logger';
2223
import { PlatformInformation } from '../platform';
2324
import * as telemetry from '../telemetry';
@@ -222,7 +223,7 @@ export async function activate(): Promise<void> {
222223
{ scheme: 'file', language: 'cpp' },
223224
{ scheme: 'file', language: 'cuda-cpp' }
224225
];
225-
codeActionProvider = vscode.languages.registerCodeActionsProvider(selector, {
226+
codeActionProvider = vscode.languages.registerCodeActionsProvider(selector, instrument({
226227
provideCodeActions: async (document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext): Promise<vscode.CodeAction[]> => {
227228

228229
if (!await clients.ActiveClient.getVcpkgEnabled()) {
@@ -248,7 +249,7 @@ export async function activate(): Promise<void> {
248249
const actions: vscode.CodeAction[] = ports.map<vscode.CodeAction>(getVcpkgClipboardInstallAction);
249250
return actions;
250251
}
251-
});
252+
}));
252253

253254
await vscode.commands.executeCommand('setContext', 'cpptools.msvcEnvironmentFound', util.hasMsvcEnvironment());
254255

@@ -1280,10 +1281,8 @@ async function handleCrashFileRead(crashDirectory: string, crashFile: string, cr
12801281
if (crashCallStack !== prevCppCrashCallStackData) {
12811282
prevCppCrashCallStackData = crashCallStack;
12821283

1283-
const settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", null);
1284-
if (lines.length >= 6 && util.getNumericLoggingLevel(settings.get<string>("loggingLevel")) >= 1) {
1285-
const out: vscode.OutputChannel = getCrashCallStacksChannel();
1286-
out.appendLine(`\n${isCppToolsSrv ? "cpptools-srv" : "cpptools"}\n${crashDate.toLocaleString()}\n${signalType}${crashCallStack}`);
1284+
if (lines.length >= 6 && util.getLoggingLevel() >= 1) {
1285+
getCrashCallStacksChannel().appendLine(`\n${isCppToolsSrv ? "cpptools-srv" : "cpptools"}\n${crashDate.toLocaleString()}\n${signalType}${crashCallStack}`);
12871286
}
12881287
}
12891288

Extension/src/common.ts

+7-10
Original file line numberDiff line numberDiff line change
@@ -759,10 +759,7 @@ export interface ProcessReturnType {
759759
export async function spawnChildProcess(program: string, args: string[] = [], continueOn?: string, skipLogging?: boolean, cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
760760
// Do not use CppSettings to avoid circular require()
761761
if (skipLogging === undefined || !skipLogging) {
762-
const settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", null);
763-
if (getNumericLoggingLevel(settings.get<string>("loggingLevel")) >= 5) {
764-
getOutputChannelLogger().appendLine(`$ ${program} ${args.join(' ')}`);
765-
}
762+
getOutputChannelLogger().appendLineAtLevel(5, `$ ${program} ${args.join(' ')}`);
766763
}
767764
const programOutput: ProcessOutput = await spawnChildProcessImpl(program, args, continueOn, skipLogging, cancellationToken);
768765
const exitCode: number | NodeJS.Signals | undefined = programOutput.exitCode;
@@ -789,10 +786,6 @@ interface ProcessOutput {
789786
async function spawnChildProcessImpl(program: string, args: string[], continueOn?: string, skipLogging?: boolean, cancellationToken?: vscode.CancellationToken): Promise<ProcessOutput> {
790787
const result = new ManualPromise<ProcessOutput>();
791788

792-
// Do not use CppSettings to avoid circular require()
793-
const settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", null);
794-
const loggingLevel: number = (skipLogging === undefined || !skipLogging) ? getNumericLoggingLevel(settings.get<string>("loggingLevel")) : 0;
795-
796789
let proc: child_process.ChildProcess;
797790
if (await isExecutable(program)) {
798791
proc = child_process.spawn(`.${isWindows ? '\\' : '/'}${path.basename(program)}`, args, { shell: true, cwd: path.dirname(program) });
@@ -817,8 +810,8 @@ async function spawnChildProcessImpl(program: string, args: string[], continueOn
817810
if (proc.stdout) {
818811
proc.stdout.on('data', data => {
819812
const str: string = data.toString();
820-
if (loggingLevel > 0) {
821-
getOutputChannelLogger().append(str);
813+
if (skipLogging === undefined || !skipLogging) {
814+
getOutputChannelLogger().appendAtLevel(1, str);
822815
}
823816
stdout += str;
824817
if (continueOn) {
@@ -1576,6 +1569,10 @@ function isIntegral(str: string): boolean {
15761569
return regex.test(str);
15771570
}
15781571

1572+
export function getLoggingLevel() {
1573+
return getNumericLoggingLevel(vscode.workspace.getConfiguration("C_Cpp", null).get<string>("loggingLevel"));
1574+
}
1575+
15791576
export function getNumericLoggingLevel(loggingLevel: string | undefined): number {
15801577
if (!loggingLevel) {
15811578
return 1;

0 commit comments

Comments
 (0)