Skip to content

Commit a386cc3

Browse files
authored
refactor(telemetry): Remove telemetry.foo.record (aws#5646)
## Problem - Theres quite a few missues of telemetry.foo.record inside of the codebase and it can be confusing for external contributors ## Solution - Clean up the telemetry interface by only allowing record/increment on spans
1 parent 9088d58 commit a386cc3

File tree

13 files changed

+41
-42
lines changed

13 files changed

+41
-42
lines changed

package-lock.json

Lines changed: 8 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"generateNonCodeFiles": "npm run generateNonCodeFiles -w packages/ --if-present"
4040
},
4141
"devDependencies": {
42-
"@aws-toolkits/telemetry": "^1.0.258",
42+
"@aws-toolkits/telemetry": "^1.0.267",
4343
"@playwright/browser-chromium": "^1.43.1",
4444
"@types/vscode": "^1.68.0",
4545
"@types/vscode-webview": "^1.57.1",

packages/amazonq/test/unit/amazonqFeatureDev/util/files.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
maxRepoSizeBytes,
1212
} from 'aws-core-vscode/amazonqFeatureDev'
1313
import { assertTelemetry, createTestWorkspace } from 'aws-core-vscode/test'
14-
import { fs, AmazonqCreateUpload, Metric } from 'aws-core-vscode/shared'
14+
import { fs, AmazonqCreateUpload } from 'aws-core-vscode/shared'
15+
import { Span } from 'aws-core-vscode/telemetry'
1516
import sinon from 'sinon'
1617

1718
describe('file utils', () => {
@@ -28,7 +29,7 @@ describe('file utils', () => {
2829
const telemetry = new TelemetryHelper()
2930
const result = await prepareRepoData([workspace.uri.fsPath], [workspace], telemetry, {
3031
record: () => {},
31-
} as unknown as Metric<AmazonqCreateUpload>)
32+
} as unknown as Span<AmazonqCreateUpload>)
3233
assert.strictEqual(Buffer.isBuffer(result.zipFileBuffer), true)
3334
// checksum is not the same across different test executions because some unique random folder names are generated
3435
assert.strictEqual(result.zipFileChecksum.length, 44)
@@ -46,7 +47,7 @@ describe('file utils', () => {
4647
const telemetry = new TelemetryHelper()
4748
const result = await prepareRepoData([workspace.uri.fsPath], [workspace], telemetry, {
4849
record: () => {},
49-
} as unknown as Metric<AmazonqCreateUpload>)
50+
} as unknown as Span<AmazonqCreateUpload>)
5051

5152
assert.strictEqual(Buffer.isBuffer(result.zipFileBuffer), true)
5253
// checksum is not the same across different test executions because some unique random folder names are generated
@@ -65,7 +66,7 @@ describe('file utils', () => {
6566
() =>
6667
prepareRepoData([workspace.uri.fsPath], [workspace], telemetry, {
6768
record: () => {},
68-
} as unknown as Metric<AmazonqCreateUpload>),
69+
} as unknown as Span<AmazonqCreateUpload>),
6970
ContentLengthError
7071
)
7172
})

packages/core/src/amazonqFeatureDev/util/files.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { maxFileSizeBytes } from '../limits'
1414
import { createHash } from 'crypto'
1515
import { CurrentWsFolders } from '../types'
1616
import { ToolkitError } from '../../shared/errors'
17-
import { AmazonqCreateUpload, Metric, telemetry as amznTelemetry } from '../../shared/telemetry/telemetry'
17+
import { AmazonqCreateUpload, Span, telemetry as amznTelemetry } from '../../shared/telemetry/telemetry'
1818
import { TelemetryHelper } from './telemetryHelper'
1919
import { maxRepoSizeBytes } from '../constants'
2020
import { isCodeFile } from '../../shared/filetypes'
@@ -28,7 +28,7 @@ export async function prepareRepoData(
2828
repoRootPaths: string[],
2929
workspaceFolders: CurrentWsFolders,
3030
telemetry: TelemetryHelper,
31-
span: Metric<AmazonqCreateUpload>
31+
span: Span<AmazonqCreateUpload>
3232
) {
3333
try {
3434
const files = await collectFiles(repoRootPaths, workspaceFolders, true, maxRepoSizeBytes)

packages/core/src/amazonqFeatureDev/util/telemetryHelper.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { globals } from '../../shared'
77
import { getLogger } from '../../shared/logger/logger'
8-
import { AmazonqApproachInvoke, AmazonqCodeGenerationInvoke, Metric } from '../../shared/telemetry/telemetry'
8+
import { AmazonqApproachInvoke, AmazonqCodeGenerationInvoke, Span } from '../../shared/telemetry/telemetry'
99
import { LLMResponseType } from '../types'
1010

1111
export class TelemetryHelper {
@@ -32,7 +32,7 @@ export class TelemetryHelper {
3232
}
3333

3434
public recordUserApproachTelemetry(
35-
span: Metric<AmazonqApproachInvoke>,
35+
span: Span<AmazonqApproachInvoke>,
3636
amazonqConversationId: string,
3737
responseType: LLMResponseType
3838
) {
@@ -48,7 +48,7 @@ export class TelemetryHelper {
4848
span.record(event)
4949
}
5050

51-
public recordUserCodeGenerationTelemetry(span: Metric<AmazonqCodeGenerationInvoke>, amazonqConversationId: string) {
51+
public recordUserCodeGenerationTelemetry(span: Span<AmazonqCodeGenerationInvoke>, amazonqConversationId: string) {
5252
const event = {
5353
amazonqConversationId,
5454
amazonqGenerateCodeIteration: this.generateCodeIteration,

packages/core/src/auth/secondaryAuth.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { isNonNullable } from '../shared/utilities/tsUtils'
1212
import { ToolIdStateKey } from '../shared/globalState'
1313
import { Connection, getTelemetryMetadataForConn, SsoConnection, StatefulConnection } from './connection'
1414
import { indent } from '../shared/utilities/textUtilities'
15-
import { AuthStatus, telemetry } from '../shared/telemetry/telemetry'
15+
import { AuthModifyConnection, AuthStatus, Span, telemetry } from '../shared/telemetry/telemetry'
1616
import { asStringifiedStack } from '../shared/telemetry/spans'
1717
import { withTelemetryContext } from '../shared/telemetry/util'
1818
import { isNetworkError } from '../shared/errors'
@@ -307,7 +307,7 @@ export class SecondaryAuth<T extends Connection = Connection> {
307307
connectionState: 'undefined',
308308
})
309309
await this.auth.tryAutoConnect()
310-
this.#savedConnection = await this._loadSavedConnection()
310+
this.#savedConnection = await this._loadSavedConnection(span)
311311
this.#onDidChangeActiveConnection.fire(this.activeConnection)
312312

313313
const conn = this.#savedConnection
@@ -328,7 +328,7 @@ export class SecondaryAuth<T extends Connection = Connection> {
328328
/**
329329
* Provides telemetry if called by restoreConnection() (or another auth_modifyConnection context)
330330
*/
331-
private async _loadSavedConnection() {
331+
private async _loadSavedConnection(span: Span<AuthModifyConnection>) {
332332
const id = this.getStateConnectionId()
333333
if (id === undefined) {
334334
return
@@ -349,7 +349,7 @@ export class SecondaryAuth<T extends Connection = Connection> {
349349
let connectionState = this.auth.getConnectionState(conn)
350350

351351
// This function is expected to be called in the context of restoreConnection()
352-
telemetry.auth_modifyConnection.record({
352+
span.record({
353353
connectionState,
354354
authStatus: getAuthStatus(connectionState),
355355
})
@@ -358,7 +358,7 @@ export class SecondaryAuth<T extends Connection = Connection> {
358358
await this.auth.refreshConnectionState(conn)
359359

360360
connectionState = this.auth.getConnectionState(conn)
361-
telemetry.auth_modifyConnection.record({
361+
span.record({
362362
connectionState,
363363
authStatus: getAuthStatus(connectionState),
364364
})
@@ -367,7 +367,7 @@ export class SecondaryAuth<T extends Connection = Connection> {
367367
// If updating the state fails, then we should delegate downstream to handle getting the proper state.
368368
getLogger().error('loadSavedConnection: Failed to refresh connection state: %s', err)
369369
if (isNetworkError(err) && connectionState === 'valid') {
370-
telemetry.auth_modifyConnection.record({
370+
span.record({
371371
authStatus: 'connectedWithNetworkError',
372372
})
373373
}

packages/core/src/shared/telemetry/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
*/
55

66
export { activate } from './activation'
7-
export { telemetry, AuthStatus } from './telemetry'
7+
export { telemetry, AuthStatus, Span } from './telemetry'
88
export { ExtStartUpSources } from './util'

packages/core/src/shared/telemetry/spans.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
MetricDefinition,
1414
MetricName,
1515
MetricShapes,
16+
Span,
1617
TelemetryBase,
1718
} from './telemetry.gen'
1819
import {
@@ -132,7 +133,7 @@ export type SpanOptions = {
132133
*
133134
* See also: docs/telemetry.md
134135
*/
135-
export class TelemetrySpan<T extends MetricBase = MetricBase> {
136+
export class TelemetrySpan<T extends MetricBase = MetricBase> implements Span<T> {
136137
#startTime?: Date
137138
#options: SpanOptions
138139

@@ -317,6 +318,9 @@ export class TelemetryTracer extends TelemetryBase {
317318
* All changes made to {@link attributes} (via {@link record}) during the execution are
318319
* reverted after the execution completes.
319320
*
321+
* Runs can be nested within each other. This allows for creating hierarchical spans,
322+
* where child spans inherit the context of their parent spans.
323+
*
320324
* This method automatically handles traceId generation and propagation:
321325
* - If no traceId exists in the current context, a new one is generated.
322326
* - The traceId is attached to all telemetry events created within this span.
@@ -325,19 +329,13 @@ export class TelemetryTracer extends TelemetryBase {
325329
*
326330
* See docs/telemetry.md
327331
*/
328-
public run<T, U extends MetricName>(name: U, fn: (span: Metric<MetricShapes[U]>) => T, options?: SpanOptions): T {
332+
public run<T, U extends MetricName>(name: U, fn: (span: Span<MetricShapes[U]>) => T, options?: SpanOptions): T {
329333
return this.withTraceId(() => {
330334
const span = this.createSpan(name, options).start()
331335
const frame = this.switchContext(span)
332336

333337
try {
334-
//
335-
// TODO: Since updating to `@types/node@16`, typescript flags this code with error:
336-
//
337-
// Error: npm ERR! src/shared/telemetry/spans.ts(255,57): error TS2345: Argument of type
338-
// 'TelemetrySpan<MetricBase>' is not assignable to parameter of type 'Metric<MetricShapes[U]>'.
339-
//
340-
const result = this.#context.run(frame, fn, span as any)
338+
const result = this.#context.run(frame, fn, span)
341339

342340
if (result instanceof Promise) {
343341
return result
@@ -444,9 +442,7 @@ export class TelemetryTracer extends TelemetryBase {
444442
return {
445443
name,
446444
emit: (data) => getSpan().emit(data),
447-
record: (data) => getSpan().record(data),
448445
run: (fn, options?: SpanOptions) => this.run(name as MetricName, fn, options),
449-
increment: (data) => getSpan().increment(data),
450446
}
451447
}
452448

packages/core/src/shared/telemetry/telemetry.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ export const telemetry = new TelemetryTracer()
2323
*/
2424
declare module './telemetry.gen' {
2525
interface Metric<T extends MetricBase = MetricBase> {
26+
run<U>(fn: (span: Span<T>) => U, options?: SpanOptions): U
27+
}
28+
29+
interface Span<T extends MetricBase = MetricBase> {
2630
increment(data: { [P in NumericKeys<T>]+?: number }): void
27-
run<U>(fn: (span: this) => U, options?: SpanOptions): U
2831
}
2932
}

packages/core/src/shared/vscode/commands2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { toTitleCase } from '../utilities/textUtilities'
88
import { getLogger, NullLogger } from '../logger/logger'
99
import { FunctionKeys, Functions, getFunctions } from '../utilities/classUtils'
1010
import { TreeItemContent, TreeNode } from '../treeview/resourceTreeDataProvider'
11-
import { telemetry, MetricName, VscodeExecuteCommand, Metric } from '../telemetry/telemetry'
11+
import { telemetry, MetricName, VscodeExecuteCommand, Metric, Span } from '../telemetry/telemetry'
1212
import globals from '../extensionGlobals'
1313
import { ToolkitError } from '../errors'
1414
import crypto from 'crypto'
@@ -498,7 +498,7 @@ function getInstrumenter(
498498
return <T extends Callback>(fn: T, ...args: Parameters<T>) =>
499499
span.run(
500500
(span) => {
501-
;(span as Metric<VscodeExecuteCommand>).record({
501+
;(span as Span<VscodeExecuteCommand>).record({
502502
command: id.id,
503503
debounceCount,
504504
...fields,

0 commit comments

Comments
 (0)