Skip to content

Commit 4a7a75f

Browse files
author
Keegan Irby
committed
Add clear screen and stop session code lens
1 parent 396c54a commit 4a7a75f

File tree

6 files changed

+115
-26
lines changed

6 files changed

+115
-26
lines changed

packages/core/src/awsService/cloudWatchLogs/activation.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ import { searchLogGroup } from './commands/searchLogGroup'
1919
import { changeLogSearchParams } from './changeLogSearch'
2020
import { CloudWatchLogsNode } from './explorer/cloudWatchLogsNode'
2121
import { loadAndOpenInitialLogStreamFile, LogStreamCodeLensProvider } from './document/logStreamsCodeLensProvider'
22-
import { tailLogGroup } from './commands/tailLogGroup'
22+
import { clearDocument, closeSession, tailLogGroup } from './commands/tailLogGroup'
2323
import { LiveTailDocumentProvider } from './document/liveTailDocumentProvider'
2424
import { LiveTailSessionRegistry } from './registry/liveTailSessionRegistry'
2525
import { DeployedResourceNode } from '../appBuilder/explorer/nodes/deployedNode'
2626
import { isTreeNode } from '../../shared/treeview/resourceTreeDataProvider'
2727
import { getLogger } from '../../shared/logger/logger'
2828
import { ToolkitError } from '../../shared'
29+
import { LiveTailCodeLensProvider } from './document/liveTailCodeLensProvider'
2930

3031
export async function activate(context: vscode.ExtensionContext, configuration: Settings): Promise<void> {
3132
const registry = LogDataRegistry.instance
@@ -48,6 +49,16 @@ export async function activate(context: vscode.ExtensionContext, configuration:
4849
vscode.workspace.registerTextDocumentContentProvider(CLOUDWATCH_LOGS_SCHEME, documentProvider)
4950
)
5051

52+
context.subscriptions.push(
53+
vscode.languages.registerCodeLensProvider(
54+
{
55+
language: 'log',
56+
scheme: cloudwatchLogsLiveTailScheme,
57+
},
58+
new LiveTailCodeLensProvider()
59+
)
60+
)
61+
5162
context.subscriptions.push(
5263
vscode.workspace.registerTextDocumentContentProvider(cloudwatchLogsLiveTailScheme, liveTailDocumentProvider)
5364
)
@@ -112,6 +123,14 @@ export async function activate(context: vscode.ExtensionContext, configuration:
112123
await tailLogGroup(liveTailRegistry, logGroupInfo)
113124
}),
114125

126+
Commands.register('aws.cwl.stopTailingLogGroup', async (document: vscode.TextDocument) => {
127+
closeSession(document.uri, liveTailRegistry)
128+
}),
129+
130+
Commands.register('aws.cwl.clearDocument', async (document: vscode.TextDocument) => {
131+
await clearDocument(document)
132+
}),
133+
115134
Commands.register('aws.appBuilder.searchLogs', async (node: DeployedResourceNode) => {
116135
try {
117136
const logGroupInfo = isTreeNode(node)

packages/core/src/awsService/cloudWatchLogs/commands/tailLogGroup.ts

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
LiveTailSessionUpdate,
1414
StartLiveTailResponseStream,
1515
} from '@aws-sdk/client-cloudwatch-logs'
16-
import { globals, ToolkitError } from '../../../shared'
16+
import { getLogger, ToolkitError } from '../../../shared'
1717

1818
export async function tailLogGroup(
1919
registry: LiveTailSessionRegistry,
@@ -32,32 +32,29 @@ export async function tailLogGroup(
3232
region: wizardResponse.regionLogGroupSubmenuResponse.region,
3333
}
3434
const session = new LiveTailSession(liveTailSessionConfig)
35-
if (registry.has(session.uri)) {
35+
if (registry.has(session.uri.toString())) {
3636
await prepareDocument(session)
3737
return
3838
}
39-
registry.set(session.uri, session)
39+
registry.set(session.uri.toString(), session)
4040

4141
const document = await prepareDocument(session)
42-
const timer = globals.clock.setInterval(() => {
43-
session.updateStatusBarItemText()
44-
}, 500)
42+
4543
hideShowStatusBarItemsOnActiveEditor(session, document)
46-
registerTabChangeCallback(session, registry, document, timer)
44+
registerTabChangeCallback(session, registry, document)
4745

4846
const stream = await session.startLiveTailSession()
4947

50-
await handleSessionStream(stream, document, session, timer)
48+
await handleSessionStream(stream, document, session)
5149
}
5250

53-
export function closeSession(sessionUri: vscode.Uri, registry: LiveTailSessionRegistry, timer: NodeJS.Timer) {
54-
globals.clock.clearInterval(timer)
55-
const session = registry.get(sessionUri)
51+
export function closeSession(sessionUri: vscode.Uri, registry: LiveTailSessionRegistry) {
52+
const session = registry.get(sessionUri.toString())
5653
if (session === undefined) {
5754
throw new ToolkitError(`No LiveTail session found for URI: ${sessionUri.toString()}`)
5855
}
5956
session.stopLiveTailSession()
60-
registry.delete(sessionUri)
57+
registry.delete(sessionUri.toString())
6158
}
6259

6360
export async function clearDocument(textDocument: vscode.TextDocument) {
@@ -80,8 +77,7 @@ async function prepareDocument(session: LiveTailSession): Promise<vscode.TextDoc
8077
async function handleSessionStream(
8178
stream: AsyncIterable<StartLiveTailResponseStream>,
8279
document: vscode.TextDocument,
83-
session: LiveTailSession,
84-
timer: NodeJS.Timer
80+
session: LiveTailSession
8581
) {
8682
try {
8783
for await (const event of stream) {
@@ -100,8 +96,21 @@ async function handleSessionStream(
10096
session.isSampled = isSampled(event.sessionUpdate)
10197
}
10298
}
103-
} finally {
104-
globals.clock.clearInterval(timer)
99+
} catch (e) {
100+
if (session.isAborted) {
101+
//Expected case. User action cancelled stream (CodeLens, Close Editor, etc.).
102+
//AbortSignal interrupts the LiveTail stream, causing error to be thrown here.
103+
//Can assume that stopLiveTailSession() has already been called - AbortSignal is only
104+
//exposed through that method.
105+
getLogger().info(`Session ${session.uri.toString()} stopped.`)
106+
} else {
107+
//Unexpected exception.
108+
session.stopLiveTailSession()
109+
throw ToolkitError.chain(
110+
e,
111+
`Unexpected on-stream execption while tailing session: ${session.uri.toString()}`
112+
)
113+
}
105114
}
106115
}
107116

@@ -196,13 +205,12 @@ function hideShowStatusBarItemsOnActiveEditor(session: LiveTailSession, document
196205
function registerTabChangeCallback(
197206
session: LiveTailSession,
198207
registry: LiveTailSessionRegistry,
199-
document: vscode.TextDocument,
200-
timer: NodeJS.Timer
208+
document: vscode.TextDocument
201209
) {
202210
vscode.window.tabGroups.onDidChangeTabs((tabEvent) => {
203211
const isOpen = isLiveTailSessionOpenInAnyTab(session)
204212
if (!isOpen) {
205-
closeSession(session.uri, registry, timer)
213+
closeSession(session.uri, registry)
206214
void clearDocument(document)
207215
}
208216
})
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as vscode from 'vscode'
7+
import { cloudwatchLogsLiveTailScheme } from '../../../shared/constants'
8+
9+
export class LiveTailCodeLensProvider implements vscode.CodeLensProvider {
10+
onDidChangeCodeLenses?: vscode.Event<void> | undefined
11+
12+
provideCodeLenses(
13+
document: vscode.TextDocument,
14+
token: vscode.CancellationToken
15+
): vscode.ProviderResult<vscode.CodeLens[]> {
16+
const uri = document.uri
17+
if (uri.scheme !== cloudwatchLogsLiveTailScheme) {
18+
return []
19+
}
20+
const codeLenses: vscode.CodeLens[] = []
21+
codeLenses.push(this.buildClearDocumentCodeLens(document))
22+
codeLenses.push(this.buildStopTailingCodeLens(document))
23+
return codeLenses
24+
}
25+
26+
private buildClearDocumentCodeLens(document: vscode.TextDocument): vscode.CodeLens {
27+
const range = new vscode.Range(
28+
new vscode.Position(document.lineCount - 1, 0),
29+
new vscode.Position(document.lineCount - 1, 0)
30+
)
31+
const command: vscode.Command = {
32+
title: 'Clear document',
33+
command: 'aws.cwl.clearDocument',
34+
arguments: [document],
35+
}
36+
return new vscode.CodeLens(range, command)
37+
}
38+
39+
private buildStopTailingCodeLens(document: vscode.TextDocument): vscode.CodeLens {
40+
const range = new vscode.Range(
41+
new vscode.Position(document.lineCount - 1, 0),
42+
new vscode.Position(document.lineCount - 1, 0)
43+
)
44+
const command: vscode.Command = {
45+
title: 'Stop tailing',
46+
command: 'aws.cwl.stopTailingLogGroup',
47+
arguments: [document],
48+
}
49+
return new vscode.CodeLens(range, command)
50+
}
51+
}

packages/core/src/awsService/cloudWatchLogs/registry/liveTailSession.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from '@aws-sdk/client-cloudwatch-logs'
1111
import { LogStreamFilterResponse } from '../wizard/liveTailLogStreamSubmenu'
1212
import { CloudWatchLogsSettings } from '../cloudWatchLogsUtils'
13-
import { convertToTimeString, Settings, ToolkitError } from '../../../shared'
13+
import { convertToTimeString, globals, Settings, ToolkitError } from '../../../shared'
1414
import { createLiveTailURIFromArgs } from './liveTailSessionRegistry'
1515
import { getUserAgent } from '../../../shared/telemetry/util'
1616

@@ -39,6 +39,9 @@ export class LiveTailSession {
3939
private _eventRate: number
4040
private _isSampled: boolean
4141

42+
//While session is running, used to update the StatusBar each half second.
43+
private statusBarUpdateTimer: NodeJS.Timer | undefined
44+
4245
static settings = new CloudWatchLogsSettings(Settings.instance)
4346

4447
public constructor(configuration: LiveTailSessionConfiguration) {
@@ -89,6 +92,10 @@ export class LiveTailSession {
8992
}
9093
this.startTime = Date.now()
9194
this.endTime = undefined
95+
this.statusBarUpdateTimer = globals.clock.setInterval(() => {
96+
this.updateStatusBarItemText()
97+
}, 500)
98+
9299
return commandOutput.responseStream
93100
} catch (e) {
94101
throw new ToolkitError('Encountered error while trying to start LiveTail session.')
@@ -98,6 +105,7 @@ export class LiveTailSession {
98105
public stopLiveTailSession() {
99106
this.endTime = Date.now()
100107
this.statusBarItem.dispose()
108+
globals.clock.clearInterval(this.statusBarUpdateTimer)
101109
this.liveTailClient.abortController.abort()
102110
this.liveTailClient.cwlClient.destroy()
103111
}
@@ -145,4 +153,8 @@ export class LiveTailSession {
145153
const sampledString = this._isSampled ? 'Yes' : 'No'
146154
this.statusBarItem.text = `Tailing: ${timeString}, ${this._eventRate} events/sec, Sampled: ${sampledString}`
147155
}
156+
157+
public get isAborted() {
158+
return this.liveTailClient.abortController.signal.aborted
159+
}
148160
}

packages/core/src/awsService/cloudWatchLogs/registry/liveTailSessionRegistry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as vscode from 'vscode'
66
import { cloudwatchLogsLiveTailScheme } from '../../../shared/constants'
77
import { LiveTailSession, LiveTailSessionConfiguration } from './liveTailSession'
88

9-
export class LiveTailSessionRegistry extends Map<vscode.Uri, LiveTailSession> {
9+
export class LiveTailSessionRegistry extends Map<string, LiveTailSession> {
1010
static #instance: LiveTailSessionRegistry
1111

1212
public static get instance() {

packages/core/src/test/awsService/cloudWatchLogs/commands/tailLogGroup.test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,14 @@ describe('TailLogGroup', function () {
125125
.callsFake(async function () {
126126
return
127127
})
128-
// const fakeClock = installFakeClock()
129-
const timer = setInterval(() => {}, 1000)
128+
130129
const session = new LiveTailSession({
131130
logGroupName: testLogGroup,
132131
region: testRegion,
133132
})
134-
registry.set(session.uri, session)
133+
registry.set(session.uri.toString(), session)
135134

136-
closeSession(session.uri, registry, timer)
135+
closeSession(session.uri, registry)
137136
assert.strictEqual(0, registry.size)
138137
assert.strictEqual(true, stopLiveTailSessionSpy.calledOnce)
139138
assert.strictEqual(0, clock.countTimers())

0 commit comments

Comments
 (0)