Skip to content

Commit 9b4a5ae

Browse files
authored
Show readme with log description and sharing instructions (#9036)
2 parents 8c77093 + 7c2aa49 commit 9b4a5ae

File tree

2 files changed

+135
-16
lines changed

2 files changed

+135
-16
lines changed

src/lsptoolshost/logging/collectLogs.ts

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
verifyOrAcquireDotnetTool,
2020
DumpType,
2121
createActivityLogCapture,
22+
generateReadmeContent,
23+
LogsToCollect,
2224
} from './loggingUtils';
2325
import { runDotnetTraceInTerminal } from './profiling';
2426
import { RazorLogger } from '../../razor/src/razorLogger';
@@ -30,13 +32,6 @@ interface CollectOptionQuickPickItem extends vscode.QuickPickItem {
3032
option: CollectOption;
3133
}
3234

33-
interface LogsToCollect {
34-
activityLogs: boolean;
35-
performanceTrace: boolean;
36-
memoryDump: boolean;
37-
gcDump: boolean;
38-
}
39-
4035
/**
4136
* Registers the unified collect logs command.
4237
*/
@@ -142,15 +137,29 @@ async function collectLogs(
142137
}),
143138
{ modal: true }
144139
);
145-
} else if (archiveResult.uri) {
146-
const openFolder = vscode.l10n.t('Open Folder');
147-
const result = await vscode.window.showInformationMessage(
148-
vscode.l10n.t('C# logs saved successfully.'),
149-
openFolder
150-
);
151-
if (result === openFolder) {
152-
await vscode.commands.executeCommand('revealFileInOS', archiveResult.uri);
153-
}
140+
return;
141+
}
142+
143+
if (archiveResult.uri) {
144+
await showReadme(selectedLogs, archiveResult.uri.fsPath);
145+
await showSuccessPopup(archiveResult.uri);
146+
}
147+
}
148+
149+
async function showReadme(selectedLogs: LogsToCollect, archivePath: string) {
150+
const readmeContent = generateReadmeContent(selectedLogs, archivePath);
151+
const document = await vscode.workspace.openTextDocument({
152+
content: readmeContent,
153+
language: 'markdown',
154+
});
155+
await vscode.commands.executeCommand('markdown.showPreview', document.uri);
156+
}
157+
158+
async function showSuccessPopup(uri: vscode.Uri) {
159+
const openFolder = vscode.l10n.t('Open Folder');
160+
const result = await vscode.window.showInformationMessage(vscode.l10n.t('C# logs saved successfully.'), openFolder);
161+
if (result === openFolder) {
162+
await vscode.commands.executeCommand('revealFileInOS', uri);
154163
}
155164
}
156165

src/lsptoolshost/logging/loggingUtils.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,3 +575,113 @@ export async function createActivityLogCapture(
575575
},
576576
};
577577
}
578+
579+
/** Describes which additional logs were selected for collection. */
580+
export interface LogsToCollect {
581+
activityLogs: boolean;
582+
performanceTrace: boolean;
583+
memoryDump: boolean;
584+
gcDump: boolean;
585+
}
586+
587+
/**
588+
* Generate a readme.md file which describes the contents of the log archive,
589+
* warns the user about potentially sensitive information in the logs, and
590+
* provides instructions on how to share the logs with Microsoft for troubleshooting.
591+
* @param options Which additional logs were selected for collection
592+
* @param archivePath The absolute path where the archive was saved on disk
593+
*/
594+
export function generateReadmeContent(options: LogsToCollect, archivePath: string): string {
595+
const lines: string[] = [];
596+
597+
lines.push('# C# Extension Log Archive');
598+
lines.push('');
599+
lines.push(
600+
'An archive was generated by the **C# extension for Visual Studio Code** (`CSharp: Collect C# Logs` command).'
601+
);
602+
lines.push('');
603+
lines.push(`**Archive location**: [${archivePath}](${archivePath})`);
604+
lines.push('');
605+
606+
lines.push('## Contents');
607+
lines.push('');
608+
609+
lines.push('### Current Logs and Settings');
610+
lines.push('');
611+
lines.push('| File | Description |');
612+
lines.push('| --- | --- |');
613+
lines.push('| `csharp.log` | C# extension output log |');
614+
lines.push('| `csharp-lsp-trace.log` | LSP trace log between VS Code and the Roslyn language server |');
615+
lines.push('| `razor.log` | Razor language support log |');
616+
lines.push('| `csharp-settings.json` | Current C# extension settings at time of capture |');
617+
lines.push('');
618+
619+
if (options.activityLogs) {
620+
lines.push('### Record Activity');
621+
lines.push('');
622+
lines.push(
623+
'Activity logs capture live output recorded during the diagnostic session with the log level set to Trace.'
624+
);
625+
lines.push('');
626+
lines.push('| File | Description |');
627+
lines.push('| --- | --- |');
628+
lines.push('| `csharp.activity.log` | C# output captured during the recording session |');
629+
lines.push('| `csharp-lsp-trace.activity.log` | LSP trace captured during the recording session |');
630+
lines.push('| `razor.activity.log` | Razor output captured during the recording session |');
631+
lines.push('');
632+
}
633+
634+
if (options.performanceTrace) {
635+
lines.push('### Performance Trace');
636+
lines.push('');
637+
lines.push(
638+
'A `.nettrace` file captured using `dotnet-trace`. This file contains runtime events from the language server process.'
639+
);
640+
lines.push('');
641+
lines.push(
642+
'You can view this file using [PerfView](https://github.com/microsoft/perfview), [dotnet-trace convert](https://learn.microsoft.com/dotnet/core/diagnostics/dotnet-trace#dotnet-trace-convert), or Visual Studio.'
643+
);
644+
lines.push('');
645+
}
646+
647+
if (options.memoryDump) {
648+
lines.push('### Memory Dump');
649+
lines.push('');
650+
lines.push(
651+
'One or more `.dmp` files captured using `dotnet-dump`. These contain a process memory dump of the language server.'
652+
);
653+
lines.push('');
654+
lines.push(
655+
'> **WARNING**: Memory dumps contain the full process memory and may include sensitive data such as source code, file contents, and credentials loaded in memory.'
656+
);
657+
lines.push('');
658+
}
659+
660+
if (options.gcDump) {
661+
lines.push('### GC Dump');
662+
lines.push('');
663+
lines.push(
664+
'One or more `.gcdump` files captured using `dotnet-gcdump`. These contain managed heap information from the language server.'
665+
);
666+
lines.push('');
667+
}
668+
669+
lines.push('## Sharing');
670+
lines.push('');
671+
672+
lines.push('> **WARNING**: This archive may contain sensitive information such as file paths, project names,');
673+
lines.push('> source code fragments, and other workspace-specific details. Please review the contents before');
674+
lines.push('> sharing publicly.');
675+
lines.push('');
676+
677+
lines.push(
678+
'**Publicly**: Attach this archive to your [GitHub issue](https://github.com/dotnet/vscode-csharp/issues).'
679+
);
680+
lines.push('');
681+
lines.push(
682+
'**Privately**: If the archive contains sensitive information, upload it via the [Developer Community](https://developercommunity.visualstudio.com/dotnet/report) page and reference your GitHub issue in the description.'
683+
);
684+
lines.push('');
685+
686+
return lines.join('\n');
687+
}

0 commit comments

Comments
 (0)