Skip to content

Commit 9bedf2d

Browse files
Kartik Rajericsnowcurrently
authored andcommitted
Added setting python.logging.level which carries the logging level value the extension will log at (#11698)
* Added setting * Code reviews * Fix unit tests * Code reviews * Put config.level back * Added commnet * Code review * More code reviews * Fix tests
1 parent f1ba490 commit 9bedf2d

File tree

10 files changed

+85
-5
lines changed

10 files changed

+85
-5
lines changed

news/3 Code Health/11699.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added setting `python.logging.level` which carries the logging level value the extension will log at.

news/3 Code Health/9837.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Move all logging to the Python output channel.
1+
Move all logging to the Python output channel.

package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,19 @@
17141714
"description": "Automatically update the language server.",
17151715
"scope": "application"
17161716
},
1717+
"python.logging.level": {
1718+
"type": "string",
1719+
"default": "error",
1720+
"enum": [
1721+
"off",
1722+
"error",
1723+
"warn",
1724+
"info",
1725+
"debug"
1726+
],
1727+
"description": "The logging level the extension logs at, defaults to 'error'",
1728+
"scope": "machine"
1729+
},
17171730
"python.experiments.enabled": {
17181731
"type": "boolean",
17191732
"default": true,

src/client/common/configSettings.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
import { LanguageServerType } from '../activation/types';
1616
import '../common/extensions';
1717
import { IInterpreterAutoSeletionProxyService, IInterpreterSecurityService } from '../interpreter/autoSelection/types';
18+
import { LogLevel } from '../logging/levels';
1819
import { sendTelemetryEvent } from '../telemetry';
1920
import { EventName } from '../telemetry/constants';
2021
import { sendSettingTelemetry } from '../telemetry/envFileTelemetry';
@@ -34,11 +35,13 @@ import {
3435
IFormattingSettings,
3536
IInterpreterPathService,
3637
ILintingSettings,
38+
ILoggingSettings,
3739
IPythonSettings,
3840
ISortImportSettings,
3941
ITerminalSettings,
4042
ITestingSettings,
4143
IWorkspaceSymbolSettings,
44+
LoggingLevelSettingType,
4245
Resource
4346
} from './types';
4447
import { debounceSync } from './utils/decorators';
@@ -111,6 +114,7 @@ export class PythonSettings implements IPythonSettings {
111114
public insidersChannel!: ExtensionChannels;
112115
public experiments!: IExperiments;
113116
public languageServer: LanguageServerType = LanguageServerType.Microsoft;
117+
public logging: ILoggingSettings = { level: LogLevel.Error };
114118

115119
protected readonly changed = new EventEmitter<void>();
116120
private workspaceRoot: Resource;
@@ -251,6 +255,15 @@ export class PythonSettings implements IPythonSettings {
251255
this.devOptions = systemVariables.resolveAny(pythonSettings.get<any[]>('devOptions'))!;
252256
this.devOptions = Array.isArray(this.devOptions) ? this.devOptions : [];
253257

258+
// tslint:disable-next-line: no-any
259+
const loggingSettings = systemVariables.resolveAny(pythonSettings.get<any>('logging'))!;
260+
loggingSettings.level = convertSettingTypeToLogLevel(loggingSettings.level);
261+
if (this.logging) {
262+
Object.assign<ILoggingSettings, ILoggingSettings>(this.logging, loggingSettings);
263+
} else {
264+
this.logging = loggingSettings;
265+
}
266+
254267
// tslint:disable-next-line:no-backbone-get-set-outside-model no-non-null-assertion
255268
const lintingSettings = systemVariables.resolveAny(pythonSettings.get<ILintingSettings>('linting'))!;
256269
if (this.linting) {
@@ -703,3 +716,23 @@ function isValidPythonPath(pythonPath: string): boolean {
703716
return false;
704717
}
705718
}
719+
720+
function convertSettingTypeToLogLevel(setting: LoggingLevelSettingType | undefined): LogLevel | 'off' {
721+
switch (setting) {
722+
case 'info': {
723+
return LogLevel.Info;
724+
}
725+
case 'warn': {
726+
return LogLevel.Warn;
727+
}
728+
case 'off': {
729+
return 'off';
730+
}
731+
case 'debug': {
732+
return LogLevel.Debug;
733+
}
734+
default: {
735+
return LogLevel.Error;
736+
}
737+
}
738+
}

src/client/common/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
WorkspaceEdit
1919
} from 'vscode';
2020
import { LanguageServerType } from '../activation/types';
21+
import { LogLevel } from '../logging/levels';
2122
import { CommandsWithoutArgs } from './application/commands';
2223
import { ExtensionChannels } from './insidersBuild/types';
2324
import { InterpreterUri } from './installer/types';
@@ -187,6 +188,7 @@ export interface IPythonSettings {
187188
readonly experiments: IExperiments;
188189
readonly languageServer: LanguageServerType;
189190
readonly defaultInterpreterPath: string;
191+
readonly logging: ILoggingSettings;
190192
}
191193
export interface ISortImportSettings {
192194
readonly path: string;
@@ -228,6 +230,12 @@ export interface IMypyCategorySeverity {
228230
readonly error: DiagnosticSeverity;
229231
readonly note: DiagnosticSeverity;
230232
}
233+
234+
export type LoggingLevelSettingType = 'off' | 'error' | 'warn' | 'info' | 'debug';
235+
236+
export interface ILoggingSettings {
237+
readonly level: LogLevel | 'off';
238+
}
231239
export interface ILintingSettings {
232240
readonly enabled: boolean;
233241
readonly ignorePatterns: string[];

src/client/extensionActivation.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import { IServiceContainer, IServiceManager } from './ioc/types';
4949
import { getLanguageConfiguration } from './language/languageConfiguration';
5050
import { LinterCommands } from './linters/linterCommands';
5151
import { registerTypes as lintersRegisterTypes } from './linters/serviceRegistry';
52-
import { addOutputChannelLogging } from './logging';
52+
import { addOutputChannelLogging, setLoggingLevel } from './logging';
5353
import { PythonCodeActionProvider } from './providers/codeActionProvider/pythonCodeActionProvider';
5454
import { PythonFormattingEditProvider } from './providers/formatProvider';
5555
import { ReplProvider } from './providers/replProvider';
@@ -117,14 +117,19 @@ async function activateLegacy(
117117
commonRegisterTerminalTypes(serviceManager);
118118
debugConfigurationRegisterTypes(serviceManager);
119119

120+
const configuration = serviceManager.get<IConfigurationService>(IConfigurationService);
121+
// We should start logging using the log level as soon as possible, so set it as soon as we can access the level.
122+
// `IConfigurationService` may depend any of the registered types, so doing it after all registrations are finished.
123+
// XXX Move this *after* abExperiments is activated?
124+
setLoggingLevel(configuration.getSettings().logging.level);
125+
120126
const abExperiments = serviceContainer.get<IExperimentsManager>(IExperimentsManager);
121127
await abExperiments.activate();
122128

123129
// Register datascience types after experiments have loaded.
124130
// To ensure we can register types based on experiments.
125131
dataScienceRegisterTypes(serviceManager);
126132

127-
const configuration = serviceManager.get<IConfigurationService>(IConfigurationService);
128133
const languageServerType = configuration.getSettings().languageServer;
129134

130135
// Language feature registrations.

src/client/logging/_global.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
// Licensed under the MIT License.
33
'use strict';
44

5+
import * as winston from 'winston';
56
import { isCI } from '../common/constants';
67
import { IOutputChannel } from '../common/types';
78
import { CallInfo } from '../common/utils/decorators';
89
import { getFormatter } from './formatters';
9-
import { LogLevel } from './levels';
10+
import { LogLevel, resolveLevelName } from './levels';
1011
import { configureLogger, createLogger, ILogger, LoggerConfig, logToAll } from './logger';
1112
import { createTracingDecorator, LogInfo, TraceOptions, tracing as _tracing } from './trace';
1213
import { getPythonOutputChannelTransport } from './transports';
@@ -70,7 +71,22 @@ function initialize() {
7071
}
7172
}
7273

73-
// Register the output channel transport the logger will log into
74+
// Set the logging level the extension logs at.
75+
export function setLoggingLevel(level: LogLevel | 'off') {
76+
if (level === 'off') {
77+
// For now we disable all logging. One alternative would be
78+
// to only disable logging to the output channel (by removing
79+
// the transport from the logger).
80+
globalLogger.clear();
81+
} else {
82+
const levelName = resolveLevelName(level, winston.config.npm.levels);
83+
if (levelName) {
84+
globalLogger.level = levelName;
85+
}
86+
}
87+
}
88+
89+
// Register the output channel transport the logger will log into.
7490
export function addOutputChannelLogging(channel: IOutputChannel) {
7591
const formatter = getFormatter();
7692
const transport = getPythonOutputChannelTransport(channel, formatter);

src/client/logging/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
export {
66
// aliases
77
// (for convenience)
8+
setLoggingLevel,
89
addOutputChannelLogging,
910
logError,
1011
logInfo,

src/test/common/configSettings/configSettings.pythonPath.unit.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ suite('Python Settings - pythonPath', () => {
4545
experimentsManager = typemoq.Mock.ofType<IExperimentsManager>();
4646
workspaceService = typemoq.Mock.ofType<IWorkspaceService>();
4747
pythonSettings.setup((p) => p.get(typemoq.It.isValue('defaultInterpreterPath'))).returns(() => 'python');
48+
pythonSettings.setup((p) => p.get('logging')).returns(() => ({ level: 'error' }));
4849
});
4950
teardown(() => {
5051
if (configSettings) {

src/test/common/configSettings/configSettings.unit.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
IExperiments,
2222
IFormattingSettings,
2323
ILintingSettings,
24+
ILoggingSettings,
2425
ISortImportSettings,
2526
ITerminalSettings,
2627
ITestingSettings,
@@ -105,6 +106,7 @@ suite('Python Settings', async () => {
105106
config.setup((c) => c.get<any[]>('devOptions')).returns(() => sourceSettings.devOptions);
106107

107108
// complex settings
109+
config.setup((c) => c.get<ILoggingSettings>('logging')).returns(() => sourceSettings.logging);
108110
config.setup((c) => c.get<ILintingSettings>('linting')).returns(() => sourceSettings.linting);
109111
config.setup((c) => c.get<IAnalysisSettings>('analysis')).returns(() => sourceSettings.analysis);
110112
config.setup((c) => c.get<ISortImportSettings>('sortImports')).returns(() => sourceSettings.sortImports);

0 commit comments

Comments
 (0)