Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Amazon Q Code Transform: Add telemetry helper functions for common API telemetry. #5044

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

arangatang
Copy link
Contributor

@arangatang arangatang commented May 23, 2024

Problem

  1. Telemetry emitted for api calls + uploads and downloads differ between different api calls despite all using the codeTransform_logApiLatency and codeTransform_logApiError metrics.
  2. codeTransform_logApiLatency only emitted on success but not also on failure
  3. downloadExportResultArchive - Inconsistent telemetry depending on who invoked
  4. Lots of duplicate code for telemetry emission

Solution

Add TelemetryHelper which offers callApi function that wraps an API call with relevant telemetry for CodeTransform APIs. Download / Upload calls are not supported as the structure of their responses differ.
TelemetryHelper is also a first step towards:

  1. Avoiding direct access to TelemetryState from core business logic (seperation of concerns)
  2. Code cleanup - gets rid of code duplication due to telemetry code

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@arangatang arangatang self-assigned this May 23, 2024
@arangatang arangatang requested review from a team as code owners May 23, 2024 10:32
@arangatang
Copy link
Contributor Author

Failures are unrelated to my changes:

Unix failures

2462 passing (2m)
  10 pending
  1 failing
  1) Auth
       promptForConnection
         reauthenticates a connection if the user selects an expired one:

      AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:

  assert_1.default.ok(!refreshedConnItem.description?.match(/expired/i))

      + expected - actual

      -false
      +true
      
      at /Users/runner/work/aws-toolkit-vscode/aws-toolkit-vscode/packages/core/src/test/credentials/auth.test.ts:512:24
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at async /Users/runner/work/aws-toolkit-vscode/aws-toolkit-vscode/packages/core/src/test/shared/vscode/window.ts:501:29

Windows failures

rejected promise not handled within 1 second: Error: ToolkitGlobals accessed before initialize()
stack trace: Error: ToolkitGlobals accessed before initialize()
    at Object.get (d:\a\aws-toolkit-vscode\aws-toolkit-vscode\packages\core\src\shared\extensionGlobals.ts:107:23)
Comment on lines +157 to +162
let uploadId = parameters.uploadId
try {
uploadId = (result as CreateUploadUrlResponse).uploadId
} catch (_) {
//noop
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try/catch is not necessary here. Just use .? operator.
that also allows use of const.

Suggested change
let uploadId = parameters.uploadId
try {
uploadId = (result as CreateUploadUrlResponse).uploadId
} catch (_) {
//noop
}
const uploadId = (result as CreateUploadUrlResponse)?.uploadId ?? parameters.uploadId
Comment on lines +165 to +169
try {
requestId = (result as PromiseResult<CodeTransformAPIresponse, AWSError>).$response.requestId
} catch (_) {
// noop
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try/catch not necessary, and discouraged. use getRequestId from errors.ts.

codeTransformRunTimeLatency: calculateTotalLatency(apiStartTime),
codeTransformJobId: parameters.jobId,
codeTransformTotalByteSize: parameters.uploadFileByteSize,
codeTransformRequestId: requestId,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a standard requestId field already. any reason not to use it?

@justinmk3
Copy link
Contributor

Glad to see this effort to reduce code duplication, but it's really unfortunate that gumby telemetry is designed this way. This could be avoided by wrapping your logic in telemetry.codeTransform_xx.run(), which automatically sets many standard metric fields (and more will be added soon, such as HTTP status code):

public stop(err?: unknown): void {
const duration = this.startTime !== undefined ? globals.clock.Date.now() - this.startTime.getTime() : undefined
// TODO: add reasonDesc/requestId to `MetricBase` so we can remove `as any` below.
this.emit({
duration,
result: getTelemetryResult(err),
reason: getTelemetryReason(err),
reasonDesc: getTelemetryReasonDesc(err),
requestId: getRequestId(err),
} as any as Partial<T>)
this.#startTime = undefined
}

Unfortunately, because gumby has not modeled telemetry to represent actions, and instead has "latency" and "error" metrics, this doesn't quite fit semantically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
5 participants