public sendUserTriggerDecisionTelemetry()

in packages/core/src/codewhisperer/util/telemetryHelper.ts [351:465]


    public sendUserTriggerDecisionTelemetry(
        sessionId: string,
        acceptedRecommendationContent: string,
        referenceCount: number,
        supplementalContextMetadata?: CodeWhispererSupplementalContext | undefined
    ) {
        // the user trigger decision will aggregate information from request level user decisions within one session
        // and add additional session level insights
        if (!this.sessionDecisions.length) {
            return
        }

        // TODO: add partial acceptance related metrics
        const autoTriggerType = this.sessionDecisions[0].codewhispererAutomatedTriggerType
        const language = this.sessionDecisions[0].codewhispererLanguage
        const aggregatedCompletionType = this.sessionDecisions[0].codewhispererCompletionType
        const aggregatedSuggestionState = this.getAggregatedSuggestionState(this.sessionDecisions)
        const selectedCustomization = getSelectedCustomization()
        const profile = AuthUtil.instance.regionProfileManager.activeRegionProfile
        const generatedLines =
            acceptedRecommendationContent.trim() === '' ? 0 : acceptedRecommendationContent.split('\n').length
        const suggestionCount = this.sessionDecisions
            .map((e) => e.codewhispererSuggestionCount)
            .reduce((a, b) => a + b, 0)

        const aggregated: CodewhispererUserTriggerDecision = {
            codewhispererAutomatedTriggerType: autoTriggerType,
            codewhispererCharactersAccepted: acceptedRecommendationContent.length,
            codewhispererClassifierResult: this.classifierResult,
            codewhispererClassifierThreshold: this.classifierThreshold,
            codewhispererCompletionType: aggregatedCompletionType,
            codewhispererCursorOffset: this.sessionDecisions[0].codewhispererCursorOffset,
            codewhispererCustomizationArn: selectedCustomization.arn === '' ? undefined : selectedCustomization.arn,
            codewhispererFeatureEvaluations: FeatureConfigProvider.instance.getFeatureConfigsTelemetry(),
            codewhispererFirstRequestId: this.sessionDecisions[0].codewhispererFirstRequestId,
            codewhispererGettingStartedTask: session.taskType,
            codewhispererLanguage: language,
            codewhispererLineNumber: this.sessionDecisions[0].codewhispererLineNumber,
            codewhispererPreviousSuggestionState: this.prevTriggerDecision,
            codewhispererSessionId: this.sessionDecisions[0].codewhispererSessionId,
            codewhispererSuggestionCount: suggestionCount,
            codewhispererSuggestionImportCount: this.sessionDecisions
                .map((e) => e.codewhispererSuggestionImportCount || 0)
                .reduce((a, b) => a + b, 0),
            codewhispererSuggestionState: aggregatedSuggestionState,
            codewhispererSupplementalContextIsUtg: supplementalContextMetadata?.isUtg,
            codewhispererSupplementalContextLength: supplementalContextMetadata?.contentsLength,
            // eslint-disable-next-line id-length
            codewhispererSupplementalContextStrategyId: supplementalContextMetadata?.strategy,
            codewhispererSupplementalContextTimeout: supplementalContextMetadata?.isProcessTimeout,
            codewhispererTimeSinceLastDocumentChange: this.timeSinceLastModification
                ? this.timeSinceLastModification
                : undefined,
            codewhispererTimeSinceLastUserDecision: this.lastTriggerDecisionTime
                ? performance.now() - this.lastTriggerDecisionTime
                : undefined,
            codewhispererTimeToFirstRecommendation: session.timeToFirstRecommendation,
            codewhispererTriggerCharacter: autoTriggerType === 'SpecialCharacters' ? this.triggerChar : undefined,
            codewhispererTriggerType: this.sessionDecisions[0].codewhispererTriggerType,
            codewhispererTypeaheadLength: this.typeAheadLength,
            credentialStartUrl: this.sessionDecisions[0].credentialStartUrl,
            traceId: this.traceId,
        }
        telemetry.codewhisperer_userTriggerDecision.emit(aggregated)
        this.prevTriggerDecision = this.getAggregatedSuggestionState(this.sessionDecisions)
        this.lastTriggerDecisionTime = performance.now()

        // When we send a userTriggerDecision for neither Accept nor Reject, service side should not use this value
        // and client side will set this value to 0.0.
        let e2eLatency = session.firstSuggestionShowTime - session.invokeSuggestionStartTime
        if (aggregatedSuggestionState !== 'Reject' && aggregatedSuggestionState !== 'Accept') {
            e2eLatency = 0.0
        }

        client
            .sendTelemetryEvent({
                telemetryEvent: {
                    userTriggerDecisionEvent: {
                        sessionId: sessionId,
                        requestId: this.sessionDecisions[0].codewhispererFirstRequestId,
                        customizationArn: selectedCustomization.arn === '' ? undefined : selectedCustomization.arn,
                        programmingLanguage: {
                            languageName: runtimeLanguageContext.toRuntimeLanguage(
                                this.sessionDecisions[0].codewhispererLanguage
                            ),
                        },
                        completionType: this.getSendTelemetryCompletionType(aggregatedCompletionType),
                        suggestionState: this.getSendTelemetrySuggestionState(aggregatedSuggestionState),
                        recommendationLatencyMilliseconds: e2eLatency,
                        triggerToResponseLatencyMilliseconds: session.timeToFirstRecommendation,
                        perceivedLatencyMilliseconds: session.perceivedLatency,
                        timestamp: new Date(Date.now()),
                        suggestionReferenceCount: referenceCount,
                        generatedLine: generatedLines,
                        numberOfRecommendations: suggestionCount,
                        acceptedCharacterCount: acceptedRecommendationContent.length,
                    },
                },
                profileArn: profile?.arn,
            })
            .then()
            .catch((error) => {
                let requestId: string | undefined
                if (isAwsError(error)) {
                    requestId = error.requestId
                }

                getLogger().debug(
                    `Failed to sendTelemetryEvent to CodeWhisperer, requestId: ${requestId ?? ''}, message: ${
                        error.message
                    }`
                )
            })
        this.resetUserTriggerDecisionTelemetry()
    }