@@ -17,7 +17,10 @@ import software.aws.toolkits.core.utils.getLogger
1717import software.aws.toolkits.core.utils.info
1818import software.aws.toolkits.core.utils.warn
1919import software.aws.toolkits.jetbrains.core.saveFileFromUrl
20+ import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.getStartUrl
2021import software.aws.toolkits.resources.AwsCoreBundle
22+ import software.aws.toolkits.telemetry.LanguageServerSetupStage
23+ import software.aws.toolkits.telemetry.Telemetry
2124import java.nio.file.Files
2225import java.nio.file.Path
2326import java.nio.file.Paths
@@ -106,33 +109,33 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
106109 }
107110
108111 suspend fun tryDownloadLspArtifacts (project : Project , targetVersion : Version , target : VersionTarget ): Path ? {
109- val temporaryDownloadPath = Files .createTempDirectory(" lsp-dl" )
110- val downloadPath = lspArtifactsPath.resolve(targetVersion.serverVersion.toString())
112+ val destinationPath = lspArtifactsPath.resolve(targetVersion.serverVersion.toString())
111113
112114 while (currentAttempt.get() < maxDownloadAttempts) {
113115 currentAttempt.incrementAndGet()
114116 logger.info { " Attempt ${currentAttempt.get()} of $maxDownloadAttempts to download LSP artifacts" }
117+ val temporaryDownloadPath = Files .createTempDirectory(" lsp-dl" )
115118
116119 try {
117120 return withBackgroundProgress(
118121 project,
119122 AwsCoreBundle .message(" amazonqFeatureDev.placeholder.downloading_and_extracting_lsp_artifacts" ),
120123 cancellable = true
121124 ) {
122- if (downloadLspArtifacts(temporaryDownloadPath, target) && ! target.contents.isNullOrEmpty()) {
123- moveFilesFromSourceToDestination(temporaryDownloadPath, downloadPath )
125+ if (downloadLspArtifacts(project, temporaryDownloadPath, target) && ! target.contents.isNullOrEmpty()) {
126+ moveFilesFromSourceToDestination(temporaryDownloadPath, destinationPath )
124127 target.contents
125128 .mapNotNull { it.filename }
126- .forEach { filename -> extractZipFile(downloadPath .resolve(filename), downloadPath ) }
127- logger.info { " Successfully downloaded and moved LSP artifacts to $downloadPath " }
129+ .forEach { filename -> extractZipFile(destinationPath .resolve(filename), destinationPath ) }
130+ logger.info { " Successfully downloaded and moved LSP artifacts to $destinationPath " }
128131
129132 val thirdPartyLicenses = targetVersion.thirdPartyLicenses
130133 logger.info {
131- " Installing Amazon Q Language Server v${targetVersion.serverVersion} to: $downloadPath . " +
134+ " Installing Amazon Q Language Server v${targetVersion.serverVersion} to: $destinationPath . " +
132135 if (thirdPartyLicenses == null ) " " else " Attribution notice can be found at $thirdPartyLicenses "
133136 }
134137
135- return @withBackgroundProgress downloadPath
138+ return @withBackgroundProgress destinationPath
136139 }
137140
138141 return @withBackgroundProgress null
@@ -146,15 +149,15 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
146149 else -> { logger.error(e) { " Failed to download/move LSP artifacts on attempt ${currentAttempt.get()} " } }
147150 }
148151 temporaryDownloadPath.toFile().deleteRecursively()
149- downloadPath .toFile().deleteRecursively()
152+ destinationPath .toFile().deleteRecursively()
150153 }
151154 }
152155 logger.error { " Failed to download LSP artifacts after $maxDownloadAttempts attempts" }
153156 return null
154157 }
155158
156159 @VisibleForTesting
157- internal fun downloadLspArtifacts (downloadPath : Path , target : VersionTarget ? ): Boolean {
160+ internal fun downloadLspArtifacts (project : Project , downloadPath : Path , target : VersionTarget ? ): Boolean {
158161 if (target == null || target.contents.isNullOrEmpty()) {
159162 logger.warn { " No target contents available for download" }
160163 return false
@@ -171,7 +174,7 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
171174 logger.warn { " No hash available for ${content.filename} " }
172175 return @forEach
173176 }
174- downloadAndValidateFile(content.url, filePath, contentHash)
177+ downloadAndValidateFile(project, content.url, filePath, contentHash)
175178 }
176179 validateDownloadedFiles(downloadPath, target.contents)
177180 } catch (e: Exception ) {
@@ -182,18 +185,46 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
182185 return true
183186 }
184187
185- private fun downloadAndValidateFile (url : String , filePath : Path , expectedHash : String ) {
188+ private fun downloadAndValidateFile (project : Project , url : String , filePath : Path , expectedHash : String ) {
189+ val recordDownload = { runnable: () -> Unit ->
190+ Telemetry .languageserver.setup.use { telemetry ->
191+ telemetry.id(" q" )
192+ telemetry.languageServerSetupStage(LanguageServerSetupStage .GetServer )
193+ telemetry.metadata(" credentialStartUrl" , getStartUrl(project))
194+ telemetry.success(true )
195+
196+ try {
197+ runnable()
198+ } catch (t: Throwable ) {
199+ telemetry.success(false )
200+ telemetry.recordException(t)
201+ }
202+ }
203+ }
204+
186205 try {
187206 if (! filePath.exists()) {
188207 logger.info { " Downloading file: ${filePath.fileName} " }
189- saveFileFromUrl(url, filePath, ProgressManager .getInstance().progressIndicator)
208+ recordDownload { saveFileFromUrl(url, filePath, ProgressManager .getInstance().progressIndicator) }
190209 }
191210 if (! validateFileHash(filePath, expectedHash)) {
192211 logger.warn { " Hash mismatch for ${filePath.fileName} , re-downloading" }
193212 filePath.deleteIfExists()
194- saveFileFromUrl(url, filePath)
195- if (! validateFileHash(filePath, expectedHash)) {
196- throw LspException (" Hash mismatch after re-download for ${filePath.fileName} " , LspException .ErrorCode .HASH_MISMATCH )
213+ recordDownload { saveFileFromUrl(url, filePath) }
214+
215+ Telemetry .languageserver.setup.use {
216+ it.id(" q" )
217+ it.languageServerSetupStage(LanguageServerSetupStage .Validate )
218+ it.metadata(" credentialStartUrl" , getStartUrl(project))
219+ it.success(true )
220+
221+ if (! validateFileHash(filePath, expectedHash)) {
222+ it.success(false )
223+
224+ val exception = LspException (" Hash mismatch after re-download for ${filePath.fileName} " , LspException .ErrorCode .HASH_MISMATCH )
225+ it.recordException(exception)
226+ throw exception
227+ }
197228 }
198229 }
199230 } catch (e: Exception ) {
0 commit comments