@@ -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,44 @@ 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.languageServerSetupStage(LanguageServerSetupStage .GetServer )
192+ telemetry.metadata(" credentialStartUrl" , getStartUrl(project))
193+ telemetry.success(true )
194+
195+ try {
196+ runnable()
197+ } catch (t: Throwable ) {
198+ telemetry.success(false )
199+ telemetry.recordException(t)
200+ }
201+ }
202+ }
203+
186204 try {
187205 if (! filePath.exists()) {
188206 logger.info { " Downloading file: ${filePath.fileName} " }
189- saveFileFromUrl(url, filePath, ProgressManager .getInstance().progressIndicator)
207+ recordDownload { saveFileFromUrl(url, filePath, ProgressManager .getInstance().progressIndicator) }
190208 }
191209 if (! validateFileHash(filePath, expectedHash)) {
192210 logger.warn { " Hash mismatch for ${filePath.fileName} , re-downloading" }
193211 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 )
212+ recordDownload { saveFileFromUrl(url, filePath) }
213+
214+ Telemetry .languageserver.setup.use {
215+ it.languageServerSetupStage(LanguageServerSetupStage .Validate )
216+ it.metadata(" credentialStartUrl" , getStartUrl(project))
217+ it.success(true )
218+
219+ if (! validateFileHash(filePath, expectedHash)) {
220+ it.success(false )
221+
222+ val exception = LspException (" Hash mismatch after re-download for ${filePath.fileName} " , LspException .ErrorCode .HASH_MISMATCH )
223+ it.recordException(exception)
224+ throw exception
225+ }
197226 }
198227 }
199228 } catch (e: Exception ) {
0 commit comments