diff --git a/news/3 Code Health/17921.md b/news/3 Code Health/17921.md new file mode 100644 index 000000000000..35e071377538 --- /dev/null +++ b/news/3 Code Health/17921.md @@ -0,0 +1 @@ +Remove dependency on `winston` logger. diff --git a/package-lock.json b/package-lock.json index 99a4f1ea65f8..5d2efc81caa3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1608,6 +1608,7 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, "requires": { "lodash": "^4.17.11" } @@ -2869,19 +2870,11 @@ "object-visit": "^1.0.0" } }, - "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -2889,16 +2882,8 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "color-support": { "version": "1.1.3", @@ -2906,25 +2891,6 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, - "colornames": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", - "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" - }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" - }, - "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", - "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" - } - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3718,16 +3684,6 @@ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, - "diagnostics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", - "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", - "requires": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" - } - }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -3986,14 +3942,6 @@ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "enabled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", - "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", - "requires": { - "env-variable": "0.0.x" - } - }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -4037,11 +3985,6 @@ } } }, - "env-variable": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", - "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" - }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -5569,11 +5512,6 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fast-safe-stringify": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", - "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" - }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -5583,11 +5521,6 @@ "pend": "~1.2.0" } }, - "fecha": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", - "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" - }, "figgy-pudding": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", @@ -7063,11 +6996,6 @@ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, "is-bigint": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", @@ -7294,7 +7222,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-string": { "version": "1.0.4", @@ -7901,14 +7830,6 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "kuler": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", - "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", - "requires": { - "colornames": "^1.1.1" - } - }, "language-subtag-registry": { "version": "0.3.20", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz", @@ -8155,18 +8076,6 @@ "chalk": "^2.4.2" } }, - "logform": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", - "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", - "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", - "ms": "^2.1.1", - "triple-beam": "^1.3.0" - } - }, "lolex": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", @@ -9000,7 +8909,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "mute-stdout": { "version": "1.0.1", @@ -9824,11 +9734,6 @@ "wrappy": "1" } }, - "one-time": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", - "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" - }, "opener": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", @@ -10706,16 +10611,6 @@ } } }, - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "readdirp": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", @@ -11205,14 +11100,6 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "requires": { - "is-arrayish": "^0.3.1" - } - }, "sinon": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-8.0.1.tgz", @@ -11557,7 +11444,8 @@ "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true }, "stat-mode": { "version": "0.2.2", @@ -11967,6 +11855,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -12164,11 +12053,6 @@ "minimatch": "^3.0.4" } }, - "text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -12393,11 +12277,6 @@ "escape-string-regexp": "^1.0.2" } }, - "triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" - }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -13769,60 +13648,6 @@ "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.4.tgz", "integrity": "sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs=" }, - "winston": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", - "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", - "requires": { - "async": "^2.6.1", - "diagnostics": "^1.1.1", - "is-stream": "^1.1.0", - "logform": "^2.1.1", - "one-time": "0.0.4", - "readable-stream": "^3.1.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.3.0" - } - }, - "winston-transport": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", - "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", - "requires": { - "readable-stream": "^2.3.6", - "triple-beam": "^1.2.0" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "wipe-node-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wipe-node-cache/-/wipe-node-cache-2.1.0.tgz", diff --git a/package.json b/package.json index 2426b4376849..1b0ab23a2ece 100644 --- a/package.json +++ b/package.json @@ -1950,7 +1950,6 @@ "vscode-languageserver-protocol": "3.16.0", "vscode-tas-client": "^0.1.22", "winreg": "^1.2.4", - "winston": "^3.2.1", "xml2js": "^0.4.19" }, "devDependencies": { diff --git a/src/client/activation/activationManager.ts b/src/client/activation/activationManager.ts index 5a8a0eeb0fe9..ade44d630004 100644 --- a/src/client/activation/activationManager.ts +++ b/src/client/activation/activationManager.ts @@ -9,11 +9,11 @@ import { IApplicationDiagnostics } from '../application/types'; import { IActiveResourceService, IDocumentManager, IWorkspaceService } from '../common/application/types'; import { PYTHON_LANGUAGE } from '../common/constants'; import { DeprecatePythonPath } from '../common/experiments/groups'; -import { traceDecorators } from '../common/logger'; import { IFileSystem } from '../common/platform/types'; import { IDisposable, IExperimentService, IInterpreterPathService, Resource } from '../common/types'; import { Deferred } from '../common/utils/async'; import { IInterpreterAutoSelectionService } from '../interpreter/autoSelection/types'; +import { traceDecoratorError } from '../logging'; import { sendActivationTelemetry } from '../telemetry/envFileTelemetry'; import { IExtensionActivationManager, IExtensionActivationService, IExtensionSingleActivationService } from './types'; @@ -62,7 +62,7 @@ export class ExtensionActivationManager implements IExtensionActivationManager { ]); } - @traceDecorators.error('Failed to activate a workspace') + @traceDecoratorError('Failed to activate a workspace') public async activateWorkspace(resource: Resource): Promise { const key = this.getWorkspaceKey(resource); if (this.activatedWorkspaces.has(key)) { diff --git a/src/client/activation/activationService.ts b/src/client/activation/activationService.ts index f79e40eca9d0..ef99d9780caa 100644 --- a/src/client/activation/activationService.ts +++ b/src/client/activation/activationService.ts @@ -6,7 +6,6 @@ import { inject, injectable } from 'inversify'; import { ConfigurationChangeEvent, Disposable, OutputChannel, Uri } from 'vscode'; import { IApplicationShell, ICommandManager, IWorkspaceService } from '../common/application/types'; import { STANDARD_OUTPUT_CHANNEL } from '../common/constants'; -import { traceError } from '../common/logger'; import { IConfigurationService, IDisposableRegistry, @@ -32,6 +31,7 @@ import { LanguageServerType, } from './types'; import { StopWatch } from '../common/utils/stopWatch'; +import { traceError } from '../logging'; const languageServerSetting: keyof IPythonSettings = 'languageServer'; const workspacePathNameForGlobalWorkspaces = ''; diff --git a/src/client/activation/common/activatorBase.ts b/src/client/activation/common/activatorBase.ts index 620f017256b2..958f9dcddc33 100644 --- a/src/client/activation/common/activatorBase.ts +++ b/src/client/activation/common/activatorBase.ts @@ -24,11 +24,11 @@ import * as vscodeLanguageClient from 'vscode-languageclient/node'; import { injectable } from 'inversify'; import { IWorkspaceService } from '../../common/application/types'; -import { traceDecorators } from '../../common/logger'; import { IFileSystem } from '../../common/platform/types'; import { IConfigurationService, Resource } from '../../common/types'; import { PythonEnvironment } from '../../pythonEnvironments/info'; import { ILanguageServerActivator, ILanguageServerManager } from '../types'; +import { traceDecoratorError } from '../../logging'; /** * Starts the language server managers per workspaces (currently one for first workspace). @@ -47,7 +47,7 @@ export abstract class LanguageServerActivatorBase implements ILanguageServerActi protected readonly configurationService: IConfigurationService, ) {} - @traceDecorators.error('Failed to activate language server') + @traceDecoratorError('Failed to activate language server') public async start(resource: Resource, interpreter?: PythonEnvironment): Promise { if (!resource) { resource = this.workspace.hasWorkspaceFolders ? this.workspace.workspaceFolders![0].uri : undefined; diff --git a/src/client/activation/common/analysisOptions.ts b/src/client/activation/common/analysisOptions.ts index 2fa8a328ff13..48433be0f5b1 100644 --- a/src/client/activation/common/analysisOptions.ts +++ b/src/client/activation/common/analysisOptions.ts @@ -4,10 +4,10 @@ import { Disposable, Event, EventEmitter, WorkspaceFolder } from 'vscode'; import { DocumentFilter, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient/node'; import { PYTHON, PYTHON_LANGUAGE } from '../../common/constants'; -import { traceDecorators } from '../../common/logger'; import { IOutputChannel, Resource } from '../../common/types'; import { debounceSync } from '../../common/utils/decorators'; import { IEnvironmentVariablesProvider } from '../../common/variables/types'; +import { traceDecoratorError } from '../../logging'; import { PythonEnvironment } from '../../pythonEnvironments/info'; import { ILanguageServerAnalysisOptions, ILanguageServerOutputChannel } from '../types'; @@ -29,7 +29,7 @@ export abstract class LanguageServerAnalysisOptionsBase implements ILanguageServ this.didChange.dispose(); } - @traceDecorators.error('Failed to get analysis options') + @traceDecoratorError('Failed to get analysis options') public async getAnalysisOptions(): Promise { const workspaceFolder = this.getWorkspaceFolder(); const documentSelector = this.getDocumentFilters(workspaceFolder); diff --git a/src/client/activation/extensionSurvey.ts b/src/client/activation/extensionSurvey.ts index a7e45e3abceb..463f84e6e36c 100644 --- a/src/client/activation/extensionSurvey.ts +++ b/src/client/activation/extensionSurvey.ts @@ -9,10 +9,10 @@ import { env, UIKind } from 'vscode'; import { IApplicationEnvironment, IApplicationShell } from '../common/application/types'; import { ShowExtensionSurveyPrompt } from '../common/experiments/groups'; import '../common/extensions'; -import { traceDecorators } from '../common/logger'; import { IPlatformService } from '../common/platform/types'; import { IBrowserService, IExperimentService, IPersistentStateFactory, IRandom } from '../common/types'; import { Common, ExtensionSurveyBanner } from '../common/utils/localize'; +import { traceDecoratorError } from '../logging'; import { sendTelemetryEvent } from '../telemetry'; import { EventName } from '../telemetry/constants'; import { IExtensionSingleActivationService } from './types'; @@ -51,7 +51,7 @@ export class ExtensionSurveyPrompt implements IExtensionSingleActivationService setTimeout(() => this.showSurvey().ignoreErrors(), this.waitTimeToShowSurvey); } - @traceDecorators.error('Failed to check whether to display prompt for extension survey') + @traceDecoratorError('Failed to check whether to display prompt for extension survey') public shouldShowBanner(): boolean { if (env.uiKind === UIKind?.Web) { return false; @@ -79,7 +79,7 @@ export class ExtensionSurveyPrompt implements IExtensionSingleActivationService return true; } - @traceDecorators.error('Failed to display prompt for extension survey') + @traceDecoratorError('Failed to display prompt for extension survey') public async showSurvey() { const prompts = [ ExtensionSurveyBanner.bannerLabelYes(), diff --git a/src/client/activation/jedi/languageServerProxy.ts b/src/client/activation/jedi/languageServerProxy.ts index 977a4efb9710..67d6c5a60919 100644 --- a/src/client/activation/jedi/languageServerProxy.ts +++ b/src/client/activation/jedi/languageServerProxy.ts @@ -12,7 +12,6 @@ import { import { ChildProcess } from 'child_process'; import { DeprecatePythonPath } from '../../common/experiments/groups'; -import { traceDecorators, traceError } from '../../common/logger'; import { IExperimentService, IInterpreterPathService, Resource } from '../../common/types'; import { PythonEnvironment } from '../../pythonEnvironments/info'; import { captureTelemetry } from '../../telemetry'; @@ -22,6 +21,7 @@ import { LanguageClientMiddleware } from '../languageClientMiddleware'; import { ProgressReporting } from '../progress'; import { ILanguageClientFactory, ILanguageServerProxy } from '../types'; import { killPid } from '../../common/process/rawProcessApis'; +import { traceDecoratorError, traceDecoratorVerbose, traceError } from '../../logging'; @injectable() export class JediLanguageServerProxy implements ILanguageServerProxy { @@ -47,7 +47,7 @@ export class JediLanguageServerProxy implements ILanguageServerProxy { }; } - @traceDecorators.verbose('Stopping language server') + @traceDecoratorVerbose('Stopping language server') public dispose(): void { if (this.languageClient) { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -81,7 +81,7 @@ export class JediLanguageServerProxy implements ILanguageServerProxy { this.disposed = true; } - @traceDecorators.error('Failed to start language server') + @traceDecoratorError('Failed to start language server') @captureTelemetry( EventName.JEDI_LANGUAGE_SERVER_ENABLED, undefined, diff --git a/src/client/activation/jedi/manager.ts b/src/client/activation/jedi/manager.ts index 5f7ffc67f001..6d748b53d132 100644 --- a/src/client/activation/jedi/manager.ts +++ b/src/client/activation/jedi/manager.ts @@ -7,7 +7,6 @@ import '../../common/extensions'; import { inject, injectable, named } from 'inversify'; import { ICommandManager } from '../../common/application/types'; -import { traceDecorators, traceVerbose } from '../../common/logger'; import { IDisposable, Resource } from '../../common/types'; import { debounceSync } from '../../common/utils/decorators'; import { EXTENSION_ROOT_DIR } from '../../constants'; @@ -23,6 +22,7 @@ import { ILanguageServerProxy, LanguageServerType, } from '../types'; +import { traceDecoratorError, traceDecoratorVerbose, traceVerbose } from '../../logging'; @injectable() export class JediLanguageServerManager implements ILanguageServerManager { @@ -75,7 +75,7 @@ export class JediLanguageServerManager implements ILanguageServerManager { return this.languageServerProxy; } - @traceDecorators.error('Failed to start language server') + @traceDecoratorError('Failed to start language server') public async start(resource: Resource, interpreter: PythonEnvironment | undefined): Promise { if (this.languageProxy) { throw new Error('Language server already started'); @@ -121,8 +121,8 @@ export class JediLanguageServerManager implements ILanguageServerManager { this.restartLanguageServer().ignoreErrors(); } - @traceDecorators.error('Failed to restart language server') - @traceDecorators.verbose('Restarting language server') + @traceDecoratorError('Failed to restart language server') + @traceDecoratorVerbose('Restarting language server') protected async restartLanguageServer(): Promise { if (this.languageProxy) { this.languageProxy.dispose(); @@ -137,7 +137,7 @@ export class JediLanguageServerManager implements ILanguageServerManager { undefined, JediLanguageServerManager.versionTelemetryProps, ) - @traceDecorators.verbose('Starting language server') + @traceDecoratorVerbose('Starting language server') protected async startLanguageServer(): Promise { this.languageServerProxy = this.serviceContainer.get(ILanguageServerProxy); diff --git a/src/client/activation/node/languageServerProxy.ts b/src/client/activation/node/languageServerProxy.ts index ba0ede400b55..37f5a681cd04 100644 --- a/src/client/activation/node/languageServerProxy.ts +++ b/src/client/activation/node/languageServerProxy.ts @@ -12,7 +12,6 @@ import { } from 'vscode-languageclient/node'; import { DeprecatePythonPath } from '../../common/experiments/groups'; -import { traceDecorators, traceError } from '../../common/logger'; import { IConfigurationService, IExperimentService, IInterpreterPathService, Resource } from '../../common/types'; import { createDeferred, Deferred, sleep } from '../../common/utils/async'; import { noop } from '../../common/utils/misc'; @@ -23,6 +22,7 @@ import { EventName } from '../../telemetry/constants'; import { FileBasedCancellationStrategy } from '../common/cancellationUtils'; import { ProgressReporting } from '../progress'; import { ILanguageClientFactory, ILanguageServerFolderService, ILanguageServerProxy } from '../types'; +import { traceDecoratorError, traceDecoratorVerbose, traceError } from '../../logging'; namespace InExperiment { export const Method = 'python/inExperiment'; @@ -74,7 +74,7 @@ export class NodeLanguageServerProxy implements ILanguageServerProxy { }; } - @traceDecorators.verbose('Stopping language server') + @traceDecoratorVerbose('Stopping language server') public dispose() { if (this.languageClient) { // Do not await on this. @@ -96,7 +96,7 @@ export class NodeLanguageServerProxy implements ILanguageServerProxy { this.disposed = true; } - @traceDecorators.error('Failed to start language server') + @traceDecoratorError('Failed to start language server') @captureTelemetry( EventName.LANGUAGE_SERVER_ENABLED, undefined, diff --git a/src/client/activation/node/manager.ts b/src/client/activation/node/manager.ts index 2d29dbd417c6..ee0c52b859d7 100644 --- a/src/client/activation/node/manager.ts +++ b/src/client/activation/node/manager.ts @@ -5,7 +5,6 @@ import '../../common/extensions'; import { inject, injectable, named } from 'inversify'; import { ICommandManager } from '../../common/application/types'; -import { traceDecorators } from '../../common/logger'; import { IDisposable, Resource } from '../../common/types'; import { debounceSync } from '../../common/utils/decorators'; import { IServiceContainer } from '../../ioc/types'; @@ -21,6 +20,7 @@ import { ILanguageServerProxy, LanguageServerType, } from '../types'; +import { traceDecoratorError, traceDecoratorVerbose } from '../../logging'; @injectable() export class NodeLanguageServerManager implements ILanguageServerManager { @@ -65,7 +65,7 @@ export class NodeLanguageServerManager implements ILanguageServerManager { return this.languageServerProxy; } - @traceDecorators.error('Failed to start language server') + @traceDecoratorError('Failed to start language server') public async start(resource: Resource, interpreter: PythonEnvironment | undefined): Promise { if (this.languageProxy) { throw new Error('Language server already started'); @@ -96,8 +96,8 @@ export class NodeLanguageServerManager implements ILanguageServerManager { this.restartLanguageServer().ignoreErrors(); } - @traceDecorators.error('Failed to restart language server') - @traceDecorators.verbose('Restarting language server') + @traceDecoratorError('Failed to restart language server') + @traceDecoratorVerbose('Restarting language server') protected async restartLanguageServer(): Promise { if (this.languageProxy) { this.languageProxy.dispose(); @@ -112,7 +112,7 @@ export class NodeLanguageServerManager implements ILanguageServerManager { undefined, NodeLanguageServerManager.versionTelemetryProps, ) - @traceDecorators.verbose('Starting language server') + @traceDecoratorVerbose('Starting language server') protected async startLanguageServer(): Promise { this.languageServerProxy = this.serviceContainer.get(ILanguageServerProxy); diff --git a/src/client/api.ts b/src/client/api.ts index 229f942be625..16eb647df7df 100644 --- a/src/client/api.ts +++ b/src/client/api.ts @@ -6,13 +6,13 @@ import { noop } from 'lodash'; import { Event, Uri } from 'vscode'; import { isTestExecution } from './common/constants'; -import { traceError } from './common/logger'; import { IConfigurationService, Resource } from './common/types'; import { getDebugpyLauncherArgs, getDebugpyPackagePath } from './debugger/extension/adapter/remoteLaunchers'; import { IInterpreterService } from './interpreter/contracts'; import { IServiceContainer, IServiceManager } from './ioc/types'; import { JupyterExtensionIntegration } from './jupyter/jupyterIntegration'; import { IDataViewerDataProvider, IJupyterUriProvider } from './jupyter/types'; +import { traceError } from './logging'; /* * Do not introduce any breaking changes to this API. diff --git a/src/client/application/diagnostics/applicationDiagnostics.ts b/src/client/application/diagnostics/applicationDiagnostics.ts index 1c7f3035a728..2081f55c2f19 100644 --- a/src/client/application/diagnostics/applicationDiagnostics.ts +++ b/src/client/application/diagnostics/applicationDiagnostics.ts @@ -6,9 +6,9 @@ import { inject, injectable, named } from 'inversify'; import { DiagnosticSeverity } from 'vscode'; import { isTestExecution, STANDARD_OUTPUT_CHANNEL } from '../../common/constants'; -import { traceError, traceInfo, traceWarning } from '../../common/logger'; import { IOutputChannel, Resource } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; +import { traceError, traceInfo, traceWarn } from '../../logging'; import { IApplicationDiagnostics } from '../types'; import { IDiagnostic, IDiagnosticsService, ISourceMapSupportService } from './types'; @@ -59,7 +59,7 @@ export class ApplicationDiagnostics implements IApplicationDiagnostics { break; } case DiagnosticSeverity.Warning: { - traceWarning(message); + traceWarn(message); this.outputChannel.appendLine(message); break; } diff --git a/src/client/application/diagnostics/checks/invalidPythonPathInDebugger.ts b/src/client/application/diagnostics/checks/invalidPythonPathInDebugger.ts index fcde53e2effe..61460f9db701 100644 --- a/src/client/application/diagnostics/checks/invalidPythonPathInDebugger.ts +++ b/src/client/application/diagnostics/checks/invalidPythonPathInDebugger.ts @@ -7,13 +7,13 @@ import * as path from 'path'; import { DiagnosticSeverity, Uri, workspace as workspc, WorkspaceFolder } from 'vscode'; import { IDocumentManager, IWorkspaceService } from '../../../common/application/types'; import '../../../common/extensions'; -import { traceError } from '../../../common/logger'; import { IConfigurationService, IDisposableRegistry, Resource } from '../../../common/types'; import { Diagnostics } from '../../../common/utils/localize'; import { SystemVariables } from '../../../common/variables/systemVariables'; import { PythonPathSource } from '../../../debugger/extension/types'; import { IInterpreterHelper } from '../../../interpreter/contracts'; import { IServiceContainer } from '../../../ioc/types'; +import { traceError } from '../../../logging'; import { BaseDiagnostic, BaseDiagnosticsService } from '../base'; import { IDiagnosticsCommandFactory } from '../commands/types'; import { DiagnosticCodes } from '../constants'; diff --git a/src/client/application/diagnostics/checks/powerShellActivation.ts b/src/client/application/diagnostics/checks/powerShellActivation.ts index 936b2acf14dc..845c7190c78c 100644 --- a/src/client/application/diagnostics/checks/powerShellActivation.ts +++ b/src/client/application/diagnostics/checks/powerShellActivation.ts @@ -5,10 +5,10 @@ import { inject, injectable } from 'inversify'; import { DiagnosticSeverity } from 'vscode'; import '../../../common/extensions'; -import { traceError } from '../../../common/logger'; import { useCommandPromptAsDefaultShell } from '../../../common/terminal/commandPrompt'; import { IConfigurationService, ICurrentProcess, IDisposableRegistry, Resource } from '../../../common/types'; import { IServiceContainer } from '../../../ioc/types'; +import { traceError } from '../../../logging'; import { sendTelemetryEvent } from '../../../telemetry'; import { EventName } from '../../../telemetry/constants'; import { BaseDiagnostic, BaseDiagnosticsService } from '../base'; diff --git a/src/client/common/editor.ts b/src/client/common/editor.ts index eeaded58fce4..efabbaf5e514 100644 --- a/src/client/common/editor.ts +++ b/src/client/common/editor.ts @@ -5,8 +5,8 @@ import { EOL } from 'os'; import * as path from 'path'; import { Position, Range, TextDocument, TextEdit, Uri, WorkspaceEdit } from 'vscode'; import { IFileSystem } from '../common/platform/types'; +import { traceError } from '../logging'; import { WrappedError } from './errors/errorUtils'; -import { traceError } from './logger'; import { IEditorUtils } from './types'; import { isNotebookCell } from './utils/misc'; diff --git a/src/client/common/insidersBuild/downloadChannelRules.ts b/src/client/common/insidersBuild/downloadChannelRules.ts index 90379a37f99b..05712fea98ce 100644 --- a/src/client/common/insidersBuild/downloadChannelRules.ts +++ b/src/client/common/insidersBuild/downloadChannelRules.ts @@ -4,7 +4,7 @@ 'use strict'; import { inject, injectable } from 'inversify'; -import { traceDecorators } from '../logger'; +import { traceDecoratorError } from '../../logging'; import { IPersistentStateFactory } from '../types'; import { IExtensionChannelRule } from './types'; @@ -29,7 +29,7 @@ export class ExtensionInsidersOffChannelRule implements IExtensionChannelRule { @injectable() export class ExtensionInsidersDailyChannelRule implements IExtensionChannelRule { constructor(@inject(IPersistentStateFactory) private readonly persistentStateFactory: IPersistentStateFactory) {} - @traceDecorators.error('Error in checking if insiders build is to be for daily channel rule') + @traceDecoratorError('Error in checking if insiders build is to be for daily channel rule') public async shouldLookForInsidersBuild(isChannelRuleNew: boolean): Promise { const lastLookUpTime = this.persistentStateFactory.createGlobalPersistentState(lastLookUpTimeKey, -1); if (isChannelRuleNew) { @@ -48,7 +48,7 @@ export class ExtensionInsidersDailyChannelRule implements IExtensionChannelRule @injectable() export class ExtensionInsidersWeeklyChannelRule implements IExtensionChannelRule { constructor(@inject(IPersistentStateFactory) private readonly persistentStateFactory: IPersistentStateFactory) {} - @traceDecorators.error('Error in checking if insiders build is to be for daily channel rule') + @traceDecoratorError('Error in checking if insiders build is to be for daily channel rule') public async shouldLookForInsidersBuild(isChannelRuleNew: boolean): Promise { const lastLookUpTime = this.persistentStateFactory.createGlobalPersistentState(lastLookUpTimeKey, -1); if (isChannelRuleNew) { diff --git a/src/client/common/insidersBuild/downloadChannelService.ts b/src/client/common/insidersBuild/downloadChannelService.ts index 8f86aaa65d8f..19a576d74d32 100644 --- a/src/client/common/insidersBuild/downloadChannelService.ts +++ b/src/client/common/insidersBuild/downloadChannelService.ts @@ -5,8 +5,8 @@ import { inject, injectable } from 'inversify'; import { ConfigurationChangeEvent, ConfigurationTarget, Event, EventEmitter } from 'vscode'; +import { traceDecoratorError } from '../../logging'; import { IWorkspaceService } from '../application/types'; -import { traceDecorators } from '../logger'; import { IConfigurationService, IDisposable, IDisposableRegistry, IPythonSettings } from '../types'; import { ExtensionChannels, IExtensionChannelService } from './types'; @@ -39,7 +39,7 @@ export class ExtensionChannelService implements IExtensionChannelService { return !settings.globalValue; } - @traceDecorators.error('Updating channel failed') + @traceDecoratorError('Updating channel failed') public async updateChannel(value: ExtensionChannels): Promise { await this.configService.updateSetting(insidersChannelSetting, value, undefined, ConfigurationTarget.Global); } diff --git a/src/client/common/insidersBuild/insidersExtensionPrompt.ts b/src/client/common/insidersBuild/insidersExtensionPrompt.ts index 9939142ac4ad..ad194ff97bc5 100644 --- a/src/client/common/insidersBuild/insidersExtensionPrompt.ts +++ b/src/client/common/insidersBuild/insidersExtensionPrompt.ts @@ -4,10 +4,10 @@ 'use strict'; import { inject, injectable } from 'inversify'; +import { traceDecoratorError } from '../../logging'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { IApplicationShell, ICommandManager } from '../application/types'; -import { traceDecorators } from '../logger'; import { IPersistentState, IPersistentStateFactory } from '../types'; import { Common, ExtensionChannels, ExtensionSurveyBanner } from '../utils/localize'; import { noop } from '../utils/misc'; @@ -30,7 +30,7 @@ export class InsidersExtensionPrompt implements IInsiderExtensionPrompt { ); } - @traceDecorators.error('Error in prompting to install insiders') + @traceDecoratorError('Error in prompting to install insiders') public async promptToInstallInsiders(): Promise { const prompts = [ ExtensionChannels.yesWeekly(), @@ -59,7 +59,7 @@ export class InsidersExtensionPrompt implements IInsiderExtensionPrompt { } } - @traceDecorators.error('Error in prompting to reload') + @traceDecoratorError('Error in prompting to reload') public async promptToReload(): Promise { const selection = await this.appShell.showInformationMessage( ExtensionChannels.reloadToUseInsidersMessage(), diff --git a/src/client/common/insidersBuild/insidersExtensionService.ts b/src/client/common/insidersBuild/insidersExtensionService.ts index 009472ffc0fa..6a4d01f2c8e9 100644 --- a/src/client/common/insidersBuild/insidersExtensionService.ts +++ b/src/client/common/insidersBuild/insidersExtensionService.ts @@ -11,11 +11,11 @@ import { IServiceContainer } from '../../ioc/types'; import { IApplicationEnvironment, ICommandManager } from '../application/types'; import { Commands, isTestExecution } from '../constants'; import { IExtensionBuildInstaller, INSIDERS_INSTALLER } from '../installer/types'; -import { traceDecorators } from '../logger'; import { IDisposable, IDisposableRegistry } from '../types'; import { ExtensionChannels, IExtensionChannelRule, IExtensionChannelService, IInsiderExtensionPrompt } from './types'; import { UIKind } from 'vscode'; import { sleep } from '../utils/async'; +import { traceDecoratorError } from '../../logging'; @injectable() export class InsidersExtensionService implements IExtensionSingleActivationService { @@ -71,7 +71,7 @@ export class InsidersExtensionService implements IExtensionSingleActivationServi // Everything past here is the "channel handler" implementation. - @traceDecorators.error('Handling channel failed') + @traceDecoratorError('Handling channel failed') public async handleChannel(installChannel: ExtensionChannels, didChannelChange: boolean = false): Promise { const channelRule = this.serviceContainer.get(IExtensionChannelRule, installChannel); const shouldInstall = await channelRule.shouldLookForInsidersBuild(didChannelChange); diff --git a/src/client/common/installer/extensionBuildInstaller.ts b/src/client/common/installer/extensionBuildInstaller.ts index cd93040877fb..1e76b7eae4c9 100644 --- a/src/client/common/installer/extensionBuildInstaller.ts +++ b/src/client/common/installer/extensionBuildInstaller.ts @@ -5,9 +5,9 @@ import { inject, injectable, named } from 'inversify'; import { Uri } from 'vscode'; +import { traceDecoratorError } from '../../logging'; import { IApplicationShell, ICommandManager } from '../application/types'; import { Octicons, PVSC_EXTENSION_ID, STANDARD_OUTPUT_CHANNEL } from '../constants'; -import { traceDecorators } from '../logger'; import { IFileSystem } from '../platform/types'; import { IFileDownloader, IOutputChannel } from '../types'; import { ExtensionChannels } from '../utils/localize'; @@ -24,7 +24,7 @@ export class StableBuildInstaller implements IExtensionBuildInstaller { @inject(IApplicationShell) private readonly appShell: IApplicationShell, ) {} - @traceDecorators.error('Installing stable build of extension failed') + @traceDecoratorError('Installing stable build of extension failed') public async install(): Promise { this.output.append(ExtensionChannels.installingStableMessage()); await this.appShell.withProgressCustomIcon(Octicons.Installing, async (progress) => { @@ -47,7 +47,7 @@ export class InsidersBuildInstaller implements IExtensionBuildInstaller { @inject(IApplicationShell) private readonly appShell: IApplicationShell, ) {} - @traceDecorators.error('Installing insiders build of extension failed') + @traceDecoratorError('Installing insiders build of extension failed') public async install(): Promise { const vsixFilePath = await this.downloadInsiders(); this.output.append(ExtensionChannels.installingInsidersMessage()); @@ -61,7 +61,7 @@ export class InsidersBuildInstaller implements IExtensionBuildInstaller { await this.fs.deleteFile(vsixFilePath); } - @traceDecorators.error('Downloading insiders build of extension failed') + @traceDecoratorError('Downloading insiders build of extension failed') public async downloadInsiders(): Promise { this.output.appendLine(ExtensionChannels.startingDownloadOutputMessage()); const downloadOptions = { diff --git a/src/client/common/installer/productInstaller.ts b/src/client/common/installer/productInstaller.ts index 52bae4d7efd6..8fd894bb0689 100644 --- a/src/client/common/installer/productInstaller.ts +++ b/src/client/common/installer/productInstaller.ts @@ -12,7 +12,6 @@ import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { IApplicationShell, ICommandManager, IWorkspaceService } from '../application/types'; import { Commands, STANDARD_OUTPUT_CHANNEL } from '../constants'; -import { traceError, traceInfo } from '../logger'; import { IProcessServiceFactory, IPythonExecutionFactory } from '../process/types'; import { IConfigurationService, @@ -36,6 +35,7 @@ import { IProductService, ModuleInstallFlags, } from './types'; +import { traceError, traceInfo } from '../../logging'; export { Product } from '../types'; diff --git a/src/client/common/interpreterPathService.ts b/src/client/common/interpreterPathService.ts index e3607323702f..d07c1a966c9a 100644 --- a/src/client/common/interpreterPathService.ts +++ b/src/client/common/interpreterPathService.ts @@ -6,10 +6,10 @@ import * as fs from 'fs-extra'; import { inject, injectable } from 'inversify'; import { ConfigurationChangeEvent, ConfigurationTarget, Event, EventEmitter, Uri } from 'vscode'; +import { traceError } from '../logging'; import { IWorkspaceService } from './application/types'; import { PythonSettings } from './configSettings'; import { isTestExecution } from './constants'; -import { traceError } from './logger'; import { FileSystemPaths } from './platform/fs-paths'; import { IDisposable, diff --git a/src/client/common/logger.ts b/src/client/common/logger.ts deleted file mode 100644 index ab1f3922c376..000000000000 --- a/src/client/common/logger.ts +++ /dev/null @@ -1,10 +0,0 @@ -// These are all just temporary aliases, for backward compatibility -// and to avoid churn. -export { - traceDecorators, - logError as traceError, - logInfo as traceInfo, - logVerbose as traceVerbose, - logWarning as traceWarning, -} from '../logging'; -export { TraceOptions as LogOptions } from '../logging/trace'; diff --git a/src/client/common/net/httpClient.ts b/src/client/common/net/httpClient.ts index b7528d3309b9..8aac63d17142 100644 --- a/src/client/common/net/httpClient.ts +++ b/src/client/common/net/httpClient.ts @@ -8,8 +8,8 @@ import { parse, ParseError } from 'jsonc-parser'; import type * as requestTypes from 'request'; import { IHttpClient } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; +import { traceError } from '../../logging'; import { IWorkspaceService } from '../application/types'; -import { traceError } from '../logger'; @injectable() export class HttpClient implements IHttpClient { diff --git a/src/client/common/persistentState.ts b/src/client/common/persistentState.ts index f8ec0b1bc032..188a9b42c1d6 100644 --- a/src/client/common/persistentState.ts +++ b/src/client/common/persistentState.ts @@ -6,9 +6,9 @@ import { inject, injectable, named } from 'inversify'; import { Memento } from 'vscode'; import { IExtensionSingleActivationService } from '../activation/types'; +import { traceError, traceVerbose } from '../logging'; import { ICommandManager } from './application/types'; import { Commands } from './constants'; -import { traceError, traceVerbose } from './logger'; import { GLOBAL_MEMENTO, IExtensionContext, diff --git a/src/client/common/platform/fileSystem.ts b/src/client/common/platform/fileSystem.ts index 64d6fffcf3f0..9d66887f4c39 100644 --- a/src/client/common/platform/fileSystem.ts +++ b/src/client/common/platform/fileSystem.ts @@ -10,8 +10,8 @@ import * as glob from 'glob'; import { injectable } from 'inversify'; import { promisify } from 'util'; import * as vscode from 'vscode'; +import { traceError } from '../../logging'; import '../extensions'; -import { traceError } from '../logger'; import { convertFileType } from '../utils/filesystem'; import { createDirNotEmptyError, isFileExistsError, isFileNotFoundError, isNoPermissionsError } from './errors'; import { FileSystemPaths, FileSystemPathUtils } from './fs-paths'; diff --git a/src/client/common/platform/fileSystemWatcher.ts b/src/client/common/platform/fileSystemWatcher.ts index 1ef9be0e1a21..5c8c966cf9a7 100644 --- a/src/client/common/platform/fileSystemWatcher.ts +++ b/src/client/common/platform/fileSystemWatcher.ts @@ -6,7 +6,7 @@ import * as chokidar from 'chokidar'; import * as path from 'path'; import { RelativePattern, workspace } from 'vscode'; -import { traceError, traceVerbose } from '../logger'; +import { traceError, traceVerbose } from '../../logging'; import { Disposables, IDisposable } from '../utils/resourceLifecycle'; import { normCasePath } from './fs-paths'; diff --git a/src/client/common/platform/registry.ts b/src/client/common/platform/registry.ts index 33ad688496a1..f1978cfa6dda 100644 --- a/src/client/common/platform/registry.ts +++ b/src/client/common/platform/registry.ts @@ -1,6 +1,6 @@ import { injectable } from 'inversify'; import { Options } from 'winreg'; -import { traceError } from '../logger'; +import { traceError } from '../../logging'; import { Architecture } from '../utils/platform'; import { IRegistry, RegistryHive } from './types'; diff --git a/src/client/common/process/logger.ts b/src/client/common/process/logger.ts index 8d3e8125fa5b..7a37e716c096 100644 --- a/src/client/common/process/logger.ts +++ b/src/client/common/process/logger.ts @@ -4,8 +4,8 @@ 'use strict'; import { inject, injectable, named } from 'inversify'; +import { traceInfo } from '../../logging'; import { isCI, isTestExecution, STANDARD_OUTPUT_CHANNEL } from '../constants'; -import { traceInfo } from '../logger'; import { IOutputChannel, IPathUtils } from '../types'; import { Logging } from '../utils/localize'; import { IProcessLogger, SpawnOptions } from './types'; diff --git a/src/client/common/process/pythonEnvironment.ts b/src/client/common/process/pythonEnvironment.ts index a100f1c55351..0c4a54cc5fd5 100644 --- a/src/client/common/process/pythonEnvironment.ts +++ b/src/client/common/process/pythonEnvironment.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import { traceError, traceInfo } from '../../logging'; import { CondaEnvironmentInfo } from '../../pythonEnvironments/common/environmentManagers/conda'; import { buildPythonExecInfo, PythonExecInfo } from '../../pythonEnvironments/exec'; import { InterpreterInformation } from '../../pythonEnvironments/info'; import { getExecutablePath } from '../../pythonEnvironments/info/executable'; import { getInterpreterInfo } from '../../pythonEnvironments/info/interpreter'; -import { traceError, traceInfo } from '../logger'; import { IFileSystem } from '../platform/types'; import * as internalPython from './internal/python'; import { ExecutionResult, IProcessService, ShellOptions, SpawnOptions } from './types'; diff --git a/src/client/common/process/pythonExecutionFactory.ts b/src/client/common/process/pythonExecutionFactory.ts index 9a5a6c211f70..f48a526c23bb 100644 --- a/src/client/common/process/pythonExecutionFactory.ts +++ b/src/client/common/process/pythonExecutionFactory.ts @@ -27,7 +27,7 @@ import { } from './types'; import { IInterpreterAutoSelectionService } from '../../interpreter/autoSelection/types'; import { sleep } from '../utils/async'; -import { traceError } from '../logger'; +import { traceError } from '../../logging'; // Minimum version number of conda required to be able to use 'conda run' export const CONDA_RUN_VERSION = '4.6.0'; diff --git a/src/client/common/terminal/helper.ts b/src/client/common/terminal/helper.ts index eb810bf78c84..1be0a94aba31 100644 --- a/src/client/common/terminal/helper.ts +++ b/src/client/common/terminal/helper.ts @@ -5,12 +5,12 @@ import { inject, injectable, multiInject, named } from 'inversify'; import { Terminal, Uri } from 'vscode'; import { IComponentAdapter, IInterpreterService } from '../../interpreter/contracts'; import { IServiceContainer } from '../../ioc/types'; +import { traceDecoratorError, traceError } from '../../logging'; import { EnvironmentType, PythonEnvironment } from '../../pythonEnvironments/info'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { ITerminalManager } from '../application/types'; import '../extensions'; -import { traceDecorators, traceError } from '../logger'; import { IPlatformService } from '../platform/types'; import { IConfigurationService, Resource } from '../types'; import { OSType } from '../utils/platform'; @@ -100,7 +100,7 @@ export class TerminalHelper implements ITerminalHelper { ).ignoreErrors(); return promise; } - @traceDecorators.error('Failed to capture telemetry') + @traceDecoratorError('Failed to capture telemetry') protected async sendTelemetry( terminalShellType: TerminalShellType, eventName: EventName, diff --git a/src/client/common/terminal/shellDetector.ts b/src/client/common/terminal/shellDetector.ts index a584652007ce..aaf04f6d057b 100644 --- a/src/client/common/terminal/shellDetector.ts +++ b/src/client/common/terminal/shellDetector.ts @@ -5,10 +5,10 @@ import { inject, injectable, multiInject } from 'inversify'; import { Terminal } from 'vscode'; +import { traceVerbose } from '../../logging'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import '../extensions'; -import { traceVerbose } from '../logger'; import { IPlatformService } from '../platform/types'; import { OSType } from '../utils/platform'; import { IShellDetector, ShellIdentificationTelemetry, TerminalShellType } from './types'; diff --git a/src/client/common/terminal/shellDetectors/baseShellDetector.ts b/src/client/common/terminal/shellDetectors/baseShellDetector.ts index 95c09567601f..4716af1a34e4 100644 --- a/src/client/common/terminal/shellDetectors/baseShellDetector.ts +++ b/src/client/common/terminal/shellDetectors/baseShellDetector.ts @@ -5,7 +5,7 @@ import { injectable, unmanaged } from 'inversify'; import { Terminal } from 'vscode'; -import { traceVerbose } from '../../logger'; +import { traceVerbose } from '../../../logging'; import { IShellDetector, ShellIdentificationTelemetry, TerminalShellType } from '../types'; /* diff --git a/src/client/common/terminal/shellDetectors/settingsShellDetector.ts b/src/client/common/terminal/shellDetectors/settingsShellDetector.ts index 25384603cb68..7ffc168db28b 100644 --- a/src/client/common/terminal/shellDetectors/settingsShellDetector.ts +++ b/src/client/common/terminal/shellDetectors/settingsShellDetector.ts @@ -5,8 +5,8 @@ import { inject, injectable } from 'inversify'; import { Terminal } from 'vscode'; +import { traceVerbose } from '../../../logging'; import { IWorkspaceService } from '../../application/types'; -import { traceVerbose } from '../../logger'; import { IPlatformService } from '../../platform/types'; import { OSType } from '../../utils/platform'; import { ShellIdentificationTelemetry, TerminalShellType } from '../types'; diff --git a/src/client/common/terminal/shellDetectors/terminalNameShellDetector.ts b/src/client/common/terminal/shellDetectors/terminalNameShellDetector.ts index 134ff4c65114..80911e85c1b5 100644 --- a/src/client/common/terminal/shellDetectors/terminalNameShellDetector.ts +++ b/src/client/common/terminal/shellDetectors/terminalNameShellDetector.ts @@ -5,7 +5,7 @@ import { injectable } from 'inversify'; import { Terminal } from 'vscode'; -import { traceVerbose } from '../../logger'; +import { traceVerbose } from '../../../logging'; import { ShellIdentificationTelemetry, TerminalShellType } from '../types'; import { BaseShellDetector } from './baseShellDetector'; diff --git a/src/client/common/terminal/shellDetectors/userEnvironmentShellDetector.ts b/src/client/common/terminal/shellDetectors/userEnvironmentShellDetector.ts index 83ad5e25f662..7d8ed34ebf62 100644 --- a/src/client/common/terminal/shellDetectors/userEnvironmentShellDetector.ts +++ b/src/client/common/terminal/shellDetectors/userEnvironmentShellDetector.ts @@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify'; import { Terminal } from 'vscode'; -import { traceVerbose } from '../../logger'; +import { traceVerbose } from '../../../logging'; import { IPlatformService } from '../../platform/types'; import { ICurrentProcess } from '../../types'; import { OSType } from '../../utils/platform'; diff --git a/src/client/common/terminal/shellDetectors/vscEnvironmentShellDetector.ts b/src/client/common/terminal/shellDetectors/vscEnvironmentShellDetector.ts index 30bee81db6a8..a4592374b36f 100644 --- a/src/client/common/terminal/shellDetectors/vscEnvironmentShellDetector.ts +++ b/src/client/common/terminal/shellDetectors/vscEnvironmentShellDetector.ts @@ -5,8 +5,8 @@ import { inject } from 'inversify'; import { Terminal } from 'vscode'; +import { traceVerbose } from '../../../logging'; import { IApplicationEnvironment } from '../../application/types'; -import { traceVerbose } from '../../logger'; import { ShellIdentificationTelemetry, TerminalShellType } from '../types'; import { BaseShellDetector } from './baseShellDetector'; diff --git a/src/client/common/terminal/syncTerminalService.ts b/src/client/common/terminal/syncTerminalService.ts index d3f19aa9a04b..4e95ddab01b5 100644 --- a/src/client/common/terminal/syncTerminalService.ts +++ b/src/client/common/terminal/syncTerminalService.ts @@ -6,9 +6,9 @@ import { inject } from 'inversify'; import { CancellationToken, Disposable, Event } from 'vscode'; import { IInterpreterService } from '../../interpreter/contracts'; +import { traceVerbose } from '../../logging'; import { PythonEnvironment } from '../../pythonEnvironments/info'; import { Cancellation } from '../cancellation'; -import { traceVerbose } from '../logger'; import { IFileSystem, TemporaryFile } from '../platform/types'; import * as internalScripts from '../process/internal/scripts'; import { createDeferred, Deferred } from '../utils/async'; diff --git a/src/client/common/utils/decorators.ts b/src/client/common/utils/decorators.ts index c024e4e9d048..689eb9acad44 100644 --- a/src/client/common/utils/decorators.ts +++ b/src/client/common/utils/decorators.ts @@ -1,9 +1,8 @@ import '../../common/extensions'; +import { traceError, traceVerbose } from '../../logging'; import { isTestExecution } from '../constants'; -import { traceError, traceVerbose } from '../logger'; import { createDeferred, Deferred } from './async'; import { getCacheKeyFromFunctionArgs, getGlobalCacheStore } from './cacheUtils'; -import { TraceInfo, tracing } from './misc'; import { StopWatch } from './stopWatch'; const _debounce = require('lodash/debounce') as typeof import('lodash/debounce'); @@ -216,42 +215,3 @@ export function swallowExceptions(scopeName?: string) { }; }; } - -// Information about a function/method call. -export type CallInfo = { - kind: string; // "Class", etc. - name: string; - - args: any[]; -}; - -export type TraceDecoratorType = ( - _: Object, - __: string, - descriptor: TypedPropertyDescriptor, -) => TypedPropertyDescriptor; - -// Return a decorator that traces the decorated function. -export function trace(log: (c: CallInfo, t: TraceInfo) => void): TraceDecoratorType { - return function (_: Object, __: string, descriptor: TypedPropertyDescriptor) { - const originalMethod = descriptor.value; - - descriptor.value = function (...args: any[]) { - const call = { - kind: 'Class', - name: _ && _.constructor ? _.constructor.name : '', - args, - }; - - const scope = this; - return tracing( - // "log()" - (t) => log(call, t), - // "run()" - () => originalMethod.apply(scope, args), - ); - }; - - return descriptor; - }; -} diff --git a/src/client/common/utils/delayTrigger.ts b/src/client/common/utils/delayTrigger.ts index 85ff5695714c..d110e005fc48 100644 --- a/src/client/common/utils/delayTrigger.ts +++ b/src/client/common/utils/delayTrigger.ts @@ -3,7 +3,7 @@ import { clearTimeout, setTimeout } from 'timers'; import { Disposable } from 'vscode'; -import { traceVerbose } from '../logger'; +import { traceVerbose } from '../../logging'; /* eslint-disable @typescript-eslint/no-explicit-any */ diff --git a/src/client/common/utils/filesystem.ts b/src/client/common/utils/filesystem.ts index 97e0ba124259..11fe52d6d495 100644 --- a/src/client/common/utils/filesystem.ts +++ b/src/client/common/utils/filesystem.ts @@ -4,7 +4,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; -import { logError } from '../../logging'; +import { traceError } from '../../logging'; import { getOSType, OSType } from './platform'; /** @@ -68,7 +68,7 @@ export async function getFileType( return undefined; } if (opts.ignoreErrors) { - logError(`lstat() failed for "${filename}" (${err})`); + traceError(`lstat() failed for "${filename}" (${err})`); return FileType.Unknown; } throw err; // re-throw diff --git a/src/client/common/utils/misc.ts b/src/client/common/utils/misc.ts index 1a6fd33e7fea..c95a3cc75575 100644 --- a/src/client/common/utils/misc.ts +++ b/src/client/common/utils/misc.ts @@ -6,8 +6,6 @@ import { InteractiveInputScheme, NotebookCellScheme } from '../constants'; import { InterpreterUri } from '../installer/types'; import { isParentPath } from '../platform/fs-paths'; import { Resource } from '../types'; -import { isPromise } from './async'; -import { StopWatch } from './stopWatch'; export function noop() {} @@ -25,44 +23,6 @@ type DeepReadonlyObject = { }; type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]; -// Information about a traced function/method call. -export type TraceInfo = { - elapsed: number; // milliseconds - // Either returnValue or err will be set. - - returnValue?: any; - err?: Error; -}; - -// Call run(), call log() with the trace info, and return the result. -export function tracing(log: (t: TraceInfo) => void, run: () => T): T { - const timer = new StopWatch(); - try { - const result = run(); - - // If method being wrapped returns a promise then wait for it. - if (isPromise(result)) { - (result as Promise) - .then((data) => { - log({ elapsed: timer.elapsedTime, returnValue: data }); - return data; - }) - .catch((ex) => { - log({ elapsed: timer.elapsedTime, err: ex }); - - // TODO(GH-11645) Re-throw the error like we do - // in the non-Promise case. - }); - } else { - log({ elapsed: timer.elapsedTime, returnValue: result }); - } - return result; - } catch (ex) { - log({ elapsed: timer.elapsedTime, err: ex }); - throw ex; - } -} - /** * Checking whether something is a Resource (Uri/undefined). * Using `instanceof Uri` doesn't always work as the object is not an instance of Uri (at least not in tests). diff --git a/src/client/common/utils/resourceLifecycle.ts b/src/client/common/utils/resourceLifecycle.ts index 9e78c66877ab..5724c2f381c6 100644 --- a/src/client/common/utils/resourceLifecycle.ts +++ b/src/client/common/utils/resourceLifecycle.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { logWarning } from '../../logging'; +import { traceWarn } from '../../logging'; /** * An object that can be disposed, like vscode.Disposable. @@ -26,7 +26,7 @@ async function disposeAll(disposables: IDisposable[]): Promise { try { await d.dispose(); } catch (err) { - logWarning(`dispose() #${index} failed (${err})`); + traceWarn(`dispose() #${index} failed (${err})`); } }), ); diff --git a/src/client/common/utils/workerPool.ts b/src/client/common/utils/workerPool.ts index ba1d4d8e55cb..5debd5b6f40f 100644 --- a/src/client/common/utils/workerPool.ts +++ b/src/client/common/utils/workerPool.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { traceError } from '../logger'; +import { traceError } from '../../logging'; import { createDeferred, Deferred } from './async'; interface IWorker { diff --git a/src/client/common/variables/environment.ts b/src/client/common/variables/environment.ts index c08ce6285b3d..60042c9b452c 100644 --- a/src/client/common/variables/environment.ts +++ b/src/client/common/variables/environment.ts @@ -3,9 +3,9 @@ import { inject, injectable } from 'inversify'; import * as path from 'path'; +import { traceError } from '../../logging'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; -import { traceError } from '../logger'; import { IFileSystem } from '../platform/types'; import { IPathUtils } from '../types'; import { EnvironmentVariables, IEnvironmentVariablesService } from './types'; diff --git a/src/client/common/variables/environmentVariablesProvider.ts b/src/client/common/variables/environmentVariablesProvider.ts index 2736a2dd8856..48864e69d509 100644 --- a/src/client/common/variables/environmentVariablesProvider.ts +++ b/src/client/common/variables/environmentVariablesProvider.ts @@ -3,10 +3,10 @@ import { inject, injectable, optional } from 'inversify'; import { ConfigurationChangeEvent, Disposable, Event, EventEmitter, FileSystemWatcher, Uri } from 'vscode'; +import { traceVerbose } from '../../logging'; import { sendFileCreationTelemetry } from '../../telemetry/envFileTelemetry'; import { IWorkspaceService } from '../application/types'; import { PythonSettings } from '../configSettings'; -import { traceVerbose } from '../logger'; import { IPlatformService } from '../platform/types'; import { ICurrentProcess, IDisposableRegistry } from '../types'; import { InMemoryCache } from '../utils/cacheUtils'; diff --git a/src/client/debugger/extension/adapter/factory.ts b/src/client/debugger/extension/adapter/factory.ts index c54d3c8d44dd..2b74a873e7ee 100644 --- a/src/client/debugger/extension/adapter/factory.ts +++ b/src/client/debugger/extension/adapter/factory.ts @@ -13,9 +13,9 @@ import { WorkspaceFolder, } from 'vscode'; import { IApplicationShell } from '../../../common/application/types'; -import { traceVerbose } from '../../../common/logger'; import { EXTENSION_ROOT_DIR } from '../../../constants'; import { IInterpreterService } from '../../../interpreter/contracts'; +import { traceVerbose } from '../../../logging'; import { sendTelemetryEvent } from '../../../telemetry'; import { EventName } from '../../../telemetry/constants'; import { AttachRequestArguments, LaunchRequestArguments } from '../../types'; diff --git a/src/client/debugger/extension/banner.ts b/src/client/debugger/extension/banner.ts index a025d06082b7..84ea1a67874d 100644 --- a/src/client/debugger/extension/banner.ts +++ b/src/client/debugger/extension/banner.ts @@ -7,9 +7,9 @@ import { inject, injectable } from 'inversify'; import { Disposable, env, UIKind } from 'vscode'; import { IApplicationShell, IDebugService } from '../../common/application/types'; import '../../common/extensions'; -import { traceError } from '../../common/logger'; import { IBrowserService, IDisposableRegistry, IPersistentStateFactory, IRandom } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; +import { traceError } from '../../logging'; import { DebuggerTypeName } from '../constants'; import { IDebuggerBanner } from './types'; diff --git a/src/client/extension.ts b/src/client/extension.ts index 6505da54f5f3..500a8ecd826a 100644 --- a/src/client/extension.ts +++ b/src/client/extension.ts @@ -9,8 +9,6 @@ if ((Reflect as any).metadata === undefined) { // Initialize source maps (this must never be moved up nor further down). import { initialize } from './sourceMapSupport'; initialize(require('vscode')); -// Initialize the logger first. -require('./common/logger'); //=============================================== // We start tracking the extension's startup time at this point. The @@ -22,6 +20,11 @@ import { StopWatch } from './common/utils/stopWatch'; // Do not move this line of code (used to measure extension load times). const stopWatch = new StopWatch(); +// Initialize file logging here. This should not depend on too many things. +import { initializeFileLogging, traceError } from './logging'; +const logDispose: { dispose: () => void }[] = []; +initializeFileLogging(logDispose); + //=============================================== // loading starts here @@ -29,7 +32,6 @@ import { ProgressLocation, ProgressOptions, window } from 'vscode'; import { buildApi, IExtensionApi } from './api'; import { IApplicationShell, IWorkspaceService } from './common/application/types'; -import { traceError } from './common/logger'; import { IAsyncDisposableRegistry, IExperimentService, IExtensionContext } from './common/types'; import { createDeferred } from './common/utils/async'; import { Common } from './common/utils/localize'; @@ -61,7 +63,7 @@ export async function activate(context: IExtensionContext): Promise, IServiceContainer]> { + // Add anything that we got from initializing logs to dispose. + context.subscriptions.push(...logDispose); + const activationDeferred = createDeferred(); displayProgress(activationDeferred.promise); startupDurations.startActivateTime = startupStopWatch.elapsedTime; diff --git a/src/client/extensionInit.ts b/src/client/extensionInit.ts index 650e8092ca24..1a8bba2e7c76 100644 --- a/src/client/extensionInit.ts +++ b/src/client/extensionInit.ts @@ -23,10 +23,11 @@ import { ExtensionState } from './components'; import { ServiceContainer } from './ioc/container'; import { ServiceManager } from './ioc/serviceManager'; import { IServiceContainer, IServiceManager } from './ioc/types'; -import { addOutputChannelLogging } from './logging'; import * as pythonEnvironments from './pythonEnvironments'; import { TEST_OUTPUT_CHANNEL } from './testing/constants'; import { IDiscoveryAPI } from './pythonEnvironments/base/locator'; +import { registerLogger } from './logging'; +import { OutputChannelLogger } from './logging/outputChannelLogger'; // The code in this module should do nothing more complex than register // objects to DI and simple init (e.g. no side effects). That implies @@ -51,7 +52,8 @@ export function initializeGlobals( serviceManager.addSingletonInstance(IExtensionContext, context); const standardOutputChannel = window.createOutputChannel(OutputChannelNames.python()); - addOutputChannelLogging(standardOutputChannel); + context.subscriptions.push(registerLogger(new OutputChannelLogger(standardOutputChannel))); + const unitTestOutChannel = window.createOutputChannel(OutputChannelNames.pythonTest()); serviceManager.addSingletonInstance(IOutputChannel, standardOutputChannel, STANDARD_OUTPUT_CHANNEL); serviceManager.addSingletonInstance(IOutputChannel, unitTestOutChannel, TEST_OUTPUT_CHANNEL); diff --git a/src/client/formatters/baseFormatter.ts b/src/client/formatters/baseFormatter.ts index bde2c6465838..b05ab916ffb1 100644 --- a/src/client/formatters/baseFormatter.ts +++ b/src/client/formatters/baseFormatter.ts @@ -4,12 +4,12 @@ import { IApplicationShell, IWorkspaceService } from '../common/application/type import { STANDARD_OUTPUT_CHANNEL } from '../common/constants'; import '../common/extensions'; import { isNotInstalledError } from '../common/helpers'; -import { traceError } from '../common/logger'; import { IFileSystem } from '../common/platform/types'; import { IPythonToolExecutionService } from '../common/process/types'; import { IDisposableRegistry, IInstaller, IOutputChannel, Product } from '../common/types'; import { isNotebookCell } from '../common/utils/misc'; import { IServiceContainer } from '../ioc/types'; +import { traceError } from '../logging'; import { getTempFileWithDocumentContents, getTextEditsFromPatch } from './../common/editor'; import { IFormatterHelper } from './types'; diff --git a/src/client/interpreter/activation/service.ts b/src/client/interpreter/activation/service.ts index 64e45055f4cc..54422b840b5f 100644 --- a/src/client/interpreter/activation/service.ts +++ b/src/client/interpreter/activation/service.ts @@ -7,7 +7,6 @@ import { inject, injectable } from 'inversify'; import { IWorkspaceService } from '../../common/application/types'; import { PYTHON_WARNINGS } from '../../common/constants'; -import { LogOptions, traceDecorators, traceError, traceInfo, traceVerbose, traceWarning } from '../../common/logger'; import { IPlatformService } from '../../common/platform/types'; import * as internalScripts from '../../common/process/internal/scripts'; import { ExecutionResult, IProcessServiceFactory } from '../../common/process/types'; @@ -22,6 +21,15 @@ import { captureTelemetry, sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { IInterpreterService } from '../contracts'; import { IEnvironmentActivationService } from './types'; +import { TraceOptions } from '../../logging/types'; +import { + traceDecoratorError, + traceDecoratorVerbose, + traceError, + traceInfo, + traceVerbose, + traceWarn, +} from '../../logging'; const ENVIRONMENT_PREFIX = 'e8b39361-0157-4923-80e1-22d70d46dee6'; const CACHE_DURATION = 10 * 60 * 1000; @@ -117,7 +125,7 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi public dispose(): void { this.disposables.forEach((d) => d.dispose()); } - @traceDecorators.verbose('getActivatedEnvironmentVariables', LogOptions.Arguments) + @traceDecoratorVerbose('getActivatedEnvironmentVariables', TraceOptions.Arguments) @captureTelemetry(EventName.PYTHON_INTERPRETER_ACTIVATION_ENVIRONMENT_VARIABLES, { failed: false }, true) public async getActivatedEnvironmentVariables( resource: Resource, @@ -217,7 +225,7 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi } if (result.stderr) { if (returnedEnv) { - traceWarning('Got env variables but with errors', result.stderr); + traceWarn('Got env variables but with errors', result.stderr); } else { throw new Error(`StdErr from ShellExec, ${result.stderr} for ${command}`); } @@ -262,8 +270,8 @@ export class EnvironmentActivationService implements IEnvironmentActivationServi // Replace 'source ' with '. ' as that works in shell exec return commands.map((cmd) => cmd.replace(/^source\s+/, '. ')); } - @traceDecorators.error('Failed to parse Environment variables') - @traceDecorators.verbose('parseEnvironmentOutput', LogOptions.None) + @traceDecoratorError('Failed to parse Environment variables') + @traceDecoratorVerbose('parseEnvironmentOutput', TraceOptions.None) protected parseEnvironmentOutput(output: string, parse: (out: string) => NodeJS.ProcessEnv | undefined) { output = output.substring(output.indexOf(ENVIRONMENT_PREFIX) + ENVIRONMENT_PREFIX.length); const js = output.substring(output.indexOf('{')).trim(); diff --git a/src/client/interpreter/configuration/pythonPathUpdaterService.ts b/src/client/interpreter/configuration/pythonPathUpdaterService.ts index 43bce0dca0c6..7bd1f99bd125 100644 --- a/src/client/interpreter/configuration/pythonPathUpdaterService.ts +++ b/src/client/interpreter/configuration/pythonPathUpdaterService.ts @@ -1,8 +1,8 @@ import { inject, injectable } from 'inversify'; import * as path from 'path'; import { ConfigurationTarget, Uri, window } from 'vscode'; -import { traceError } from '../../common/logger'; import { StopWatch } from '../../common/utils/stopWatch'; +import { traceError } from '../../logging'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { PythonInterpreterTelemetry } from '../../telemetry/types'; diff --git a/src/client/interpreter/display/progressDisplay.ts b/src/client/interpreter/display/progressDisplay.ts index ada2594b2e37..d273b94801ac 100644 --- a/src/client/interpreter/display/progressDisplay.ts +++ b/src/client/interpreter/display/progressDisplay.ts @@ -7,10 +7,10 @@ import { inject, injectable } from 'inversify'; import { Disposable, ProgressLocation, ProgressOptions } from 'vscode'; import { IExtensionSingleActivationService } from '../../activation/types'; import { IApplicationShell } from '../../common/application/types'; -import { traceDecorators } from '../../common/logger'; import { IDisposableRegistry } from '../../common/types'; import { createDeferred, Deferred } from '../../common/utils/async'; import { Interpreters } from '../../common/utils/localize'; +import { traceDecoratorVerbose } from '../../logging'; import { IComponentAdapter } from '../contracts'; // The parts of IComponentAdapter used here. @@ -39,14 +39,14 @@ export class InterpreterLocatorProgressStatubarHandler implements IExtensionSing ); } - @traceDecorators.verbose('Display locator refreshing progress') + @traceDecoratorVerbose('Display locator refreshing progress') private showProgress(): void { if (!this.deferred) { this.createProgress(); } } - @traceDecorators.verbose('Hide locator refreshing progress') + @traceDecoratorVerbose('Hide locator refreshing progress') private hideProgress(): void { if (this.deferred) { this.deferred.resolve(); diff --git a/src/client/interpreter/interpreterService.ts b/src/client/interpreter/interpreterService.ts index eb5b8dd9e586..eb93042a978f 100644 --- a/src/client/interpreter/interpreterService.ts +++ b/src/client/interpreter/interpreterService.ts @@ -3,7 +3,6 @@ import { Disposable, Event, EventEmitter, Uri } from 'vscode'; import '../common/extensions'; import { IDocumentManager, IWorkspaceService } from '../common/application/types'; import { DeprecatePythonPath } from '../common/experiments/groups'; -import { traceError } from '../common/logger'; import { IPythonExecutionFactory } from '../common/process/types'; import { IConfigurationService, @@ -20,6 +19,7 @@ import { PythonEnvironmentsChangedEvent, } from './contracts'; import { PythonLocatorQuery } from '../pythonEnvironments/base/locator'; +import { traceError } from '../logging'; type StoredPythonEnvironment = PythonEnvironment & { store?: boolean }; diff --git a/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts b/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts index 5bde0e33e6d0..09f1ea32f10a 100644 --- a/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts +++ b/src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts @@ -5,10 +5,10 @@ import { inject, injectable, optional } from 'inversify'; import { ConfigurationTarget, Uri } from 'vscode'; import { IExtensionActivationService } from '../../activation/types'; import { IApplicationShell, IWorkspaceService } from '../../common/application/types'; -import { traceDecorators, traceError } from '../../common/logger'; import { IPlatformService } from '../../common/platform/types'; import { IBrowserService, IPersistentStateFactory } from '../../common/types'; import { Common, Interpreters } from '../../common/utils/localize'; +import { traceDecoratorError, traceError } from '../../logging'; import { EnvironmentType } from '../../pythonEnvironments/info'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; @@ -32,7 +32,7 @@ export class CondaInheritEnvPrompt implements IExtensionActivationService { this.initializeInBackground(resource).ignoreErrors(); } - @traceDecorators.error('Failed to intialize conda inherit env prompt') + @traceDecoratorError('Failed to intialize conda inherit env prompt') public async initializeInBackground(resource: Uri): Promise { const show = await this.shouldShowPrompt(resource); if (!show) { @@ -41,7 +41,7 @@ export class CondaInheritEnvPrompt implements IExtensionActivationService { await this.promptAndUpdate(); } - @traceDecorators.error('Failed to display conda inherit env prompt') + @traceDecoratorError('Failed to display conda inherit env prompt') public async promptAndUpdate() { const notificationPromptEnabled = this.persistentStateFactory.createGlobalPersistentState( condaInheritEnvPromptKey, @@ -70,7 +70,7 @@ export class CondaInheritEnvPrompt implements IExtensionActivationService { } } - @traceDecorators.error('Failed to check whether to display prompt for conda inherit env setting') + @traceDecoratorError('Failed to check whether to display prompt for conda inherit env setting') public async shouldShowPrompt(resource: Uri): Promise { if (this.hasPromptBeenShownInCurrentSession) { return false; diff --git a/src/client/interpreter/virtualEnvs/virtualEnvPrompt.ts b/src/client/interpreter/virtualEnvs/virtualEnvPrompt.ts index 5f7dd2499f04..0f8223647c0a 100644 --- a/src/client/interpreter/virtualEnvs/virtualEnvPrompt.ts +++ b/src/client/interpreter/virtualEnvs/virtualEnvPrompt.ts @@ -5,10 +5,10 @@ import { inject, injectable } from 'inversify'; import { ConfigurationTarget, Disposable, Uri } from 'vscode'; import { IExtensionActivationService } from '../../activation/types'; import { IApplicationShell } from '../../common/application/types'; -import { traceDecorators } from '../../common/logger'; import { IDisposableRegistry, IPersistentStateFactory } from '../../common/types'; import { sleep } from '../../common/utils/async'; import { Common, Interpreters } from '../../common/utils/localize'; +import { traceDecoratorError } from '../../logging'; import { PythonEnvironment } from '../../pythonEnvironments/info'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; @@ -33,7 +33,7 @@ export class VirtualEnvironmentPrompt implements IExtensionActivationService { this.disposableRegistry.push(disposable); } - @traceDecorators.error('Error in event handler for detection of new environment') + @traceDecoratorError('Error in event handler for detection of new environment') protected async handleNewEnvironment(resource: Uri): Promise { // Wait for a while, to ensure environment gets created and is accessible (as this is slow on Windows) await sleep(1000); diff --git a/src/client/ioc/container.ts b/src/client/ioc/container.ts index f2dbe77eee79..0f1302061a67 100644 --- a/src/client/ioc/container.ts +++ b/src/client/ioc/container.ts @@ -3,7 +3,7 @@ import { EventEmitter } from 'events'; import { Container, decorate, injectable, interfaces } from 'inversify'; -import { traceWarning } from '../common/logger'; +import { traceWarn } from '../logging'; import { Abstract, IServiceContainer, Newable } from './types'; // This needs to be done once, hence placed in a common location. @@ -13,7 +13,7 @@ import { Abstract, IServiceContainer, Newable } from './types'; try { decorate(injectable(), EventEmitter); } catch (ex) { - traceWarning('Failed to decorate EventEmitter for DI (possibly already decorated by another Extension)', ex); + traceWarn('Failed to decorate EventEmitter for DI (possibly already decorated by another Extension)', ex); } @injectable() diff --git a/src/client/linters/baseLinter.ts b/src/client/linters/baseLinter.ts index c7c57619a6a6..c627b7c539cd 100644 --- a/src/client/linters/baseLinter.ts +++ b/src/client/linters/baseLinter.ts @@ -7,10 +7,10 @@ import * as vscode from 'vscode'; import { IWorkspaceService } from '../common/application/types'; import { isTestExecution } from '../common/constants'; import '../common/extensions'; -import { traceError } from '../common/logger'; import { IPythonToolExecutionService } from '../common/process/types'; import { ExecutionInfo, IConfigurationService, IPythonSettings, Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; +import { traceError } from '../logging'; import { ErrorHandler } from './errorHandlers/errorHandler'; import { ILinter, ILinterInfo, ILinterManager, ILintMessage, LinterId, LintMessageSeverity } from './types'; diff --git a/src/client/linters/errorHandlers/notInstalled.ts b/src/client/linters/errorHandlers/notInstalled.ts index 16871e7ee71f..b11a5d5b6d97 100644 --- a/src/client/linters/errorHandlers/notInstalled.ts +++ b/src/client/linters/errorHandlers/notInstalled.ts @@ -1,8 +1,8 @@ import { OutputChannel, Uri } from 'vscode'; -import { traceError, traceWarning } from '../../common/logger'; import { IPythonExecutionFactory } from '../../common/process/types'; import { ExecutionInfo, Product } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; +import { traceError, traceWarn } from '../../logging'; import { ILinterManager } from '../types'; import { BaseErrorHandler } from './baseErrorHandler'; @@ -27,7 +27,7 @@ export class NotInstalledErrorHandler extends BaseErrorHandler { const info = linterManager.getLinterInfo(execInfo.product!); const customError = `Linter '${info.id}' is not installed. Please install it or select another linter".`; this.outputChannel.appendLine(`\n${customError}\n${error}`); - traceWarning(customError, error); + traceWarn(customError, error); return true; } } diff --git a/src/client/linters/errorHandlers/standard.ts b/src/client/linters/errorHandlers/standard.ts index ca1148332d09..b1763d87ed50 100644 --- a/src/client/linters/errorHandlers/standard.ts +++ b/src/client/linters/errorHandlers/standard.ts @@ -1,8 +1,8 @@ import { OutputChannel, Uri } from 'vscode'; import { IApplicationShell } from '../../common/application/types'; -import { traceError } from '../../common/logger'; import { ExecutionInfo, Product } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; +import { traceError } from '../../logging'; import { ILinterManager, LinterId } from '../types'; import { BaseErrorHandler } from './baseErrorHandler'; diff --git a/src/client/linters/linterManager.ts b/src/client/linters/linterManager.ts index e8ec38c5ca08..4e40f8835e9c 100644 --- a/src/client/linters/linterManager.ts +++ b/src/client/linters/linterManager.ts @@ -5,9 +5,9 @@ import { inject, injectable } from 'inversify'; import { CancellationToken, OutputChannel, TextDocument, Uri } from 'vscode'; -import { traceError } from '../common/logger'; import { IConfigurationService, Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; +import { traceError } from '../logging'; import { Bandit } from './bandit'; import { Flake8 } from './flake8'; import { LinterInfo } from './linterInfo'; diff --git a/src/client/linters/prospector.ts b/src/client/linters/prospector.ts index 50524b2e3b33..7ae7c759df13 100644 --- a/src/client/linters/prospector.ts +++ b/src/client/linters/prospector.ts @@ -1,9 +1,9 @@ import * as path from 'path'; import { CancellationToken, OutputChannel, TextDocument } from 'vscode'; import '../common/extensions'; -import { traceError } from '../common/logger'; import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; +import { traceError } from '../logging'; import { BaseLinter } from './baseLinter'; import { ILintMessage } from './types'; diff --git a/src/client/linters/pydocstyle.ts b/src/client/linters/pydocstyle.ts index 33d9db2cfb07..2702e79404d2 100644 --- a/src/client/linters/pydocstyle.ts +++ b/src/client/linters/pydocstyle.ts @@ -1,9 +1,9 @@ import * as path from 'path'; import { CancellationToken, OutputChannel, TextDocument } from 'vscode'; import '../common/extensions'; -import { traceError } from '../common/logger'; import { Product } from '../common/types'; import { IServiceContainer } from '../ioc/types'; +import { traceError } from '../logging'; import { IS_WINDOWS } from './../common/platform/constants'; import { BaseLinter } from './baseLinter'; import { ILintMessage, LintMessageSeverity } from './types'; diff --git a/src/client/logging/_global.ts b/src/client/logging/_global.ts deleted file mode 100644 index baf7861e7b70..000000000000 --- a/src/client/logging/_global.ts +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -import * as winston from 'winston'; -import { IOutputChannel } from '../common/types'; -import { CallInfo } from '../common/utils/decorators'; -import { getFormatter } from './formatters'; -import { LogLevel, resolveLevelName } from './levels'; -import { configureLogger, createLogger, getPreDefinedConfiguration, logToAll } from './logger'; -import { LogInfo, tracing as _tracing } from './trace'; -import { getPythonOutputChannelTransport, IPythonOutputChannelContent } from './transports'; -import { Arguments } from './util'; - -const globalLogger = createLogger(); -let _globalLoggerContent: IPythonOutputChannelContent; -initialize(); - -/** - * Initialize the logger. - * - * For console we do two things here: - * - Anything written to the logger will be displayed in the console - * window as well This is the behavior of the extension when running - * it. When running tests on CI, we might not want this behavior, as - * it'll pollute the test output with logging (as mentioned this is - * optional). Messages logged using our logger will be prefixed with - * `Python Extension: ....` for console window. This way, its easy - * to identify messages specific to the python extension. - * - Monkey patch the console.log and similar methods to send messages - * to the file logger. When running UI tests or similar, and we want - * to see everything that was dumped into `console window`, then we - * need to hijack the console logger. To do this we need to monkey - * patch the console methods. This is optional (generally done when - * running tests on CI). - * - * For the logfile: - * - we send all logging output to a log file. We log to the file - * only if a file has been specified as an env variable. Currently - * this is setup on CI servers. - */ -function initialize() { - configureLogger(globalLogger, getPreDefinedConfiguration()); -} - -// Set the logging level the extension logs at. -export function setLoggingLevel(level: LogLevel | 'off'): void { - if (level === 'off') { - // For now we disable all logging. One alternative would be - // to only disable logging to the output channel (by removing - // the transport from the logger). - globalLogger.clear(); - } else { - const levelName = resolveLevelName(level, winston.config.npm.levels); - if (levelName) { - globalLogger.level = levelName; - } - } -} - -// Register the output channel transport the logger will log into. -export function addOutputChannelLogging(channel: IOutputChannel): void { - 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); -} - -export function logVerbose(...args: Arguments): void { - log(LogLevel.Info, ...args); -} - -export function logError(...args: Arguments): void { - log(LogLevel.Error, ...args); -} - -export function logInfo(...args: Arguments): void { - log(LogLevel.Info, ...args); -} - -export function logWarning(...args: Arguments): void { - log(LogLevel.Warn, ...args); -} - -// This is like a "context manager" that logs tracing info. -export function tracing(info: LogInfo, run: () => T, call?: CallInfo): T { - return _tracing([globalLogger], info, run, call); -} - -export function getGlobalLogger(): winston.Logger { - return globalLogger; -} diff --git a/src/client/logging/fileLogger.ts b/src/client/logging/fileLogger.ts new file mode 100644 index 000000000000..c04b6c8fc52d --- /dev/null +++ b/src/client/logging/fileLogger.ts @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { WriteStream } from 'fs-extra'; +import * as util from 'util'; +import { Disposable } from 'vscode-jsonrpc'; +import { Arguments, ILogging } from './types'; +import { getTimeForLogging } from './util'; + +function formatMessage(level: string, ...data: Arguments): string { + return `[${level.toUpperCase()} ${getTimeForLogging()}]: ${util.format(...data)}\r\n`; +} + +export class FileLogger implements ILogging, Disposable { + constructor(private readonly stream: WriteStream) {} + + public traceError(...data: Arguments): void { + this.stream.write(formatMessage('error', ...data)); + } + + public traceWarn(...data: Arguments): void { + this.stream.write(formatMessage('warn', ...data)); + } + + public traceInfo(...data: Arguments): void { + this.stream.write(formatMessage('info', ...data)); + } + + public traceVerbose(...data: Arguments): void { + this.stream.write(formatMessage('debug', ...data)); + } + + public dispose(): void { + try { + this.stream.close(); + } catch (ex) { + /** do nothing */ + } + } +} diff --git a/src/client/logging/formatters.ts b/src/client/logging/formatters.ts deleted file mode 100644 index fd349c0e0b71..000000000000 --- a/src/client/logging/formatters.ts +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -import { Format } from 'logform'; -import { format } from 'winston'; -import { isTestExecution } from '../common/constants'; -import { getLevel, LogLevel, LogLevelName } from './levels'; - -const TIMESTAMP = 'YYYY-MM-DD HH:mm:ss'; - -// Knobs used when creating a formatter. -type FormatterOptions = { - label?: string; -}; - -// Pascal casing is used so log files get highlighted when viewing -// in VSC and other editors. -const formattedLogLevels: { [K in LogLevel]: string } = { - [LogLevel.Error]: 'Error', - [LogLevel.Warn]: 'Warn', - [LogLevel.Info]: 'Info', - [LogLevel.Debug]: 'Debug', - [LogLevel.Trace]: 'Trace', -}; - -// Return a consistent representation of the given log level. -function normalizeLevel(name: LogLevelName): string { - const level = getLevel(name); - if (level) { - const norm = formattedLogLevels[level]; - if (norm) { - return norm; - } - } - return `${name.substring(0, 1).toUpperCase()}${name.substring(1).toLowerCase()}`; -} - -// Return a log entry that can be emitted as-is. -function formatMessage(level: LogLevelName, timestamp: string, message: string): string { - const levelFormatted = normalizeLevel(level); - return isTestExecution() - ? `${process.pid} ${levelFormatted} ${timestamp}: ${message}` - : `${levelFormatted} ${timestamp}: ${message}`; -} - -// Return a log entry that can be emitted as-is. -function formatLabeledMessage(level: LogLevelName, timestamp: string, label: string, message: string): string { - const levelFormatted = normalizeLevel(level); - return isTestExecution() - ? `${process.pid} ${levelFormatted} ${label} ${timestamp}: ${message}` - : `${levelFormatted} ${label} ${timestamp}: ${message}`; -} - -// Return a minimal format object that can be used with a "winston" -// logging transport. -function getMinimalFormatter() { - return format.combine( - format.timestamp({ format: TIMESTAMP }), - format.printf( - // This relies on the timestamp formatter we added above: - ({ level, message, timestamp }) => formatMessage(level as LogLevelName, timestamp, message), - ), - ); -} - -// Return a minimal format object that can be used with a "winston" -// logging transport. -function getLabeledFormatter(label_: string) { - return format.combine( - format.label({ label: label_ }), - format.timestamp({ format: TIMESTAMP }), - format.printf( - // This relies on the label and timestamp formatters we added above: - ({ level, message, label, timestamp }) => - formatLabeledMessage(level as LogLevelName, timestamp, label, message), - ), - ); -} - -// Return a format object that can be used with a "winston" logging transport. -export function getFormatter(opts: FormatterOptions = {}): Format { - if (opts.label) { - return getLabeledFormatter(opts.label); - } - return getMinimalFormatter(); -} diff --git a/src/client/logging/index.ts b/src/client/logging/index.ts index 0f949625c282..866b844f275c 100644 --- a/src/client/logging/index.ts +++ b/src/client/logging/index.ts @@ -1,18 +1,234 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -'use strict'; - -export { - // aliases - // (for convenience) - setLoggingLevel, - addOutputChannelLogging, - logError, - logInfo, - logVerbose, - logWarning, - getPythonOutputChannelContent, -} from './_global'; - -export * as traceDecorators from './traceDecorators'; +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { createWriteStream } from 'fs-extra'; +import { isPromise } from 'rxjs/internal-compatibility'; +import { Disposable } from 'vscode'; +import { StopWatch } from '../common/utils/stopWatch'; +import { sendTelemetryEvent } from '../telemetry'; +import { EventName } from '../telemetry/constants'; +import { FileLogger } from './fileLogger'; +import { Arguments, ILogging, LoggingLevelSettingType, LogLevel, TraceDecoratorType, TraceOptions } from './types'; +import { argsToLogString, returnValueToLogString } from './util'; + +const DEFAULT_OPTS: TraceOptions = TraceOptions.Arguments | TraceOptions.ReturnValue; + +let loggers: ILogging[] = []; +export function registerLogger(logger: ILogging): Disposable { + loggers.push(logger); + return { + dispose: () => { + loggers = loggers.filter((l) => l !== logger); + }, + }; +} + +const logLevelMap: Map = new Map([ + ['error', LogLevel.Error], + ['warn', LogLevel.Warn], + ['info', LogLevel.Info], + ['debug', LogLevel.Debug], + ['none', LogLevel.Off], + ['off', LogLevel.Off], + [undefined, LogLevel.Error], +]); + +let globalLoggingLevel: LogLevel; +export function setLoggingLevel(level?: LoggingLevelSettingType): void { + globalLoggingLevel = logLevelMap.get(level) ?? LogLevel.Error; +} + +export function initializeFileLogging(disposables: Disposable[]): void { + if (process.env.VSC_PYTHON_LOG_FILE) { + const fileLogger = new FileLogger(createWriteStream(process.env.VSC_PYTHON_LOG_FILE)); + disposables.push(fileLogger); + disposables.push(registerLogger(fileLogger)); + } +} + +export function traceError(...args: Arguments): void { + if (globalLoggingLevel >= LogLevel.Error) { + loggers.forEach((l) => l.traceError(...args)); + } +} + +export function traceWarn(...args: Arguments): void { + if (globalLoggingLevel >= LogLevel.Warn) { + loggers.forEach((l) => l.traceWarn(...args)); + } +} + +export function traceInfo(...args: Arguments): void { + if (globalLoggingLevel >= LogLevel.Info) { + loggers.forEach((l) => l.traceInfo(...args)); + } +} + +export function traceVerbose(...args: Arguments): void { + if (globalLoggingLevel >= LogLevel.Debug) { + loggers.forEach((l) => l.traceVerbose(...args)); + } +} + +/** Logging Decorators go here */ + +export function traceDecoratorVerbose(message: string, opts: TraceOptions = DEFAULT_OPTS): TraceDecoratorType { + return createTracingDecorator({ message, opts, level: LogLevel.Debug }); +} +export function traceDecoratorError(message: string): TraceDecoratorType { + return createTracingDecorator({ message, opts: DEFAULT_OPTS, level: LogLevel.Error }); +} +export function traceDecoratorInfo(message: string): TraceDecoratorType { + return createTracingDecorator({ message, opts: DEFAULT_OPTS, level: LogLevel.Info }); +} +export function traceDecoratorWarn(message: string): TraceDecoratorType { + return createTracingDecorator({ message, opts: DEFAULT_OPTS, level: LogLevel.Warn }); +} + +// Information about a function/method call. +type CallInfo = { + kind: string; // "Class", etc. + name: string; + + args: unknown[]; +}; + +// Information about a traced function/method call. +type TraceInfo = { + elapsed: number; // milliseconds + // Either returnValue or err will be set. + + returnValue?: any; + err?: Error; +}; + +type LogInfo = { + opts: TraceOptions; + message: string; + level?: LogLevel; +}; + +// Return a decorator that traces the decorated function. +function traceDecorator(log: (c: CallInfo, t: TraceInfo) => void): TraceDecoratorType { + return function (_: Object, __: string, descriptor: TypedPropertyDescriptor) { + const originalMethod = descriptor.value; + + descriptor.value = function (...args: unknown[]) { + const call = { + kind: 'Class', + name: _ && _.constructor ? _.constructor.name : '', + args, + }; + + // eslint-disable-next-line @typescript-eslint/no-this-alias + const scope = this; + return tracing( + // "log()" + (t) => log(call, t), + // "run()" + () => originalMethod.apply(scope, args), + ); + }; + + return descriptor; + }; +} + +// Call run(), call log() with the trace info, and return the result. +function tracing(log: (t: TraceInfo) => void, run: () => T): T { + const timer = new StopWatch(); + try { + const result = run(); + + // If method being wrapped returns a promise then wait for it. + if (isPromise(result)) { + ((result as unknown) as Promise) + .then((data) => { + log({ elapsed: timer.elapsedTime, returnValue: data }); + return data; + }) + .catch((ex) => { + log({ elapsed: timer.elapsedTime, err: ex }); + + // TODO(GH-11645) Re-throw the error like we do + // in the non-Promise case. + }); + } else { + log({ elapsed: timer.elapsedTime, returnValue: result }); + } + return result; + } catch (ex) { + log({ elapsed: timer.elapsedTime, err: ex as Error | undefined }); + throw ex; + } +} + +function createTracingDecorator(logInfo: LogInfo): TraceDecoratorType { + return traceDecorator((call, traced) => logResult(logInfo, traced, call)); +} + +function normalizeCall(call: CallInfo): CallInfo { + let { kind, name, args } = call; + if (!kind || kind === '') { + kind = 'Function'; + } + if (!name || name === '') { + name = ''; + } + if (!args) { + args = []; + } + return { kind, name, args }; +} + +function formatMessages(logInfo: LogInfo, traced: TraceInfo, call?: CallInfo): string { + call = normalizeCall(call!); + const messages = [logInfo.message]; + messages.push( + `${call.kind} name = ${call.name}`.trim(), + `completed in ${traced.elapsed}ms`, + `has a ${traced.returnValue ? 'truthy' : 'falsy'} return value`, + ); + if ((logInfo.opts & TraceOptions.Arguments) === TraceOptions.Arguments) { + messages.push(argsToLogString(call.args)); + } + if ((logInfo.opts & TraceOptions.ReturnValue) === TraceOptions.ReturnValue) { + messages.push(returnValueToLogString(traced.returnValue)); + } + return messages.join(', '); +} + +function logResult(logInfo: LogInfo, traced: TraceInfo, call?: CallInfo) { + const formatted = formatMessages(logInfo, traced, call); + if (traced.err === undefined) { + // The call did not fail. + if (!logInfo.level || logInfo.level > LogLevel.Error) { + logTo(LogLevel.Info, [formatted]); + } + } else { + logTo(LogLevel.Error, [formatted, traced.err]); + sendTelemetryEvent(('ERROR' as unknown) as EventName, undefined, undefined, traced.err); + } +} + +export function logTo(logLevel: LogLevel, ...args: Arguments): void { + switch (logLevel) { + case LogLevel.Error: + traceError(...args); + break; + case LogLevel.Warn: + traceWarn(...args); + break; + case LogLevel.Info: + traceInfo(...args); + break; + case LogLevel.Debug: + traceVerbose(...args); + break; + default: + break; + } +} diff --git a/src/client/logging/levels.ts b/src/client/logging/levels.ts deleted file mode 100644 index 6d239a65becc..000000000000 --- a/src/client/logging/levels.ts +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -// IMPORTANT: This file should only be importing from the '../client/logging' directory, as we -// delete everything in '../client' except for '../client/logging' before running smoke tests. - -import * as winston from 'winston'; - -// Our custom log levels - -export enum LogLevel { - // Larger numbers are higher priority. - Error = 40, - Warn = 30, - Info = 20, - Debug = 10, - Trace = 5, -} -export type LogLevelName = 'ERROR' | 'WARNING' | 'INFORMATION' | 'DEBUG' | 'DEBUG-TRACE'; -const logLevelMap: { [K in LogLevel]: LogLevelName } = { - [LogLevel.Error]: 'ERROR', - [LogLevel.Warn]: 'WARNING', - [LogLevel.Info]: 'INFORMATION', - [LogLevel.Debug]: 'DEBUG', - [LogLevel.Trace]: 'DEBUG-TRACE', -}; -// This can be used for winston.LoggerOptions.levels. -const configLevels: winston.config.AbstractConfigSetLevels = { - ERROR: 0, - WARNING: 1, - INFORMATION: 2, - DEBUG: 4, - 'DEBUG-TRACE': 5, -}; - -// Other log levels - -// The level names from winston/config.npm. -// See: https://www.npmjs.com/package/winston#logging-levels -type NPMLogLevelName = 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly'; -const npmLogLevelMap: { [K in LogLevel]: NPMLogLevelName } = { - [LogLevel.Error]: 'error', - [LogLevel.Warn]: 'warn', - [LogLevel.Info]: 'info', - [LogLevel.Debug]: 'debug', - [LogLevel.Trace]: 'silly', -}; - -// Lookup functions - -// Convert from LogLevel enum to the proper level name. -export function resolveLevelName( - level: LogLevel, - // Default to configLevels. - levels?: winston.config.AbstractConfigSetLevels, -): string | undefined { - if (levels === undefined) { - return getLevelName(level); - } - if (levels === configLevels) { - return getLevelName(level); - } - if (levels === winston.config.npm.levels) { - return npmLogLevelMap[level]; - } - return undefined; -} -function getLevelName(level: LogLevel): LogLevelName | undefined { - return logLevelMap[level]; -} - -// Convert from a level name to the actual level. -export function resolveLevel( - levelName: string, - // Default to configLevels. - levels?: winston.config.AbstractConfigSetLevels, -): LogLevel | undefined { - let levelMap: { [K in LogLevel]: string }; - if (levels === undefined) { - levelMap = logLevelMap; - } else if (levels === configLevels) { - levelMap = logLevelMap; - } else if (levels === winston.config.npm.levels) { - levelMap = npmLogLevelMap; - } else { - return undefined; - } - for (const level of Object.keys(levelMap)) { - if (typeof level !== 'string' && logLevelMap[level] === levelName) { - return level; - } - } - return undefined; -} -export function getLevel(name: LogLevelName): LogLevel | undefined { - return resolveLevel(name); -} diff --git a/src/client/logging/logger.ts b/src/client/logging/logger.ts deleted file mode 100644 index 5e2e70800b27..000000000000 --- a/src/client/logging/logger.ts +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -// IMPORTANT: This file should only be importing from the '../client/logging' directory, as we -// delete everything in '../client' except for '../client/logging' before running smoke tests. - -import * as util from 'util'; -import * as winston from 'winston'; -import * as Transport from 'winston-transport'; -import { getFormatter } from './formatters'; -import { LogLevel, resolveLevelName } from './levels'; -import { getConsoleTransport, getFileTransport, isConsoleTransport } from './transports'; -import { Arguments } from './util'; - -type LoggerConfig = { - level?: LogLevel; - file?: { - logfile: string; - }; - console?: { - label?: string; - }; -}; - -// Create a logger just the way we like it. -export function createLogger(config?: LoggerConfig): winston.Logger { - const logger = winston.createLogger({ - // We would also set "levels" here. - exitOnError: false, // Do not exit extension host if there is an exception. - }); - if (config) { - configureLogger(logger, config); - } - return logger; -} - -interface IConfigurableLogger { - level: string; - add(transport: Transport): void; -} - -/** - * TODO: We should actually have this method in `./_global.ts` as this is exported globally. - * But for some reason, importing '../client/logging/_global' fails when launching the tests. - * More details in the comment https://github.com/microsoft/vscode-python/pull/11897#discussion_r433954993 - * https://github.com/microsoft/vscode-python/issues/12137 - */ -export function getPreDefinedConfiguration(): LoggerConfig { - const config: LoggerConfig = {}; - - // Do not log to console if running tests and we're not - // asked to do so. - if (process.env.VSC_PYTHON_FORCE_LOGGING) { - config.console = {}; - // In CI there's no need for the label. - const isCI = process.env.TRAVIS === 'true' || process.env.TF_BUILD !== undefined; - if (!isCI) { - config.console.label = 'Python Extension:'; - } - } - if (process.env.VSC_PYTHON_LOG_FILE) { - config.file = { - logfile: process.env.VSC_PYTHON_LOG_FILE, - }; - } - return config; -} - -// Set up a logger just the way we like it. -export function configureLogger(logger: IConfigurableLogger, config: LoggerConfig): void { - if (config.level) { - const levelName = resolveLevelName(config.level); - if (levelName) { - logger.level = levelName; - } - } - - if (config.file) { - const formatter = getFormatter(); - const transport = getFileTransport(config.file.logfile, formatter); - logger.add(transport); - } - if (config.console) { - const formatter = getFormatter({ label: config.console.label }); - const transport = getConsoleTransport(formatter); - logger.add(transport); - } -} - -export interface ILogger { - transports: unknown[]; - levels: winston.config.AbstractConfigSetLevels; - log(level: string, message: string): void; -} - -// Emit a log message derived from the args to all enabled transports. -export function logToAll(loggers: ILogger[], logLevel: LogLevel, args: Arguments): void { - const message = args.length === 0 ? '' : util.format(args[0], ...args.slice(1)); - for (const logger of loggers) { - if (logger.transports.length > 0) { - const levelName = getLevelName(logLevel, logger.levels, isConsoleLogger(logger)); - logger.log(levelName, message); - } - } -} - -function isConsoleLogger(logger: ILogger): boolean { - for (const transport of logger.transports) { - if (isConsoleTransport(transport)) { - return true; - } - } - return false; -} - -function getLevelName(level: LogLevel, levels: winston.config.AbstractConfigSetLevels, isConsole?: boolean): string { - const levelName = resolveLevelName(level, levels); - if (levelName) { - return levelName; - } - if (isConsole) { - // XXX Hard-coding this is fragile: - return 'silly'; - } - return resolveLevelName(LogLevel.Info, levels) || 'info'; -} diff --git a/src/client/logging/outputChannelLogger.ts b/src/client/logging/outputChannelLogger.ts new file mode 100644 index 000000000000..bd2e3c841724 --- /dev/null +++ b/src/client/logging/outputChannelLogger.ts @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as util from 'util'; +import { OutputChannel } from 'vscode'; +import { Arguments, ILogging } from './types'; +import { getTimeForLogging } from './util'; + +function formatMessage(level: string, ...data: Arguments): string { + return `[${level.toUpperCase()} ${getTimeForLogging()}]: ${util.format(...data)}`; +} + +export class OutputChannelLogger implements ILogging { + constructor(private readonly channel: OutputChannel) {} + + public traceError(...data: Arguments): void { + this.channel.appendLine(formatMessage('error', ...data)); + } + + public traceWarn(...data: Arguments): void { + this.channel.appendLine(formatMessage('warn', ...data)); + } + + public traceInfo(...data: Arguments): void { + this.channel.appendLine(formatMessage('info', ...data)); + } + + public traceVerbose(...data: Arguments): void { + this.channel.appendLine(formatMessage('debug', ...data)); + } +} diff --git a/src/client/logging/settings.ts b/src/client/logging/settings.ts index ba0860dfbbc9..97dce79700d2 100644 --- a/src/client/logging/settings.ts +++ b/src/client/logging/settings.ts @@ -1,38 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. - -'use strict'; - +import { LoggingLevelSettingType } from './types'; import { WorkspaceService } from '../common/application/workspace'; -import { LogLevel } from './levels'; - -type LoggingLevelSettingType = 'off' | 'error' | 'warn' | 'info' | 'debug'; /** * Uses Workspace service to query for `python.logging.level` setting and returns it. */ -export function getLoggingLevel(): LogLevel | 'off' { +export function getLoggingLevel(): LoggingLevelSettingType | 'off' { const workspace = new WorkspaceService(); - const value = workspace.getConfiguration('python').get('logging.level'); - return convertSettingTypeToLogLevel(value); -} - -function convertSettingTypeToLogLevel(setting: LoggingLevelSettingType | undefined): LogLevel | 'off' { - switch (setting) { - case 'info': { - return LogLevel.Info; - } - case 'warn': { - return LogLevel.Warn; - } - case 'off': { - return 'off'; - } - case 'debug': { - return LogLevel.Debug; - } - default: { - return LogLevel.Error; - } - } + return workspace.getConfiguration('python').get('logging.level') ?? 'error'; } diff --git a/src/client/logging/trace.ts b/src/client/logging/trace.ts deleted file mode 100644 index f1118b17b61b..000000000000 --- a/src/client/logging/trace.ts +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -import { CallInfo, trace as traceDecorator, TraceDecoratorType } from '../common/utils/decorators'; -import { TraceInfo, tracing as _tracing } from '../common/utils/misc'; -import { sendTelemetryEvent } from '../telemetry'; -import { EventName } from '../telemetry/constants'; -import { LogLevel } from './levels'; -import { ILogger, logToAll } from './logger'; -import { argsToLogString, returnValueToLogString } from './util'; - -// The information we want to log. -export enum TraceOptions { - None = 0, - Arguments = 1, - ReturnValue = 2, -} - -export function createTracingDecorator(loggers: ILogger[], logInfo: LogInfo): TraceDecoratorType { - return traceDecorator((call, traced) => logResult(loggers, logInfo, traced, call)); -} - -// This is like a "context manager" that logs tracing info. -export function tracing(loggers: ILogger[], logInfo: LogInfo, run: () => T, call?: CallInfo): T { - return _tracing((traced) => logResult(loggers, logInfo, traced, call), run); -} - -export type LogInfo = { - opts: TraceOptions; - message: string; - level?: LogLevel; -}; - -function normalizeCall(call: CallInfo): CallInfo { - let { kind, name, args } = call; - if (!kind || kind === '') { - kind = 'Function'; - } - if (!name || name === '') { - name = ''; - } - if (!args) { - args = []; - } - return { kind, name, args }; -} - -function formatMessages(info: LogInfo, traced: TraceInfo, call?: CallInfo): string { - call = normalizeCall(call!); - const messages = [info.message]; - messages.push( - `${call.kind} name = ${call.name}`.trim(), - `completed in ${traced.elapsed}ms`, - `has a ${traced.returnValue ? 'truthy' : 'falsy'} return value`, - ); - if ((info.opts & TraceOptions.Arguments) === TraceOptions.Arguments) { - messages.push(argsToLogString(call.args)); - } - if ((info.opts & TraceOptions.ReturnValue) === TraceOptions.ReturnValue) { - messages.push(returnValueToLogString(traced.returnValue)); - } - return messages.join(', '); -} - -function logResult(loggers: ILogger[], info: LogInfo, traced: TraceInfo, call?: CallInfo) { - const formatted = formatMessages(info, traced, call); - if (traced.err === undefined) { - // The call did not fail. - if (!info.level || info.level > LogLevel.Error) { - logToAll(loggers, LogLevel.Info, [formatted]); - } - } else { - logToAll(loggers, LogLevel.Error, [formatted, traced.err]); - - sendTelemetryEvent(('ERROR' as unknown) as EventName, undefined, undefined, traced.err); - } -} diff --git a/src/client/logging/traceDecorators.ts b/src/client/logging/traceDecorators.ts deleted file mode 100644 index d710b58fd6da..000000000000 --- a/src/client/logging/traceDecorators.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { TraceDecoratorType } from '../common/utils/decorators'; -import { LogLevel } from './levels'; -import { createTracingDecorator, TraceOptions } from './trace'; -import { getGlobalLogger } from './_global'; - -const DEFAULT_OPTS: TraceOptions = TraceOptions.Arguments | TraceOptions.ReturnValue; - -export function verbose(message: string, opts: TraceOptions = DEFAULT_OPTS): TraceDecoratorType { - const globalLogger = getGlobalLogger(); - return createTracingDecorator([globalLogger], { message, opts }); -} -export function error(message: string): TraceDecoratorType { - const opts = DEFAULT_OPTS; - const level = LogLevel.Error; - const globalLogger = getGlobalLogger(); - return createTracingDecorator([globalLogger], { message, opts, level }); -} -export function info(message: string): TraceDecoratorType { - const opts = TraceOptions.None; - const globalLogger = getGlobalLogger(); - return createTracingDecorator([globalLogger], { message, opts }); -} -export function warn(message: string): TraceDecoratorType { - const opts = DEFAULT_OPTS; - const level = LogLevel.Warn; - const globalLogger = getGlobalLogger(); - return createTracingDecorator([globalLogger], { message, opts, level }); -} diff --git a/src/client/logging/transports/consoleTransport.ts b/src/client/logging/transports/consoleTransport.ts deleted file mode 100644 index 6b627bce2af4..000000000000 --- a/src/client/logging/transports/consoleTransport.ts +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -// IMPORTANT: This file should only be importing from the '../../client/logging' directory, as we -// delete everything in '../../client' except for '../../client/logging' before running smoke tests. - -import * as logform from 'logform'; -import * as winston from 'winston'; -import * as Transport from 'winston-transport'; -import { LogLevel, resolveLevel } from '../levels'; -import { Arguments } from '../util'; - -const formattedMessage = Symbol.for('message'); - -// A winston-compatible transport type. -// We do not use transports.ConsoleTransport because it cannot -// adapt to our custom log levels very well. -export class ConsoleTransport extends Transport { - private static funcByLevel: { [K in LogLevel]: (...args: Arguments) => void } = { - [LogLevel.Error]: console.error, - [LogLevel.Warn]: console.warn, - [LogLevel.Info]: console.info, - [LogLevel.Debug]: console.debug, - [LogLevel.Trace]: console.trace, - }; - - private static defaultFunc = console.log; - - // This is used to identify the type. - public readonly isConsole = true; - - constructor( - options?: Transport.TransportStreamOptions, - private readonly levels?: winston.config.AbstractConfigSetLevels, - ) { - super(options); - } - - public log?(info: { level: string; message: string; [formattedMessage]: string }, next: () => void): void { - setImmediate(() => this.emit('logged', info)); - const level = resolveLevel(info.level, this.levels); - const msg = info[formattedMessage] || info.message; - this.logToConsole(level, msg); - if (next) { - next(); - } - } - - // eslint-disable-next-line class-methods-use-this - private logToConsole(level?: LogLevel, msg?: string) { - let func = ConsoleTransport.defaultFunc; - if (level) { - func = ConsoleTransport.funcByLevel[level] || func; - } - func(msg); - } -} - -export function isConsoleTransport(transport: unknown): transport is ConsoleTransport { - return transport !== undefined && (transport as Record).hasOwnProperty('isConsole'); -} - -// Create a console-targeting transport that can be added to a winston logger. -export function getConsoleTransport(formatter: logform.Format): Transport { - return new ConsoleTransport({ - // We minimize customization. - format: formatter, - }); -} diff --git a/src/client/logging/transports/index.ts b/src/client/logging/transports/index.ts deleted file mode 100644 index 28075f211409..000000000000 --- a/src/client/logging/transports/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as logform from 'logform'; -import * as path from 'path'; -import * as winston from 'winston'; -import * as Transport from 'winston-transport'; - -const folderPath = path.dirname(__dirname); -const folderName = path.basename(folderPath); -const EXTENSION_ROOT_DIR = - folderName === 'client' ? path.join(folderPath, '..', '..') : path.join(folderPath, '..', '..', '..', '..'); - -// Create a file-targeting transport that can be added to a winston logger. -export function getFileTransport(logfile: string, formatter: logform.Format): Transport { - if (!path.isAbsolute(logfile)) { - logfile = path.join(EXTENSION_ROOT_DIR, logfile); - } - return new winston.transports.File({ - format: formatter, - filename: logfile, - handleExceptions: true, - }); -} - -export * from './consoleTransport'; -export * from './pythonOutputChannelTransport'; diff --git a/src/client/logging/transports/pythonOutputChannelTransport.ts b/src/client/logging/transports/pythonOutputChannelTransport.ts deleted file mode 100644 index 26ad595db3ab..000000000000 --- a/src/client/logging/transports/pythonOutputChannelTransport.ts +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -// IMPORTANT: This file should only be importing from the '../../client/logging' directory, as we -// delete everything in '../../client' except for '../../client/logging' before running smoke tests. - -import * as logform from 'logform'; -import { EOL } from 'os'; -import { OutputChannel } from 'vscode'; -import * as Transport from 'winston-transport'; - -const formattedMessage = Symbol.for('message'); - -export interface IPythonOutputChannelContent { - getContent(): Promise; -} - -class PythonOutputChannelTransport extends Transport implements IPythonOutputChannelContent { - private content: string[] = []; - - constructor(private readonly channel: OutputChannel, options?: Transport.TransportStreamOptions) { - super(options); - } - - public log?(info: { message: string; [formattedMessage]: string }, next: () => void): void { - setImmediate(() => this.emit('logged', info)); - 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. -export function getPythonOutputChannelTransport( - channel: OutputChannel, - formatter: logform.Format, -): PythonOutputChannelTransport { - return new PythonOutputChannelTransport(channel, { - // We minimize customization. - format: formatter, - }); -} diff --git a/src/client/logging/types.ts b/src/client/logging/types.ts new file mode 100644 index 000000000000..68d8d841b448 --- /dev/null +++ b/src/client/logging/types.ts @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export type LoggingLevelSettingType = 'off' | 'error' | 'warn' | 'info' | 'debug'; +export enum LogLevel { + Off = 0, + Error = 10, + Warn = 20, + Info = 30, + Debug = 40, +} + +export type Arguments = unknown[]; + +export interface ILogging { + traceError(...data: Arguments): void; + traceWarn(...data: Arguments): void; + traceInfo(...data: Arguments): void; + traceVerbose(...data: Arguments): void; +} + +export type TraceDecoratorType = ( + _: Object, + __: string, + descriptor: TypedPropertyDescriptor, +) => TypedPropertyDescriptor; + +// The information we want to log. +export enum TraceOptions { + None = 0, + Arguments = 1, + ReturnValue = 2, +} diff --git a/src/client/logging/util.ts b/src/client/logging/util.ts index 68485fe57895..4229fd7976a5 100644 --- a/src/client/logging/util.ts +++ b/src/client/logging/util.ts @@ -47,3 +47,8 @@ export function returnValueToLogString(returnValue: unknown): string { const valueString = valueToLogString(returnValue, 'Return value'); return `Return Value: ${valueString}`; } + +export function getTimeForLogging(): string { + const date = new Date(); + return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}.${date.getMilliseconds()}`; +} diff --git a/src/client/providers/importSortProvider.ts b/src/client/providers/importSortProvider.ts index 204c1a1e9c2d..53b25178a7a2 100644 --- a/src/client/providers/importSortProvider.ts +++ b/src/client/providers/importSortProvider.ts @@ -4,7 +4,6 @@ import * as path from 'path'; import { CancellationToken, CancellationTokenSource, TextDocument, Uri, WorkspaceEdit } from 'vscode'; import { IApplicationShell, ICommandManager, IDocumentManager } from '../common/application/types'; import { Commands, PYTHON_LANGUAGE, STANDARD_OUTPUT_CHANNEL } from '../common/constants'; -import { traceError } from '../common/logger'; import * as internalScripts from '../common/process/internal/scripts'; import { IProcessServiceFactory, IPythonExecutionFactory, ObservableExecutionResult } from '../common/process/types'; import { @@ -18,6 +17,7 @@ import { createDeferred, createDeferredFromPromise, Deferred } from '../common/u import { Common, Diagnostics } from '../common/utils/localize'; import { noop } from '../common/utils/misc'; import { IServiceContainer } from '../ioc/types'; +import { traceError } from '../logging'; import { captureTelemetry } from '../telemetry'; import { EventName } from '../telemetry/constants'; import { ISortImportsEditingProvider } from './types'; diff --git a/src/client/pythonEnvironments/base/info/environmentInfoService.ts b/src/client/pythonEnvironments/base/info/environmentInfoService.ts index 490a556a50ba..583f3048f78c 100644 --- a/src/client/pythonEnvironments/base/info/environmentInfoService.ts +++ b/src/client/pythonEnvironments/base/info/environmentInfoService.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { traceVerbose } from '../../../common/logger'; import { IDisposableRegistry } from '../../../common/types'; import { createDeferred, Deferred } from '../../../common/utils/async'; import { createRunningWorkerPool, IWorkerPool, QueuePosition } from '../../../common/utils/workerPool'; import { getInterpreterInfo, InterpreterInformation } from './interpreter'; import { buildPythonExecInfo } from '../../exec'; +import { traceVerbose } from '../../../logging'; export enum EnvironmentInfoServiceQueuePriority { Default, diff --git a/src/client/pythonEnvironments/base/info/interpreter.ts b/src/client/pythonEnvironments/base/info/interpreter.ts index b924036ba1ae..9b8759e1c63c 100644 --- a/src/client/pythonEnvironments/base/info/interpreter.ts +++ b/src/client/pythonEnvironments/base/info/interpreter.ts @@ -2,12 +2,12 @@ // Licensed under the MIT License. import { PythonExecutableInfo, PythonVersion } from '.'; -import { traceError, traceInfo } from '../../../common/logger'; import { interpreterInfo as getInterpreterInfoCommand, InterpreterInfoJson, } from '../../../common/process/internal/scripts'; import { Architecture } from '../../../common/utils/platform'; +import { traceError, traceInfo } from '../../../logging'; import { shellExecute } from '../../common/externalDependencies'; import { copyPythonExecInfo, PythonExecInfo } from '../../exec'; import { parseVersion } from './pythonVersion'; diff --git a/src/client/pythonEnvironments/base/info/pythonVersion.ts b/src/client/pythonEnvironments/base/info/pythonVersion.ts index a28747bd759a..589bf4c7b7af 100644 --- a/src/client/pythonEnvironments/base/info/pythonVersion.ts +++ b/src/client/pythonEnvironments/base/info/pythonVersion.ts @@ -3,10 +3,10 @@ import { cloneDeep } from 'lodash'; import * as path from 'path'; -import { traceError } from '../../../common/logger'; import * as basic from '../../../common/utils/version'; import { PythonReleaseLevel, PythonVersion, PythonVersionRelease, UNKNOWN_PYTHON_VERSION } from '.'; +import { traceError } from '../../../logging'; // XXX getPythonVersionFromPath() should go away in favor of parseVersionFromExecutable(). diff --git a/src/client/pythonEnvironments/base/locatorUtils.ts b/src/client/pythonEnvironments/base/locatorUtils.ts index d0fe3a75a060..a84f262bb3e9 100644 --- a/src/client/pythonEnvironments/base/locatorUtils.ts +++ b/src/client/pythonEnvironments/base/locatorUtils.ts @@ -2,9 +2,9 @@ // Licensed under the MIT License. import { Uri } from 'vscode'; -import { traceVerbose } from '../../common/logger'; import { createDeferred } from '../../common/utils/async'; import { getURIFilter } from '../../common/utils/misc'; +import { traceVerbose } from '../../logging'; import { PythonEnvInfo } from './info'; import { IPythonEnvsIterator, PythonEnvUpdatedEvent, PythonLocatorQuery } from './locator'; diff --git a/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts b/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts index 7474054c7e10..0b58d99f5d6c 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsCollectionCache.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { Event } from 'vscode'; -import { traceInfo } from '../../../../common/logger'; +import { traceInfo } from '../../../../logging'; import { pathExists } from '../../../common/externalDependencies'; import { PythonEnvInfo } from '../../info'; import { areSameEnv } from '../../info/env'; diff --git a/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts b/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts index 3a7d24a635a5..ea5e0bc86726 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts @@ -3,9 +3,9 @@ import { Event, EventEmitter } from 'vscode'; import '../../../../common/extensions'; -import { traceError } from '../../../../common/logger'; import { createDeferred } from '../../../../common/utils/async'; import { StopWatch } from '../../../../common/utils/stopWatch'; +import { traceError } from '../../../../logging'; import { sendTelemetryEvent } from '../../../../telemetry'; import { EventName } from '../../../../telemetry/constants'; import { PythonEnvInfo } from '../../info'; diff --git a/src/client/pythonEnvironments/base/locators/composite/envsReducer.ts b/src/client/pythonEnvironments/base/locators/composite/envsReducer.ts index 9e9e2a8e050d..ce326c9f8d08 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsReducer.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsReducer.ts @@ -3,7 +3,7 @@ import { cloneDeep, isEqual, uniq } from 'lodash'; import { Event, EventEmitter } from 'vscode'; -import { traceVerbose } from '../../../../common/logger'; +import { traceVerbose } from '../../../../logging'; import { PythonEnvKind } from '../../info'; import { areSameEnv } from '../../info/env'; import { BasicEnvInfo, ILocator, IPythonEnvsIterator, PythonEnvUpdatedEvent, PythonLocatorQuery } from '../../locator'; diff --git a/src/client/pythonEnvironments/base/locators/composite/envsResolver.ts b/src/client/pythonEnvironments/base/locators/composite/envsResolver.ts index a35582308050..5b12ee589c25 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsResolver.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsResolver.ts @@ -3,7 +3,6 @@ import { cloneDeep } from 'lodash'; import { Event, EventEmitter } from 'vscode'; -import { traceVerbose } from '../../../../common/logger'; import { identifyEnvironment } from '../../../common/environmentIdentifier'; import { IEnvironmentInfoService } from '../../info/environmentInfoService'; import { PythonEnvInfo } from '../../info'; @@ -19,6 +18,7 @@ import { } from '../../locator'; import { PythonEnvsChangedEvent } from '../../watcher'; import { resolveBasicEnv } from './resolverUtils'; +import { traceVerbose } from '../../../../logging'; /** * Calls environment info service which runs `interpreterInfo.py` script on environments received diff --git a/src/client/pythonEnvironments/base/locators/composite/resolverUtils.ts b/src/client/pythonEnvironments/base/locators/composite/resolverUtils.ts index 0ecd54b26591..fe1f548fe09b 100644 --- a/src/client/pythonEnvironments/base/locators/composite/resolverUtils.ts +++ b/src/client/pythonEnvironments/base/locators/composite/resolverUtils.ts @@ -4,7 +4,6 @@ import * as path from 'path'; import { Uri } from 'vscode'; import { uniq } from 'lodash'; -import { traceError, traceWarning } from '../../../../common/logger'; import { PythonEnvInfo, PythonEnvKind, PythonEnvSource, UNKNOWN_PYTHON_VERSION, virtualEnvKinds } from '../../info'; import { buildEnvInfo, comparePythonVersionSpecificity, getEnvDisplayString, getEnvMatcher } from '../../info/env'; import { @@ -20,6 +19,7 @@ import { getPythonVersionFromPath as parsePythonVersionFromPath, parseVersion } import { getRegistryInterpreters, getRegistryInterpretersSync } from '../../../common/windowsUtils'; import { BasicEnvInfo } from '../../locator'; import { parseVersionFromExecutable } from '../../info/executable'; +import { traceError, traceWarn } from '../../../../logging'; function getResolvers(): Map Promise> { const resolvers = new Map Promise>(); @@ -98,7 +98,7 @@ async function updateEnvUsingRegistry(env: PythonEnvInfo): Promise { env.distro.org = data.distroOrgName ?? env.distro.org; env.source = uniq(env.source.concat(PythonEnvSource.WindowsRegistry)); } else { - traceWarning('Expected registry to find the interpreter as source was set'); + traceWarn('Expected registry to find the interpreter as source was set'); } } @@ -132,7 +132,7 @@ async function resolveSimpleEnv(executablePath: string, kind: PythonEnvKind): Pr async function resolveCondaEnv(executablePath: string): Promise { const conda = await Conda.getConda(); if (conda === undefined) { - traceWarning(`${executablePath} identified as Conda environment even though Conda is not installed`); + traceWarn(`${executablePath} identified as Conda environment even though Conda is not installed`); } const envs = (await conda?.getEnvList()) ?? []; const matchEnv = getEnvMatcher(executablePath); diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/condaLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/condaLocator.ts index 7e54e9efcb82..766eae9c4ae5 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/condaLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/condaLocator.ts @@ -5,7 +5,7 @@ import { PythonEnvKind } from '../../info'; import { BasicEnvInfo, IPythonEnvsIterator, Locator } from '../../locator'; import { getInterpreterPathFromDir } from '../../../common/commonUtils'; import { Conda } from '../../../common/environmentManagers/conda'; -import { traceError, traceVerbose } from '../../../../common/logger'; +import { traceError, traceVerbose } from '../../../../logging'; export class CondaEnvironmentLocator extends Locator { // eslint-disable-next-line class-methods-use-this diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/customVirtualEnvLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/customVirtualEnvLocator.ts index dcdc9aaa0685..172a57bb102f 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/customVirtualEnvLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/customVirtualEnvLocator.ts @@ -3,7 +3,6 @@ import { uniq } from 'lodash'; import * as path from 'path'; -import { traceError, traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { getUserHomeDir } from '../../../../common/utils/platform'; import { PythonEnvKind } from '../../info'; @@ -24,6 +23,7 @@ import { } from '../../../common/environmentManagers/simplevirtualenvs'; import '../../../../common/extensions'; import { asyncFilter } from '../../../../common/utils/arrayUtils'; +import { traceError, traceVerbose } from '../../../../logging'; /** * Default number of levels of sub-directories to recurse when looking for interpreters. */ diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/fsWatchingLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/fsWatchingLocator.ts index c78ee7c92953..d1352ac80397 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/fsWatchingLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/fsWatchingLocator.ts @@ -4,10 +4,9 @@ import * as fs from 'fs'; import * as path from 'path'; import { Uri } from 'vscode'; -import { traceError, traceVerbose } from '../../../../common/logger'; import { FileChangeType } from '../../../../common/platform/fileSystemWatcher'; import { sleep } from '../../../../common/utils/async'; -import { logError } from '../../../../logging'; +import { traceError, traceVerbose } from '../../../../logging'; import { getEnvironmentDirFromPath } from '../../../common/commonUtils'; import { PythonEnvStructure, @@ -105,7 +104,7 @@ export abstract class FSWatchingLocator extends LazyResourceB // that might be watched due to a glob are not checked. const unwatchable = await checkDirWatchable(root); if (unwatchable) { - logError(`Dir "${root}" is not watchable (${unwatchable})`); + traceError(`Dir "${root}" is not watchable (${unwatchable})`); return undefined; } return root; diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/globalVirtualEnvronmentLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/globalVirtualEnvronmentLocator.ts index 2e17639dcb3a..e215cdb2a3dd 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/globalVirtualEnvronmentLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/globalVirtualEnvronmentLocator.ts @@ -3,7 +3,6 @@ import { uniq } from 'lodash'; import * as path from 'path'; -import { traceError, traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { getEnvironmentVariable, getOSType, getUserHomeDir, OSType } from '../../../../common/utils/platform'; import { PythonEnvKind } from '../../info'; @@ -19,6 +18,7 @@ import { } from '../../../common/environmentManagers/simplevirtualenvs'; import '../../../../common/extensions'; import { asyncFilter } from '../../../../common/utils/arrayUtils'; +import { traceError, traceVerbose } from '../../../../logging'; const DEFAULT_SEARCH_DEPTH = 2; /** diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/poetryLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/poetryLocator.ts index 395e3d6352a8..e37e64347983 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/poetryLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/poetryLocator.ts @@ -4,7 +4,6 @@ 'use strict'; import * as path from 'path'; -import { traceError, traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { PythonEnvKind } from '../../info'; import { BasicEnvInfo, IPythonEnvsIterator } from '../../locator'; @@ -14,6 +13,7 @@ import { pathExists } from '../../../common/externalDependencies'; import { isPoetryEnvironment, localPoetryEnvDirName, Poetry } from '../../../common/environmentManagers/poetry'; import '../../../../common/extensions'; import { asyncFilter } from '../../../../common/utils/arrayUtils'; +import { traceError, traceVerbose } from '../../../../logging'; /** * Gets all default virtual environment locations to look for in a workspace. diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/posixKnownPathsLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/posixKnownPathsLocator.ts index 1b945c7617ad..02671d27c9bd 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/posixKnownPathsLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/posixKnownPathsLocator.ts @@ -3,13 +3,13 @@ import * as os from 'os'; import { gte } from 'semver'; -import { traceError } from '../../../../common/logger'; import { PythonEnvKind, PythonEnvSource } from '../../info'; import { BasicEnvInfo, IPythonEnvsIterator, Locator } from '../../locator'; import { commonPosixBinPaths, getPythonBinFromPosixPaths } from '../../../common/posixUtils'; import { isPyenvShimDir } from '../../../common/environmentManagers/pyenv'; import { getOSType, OSType } from '../../../../common/utils/platform'; import { isMacDefaultPythonPath } from './macDefaultLocator'; +import { traceError } from '../../../../logging'; export class PosixKnownPathsLocator extends Locator { private kind: PythonEnvKind = PythonEnvKind.OtherGlobal; diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/pyenvLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/pyenvLocator.ts index 00f71eaa65ab..ca3cd6c6de8b 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/pyenvLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/pyenvLocator.ts @@ -2,13 +2,13 @@ // Licensed under the MIT License. import * as path from 'path'; -import { traceError } from '../../../../common/logger'; import { PythonEnvKind } from '../../info'; import { BasicEnvInfo, IPythonEnvsIterator } from '../../locator'; import { FSWatchingLocator } from './fsWatchingLocator'; import { getInterpreterPathFromDir } from '../../../common/commonUtils'; import { getSubDirs } from '../../../common/externalDependencies'; import { getPyenvDir } from '../../../common/environmentManagers/pyenv'; +import { traceError } from '../../../../logging'; function getPyenvVersionsDir(): string { return path.join(getPyenvDir(), 'versions'); diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/windowsRegistryLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/windowsRegistryLocator.ts index fc493fc13e16..0d44e3c3699e 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/windowsRegistryLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/windowsRegistryLocator.ts @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { traceError } from '../../../../common/logger'; import { PythonEnvKind, PythonEnvSource } from '../../info'; import { BasicEnvInfo, IPythonEnvsIterator, Locator } from '../../locator'; import { getRegistryInterpreters } from '../../../common/windowsUtils'; +import { traceError } from '../../../../logging'; export class WindowsRegistryLocator extends Locator { // eslint-disable-next-line class-methods-use-this diff --git a/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts b/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts index ebee7cbabd11..751c9b97c162 100644 --- a/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts +++ b/src/client/pythonEnvironments/base/locators/lowLevel/workspaceVirtualEnvLocator.ts @@ -2,7 +2,6 @@ // Licensed under the MIT License. import * as path from 'path'; -import { traceVerbose } from '../../../../common/logger'; import { chain, iterable } from '../../../../common/utils/async'; import { findInterpretersInDir, looksLikeBasicVirtualPython } from '../../../common/commonUtils'; import { pathExists } from '../../../common/externalDependencies'; @@ -13,6 +12,7 @@ import { BasicEnvInfo, IPythonEnvsIterator } from '../../locator'; import { FSWatcherKind, FSWatchingLocator } from './fsWatchingLocator'; import '../../../../common/extensions'; import { asyncFilter } from '../../../../common/utils/arrayUtils'; +import { traceVerbose } from '../../../../logging'; /** * Default number of levels of sub-directories to recurse when looking for interpreters. diff --git a/src/client/pythonEnvironments/common/commonUtils.ts b/src/client/pythonEnvironments/common/commonUtils.ts index 531d20c537f2..b60f23c5e442 100644 --- a/src/client/pythonEnvironments/common/commonUtils.ts +++ b/src/client/pythonEnvironments/common/commonUtils.ts @@ -5,7 +5,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { convertFileType, DirEntry, FileType, getFileFilter, getFileType } from '../../common/utils/filesystem'; import { getOSType, OSType } from '../../common/utils/platform'; -import { logError } from '../../logging'; +import { traceError } from '../../logging'; import { PythonVersion, UNKNOWN_PYTHON_VERSION } from '../base/info'; import { comparePythonVersionSpecificity } from '../base/info/env'; import { parseVersion } from '../base/info/pythonVersion'; @@ -122,7 +122,7 @@ async function readDirEntries( return []; } if (ignoreErrors) { - logError(`readdir() failed for "${dirname}" (${err})`); + traceError(`readdir() failed for "${dirname}" (${err})`); return []; } throw err; // re-throw @@ -147,7 +147,7 @@ async function readDirEntries( return []; } if (ignoreErrors) { - logError(`readdir() failed for "${dirname}" (${err})`); + traceError(`readdir() failed for "${dirname}" (${err})`); return []; } throw err; // re-throw @@ -187,7 +187,7 @@ function matchFile( return filterFile(filename); } catch (err) { if (ignoreErrors) { - logError(`filter failed for "${filename}" (${err})`); + traceError(`filter failed for "${filename}" (${err})`); return false; } throw err; // re-throw diff --git a/src/client/pythonEnvironments/common/environmentManagers/conda.ts b/src/client/pythonEnvironments/common/environmentManagers/conda.ts index b3fd3f3827bd..ac3ed5898e93 100644 --- a/src/client/pythonEnvironments/common/environmentManagers/conda.ts +++ b/src/client/pythonEnvironments/common/environmentManagers/conda.ts @@ -1,6 +1,5 @@ import * as fsapi from 'fs-extra'; import * as path from 'path'; -import { traceVerbose } from '../../../common/logger'; import { getEnvironmentVariable, getOSType, getUserHomeDir, OSType } from '../../../common/utils/platform'; import { arePathsSame, exec, getPythonSetting, pathExists, readFile } from '../externalDependencies'; @@ -11,6 +10,7 @@ import { getRegistryInterpreters } from '../windowsUtils'; import { EnvironmentType, PythonEnvironment } from '../../info'; import { cache } from '../../../common/utils/decorators'; import { isTestExecution } from '../../../common/constants'; +import { traceVerbose } from '../../../logging'; export const AnacondaCompanyName = 'Anaconda, Inc.'; diff --git a/src/client/pythonEnvironments/common/environmentManagers/condaService.ts b/src/client/pythonEnvironments/common/environmentManagers/condaService.ts index 43f896c08994..f00fc3594304 100644 --- a/src/client/pythonEnvironments/common/environmentManagers/condaService.ts +++ b/src/client/pythonEnvironments/common/environmentManagers/condaService.ts @@ -3,12 +3,12 @@ import * as path from 'path'; import { parse, SemVer } from 'semver'; import { ConfigurationChangeEvent, Uri } from 'vscode'; import { IWorkspaceService } from '../../../common/application/types'; -import { traceDecorators, traceWarning } from '../../../common/logger'; import { IFileSystem, IPlatformService } from '../../../common/platform/types'; import { IProcessServiceFactory } from '../../../common/process/types'; import { IDisposableRegistry } from '../../../common/types'; import { cache } from '../../../common/utils/decorators'; import { ICondaService } from '../../../interpreter/contracts'; +import { traceDecoratorVerbose, traceWarn } from '../../../logging'; import { Conda, CondaInfo } from './conda'; /** @@ -83,7 +83,7 @@ export class CondaService implements ICondaService { return version; } // Use a bogus version, at least to indicate the fact that a version was returned. - traceWarning(`Unable to parse Version of Conda, ${versionString}`); + traceWarn(`Unable to parse Version of Conda, ${versionString}`); return new SemVer('0.0.1'); } @@ -95,7 +95,7 @@ export class CondaService implements ICondaService { * The only way this can change is if user installs conda into this same environment. * Generally we expect that to happen the other way, the user creates a conda environment with conda in it. */ - @traceDecorators.verbose('Get Conda File from interpreter') + @traceDecoratorVerbose('Get Conda File from interpreter') @cache(120_000) public async getCondaFileFromInterpreter(interpreterPath?: string, envName?: string): Promise { const condaExe = this.platform.isWindows ? 'conda.exe' : 'conda'; diff --git a/src/client/pythonEnvironments/common/environmentManagers/pipenv.ts b/src/client/pythonEnvironments/common/environmentManagers/pipenv.ts index 9bfbbcea4d08..35025b7d6e5d 100644 --- a/src/client/pythonEnvironments/common/environmentManagers/pipenv.ts +++ b/src/client/pythonEnvironments/common/environmentManagers/pipenv.ts @@ -2,8 +2,8 @@ // Licensed under the MIT License. import * as path from 'path'; -import { traceError } from '../../../common/logger'; import { getEnvironmentVariable } from '../../../common/utils/platform'; +import { traceError } from '../../../logging'; import { arePathsSame, normCasePath, pathExists, readFile } from '../externalDependencies'; function getSearchHeight() { diff --git a/src/client/pythonEnvironments/common/environmentManagers/poetry.ts b/src/client/pythonEnvironments/common/environmentManagers/poetry.ts index cafa58835072..b77ecd9c6db3 100644 --- a/src/client/pythonEnvironments/common/environmentManagers/poetry.ts +++ b/src/client/pythonEnvironments/common/environmentManagers/poetry.ts @@ -4,7 +4,6 @@ 'use strict'; import * as path from 'path'; -import { traceError, traceVerbose } from '../../../common/logger'; import { getOSType, getUserHomeDir, OSType } from '../../../common/utils/platform'; import { getPythonSetting, isParentPath, pathExistsSync, readFileSync, shellExecute } from '../externalDependencies'; import { getEnvironmentDirFromPath } from '../commonUtils'; @@ -12,6 +11,7 @@ import { isVirtualenvEnvironment } from './simplevirtualenvs'; import { StopWatch } from '../../../common/utils/stopWatch'; import { cache } from '../../../common/utils/decorators'; import { isTestExecution } from '../../../common/constants'; +import { traceError, traceVerbose } from '../../../logging'; /** * Global virtual env dir for a project is named as: diff --git a/src/client/pythonEnvironments/common/environmentManagers/windowsStoreEnv.ts b/src/client/pythonEnvironments/common/environmentManagers/windowsStoreEnv.ts index 098cb75eb6eb..0d72e0afceef 100644 --- a/src/client/pythonEnvironments/common/environmentManagers/windowsStoreEnv.ts +++ b/src/client/pythonEnvironments/common/environmentManagers/windowsStoreEnv.ts @@ -2,8 +2,8 @@ // Licensed under the MIT License. import * as path from 'path'; -import { traceWarning } from '../../../common/logger'; import { getEnvironmentVariable } from '../../../common/utils/platform'; +import { traceWarn } from '../../../logging'; import { pathExists } from '../externalDependencies'; /** @@ -114,7 +114,7 @@ export async function isWindowsStoreEnvironment(interpreterPath: string): Promis // Program Files store path is a forbidden path. Only admins and system has access this path. // We should never have to look at this path or even execute python from this path. if (isForbiddenStorePath(pythonPathToCompare)) { - traceWarning('isWindowsStoreEnvironment called with Program Files store path.'); + traceWarn('isWindowsStoreEnvironment called with Program Files store path.'); return true; } } diff --git a/src/client/pythonEnvironments/common/posixUtils.ts b/src/client/pythonEnvironments/common/posixUtils.ts index be29a3960f32..cba484ecfe48 100644 --- a/src/client/pythonEnvironments/common/posixUtils.ts +++ b/src/client/pythonEnvironments/common/posixUtils.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import { uniq } from 'lodash'; import { getSearchPathEntries } from '../../common/utils/exec'; import { resolveSymbolicLink } from './externalDependencies'; -import { traceError, traceInfo } from '../../common/logger'; +import { traceError, traceInfo } from '../../logging'; /** * Determine if the given filename looks like the simplest Python executable. diff --git a/src/client/pythonEnvironments/common/pythonBinariesWatcher.ts b/src/client/pythonEnvironments/common/pythonBinariesWatcher.ts index 3cdf9860814b..b2ca6920437e 100644 --- a/src/client/pythonEnvironments/common/pythonBinariesWatcher.ts +++ b/src/client/pythonEnvironments/common/pythonBinariesWatcher.ts @@ -5,10 +5,10 @@ import * as minimatch from 'minimatch'; import * as path from 'path'; -import { traceVerbose } from '../../common/logger'; import { FileChangeType, watchLocationForPattern } from '../../common/platform/fileSystemWatcher'; import { getOSType, OSType } from '../../common/utils/platform'; import { IDisposable } from '../../common/utils/resourceLifecycle'; +import { traceVerbose } from '../../logging'; const [executable, binName] = getOSType() === OSType.Windows ? ['python.exe', 'Scripts'] : ['python', 'bin']; diff --git a/src/client/pythonEnvironments/common/windowsUtils.ts b/src/client/pythonEnvironments/common/windowsUtils.ts index ab5834ac83a2..a47025ceef6f 100644 --- a/src/client/pythonEnvironments/common/windowsUtils.ts +++ b/src/client/pythonEnvironments/common/windowsUtils.ts @@ -4,7 +4,7 @@ import { uniqBy } from 'lodash'; import * as path from 'path'; import { isTestExecution } from '../../common/constants'; -import { traceError, traceVerbose } from '../../common/logger'; +import { traceError, traceVerbose } from '../../logging'; import { HKCU, HKLM, diff --git a/src/client/pythonEnvironments/legacyIOC.ts b/src/client/pythonEnvironments/legacyIOC.ts index 6cf280fdd8b8..2dc63c60bfee 100644 --- a/src/client/pythonEnvironments/legacyIOC.ts +++ b/src/client/pythonEnvironments/legacyIOC.ts @@ -4,7 +4,6 @@ import { injectable } from 'inversify'; import { intersection } from 'lodash'; import * as vscode from 'vscode'; -import { traceVerbose } from '../common/logger'; import { FileChangeType } from '../common/platform/fileSystemWatcher'; import { Resource } from '../common/types'; import { IComponentAdapter, ICondaService, PythonEnvironmentsChangedEvent } from '../interpreter/contracts'; @@ -23,6 +22,7 @@ import { asyncFilter } from '../common/utils/arrayUtils'; import { CondaEnvironmentInfo, isCondaEnvironment } from './common/environmentManagers/conda'; import { isWindowsStoreEnvironment } from './common/environmentManagers/windowsStoreEnv'; import { CondaService } from './common/environmentManagers/condaService'; +import { traceVerbose } from '../logging'; const convertedKinds = new Map( Object.entries({ @@ -126,7 +126,7 @@ class ComponentAdapter implements IComponentAdapter { if (!workspaceFolder || !e.searchLocation) { return; } - traceVerbose(`Recieved event ${JSON.stringify(e)} file change event`); + traceVerbose(`Received event ${JSON.stringify(e)} file change event`); if ( e.type === FileChangeType.Created && isParentPath(e.searchLocation.fsPath, workspaceFolder.uri.fsPath) diff --git a/src/client/sourceMapSupport.ts b/src/client/sourceMapSupport.ts index 6ccdf87cfc47..8800fd7d3e29 100644 --- a/src/client/sourceMapSupport.ts +++ b/src/client/sourceMapSupport.ts @@ -6,9 +6,9 @@ import * as path from 'path'; import { WorkspaceConfiguration } from 'vscode'; import './common/extensions'; -import { traceError } from './common/logger'; import { FileSystem } from './common/platform/fileSystem'; import { EXTENSION_ROOT_DIR } from './constants'; +import { traceError } from './logging'; type VSCode = typeof import('vscode'); diff --git a/src/client/startupTelemetry.ts b/src/client/startupTelemetry.ts index b936710b839e..5390016253cc 100644 --- a/src/client/startupTelemetry.ts +++ b/src/client/startupTelemetry.ts @@ -4,7 +4,6 @@ import { IWorkspaceService } from './common/application/types'; import { isTestExecution } from './common/constants'; import { DeprecatePythonPath } from './common/experiments/groups'; -import { traceError } from './common/logger'; import { ITerminalHelper } from './common/terminal/types'; import { IConfigurationService, @@ -17,6 +16,7 @@ import { IStopWatch } from './common/utils/stopWatch'; import { IInterpreterAutoSelectionService } from './interpreter/autoSelection/types'; import { ICondaService, IInterpreterService } from './interpreter/contracts'; import { IServiceContainer } from './ioc/types'; +import { traceError } from './logging'; import { EnvironmentType, PythonEnvironment } from './pythonEnvironments/info'; import { sendTelemetryEvent } from './telemetry'; import { EventName } from './telemetry/constants'; diff --git a/src/client/telemetry/index.ts b/src/client/telemetry/index.ts index ac302d29d623..cabd2f4a1829 100644 --- a/src/client/telemetry/index.ts +++ b/src/client/telemetry/index.ts @@ -8,7 +8,6 @@ import { LanguageServerType } from '../activation/types'; import { DiagnosticCodes } from '../application/diagnostics/constants'; import { IWorkspaceService } from '../common/application/types'; import { AppinsightsKey, isTestExecution, isUnitTestExecution, PVSC_EXTENSION_ID } from '../common/constants'; -import { traceError, traceInfo } from '../common/logger'; import type { TerminalShellType } from '../common/terminal/types'; import { StopWatch } from '../common/utils/stopWatch'; import { isPromise } from '../common/utils/async'; @@ -137,7 +136,7 @@ export function sendTelemetryEvent

{ this.updateTestSettings(resource).ignoreErrors(); } - @traceDecorators.error('Failed to update test settings') + @traceDecoratorError('Failed to update test settings') public async updateTestSettings(resource: Resource): Promise { const filesToBeFixed = await this.getFilesToBeFixed(resource); await Promise.all(filesToBeFixed.map((file) => this.fixSettingInFile(file))); diff --git a/src/client/testing/configuration/index.ts b/src/client/testing/configuration/index.ts index b803bb106230..e85154e72738 100644 --- a/src/client/testing/configuration/index.ts +++ b/src/client/testing/configuration/index.ts @@ -3,9 +3,9 @@ import { inject, injectable } from 'inversify'; import { Uri } from 'vscode'; import { IApplicationShell, IWorkspaceService } from '../../common/application/types'; -import { traceError } from '../../common/logger'; import { IConfigurationService, Product } from '../../common/types'; import { IServiceContainer } from '../../ioc/types'; +import { traceError } from '../../logging'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { TestConfiguringTelemetry } from '../../telemetry/types'; diff --git a/src/client/testing/main.ts b/src/client/testing/main.ts index cc731ac0033c..bc4d69412a4e 100644 --- a/src/client/testing/main.ts +++ b/src/client/testing/main.ts @@ -16,11 +16,11 @@ import { ITestConfigurationService, ITestsHelper } from './common/types'; import { ITestingService } from './types'; import { IExtensionActivationService } from '../activation/types'; import { ITestController } from './testController/common/types'; -import { traceVerbose } from '../common/logger'; import { DelayedTrigger, IDelayedTrigger } from '../common/utils/delayTrigger'; import { ExtensionContextKey } from '../common/application/contextKeys'; import { checkForFailedTests, updateTestResultMap } from './testController/common/testItemUtilities'; import { Testing } from '../common/utils/localize'; +import { traceVerbose } from '../logging'; @injectable() export class TestingService implements ITestingService { diff --git a/src/client/testing/testController/common/argumentsHelper.ts b/src/client/testing/testController/common/argumentsHelper.ts index 69e27b915896..ef2999551f02 100644 --- a/src/client/testing/testController/common/argumentsHelper.ts +++ b/src/client/testing/testController/common/argumentsHelper.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { traceWarning } from '../../../common/logger'; +import { traceWarn } from '../../../logging'; export function getOptionValues(args: string[], option: string): string[] { const values: string[] = []; @@ -36,13 +36,13 @@ export function getPositionalArguments( nonPositionalIndexes.push(index); } else if (arg.startsWith('-')) { // Ok this is an unknown option, lets treat this as one without values. - traceWarning( + traceWarn( `Unknown command line option passed into args parser for tests '${arg}'. Please report on https://github.com/Microsoft/vscode-python/issues/new`, ); nonPositionalIndexes.push(index); } else if (arg.indexOf('=') > 0) { // Ok this is an unknown option with a value - traceWarning( + traceWarn( `Unknown command line option passed into args parser for tests '${arg}'. Please report on https://github.com/Microsoft/vscode-python/issues/new`, ); nonPositionalIndexes.push(index); diff --git a/src/client/testing/testController/common/testItemUtilities.ts b/src/client/testing/testController/common/testItemUtilities.ts index f151e274a179..525e36e4235d 100644 --- a/src/client/testing/testController/common/testItemUtilities.ts +++ b/src/client/testing/testController/common/testItemUtilities.ts @@ -14,8 +14,8 @@ import { TestItemCollection, } from 'vscode'; import { CancellationToken } from 'vscode-jsonrpc'; -import { traceError, traceVerbose } from '../../../common/logger'; import { asyncForEach } from '../../../common/utils/arrayUtils'; +import { traceError, traceVerbose } from '../../../logging'; import { RawDiscoveredTests, RawTest, diff --git a/src/client/testing/testController/controller.ts b/src/client/testing/testController/controller.ts index 3c2551154d7f..af0f56106a1b 100644 --- a/src/client/testing/testController/controller.ts +++ b/src/client/testing/testController/controller.ts @@ -17,9 +17,9 @@ import { EventEmitter, } from 'vscode'; import { IWorkspaceService } from '../../common/application/types'; -import { traceVerbose } from '../../common/logger'; import { IConfigurationService, IDisposableRegistry, Resource } from '../../common/types'; import { DelayedTrigger, IDelayedTrigger } from '../../common/utils/delayTrigger'; +import { traceVerbose } from '../../logging'; import { sendTelemetryEvent } from '../../telemetry'; import { EventName } from '../../telemetry/constants'; import { PYTEST_PROVIDER, UNITTEST_PROVIDER } from '../common/constants'; diff --git a/src/client/testing/testController/pytest/pytestController.ts b/src/client/testing/testController/pytest/pytestController.ts index 987562777480..c6f3e3f51180 100644 --- a/src/client/testing/testController/pytest/pytestController.ts +++ b/src/client/testing/testController/pytest/pytestController.ts @@ -7,11 +7,11 @@ import * as path from 'path'; import * as util from 'util'; import { CancellationToken, TestItem, Uri, TestController, WorkspaceFolder } from 'vscode'; import { IWorkspaceService } from '../../../common/application/types'; -import { traceError } from '../../../common/logger'; import { runAdapter } from '../../../common/process/internal/scripts/testing_tools'; import { IConfigurationService } from '../../../common/types'; import { asyncForEach } from '../../../common/utils/arrayUtils'; import { createDeferred, Deferred } from '../../../common/utils/async'; +import { traceError } from '../../../logging'; import { sendTelemetryEvent } from '../../../telemetry'; import { EventName } from '../../../telemetry/constants'; import { PYTEST_PROVIDER } from '../../common/constants'; diff --git a/src/client/testing/testController/unittest/runner.ts b/src/client/testing/testController/unittest/runner.ts index fb1482c2e9b4..1ca2c737c977 100644 --- a/src/client/testing/testController/unittest/runner.ts +++ b/src/client/testing/testController/unittest/runner.ts @@ -3,10 +3,10 @@ import { injectable, inject, named } from 'inversify'; import { Location, TestController, TestItem, TestMessage, TestRun, TestRunProfileKind } from 'vscode'; -import { traceError, traceInfo } from '../../../common/logger'; import * as internalScripts from '../../../common/process/internal/scripts'; import { IOutputChannel } from '../../../common/types'; import { noop } from '../../../common/utils/misc'; +import { traceError, traceInfo } from '../../../logging'; import { UNITTEST_PROVIDER } from '../../common/constants'; import { ITestRunner, ITestDebugLauncher, IUnitTestSocketServer, LaunchOptions, Options } from '../../common/types'; import { TEST_OUTPUT_CHANNEL } from '../../constants'; diff --git a/src/client/testing/testController/unittest/unittestController.ts b/src/client/testing/testController/unittest/unittestController.ts index 0a54bc5d0531..2fb4cb91c539 100644 --- a/src/client/testing/testController/unittest/unittestController.ts +++ b/src/client/testing/testController/unittest/unittestController.ts @@ -27,10 +27,10 @@ import { getWorkspaceNode, updateTestItemFromRawData, } from '../common/testItemUtilities'; -import { traceError } from '../../../common/logger'; import { sendTelemetryEvent } from '../../../telemetry'; import { EventName } from '../../../telemetry/constants'; import { unittestDiscovery } from '../../../common/process/internal/scripts/testing_tools'; +import { traceError } from '../../../logging'; @injectable() export class UnittestController implements ITestFrameworkController { diff --git a/src/test/common/application/commands/reportIssueCommand.unit.test.ts b/src/test/common/application/commands/reportIssueCommand.unit.test.ts index 21fcb7223a92..323240fb7d3b 100644 --- a/src/test/common/application/commands/reportIssueCommand.unit.test.ts +++ b/src/test/common/application/commands/reportIssueCommand.unit.test.ts @@ -18,7 +18,6 @@ import { IInterpreterService } from '../../../../client/interpreter/contracts'; import { MockWorkspaceConfiguration } from '../../../mocks/mockWorkspaceConfig'; import { EXTENSION_ROOT_DIR_FOR_TESTS } from '../../../constants'; import { InterpreterService } from '../../../../client/interpreter/interpreterService'; -import * as Logging from '../../../../client/logging/_global'; import { Commands } from '../../../../client/common/constants'; import { AllCommands } from '../../../../client/common/application/commands'; import { ConfigurationService } from '../../../../client/common/configuration/service'; @@ -32,7 +31,6 @@ suite('Report Issue Command', () => { let workspaceService: IWorkspaceService; let interpreterService: IInterpreterService; let configurationService: IConfigurationService; - let getPythonOutputContentStub: sinon.SinonStub; setup(async () => { workspaceService = mock(WorkspaceService); @@ -65,8 +63,6 @@ suite('Report Issue Command', () => { cmdManager = mock(CommandManager); - getPythonOutputContentStub = sinon.stub(Logging, 'getPythonOutputChannelContent'); - getPythonOutputContentStub.resolves('Python Output'); reportIssueCommandHandler = new ReportIssueCommandHandler( instance(cmdManager), instance(workspaceService), diff --git a/src/test/pythonEnvironments/base/locators/lowLevel/watcherTestUtils.ts b/src/test/pythonEnvironments/base/locators/lowLevel/watcherTestUtils.ts index 8130ec281984..a898a770ebb9 100644 --- a/src/test/pythonEnvironments/base/locators/lowLevel/watcherTestUtils.ts +++ b/src/test/pythonEnvironments/base/locators/lowLevel/watcherTestUtils.ts @@ -4,11 +4,11 @@ import { assert } from 'chai'; import * as fs from 'fs-extra'; import * as path from 'path'; -import { traceWarning } from '../../../../../client/common/logger'; import { FileChangeType } from '../../../../../client/common/platform/fileSystemWatcher'; import { createDeferred, Deferred, sleep } from '../../../../../client/common/utils/async'; import { getOSType, OSType } from '../../../../../client/common/utils/platform'; import { IDisposable } from '../../../../../client/common/utils/resourceLifecycle'; +import { traceWarn } from '../../../../../client/logging'; import { PythonEnvKind } from '../../../../../client/pythonEnvironments/base/info'; import { BasicEnvInfo, ILocator } from '../../../../../client/pythonEnvironments/base/locator'; import { getEnvs } from '../../../../../client/pythonEnvironments/base/locatorUtils'; @@ -79,7 +79,7 @@ class Venvs { try { await fs.remove(filename); } catch (err) { - traceWarning(`Failed to clean up ${filename}`); + traceWarn(`Failed to clean up ${filename}`); } } diff --git a/src/test/pythonEnvironments/base/locators/lowLevel/windowsStoreLocator.test.ts b/src/test/pythonEnvironments/base/locators/lowLevel/windowsStoreLocator.test.ts index 02301f862cbe..52a1c1c09061 100644 --- a/src/test/pythonEnvironments/base/locators/lowLevel/windowsStoreLocator.test.ts +++ b/src/test/pythonEnvironments/base/locators/lowLevel/windowsStoreLocator.test.ts @@ -5,7 +5,6 @@ import { assert } from 'chai'; import * as fs from 'fs-extra'; import * as path from 'path'; import { Uri } from 'vscode'; -import { traceWarning } from '../../../../../client/common/logger'; import { FileChangeType } from '../../../../../client/common/platform/fileSystemWatcher'; import { createDeferred, Deferred, sleep } from '../../../../../client/common/utils/async'; import { PythonEnvKind } from '../../../../../client/pythonEnvironments/base/info'; @@ -15,6 +14,7 @@ import * as externalDeps from '../../../../../client/pythonEnvironments/common/e import { WindowsStoreLocator } from '../../../../../client/pythonEnvironments/base/locators/lowLevel/windowsStoreLocator'; import { TEST_TIMEOUT } from '../../../../constants'; import { TEST_LAYOUT_ROOT } from '../../../common/commonTestConstants'; +import { traceWarn } from '../../../../../client/logging'; class WindowsStoreEnvs { private executables: string[] = []; @@ -58,7 +58,7 @@ class WindowsStoreEnvs { try { await fs.remove(filename); } catch (err) { - traceWarning(`Failed to clean up ${filename}`); + traceWarn(`Failed to clean up ${filename}`); } }), ); @@ -67,7 +67,7 @@ class WindowsStoreEnvs { try { await fs.rmdir(dir); } catch (err) { - traceWarning(`Failed to clean up ${dir}`); + traceWarn(`Failed to clean up ${dir}`); } }), ); diff --git a/src/test/testLogger.ts b/src/test/testLogger.ts index ea0fce5b9976..b41f17ecafcc 100644 --- a/src/test/testLogger.ts +++ b/src/test/testLogger.ts @@ -3,22 +3,16 @@ 'use strict'; +import { initializeFileLogging, logTo } from '../client/logging'; +import { LogLevel } from '../client/logging/types'; // IMPORTANT: This file should only be importing from the '../client/logging' directory, as we // delete everything in '../client' except for '../client/logging' before running smoke tests. -import { LogLevel } from '../client/logging/levels'; -import { configureLogger, createLogger, getPreDefinedConfiguration, logToAll } from '../client/logging/logger'; - const isCI = process.env.TRAVIS === 'true' || process.env.TF_BUILD !== undefined; -const monkeyPatchLogger = createLogger(); export function initializeLogger() { - const config = getPreDefinedConfiguration(); if (isCI && process.env.VSC_PYTHON_LOG_FILE) { - delete config.console; - // This is a separate logger that matches our config but - // does not do any console logging. - configureLogger(monkeyPatchLogger, config); + initializeFileLogging([]); // Send console.*() to the non-console loggers. monkeypatchConsole(); } @@ -38,6 +32,10 @@ function monkeypatchConsole() { const levels: { [key: string]: LogLevel } = { error: LogLevel.Error, warn: LogLevel.Warn, + debug: LogLevel.Debug, + trace: LogLevel.Debug, + info: LogLevel.Info, + log: LogLevel.Info, }; const consoleAny: any = console; @@ -47,13 +45,12 @@ function monkeypatchConsole() { // We could use a closure but it's a bit trickier. const sym = Symbol.for(stream); consoleAny[sym] = consoleAny[stream]; - consoleAny[stream] = function () { const args = Array.prototype.slice.call(arguments); const fn = consoleAny[sym]; fn(...args); const level = levels[stream] || LogLevel.Info; - logToAll([monkeyPatchLogger], level, args); + logTo(level, args); }; } }