diff --git a/resources/report_issue_template.md b/resources/report_issue_template.md
index 232626d9bf4d..11cb49166ea5 100644
--- a/resources/report_issue_template.md
+++ b/resources/report_issue_template.md
@@ -40,7 +40,7 @@ You can attach such things **after** you create your issue on GitHub.
```
-XXX
+{3}
```
diff --git a/src/client/common/application/commands/reportIssueCommand.ts b/src/client/common/application/commands/reportIssueCommand.ts
index 8c39d0b504e3..b144aae1e145 100644
--- a/src/client/common/application/commands/reportIssueCommand.ts
+++ b/src/client/common/application/commands/reportIssueCommand.ts
@@ -11,6 +11,7 @@ import { ICommandManager, IWorkspaceService } from '../types';
import { EXTENSION_ROOT_DIR } from '../../../constants';
import { IInterpreterService, IInterpreterVersionService } from '../../../interpreter/contracts';
import { identifyEnvironment } from '../../../pythonEnvironments/common/environmentIdentifier';
+import { getPythonOutputChannelContent } from '../../../logging';
/**
* Allows the user to report an issue related to the Python extension using our template.
@@ -31,6 +32,7 @@ export class ReportIssueCommandHandler implements IExtensionSingleActivationServ
private templatePath = path.join(EXTENSION_ROOT_DIR, 'resources', 'report_issue_template.md');
public async openReportIssue(): Promise {
+ const pythonLogs = await getPythonOutputChannelContent();
const template = await fs.readFile(this.templatePath, 'utf8');
const interpreterPath = (await this.interpreterService.getActiveInterpreter())?.path || 'not-selected';
const pythonVersion = await this.interpreterVersionService.getVersion(interpreterPath, '');
@@ -40,7 +42,7 @@ export class ReportIssueCommandHandler implements IExtensionSingleActivationServ
this.commandManager.executeCommand('workbench.action.openIssueReporter', {
extensionId: 'ms-python.python',
- issueBody: template.format(pythonVersion, virtualEnv, languageServer),
+ issueBody: template.format(pythonVersion, virtualEnv, languageServer, pythonLogs),
});
}
}
diff --git a/src/client/logging/_global.ts b/src/client/logging/_global.ts
index 14eb237419f4..aae751590b2e 100644
--- a/src/client/logging/_global.ts
+++ b/src/client/logging/_global.ts
@@ -9,10 +9,11 @@ import { getFormatter } from './formatters';
import { LogLevel, resolveLevelName } from './levels';
import { configureLogger, createLogger, getPreDefinedConfiguration, logToAll } from './logger';
import { createTracingDecorator, LogInfo, TraceOptions, tracing as _tracing } from './trace';
-import { getPythonOutputChannelTransport } from './transports';
+import { getPythonOutputChannelTransport, IPythonOutputChannelContent } from './transports';
import { Arguments } from './util';
const globalLogger = createLogger();
+let _globalLoggerContent: IPythonOutputChannelContent;
initialize();
/**
@@ -61,9 +62,14 @@ export function setLoggingLevel(level: LogLevel | 'off') {
export function addOutputChannelLogging(channel: IOutputChannel) {
const formatter = getFormatter();
const transport = getPythonOutputChannelTransport(channel, formatter);
+ _globalLoggerContent = transport;
globalLogger.add(transport);
}
+export function getPythonOutputChannelContent(): Promise {
+ return _globalLoggerContent?.getContent() ?? '';
+}
+
// Emit a log message derived from the args to all enabled transports.
function log(logLevel: LogLevel, ...args: Arguments) {
logToAll([globalLogger], logLevel, args);
diff --git a/src/client/logging/index.ts b/src/client/logging/index.ts
index 5df347fc680f..1e0209b13624 100644
--- a/src/client/logging/index.ts
+++ b/src/client/logging/index.ts
@@ -11,5 +11,6 @@ export {
logInfo,
logVerbose,
logWarning,
+ getPythonOutputChannelContent,
traceDecorators,
} from './_global';
diff --git a/src/client/logging/transports.ts b/src/client/logging/transports.ts
index a8c99af46605..7f0aecba346f 100644
--- a/src/client/logging/transports.ts
+++ b/src/client/logging/transports.ts
@@ -6,6 +6,7 @@
// delete everything in '../client' except for '../client/logging' before running smoke tests.
import * as logform from 'logform';
+import { EOL } from 'os';
import * as path from 'path';
import { OutputChannel } from 'vscode';
import * as winston from 'winston';
@@ -70,18 +71,29 @@ export function getConsoleTransport(formatter: logform.Format): Transport {
});
}
-class PythonOutputChannelTransport extends Transport {
+export interface IPythonOutputChannelContent {
+ getContent(): Promise;
+}
+
+class PythonOutputChannelTransport extends Transport implements IPythonOutputChannelContent {
+ private content: string[] = [];
constructor(private readonly channel: OutputChannel, options?: any) {
super(options);
}
public log?(info: { message: string; [formattedMessage]: string }, next: () => void): any {
setImmediate(() => this.emit('logged', info));
- this.channel.appendLine(info[formattedMessage] || info.message);
+ const message = info[formattedMessage] || info.message;
+ this.channel.appendLine(message);
+ this.content.push(message);
if (next) {
next();
}
}
+
+ public getContent(): Promise {
+ return Promise.resolve(this.content.join(EOL));
+ }
}
// Create a Python output channel targeting transport that can be added to a winston logger.
diff --git a/src/test/common/application/commands/issueTemplateVenv1.md b/src/test/common/application/commands/issueTemplateVenv1.md
index a8e4c29ea8c4..15a529904827 100644
--- a/src/test/common/application/commands/issueTemplateVenv1.md
+++ b/src/test/common/application/commands/issueTemplateVenv1.md
@@ -40,7 +40,7 @@ You can attach such things **after** you create your issue on GitHub.
```
-XXX
+Python Output
```
diff --git a/src/test/common/application/commands/reportIssueCommand.unit.test.ts b/src/test/common/application/commands/reportIssueCommand.unit.test.ts
index f19d94473195..f58c1aaa766d 100644
--- a/src/test/common/application/commands/reportIssueCommand.unit.test.ts
+++ b/src/test/common/application/commands/reportIssueCommand.unit.test.ts
@@ -6,7 +6,7 @@
import * as sinon from 'sinon';
import * as fs from 'fs-extra';
import * as path from 'path';
-import { anyString, anything, capture, instance, mock, verify, when } from 'ts-mockito';
+import { anything, capture, instance, mock, verify, when } from 'ts-mockito';
import { expect } from 'chai';
import { LanguageServerType } from '../../../../client/activation/types';
import { CommandManager } from '../../../../client/common/application/commandManager';
@@ -20,6 +20,7 @@ import * as EnvIdentifier from '../../../../client/pythonEnvironments/common/env
import { MockWorkspaceConfiguration } from '../../../startPage/mockWorkspaceConfig';
import { EXTENSION_ROOT_DIR_FOR_TESTS } from '../../../constants';
import { InterpreterService } from '../../../../client/interpreter/interpreterService';
+import * as Logging from '../../../../client/logging/_global';
suite('Report Issue Command', () => {
let reportIssueCommandHandler: ReportIssueCommandHandler;
@@ -28,6 +29,7 @@ suite('Report Issue Command', () => {
let interpreterVersionService: IInterpreterVersionService;
let interpreterService: IInterpreterService;
let identifyEnvironmentStub: sinon.SinonStub;
+ let getPythonOutputContentStub: sinon.SinonStub;
setup(async () => {
interpreterVersionService = mock(InterpreterVersionService);
@@ -35,6 +37,7 @@ suite('Report Issue Command', () => {
cmdManager = mock(CommandManager);
interpreterService = mock(InterpreterService);
+ when(cmdManager.executeCommand('workbench.action.openIssueReporter', anything())).thenResolve();
when(interpreterVersionService.getVersion(anything(), anything())).thenResolve('3.9.0');
when(workspaceService.getConfiguration('python')).thenReturn(
new MockWorkspaceConfiguration({
@@ -46,19 +49,21 @@ suite('Report Issue Command', () => {
identifyEnvironmentStub.resolves(PythonEnvKind.Venv);
cmdManager = mock(CommandManager);
+
+ getPythonOutputContentStub = sinon.stub(Logging, 'getPythonOutputChannelContent');
+ getPythonOutputContentStub.resolves('Python Output');
reportIssueCommandHandler = new ReportIssueCommandHandler(
instance(cmdManager),
instance(workspaceService),
instance(interpreterService),
instance(interpreterVersionService),
);
-
- when(cmdManager.executeCommand(anyString(), anything())).thenResolve();
await reportIssueCommandHandler.activate();
});
teardown(() => {
identifyEnvironmentStub.restore();
+ getPythonOutputContentStub.restore();
});
test('Test if issue body is filled', async () => {