Skip to content

Commit 3d4c65e

Browse files
authored
feat(logging): leverage vscode OutputChannel, drop watch/cleanup #4688
Problem: - We start a logfile watcher on startup, which adds (1) unnecessary latency and complexity, and (2) uses node fs watcher (unreliable, not web-compatible) instead of vscode watcher. - vscode OutputChannel has gained capabilities such that we no longer need to manage logfiles: - "Open Output in Editor" - Log syntax highlighting - Set log level (TODO: we aren't currently leveraging this) Solution: - Only log to OutputChannel. Don't log to a file unless "aws.dev.logfile" (developer-mode setting) is set. - Update "View Logs" commands to show the "AWS Toolkit Logs" OutputChannel instead of the logfile (unless "aws.dev.logfile" is set). - Remove all logfile watch/cleanup code.
1 parent 7d7d9bb commit 3d4c65e

File tree

4 files changed

+15
-235
lines changed

4 files changed

+15
-235
lines changed

packages/core/src/shared/logger/activation.ts

Lines changed: 3 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,17 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import * as path from 'path'
76
import * as vscode from 'vscode'
8-
import * as nls from 'vscode-nls'
97
import { Logger, LogLevel, getLogger } from '.'
108
import { setLogger } from './logger'
119
import { logOutputChannel } from './outputChannel'
1210
import { WinstonToolkitLogger } from './winstonToolkitLogger'
13-
import { waitUntil } from '../utilities/timeoutUtils'
14-
import { cleanLogFiles } from './util'
1511
import { Settings } from '../settings'
1612
import { Logging } from './commands'
1713
import { resolvePath } from '../utilities/pathUtils'
1814
import { isWeb } from '../../common/webUtils'
1915
import { fsCommon } from '../../srcShared/fs'
2016

21-
const localize = nls.loadMessageBundle()
22-
2317
const defaultLogLevel: LogLevel = 'info'
2418

2519
/**
@@ -32,15 +26,13 @@ export async function activate(
3226
const chan = logOutputChannel
3327
const settings = Settings.instance.getSection('aws')
3428
const devLogfile = settings.get('dev.logfile', '')
35-
const logUri = devLogfile
36-
? vscode.Uri.file(resolvePath(devLogfile))
37-
: vscode.Uri.joinPath(extensionContext.logUri, makeLogFilename())
29+
const logUri = devLogfile ? vscode.Uri.file(resolvePath(devLogfile)) : undefined
3830

3931
await fsCommon.mkdir(extensionContext.logUri)
4032

4133
const mainLogger = makeLogger(
4234
{
43-
logPaths: [logUri],
35+
logPaths: logUri ? [logUri] : undefined,
4436
outputChannels: [chan],
4537
useConsoleLog: isWeb(),
4638
},
@@ -54,7 +46,7 @@ export async function activate(
5446
setLogger(
5547
makeLogger(
5648
{
57-
logPaths: [logUri],
49+
logPaths: logUri ? [logUri] : undefined,
5850
outputChannels: [outputChannel, chan],
5951
},
6052
extensionContext.subscriptions
@@ -79,18 +71,6 @@ export async function activate(
7971

8072
const commands = new Logging(logUri, mainLogger)
8173
extensionContext.subscriptions.push(...Object.values(Logging.declared).map(c => c.register(commands)))
82-
83-
createLogWatcher(logUri)
84-
.then(sub => {
85-
extensionContext.subscriptions.push(sub)
86-
})
87-
.catch(err => {
88-
getLogger().warn('Failed to start log file watcher: %s', err)
89-
})
90-
91-
cleanLogFiles(path.dirname(logUri.fsPath)).catch(err => {
92-
getLogger().warn('Failed to clean-up old logs: %s', err)
93-
})
9474
}
9575

9676
/**
@@ -149,60 +129,3 @@ function getLogLevel(): LogLevel {
149129
const configuration = Settings.instance.getSection('aws')
150130
return configuration.get('logLevel', defaultLogLevel)
151131
}
152-
153-
/**
154-
* Creates a name for the toolkit's logfile.
155-
* Essentially an ISO string, but in the local timezone and without the trailing "Z"
156-
* @returns Log filename
157-
*/
158-
function makeLogFilename(): string {
159-
const now = new Date()
160-
// local to machine: use getMonth/Date instead of UTC equivalent
161-
// month is zero-terminated: offset by 1
162-
const m = (now.getMonth() + 1).toString().padStart(2, '0')
163-
const d = now.getDate().toString().padStart(2, '0')
164-
const h = now.getHours().toString().padStart(2, '0')
165-
const mn = now.getMinutes().toString().padStart(2, '0')
166-
const s = now.getSeconds().toString().padStart(2, '0')
167-
const dt = `${now.getFullYear()}${m}${d}T${h}${mn}${s}`
168-
169-
return `aws_toolkit_${dt}.log`
170-
}
171-
172-
/**
173-
* Watches for renames on the log file and notifies the user.
174-
*/
175-
async function createLogWatcher(logFile: vscode.Uri): Promise<vscode.Disposable> {
176-
if (isWeb()) {
177-
getLogger().debug(`Not watching log file since we are in Browser.`)
178-
return { dispose: () => {} }
179-
}
180-
181-
const exists = await waitUntil(() => fsCommon.existsFile(logFile), { interval: 1000, timeout: 60000 })
182-
183-
if (!exists) {
184-
getLogger().warn(`Log file ${logFile.path} does not exist!`)
185-
return { dispose: () => {} }
186-
}
187-
188-
let checking = false
189-
// TODO: fs.watch() has many problems, consider instead:
190-
// - https://github.com/paulmillr/chokidar
191-
// - https://www.npmjs.com/package/fb-watchman
192-
const fs = await import('fs')
193-
const watcher = fs.watch(logFile.fsPath, async eventType => {
194-
if (checking || eventType !== 'rename') {
195-
return
196-
}
197-
checking = true
198-
if (!(await fsCommon.existsFile(logFile))) {
199-
await vscode.window.showWarningMessage(
200-
localize('AWS.log.logFileMove', 'The log file for this session has been moved or deleted.')
201-
)
202-
watcher.close()
203-
}
204-
checking = false
205-
})
206-
207-
return { dispose: () => watcher.close() }
208-
}

packages/core/src/shared/logger/commands.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import * as vscode from 'vscode'
7-
import { Logger } from '.'
7+
import { Logger, showLogOutputChannel } from '.'
88
import { telemetry } from '../telemetry/telemetry'
99
import { Commands } from '../vscode/commands2'
1010
import { getLogger } from './logger'
@@ -25,18 +25,28 @@ function clearSelection(editor: vscode.TextEditor): void {
2525

2626
export class Logging {
2727
public static readonly declared = {
28+
// Calls openLogUri().
2829
viewLogs: Commands.from(this).declareOpenLogUri('aws.viewLogs'),
30+
// Calls openLogId().
2931
viewLogsAtMessage: Commands.from(this).declareOpenLogId('aws.viewLogsAtMessage'),
3032
}
3133

32-
public constructor(private readonly logUri: vscode.Uri, private readonly logger: Logger) {}
34+
public constructor(private readonly logUri: vscode.Uri | undefined, private readonly logger: Logger) {}
3335

3436
public async openLogUri(): Promise<vscode.TextEditor | undefined> {
37+
if (!this.logUri) {
38+
showLogOutputChannel()
39+
return undefined
40+
}
3541
telemetry.toolkit_viewLogs.emit({ result: 'Succeeded' })
3642
return vscode.window.showTextDocument(this.logUri)
3743
}
3844

3945
public async openLogId(logId: number) {
46+
if (!this.logUri) {
47+
showLogOutputChannel()
48+
return
49+
}
4050
const msg = this.logger.getLogById(logId, this.logUri)
4151
const editor = await this.openLogUri()
4252
if (!msg || !editor) {

packages/core/src/shared/logger/util.ts

Lines changed: 0 additions & 80 deletions
This file was deleted.

packages/core/src/test/shared/logger/util.test.ts

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)