From e94a2864502c2da0e7ed21c0f2fc42e99a2d64bc Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Fri, 4 Oct 2024 16:33:05 -0700 Subject: [PATCH 1/2] Add metadata to authAddConnection metrics --- .../services/amazonq/auth/AuthController.kt | 2 +- .../explorerActions/SignInToQAction.kt | 4 +- .../resources/telemetryOverride.json | 44 ------------------- .../gettingstarted/GettingStartedAuthUtils.kt | 14 ++++-- .../SetupAuthenticationDialog.kt | 12 +++-- .../editor/GettingStartedPanelUtils.kt | 1 + .../jetbrains/core/webview/LoginBrowser.kt | 32 +++++++++++--- .../core/webview/WebviewTelemetryUtils.kt | 12 +++++ .../gettingstarted/GettingStartedOnStartup.kt | 6 ++- .../ToolkitGettingStartedAuthUtils.kt | 8 +++- .../editor/GettingStartedPanel.kt | 3 +- 11 files changed, 71 insertions(+), 67 deletions(-) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/auth/AuthController.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/auth/AuthController.kt index 36547a3c38d..b782ca7bfa2 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/auth/AuthController.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/auth/AuthController.kt @@ -87,7 +87,7 @@ class AuthController { AuthFollowUpType.Unsupported, AuthFollowUpType.FullAuth -> runInEdt { UiTelemetry.click(project, "amazonq_chatAuthenticate") - requestCredentialsForQ(project, connectionInitiatedFromQChatPanel = true) + requestCredentialsForQ(project, connectionInitiatedFromQChatPanel = true, isReauth = false) } AuthFollowUpType.ReAuth, diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/explorerActions/SignInToQAction.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/explorerActions/SignInToQAction.kt index 7599cbf6355..6cfc58573ab 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/explorerActions/SignInToQAction.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/explorerActions/SignInToQAction.kt @@ -24,7 +24,7 @@ class SignInToQAction : SignInToQActionBase(message("q.sign.in")) { UiTelemetry.click(project, "auth_start_Q") if (!isQWebviewsAvailable()) { - requestCredentialsForQ(project) + requestCredentialsForQ(project, isReauth = false) } else { ToolWindowManager.getInstance(project).getToolWindow(AmazonQToolWindowFactory.WINDOW_ID)?.show() } @@ -42,7 +42,7 @@ abstract class SignInToQActionBase(actionName: String) : DumbAwareAction(actionN reauthConnectionIfNeeded(project, it, isReAuth = true) } ?: run { runInEdt { - if (requestCredentialsForQ(project)) { + if (requestCredentialsForQ(project, isReauth = false)) { if (!openMeetQPage(project)) { return@runInEdt } diff --git a/plugins/core/jetbrains-community/resources/telemetryOverride.json b/plugins/core/jetbrains-community/resources/telemetryOverride.json index e221fbcfb84..f9f1c5ee8e3 100644 --- a/plugins/core/jetbrains-community/resources/telemetryOverride.json +++ b/plugins/core/jetbrains-community/resources/telemetryOverride.json @@ -810,50 +810,6 @@ "type": "authType" } ] - }, - { - "name": "auth_addConnection", - "description": "Captures the result of adding a new connection in the 'Add New Connection' workflow", - "metadata": [ - { - "type": "attempts", - "required": false - }, - { - "type": "credentialSourceId" - }, - { - "type": "featureId", - "required": false - }, - { - "type": "invalidInputFields", - "required": false - }, - { - "type": "isAggregated", - "required": false - }, - { - "type": "reason", - "required": false - }, - { - "type": "result" - }, - { - "type": "source", - "required": false - }, - { - "type": "credentialStartUrl", - "required": false - }, - { - "type": "isReAuth", - "required": false - } - ] } ] } diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt index b35d8ff5661..4cb8376812c 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt @@ -35,7 +35,8 @@ fun requestCredentialsForCodeWhisperer( project ), isFirstInstance: Boolean = false, - connectionInitiatedFromExplorer: Boolean = false + connectionInitiatedFromExplorer: Boolean = false, + isReauth: Boolean = false ): Boolean { val authenticationDialog = SetupAuthenticationDialog( project, @@ -87,7 +88,8 @@ fun requestCredentialsForCodeWhisperer( credentialSourceId = authenticationDialog.authType, isAggregated = true, attempts = authenticationDialog.attempts + 1, - result = Result.Succeeded + result = Result.Succeeded, + isReAuth = isReauth ) AuthTelemetry.addedConnections( project, @@ -108,6 +110,7 @@ fun requestCredentialsForCodeWhisperer( isAggregated = false, attempts = authenticationDialog.attempts + 1, result = Result.Cancelled, + isReAuth = isReauth ) } return isAuthenticationSuccessful @@ -122,7 +125,8 @@ fun requestCredentialsForQ( ), isFirstInstance: Boolean = false, connectionInitiatedFromExplorer: Boolean = false, - connectionInitiatedFromQChatPanel: Boolean = false + connectionInitiatedFromQChatPanel: Boolean = false, + isReauth: Boolean ): Boolean { // try to scope upgrade if we have a codewhisperer connection val codeWhispererConnection = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(CodeWhispererConnection.getInstance()) @@ -194,7 +198,8 @@ fun requestCredentialsForQ( credentialSourceId = authenticationDialog.authType, isAggregated = true, attempts = authenticationDialog.attempts + 1, - result = Result.Succeeded + result = Result.Succeeded, + isReAuth = isReauth ) AuthTelemetry.addedConnections( project, @@ -215,6 +220,7 @@ fun requestCredentialsForQ( isAggregated = false, attempts = authenticationDialog.attempts + 1, result = Result.Cancelled, + isReAuth = isReauth ) } return isAuthenticationSuccessful diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/SetupAuthenticationDialog.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/SetupAuthenticationDialog.kt index a5679e810dc..bb719ef4427 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/SetupAuthenticationDialog.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/SetupAuthenticationDialog.kt @@ -287,7 +287,8 @@ class SetupAuthenticationDialog( isAggregated = false, attempts = ++attempts, result = Result.Failed, - reason = "ConnectionUnsuccessful" + reason = "ConnectionUnsuccessful", + isReAuth = false ) } ?: return @@ -339,7 +340,8 @@ class SetupAuthenticationDialog( isAggregated = false, attempts = ++attempts, result = Result.Failed, - reason = "DuplicateProfileName" + reason = "DuplicateProfileName", + isReAuth = false ) return } @@ -365,7 +367,8 @@ class SetupAuthenticationDialog( isAggregated = false, attempts = ++attempts, result = Result.Failed, - reason = "InvalidCredentials" + reason = "InvalidCredentials", + isReAuth = false ) return } @@ -438,7 +441,8 @@ class SetupAuthenticationDialog( isAggregated = false, attempts = ++attempts, result = Result.Failed, - reason = errorType + reason = errorType, + isReAuth = false ) LOG.error(e) { errorMessage } diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt index abb801519dd..a39ecb24903 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt @@ -181,6 +181,7 @@ enum class SourceOfEntry { FIRST_STARTUP, Q, AMAZONQ_CHAT_PANEL, + LOGIN_BROWSER, UNKNOWN; override fun toString(): String { val value = this.name.lowercase() diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/LoginBrowser.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/LoginBrowser.kt index 50753abc661..abeca20683d 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/LoginBrowser.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/LoginBrowser.kt @@ -39,6 +39,7 @@ import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_URL import software.aws.toolkits.jetbrains.core.credentials.sso.PendingAuthorization import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.InteractiveBearerTokenProvider import software.aws.toolkits.jetbrains.core.credentials.ssoErrorMessageFromException +import software.aws.toolkits.jetbrains.core.gettingstarted.editor.SourceOfEntry import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread import software.aws.toolkits.jetbrains.utils.pollFor import software.aws.toolkits.resources.AwsCoreBundle @@ -87,7 +88,7 @@ abstract class LoginBrowser( private var browserOpenTimer: Timer? = null - private fun startBrowserOpenTimer(startUrl: String, ssoRegion: String) { + private fun startBrowserOpenTimer(startUrl: String, ssoRegion: String, scopes: List) { browserOpenTimer = Timer() browserOpenTimer?.schedule( object : TimerTask() { @@ -103,7 +104,11 @@ abstract class LoginBrowser( AuthTelemetry.addConnection( result = Result.Failed, reason = "Browser authentication idle for more than 15min", - credentialSourceId = if (startUrl == SONO_URL) CredentialSourceId.AwsId else CredentialSourceId.IamIdentityCenter + credentialSourceId = if (startUrl == SONO_URL) CredentialSourceId.AwsId else CredentialSourceId.IamIdentityCenter, + isAggregated = false, + source = SourceOfEntry.LOGIN_BROWSER.toString(), + featureId = getFeatureId(scopes), + isReAuth = isReAuth(scopes, startUrl) ) stopAndClearBrowserOpenTimer() } @@ -121,7 +126,7 @@ abstract class LoginBrowser( } protected val onPendingToken: (InteractiveBearerTokenProvider) -> Unit = { provider -> - startBrowserOpenTimer(provider.startUrl, provider.region) + startBrowserOpenTimer(provider.startUrl, provider.region, provider.scopes) projectCoroutineScope(project).launch { val authorization = pollForAuthorization(provider) if (authorization != null) { @@ -180,6 +185,7 @@ abstract class LoginBrowser( open fun loginBuilderId(scopes: List) { val isReauth = isReAuth(scopes, SONO_URL) + val featureId = getFeatureId(scopes) val onError: (Exception) -> Unit = { e -> stopAndClearBrowserOpenTimer() isUserCancellation(e) @@ -196,7 +202,10 @@ abstract class LoginBrowser( result = Result.Failed, credentialSourceId = CredentialSourceId.AwsId, reason = e.message, - isReAuth = isReauth + isReAuth = isReauth, + featureId = featureId, + isAggregated = false, + source = SourceOfEntry.LOGIN_BROWSER.toString() ) } val onSuccess: () -> Unit = { @@ -212,7 +221,10 @@ abstract class LoginBrowser( AuthTelemetry.addConnection( result = Result.Succeeded, credentialSourceId = CredentialSourceId.AwsId, - isReAuth = isReauth + isReAuth = isReauth, + featureId = featureId, + isAggregated = true, + source = SourceOfEntry.LOGIN_BROWSER.toString() ) } @@ -239,7 +251,7 @@ abstract class LoginBrowser( region: AwsRegion ): Pair<(Exception) -> Unit, () -> Unit> { val isReAuth = isReAuth(scopes, url) - + val featureId = getFeatureId(scopes) val onError: (Exception) -> Unit = { e -> stopAndClearBrowserOpenTimer() val message = ssoErrorMessageFromException(e) @@ -269,6 +281,9 @@ abstract class LoginBrowser( credentialSourceId = CredentialSourceId.IamIdentityCenter, reason = message, isReAuth = isReAuth, + featureId = featureId, + isAggregated = false, + source = SourceOfEntry.LOGIN_BROWSER.toString() ) } val onSuccess: () -> Unit = { @@ -286,7 +301,10 @@ abstract class LoginBrowser( project = null, result = Result.Succeeded, isReAuth = isReAuth, - credentialSourceId = CredentialSourceId.IamIdentityCenter + credentialSourceId = CredentialSourceId.IamIdentityCenter, + featureId = featureId, + isAggregated = true, + source = SourceOfEntry.LOGIN_BROWSER.toString() ) } return Pair(onError, onSuccess) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/WebviewTelemetryUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/WebviewTelemetryUtils.kt index 628a887afea..186d676fac8 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/WebviewTelemetryUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/webview/WebviewTelemetryUtils.kt @@ -4,7 +4,10 @@ package software.aws.toolkits.jetbrains.core.webview import com.intellij.openapi.util.registry.Registry +import software.aws.toolkits.jetbrains.core.credentials.sono.CODECATALYST_SCOPES +import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES import software.aws.toolkits.telemetry.AuthType +import software.aws.toolkits.telemetry.FeatureId fun getAuthType(region: String = "us-east-1"): AuthType { val isCommercialRegion = !region.startsWith("us-gov") && !region.startsWith("us-iso") && !region.startsWith("cn") @@ -14,3 +17,12 @@ fun getAuthType(region: String = "us-east-1"): AuthType { return AuthType.DeviceCode } } + +fun getFeatureId(scopes: List): FeatureId = + if (scopes.intersect(Q_SCOPES.toSet()).isNotEmpty()) { + FeatureId.Q + } else if (scopes.intersect(CODECATALYST_SCOPES.toSet()).isNotEmpty()) { + FeatureId.Codecatalyst + } else { + FeatureId.AwsExplorer + } diff --git a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedOnStartup.kt b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedOnStartup.kt index cbceeff6e71..247e9443ac7 100644 --- a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedOnStartup.kt +++ b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedOnStartup.kt @@ -43,7 +43,8 @@ class GettingStartedOnStartup : StartupActivity { featureId = FeatureId.Unknown, credentialSourceId = CredentialSourceId.Unknown, isAggregated = true, - result = Result.Succeeded + result = Result.Succeeded, + isReAuth = false ) AuthTelemetry.addedConnections( project, @@ -66,7 +67,8 @@ class GettingStartedOnStartup : StartupActivity { credentialSourceId = CredentialSourceId.Unknown, isAggregated = false, result = Result.Failed, - reason = "Error opening getting started panel" + reason = "Error opening getting started panel", + isReAuth = false ) AuthTelemetry.addedConnections( project, diff --git a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/ToolkitGettingStartedAuthUtils.kt b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/ToolkitGettingStartedAuthUtils.kt index d84a424c578..516c02951dc 100644 --- a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/ToolkitGettingStartedAuthUtils.kt +++ b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/ToolkitGettingStartedAuthUtils.kt @@ -89,7 +89,8 @@ fun requestCredentialsForCodeCatalyst( credentialSourceId = authenticationDialog.authType, isAggregated = true, attempts = authenticationDialog.attempts + 1, - result = Result.Succeeded + result = Result.Succeeded, + isReAuth = false ) AuthTelemetry.addedConnections( project, @@ -110,6 +111,7 @@ fun requestCredentialsForCodeCatalyst( isAggregated = false, attempts = authenticationDialog.attempts + 1, result = Result.Cancelled, + isReAuth = false ) } return isAuthenticationSuccessful @@ -157,7 +159,8 @@ fun requestCredentialsForExplorer( credentialSourceId = authenticationDialog.authType, isAggregated = true, attempts = authenticationDialog.attempts + 1, - result = Result.Succeeded + result = Result.Succeeded, + isReAuth = false ) AuthTelemetry.addedConnections( project, @@ -178,6 +181,7 @@ fun requestCredentialsForExplorer( isAggregated = false, attempts = authenticationDialog.attempts + 1, result = Result.Cancelled, + isReAuth = false ) } return isAuthSuccessful diff --git a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanel.kt b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanel.kt index c3d45c2107a..65ef5d2825b 100644 --- a/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanel.kt +++ b/plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanel.kt @@ -957,7 +957,8 @@ class GettingStartedPanel( oldConnectionCount, initialEnabledConnection, isFirstInstance, - connectionInitiatedFromExplorer + connectionInitiatedFromExplorer, + isReauth = true ), panelReauthenticationRequired ) From 5097cb92ec64e4be0105753a2a5a38770bc74be4 Mon Sep 17 00:00:00 2001 From: Manodnya Jaydeep Bhoite Date: Tue, 8 Oct 2024 15:33:35 -0700 Subject: [PATCH 2/2] detekt --- .../jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt index 4cb8376812c..4cda831d987 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt @@ -36,7 +36,7 @@ fun requestCredentialsForCodeWhisperer( ), isFirstInstance: Boolean = false, connectionInitiatedFromExplorer: Boolean = false, - isReauth: Boolean = false + isReauth: Boolean = false, ): Boolean { val authenticationDialog = SetupAuthenticationDialog( project, @@ -126,7 +126,7 @@ fun requestCredentialsForQ( isFirstInstance: Boolean = false, connectionInitiatedFromExplorer: Boolean = false, connectionInitiatedFromQChatPanel: Boolean = false, - isReauth: Boolean + isReauth: Boolean, ): Boolean { // try to scope upgrade if we have a codewhisperer connection val codeWhispererConnection = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(CodeWhispererConnection.getInstance())