diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0e946609f9..311aebf7e65 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -345,14 +345,16 @@ The `aws.dev.forceDevMode` setting enables or disables Toolkit "dev mode". Witho - Example: `getLogger().error('topic: widget failed: %O', { foo: 'bar', baz: 42 })` - Log messages are written to the extension Output channel, which you can view in vscode by visiting the "Output" panel and selecting `AWS Toolkit Logs` or `Amazon Q Logs`. - Use the `aws.dev.logfile` setting to set the logfile path to a fixed location, so you can follow - and filter logs using shell tools like `tail` and `grep`. For example in settings.json, - ``` - "aws.dev.logfile": "~/awstoolkit.log", - ``` - then you can tail the logfile in your terminal: - ``` - tail -F ~/awstoolkit.log - ``` + and filter logs using shell tools like `tail` and `grep`. + - Note: this always logs at **debug log-level** (though you can temporarily override that from the `AWS Toolkit Logs` UI). + - Example `settings.json`: + ``` + "aws.dev.logfile": "~/awstoolkit.log", + ``` + then you can tail the logfile in your terminal: + ``` + tail -F ~/awstoolkit.log + ``` - Use the `AWS (Developer): Watch Logs` command to watch and filter Toolkit logs (including telemetry) in VSCode. - Only available if you enabled "dev mode" (`aws.dev.forceDevMode` setting, see above). diff --git a/packages/core/src/shared/logger/activation.ts b/packages/core/src/shared/logger/activation.ts index a7c12e95513..29d8f8f6fd9 100644 --- a/packages/core/src/shared/logger/activation.ts +++ b/packages/core/src/shared/logger/activation.ts @@ -35,7 +35,7 @@ export async function activate( const mainLogger = makeLogger({ logLevel: chanLogLevel, - logPaths: logUri ? [logUri] : undefined, + logFile: logUri, outputChannels: [logChannel], useConsoleLog: isWeb(), }) @@ -43,6 +43,7 @@ export async function activate( const newLogLevel = fromVscodeLogLevel(logLevel) mainLogger.setLogLevel(newLogLevel) // Also logs a message. }) + mainLogger.setLogLevel('debug') // HACK: set to "debug" when debugging the extension. setLogger(mainLogger) @@ -56,7 +57,7 @@ export async function activate( 'debugConsole' ) - getLogger().info('Log level: %s%s', chanLogLevel, logUri ? `, file: ${logUri.fsPath}` : '') + getLogger().info('Log level: %s%s', chanLogLevel, logUri ? `, file (always "debug" level): ${logUri.fsPath}` : '') getLogger().debug('User agent: %s', getUserAgent({ includePlatform: true, includeClientId: true })) if (devLogfile && typeof devLogfile !== 'string') { getLogger().error('invalid aws.dev.logfile setting') @@ -69,20 +70,23 @@ export async function activate( /** * Creates a logger off of specified params * @param opts.logLevel Log messages at or above this level - * @param opts.logPaths Array of paths to output log entries to + * @param opts.logFile See {@link Logger.logFile} * @param opts.outputChannels Array of output channels to log entries to * @param opts.useConsoleLog If true, outputs log entries to the nodejs or browser devtools console. */ export function makeLogger(opts: { logLevel: LogLevel - logPaths?: vscode.Uri[] + logFile?: vscode.Uri outputChannels?: vscode.OutputChannel[] useConsoleLog?: boolean }): Logger { const logger = new ToolkitLogger(opts.logLevel) - // debug console can show ANSI colors, output channels can not - for (const logPath of opts.logPaths ?? []) { - logger.logToFile(logPath) + if (opts.logFile) { + logger.logToFile(opts.logFile) + logger.logFile = opts.logFile + // XXX: `vscode.LogOutputChannel` does not support programmatically setting the log-level, + // so this has no effect there. But this at least enables sinking to `SharedFileTransport`. + logger.setLogLevel('debug') } for (const outputChannel of opts.outputChannels ?? []) { logger.logToOutputChannel(outputChannel) diff --git a/packages/core/src/shared/logger/logger.ts b/packages/core/src/shared/logger/logger.ts index a1a2dd6a225..3c602c2db35 100644 --- a/packages/core/src/shared/logger/logger.ts +++ b/packages/core/src/shared/logger/logger.ts @@ -12,6 +12,11 @@ const toolkitLoggers: { } = { main: undefined, debugConsole: undefined } export interface Logger { + /** + * Developer-only: Optional log file, which gets all log messages (regardless of the configured + * log-level). + */ + logFile?: vscode.Uri debug(message: string | Error, ...meta: any[]): number verbose(message: string | Error, ...meta: any[]): number info(message: string | Error, ...meta: any[]): number @@ -27,6 +32,8 @@ export interface Logger { } export abstract class BaseLogger implements Logger { + logFile?: vscode.Uri + debug(message: string | Error, ...meta: any[]): number { return this.sendToLog('debug', message, ...meta) } diff --git a/packages/core/src/test/shared/logger/activation.test.ts b/packages/core/src/test/shared/logger/activation.test.ts index df78041ca83..a9167c70ee9 100644 --- a/packages/core/src/test/shared/logger/activation.test.ts +++ b/packages/core/src/test/shared/logger/activation.test.ts @@ -18,7 +18,7 @@ describe('makeLogger', function () { before(async function () { tempFolder = await makeTemporaryToolkitFolder() const logPath = vscode.Uri.joinPath(vscode.Uri.file(tempFolder), 'log.txt') - testLogger = makeLogger({ logLevel: 'debug', logPaths: [logPath] }) + testLogger = makeLogger({ logLevel: 'debug', logFile: logPath }) }) after(async function () {