Skip to content

Commit 0aadddf

Browse files
committed
implement logic for manifest telemetry
1 parent abdb5fd commit 0aadddf

File tree

4 files changed

+61
-38
lines changed

4 files changed

+61
-38
lines changed

packages/core/src/amazonq/lsp/lspController.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,7 @@ export class LspController {
161161
}
162162
setImmediate(async () => {
163163
try {
164-
await lspSetupStage('final', async () => {
165-
const installResult = await new WorkspaceLSPResolver().resolve()
166-
await lspSetupStage('launch', async () => activateLsp(context, installResult.resourcePaths))
167-
getLogger().info('LspController: LSP activated')
168-
})
164+
await this.setupLsp(context)
169165
void LspController.instance.buildIndex(buildIndexConfig)
170166
// log the LSP server CPU and Memory usage per 30 minutes.
171167
globals.clock.setInterval(
@@ -186,4 +182,12 @@ export class LspController {
186182
}
187183
})
188184
}
185+
186+
private async setupLsp(context: vscode.ExtensionContext) {
187+
await lspSetupStage('all', async () => {
188+
const installResult = await new WorkspaceLSPResolver().resolve()
189+
await lspSetupStage('launch', async () => activateLsp(context, installResult.resourcePaths))
190+
getLogger().info('LspController: LSP activated')
191+
})
192+
}
189193
}

packages/core/src/amazonq/lsp/util.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,43 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { LanguageServerSetupStage, telemetry } from '../../shared/telemetry'
6+
import { LanguageServerSetup, LanguageServerSetupStage, telemetry } from '../../shared/telemetry'
77

8-
export async function lspSetupStage<T>(stageName: LanguageServerSetupStage, stage: () => Promise<T>) {
8+
/**
9+
* Runs the designated stage within a telemetry span and optionally uses the getMetadata extractor to record metadata from the result of the stage.
10+
* @param stageName name of stage for telemetry.
11+
* @param runStage stage to be run.
12+
* @param getMetadata metadata extracter to be applied to result.
13+
* @returns result of stage
14+
*/
15+
export async function lspSetupStage<T>(
16+
stageName: LanguageServerSetupStage,
17+
runStage: () => Promise<T>,
18+
getMetadata?: (result: T) => Partial<LanguageServerSetup>
19+
) {
920
return await telemetry.languageServer_setup.run(async (span) => {
10-
const startTime = performance.now()
11-
const result = await stage()
21+
const result = await runStage()
1222
span.record({ languageServerSetupStage: stageName })
13-
span.record({ duration: performance.now() - startTime })
23+
if (getMetadata) {
24+
span.record(getMetadata(result))
25+
}
1426
return result
1527
})
1628
}
29+
30+
/**
31+
* Try Functions in the order presented and return the first returned result. If none return, throw the final error.
32+
* @param functions non-empty list of functions to try.
33+
* @returns
34+
*/
35+
export async function tryFunctions<Result>(functions: (() => Promise<Result>)[]): Promise<Result> {
36+
let currentError: Error = new Error('No functions provided')
37+
for (const func of functions) {
38+
try {
39+
return await func()
40+
} catch (e) {
41+
currentError = e as Error
42+
}
43+
}
44+
throw currentError
45+
}

packages/core/src/amazonq/lsp/workspaceInstaller.ts

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import { LanguageServerResolver } from '../../shared/lsp/lspResolver'
1010
import { Range } from 'semver'
1111
import { getNodeExecutableName } from '../../shared/lsp/utils/platform'
1212
import { fs } from '../../shared/fs/fs'
13-
import { telemetry } from '../../shared/telemetry'
14-
import { lspSetupStage } from './util'
1513

1614
const manifestUrl = 'https://aws-toolkit-language-servers.amazonaws.com/q-context/manifest.json'
1715
// this LSP client in Q extension is only going to work with these LSP server versions
@@ -20,28 +18,12 @@ const supportedLspServerVersions = '0.1.32'
2018
export class WorkspaceLSPResolver implements LspResolver {
2119
async resolve(): Promise<LspResolution> {
2220
const name = 'AmazonQ-Workspace'
23-
const manifest = await lspSetupStage('getManifest', async () => {
24-
const result = await new ManifestResolver(manifestUrl, name).resolve()
25-
telemetry.record({
26-
manifestVersion: result.manifestSchemaVersion,
27-
languageServerResourceLocation: result.location ?? 'unknown',
28-
})
29-
return result
30-
})
31-
telemetry.record({
32-
manifestVersion: manifest.manifestSchemaVersion,
33-
})
34-
const installationResult = await lspSetupStage('getServer', async () => {
35-
const result = await new LanguageServerResolver(
36-
manifest,
37-
name,
38-
new Range(supportedLspServerVersions)
39-
).resolve()
40-
telemetry.record({
41-
languageServerResourceLocation: result.location ?? 'unknown',
42-
})
43-
return result
44-
})
21+
const manifest = await new ManifestResolver(manifestUrl, name).resolve()
22+
const installationResult = await new LanguageServerResolver(
23+
manifest,
24+
name,
25+
new Range(supportedLspServerVersions)
26+
).resolve()
4527

4628
const nodeName =
4729
process.platform === 'win32' ? getNodeExecutableName() : `node-${process.platform}-${process.arch}`

packages/core/src/shared/lsp/manifestResolver.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { RetryableResourceFetcher } from '../resourcefetcher/httpResourceFetcher
99
import { Timeout } from '../utilities/timeoutUtils'
1010
import globals from '../extensionGlobals'
1111
import { Manifest } from './types'
12+
import { lspSetupStage, tryFunctions } from '../../amazonq/lsp/util'
1213

1314
const logger = getLogger('lsp')
1415

@@ -32,10 +33,17 @@ export class ManifestResolver {
3233
* Fetches the latest manifest, falling back to local cache on failure
3334
*/
3435
async resolve(): Promise<Manifest> {
35-
try {
36-
return await this.fetchRemoteManifest()
37-
} catch (error) {
38-
return await this.getLocalManifest()
36+
return await tryFunctions([
37+
async () => await resolveManifestWith(async () => await this.fetchRemoteManifest()),
38+
async () => await resolveManifestWith(async () => await this.getLocalManifest()),
39+
])
40+
41+
async function resolveManifestWith(resolver: () => Promise<Manifest>) {
42+
return await lspSetupStage('getManifest', async () => await resolver(), extractVersionFromResult)
43+
}
44+
45+
function extractVersionFromResult(r: Manifest) {
46+
return { manifestSchemaVersion: r.manifestSchemaVersion }
3947
}
4048
}
4149

0 commit comments

Comments
 (0)