@@ -17,7 +17,10 @@ import software.aws.toolkits.core.utils.getLogger
17
17
import software.aws.toolkits.core.utils.info
18
18
import software.aws.toolkits.core.utils.warn
19
19
import software.aws.toolkits.jetbrains.core.saveFileFromUrl
20
+ import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.getStartUrl
20
21
import software.aws.toolkits.resources.AwsCoreBundle
22
+ import software.aws.toolkits.telemetry.LanguageServerSetupStage
23
+ import software.aws.toolkits.telemetry.Telemetry
21
24
import java.nio.file.Files
22
25
import java.nio.file.Path
23
26
import java.nio.file.Paths
@@ -106,33 +109,33 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
106
109
}
107
110
108
111
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())
111
113
112
114
while (currentAttempt.get() < maxDownloadAttempts) {
113
115
currentAttempt.incrementAndGet()
114
116
logger.info { " Attempt ${currentAttempt.get()} of $maxDownloadAttempts to download LSP artifacts" }
117
+ val temporaryDownloadPath = Files .createTempDirectory(" lsp-dl" )
115
118
116
119
try {
117
120
return withBackgroundProgress(
118
121
project,
119
122
AwsCoreBundle .message(" amazonqFeatureDev.placeholder.downloading_and_extracting_lsp_artifacts" ),
120
123
cancellable = true
121
124
) {
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 )
124
127
target.contents
125
128
.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 " }
128
131
129
132
val thirdPartyLicenses = targetVersion.thirdPartyLicenses
130
133
logger.info {
131
- " Installing Amazon Q Language Server v${targetVersion.serverVersion} to: $downloadPath . " +
134
+ " Installing Amazon Q Language Server v${targetVersion.serverVersion} to: $destinationPath . " +
132
135
if (thirdPartyLicenses == null ) " " else " Attribution notice can be found at $thirdPartyLicenses "
133
136
}
134
137
135
- return @withBackgroundProgress downloadPath
138
+ return @withBackgroundProgress destinationPath
136
139
}
137
140
138
141
return @withBackgroundProgress null
@@ -146,15 +149,15 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
146
149
else -> { logger.error(e) { " Failed to download/move LSP artifacts on attempt ${currentAttempt.get()} " } }
147
150
}
148
151
temporaryDownloadPath.toFile().deleteRecursively()
149
- downloadPath .toFile().deleteRecursively()
152
+ destinationPath .toFile().deleteRecursively()
150
153
}
151
154
}
152
155
logger.error { " Failed to download LSP artifacts after $maxDownloadAttempts attempts" }
153
156
return null
154
157
}
155
158
156
159
@VisibleForTesting
157
- internal fun downloadLspArtifacts (downloadPath : Path , target : VersionTarget ? ): Boolean {
160
+ internal fun downloadLspArtifacts (project : Project , downloadPath : Path , target : VersionTarget ? ): Boolean {
158
161
if (target == null || target.contents.isNullOrEmpty()) {
159
162
logger.warn { " No target contents available for download" }
160
163
return false
@@ -171,7 +174,7 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
171
174
logger.warn { " No hash available for ${content.filename} " }
172
175
return @forEach
173
176
}
174
- downloadAndValidateFile(content.url, filePath, contentHash)
177
+ downloadAndValidateFile(project, content.url, filePath, contentHash)
175
178
}
176
179
validateDownloadedFiles(downloadPath, target.contents)
177
180
} catch (e: Exception ) {
@@ -182,18 +185,46 @@ class ArtifactHelper(private val lspArtifactsPath: Path = DEFAULT_ARTIFACT_PATH,
182
185
return true
183
186
}
184
187
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
+
186
205
try {
187
206
if (! filePath.exists()) {
188
207
logger.info { " Downloading file: ${filePath.fileName} " }
189
- saveFileFromUrl(url, filePath, ProgressManager .getInstance().progressIndicator)
208
+ recordDownload { saveFileFromUrl(url, filePath, ProgressManager .getInstance().progressIndicator) }
190
209
}
191
210
if (! validateFileHash(filePath, expectedHash)) {
192
211
logger.warn { " Hash mismatch for ${filePath.fileName} , re-downloading" }
193
212
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
+ }
197
228
}
198
229
}
199
230
} catch (e: Exception ) {
0 commit comments