Skip to content

Commit b66fb94

Browse files
feat(amazonq): Enable one-click collection of logs from chat (#5923)
* feat(amazonq): Enable one-click collection of logs from chat * Add progress indicator * changed tooltip, made icon brighter in light mode * use action instead of internal api * feedback * Detekt --------- Co-authored-by: Laxman Reddy <[email protected]>
1 parent faaa62b commit b66fb94

File tree

7 files changed

+117
-25
lines changed

7 files changed

+117
-25
lines changed

plugins/amazonq/chat/jetbrains-community/resources/META-INF/plugin-chat.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<action id="aws.toolkit.open.q.window" class="software.aws.toolkits.jetbrains.services.amazonq.QRefreshPanelAction"/>
3434
<group id="aws.q.toolwindow.titleBar" popup="false" compact="true">
3535
<reference id="aws.toolkit.open.q.window"/>
36+
<action class="software.aws.toolkits.jetbrains.services.amazonq.GetAmazonQLogsAction" id="q.getLogs"/>
3637
</group>
3738
<!-- TODO: q.openchat will eventually be in amazonq, aws.toolkit.q.sign.in will eventually be in core. -->
3839
<action id="q.openchat" class="software.aws.toolkits.jetbrains.services.amazonq.QOpenPanelAction"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.amazonq
5+
6+
import com.intellij.icons.AllIcons
7+
import com.intellij.ide.actions.RevealFileAction
8+
import com.intellij.ide.logsUploader.LogPacker
9+
import com.intellij.openapi.actionSystem.ActionUpdateThread
10+
import com.intellij.openapi.actionSystem.AnActionEvent
11+
import com.intellij.openapi.project.DumbAwareAction
12+
import com.intellij.openapi.project.Project
13+
import com.intellij.openapi.ui.Messages
14+
import com.intellij.openapi.util.IconLoader
15+
import com.intellij.ui.ColorUtil
16+
import com.intellij.ui.JBColor
17+
import com.intellij.util.IconUtil
18+
import com.intellij.util.ui.UIUtil
19+
import kotlinx.coroutines.runBlocking
20+
import software.aws.toolkits.jetbrains.utils.notifyInfo
21+
import software.aws.toolkits.jetbrains.utils.runUnderProgressIfNeeded
22+
import software.aws.toolkits.resources.AmazonQBundle.message
23+
import software.aws.toolkits.resources.AwsCoreBundle
24+
25+
class GetAmazonQLogsAction : DumbAwareAction(message("amazonq.getLogs.tooltip.text")) {
26+
private val baseIcon = IconLoader.getIcon("/icons/file.svg", GetAmazonQLogsAction::class.java)
27+
28+
private val lightIcon by lazy {
29+
IconUtil.colorize(baseIcon, ColorUtil.brighter(UIUtil.getLabelForeground(), 2))
30+
}
31+
32+
override fun update(e: AnActionEvent) {
33+
e.presentation.icon = if (!JBColor.isBright()) {
34+
baseIcon
35+
} else {
36+
lightIcon
37+
}
38+
}
39+
40+
override fun getActionUpdateThread() = ActionUpdateThread.BGT
41+
override fun actionPerformed(e: AnActionEvent) {
42+
val project = e.project ?: return
43+
showLogCollectionWarningGetLogs(project)
44+
}
45+
46+
companion object {
47+
fun showLogCollectionWarningGetLogs(project: Project) {
48+
if (Messages.showOkCancelDialog(
49+
message("amazonq.logs.warning"),
50+
message("amazonq.getLogs"),
51+
AwsCoreBundle.message("general.ok"),
52+
AwsCoreBundle.message("general.cancel"),
53+
AllIcons.General.Warning
54+
) == 0
55+
) {
56+
runUnderProgressIfNeeded(project, message("amazonq.getLogs"), cancelable = true) {
57+
runBlocking {
58+
try {
59+
RevealFileAction.openFile(LogPacker.packLogs(project))
60+
} catch (_: Exception) {
61+
notifyInfo(message("amazonq.getLogs"), message("amazonq.logs.error"), project)
62+
}
63+
}
64+
}
65+
}
66+
}
67+
}
68+
}

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/BrowserConnector.kt

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import software.aws.toolkits.core.utils.error
3333
import software.aws.toolkits.core.utils.getLogger
3434
import software.aws.toolkits.core.utils.info
3535
import software.aws.toolkits.core.utils.warn
36+
import software.aws.toolkits.jetbrains.services.amazonq.GetAmazonQLogsAction
3637
import software.aws.toolkits.jetbrains.services.amazonq.apps.AppConnection
3738
import software.aws.toolkits.jetbrains.services.amazonq.commands.MessageSerializer
3839
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQChatServer
@@ -419,33 +420,40 @@ class BrowserConnector(
419420
}
420421

421422
CHAT_TAB_BAR_ACTIONS -> {
422-
handleChat(AmazonQChatServer.tabBarActions, node) { params, invoke ->
423-
invoke()
424-
.whenComplete { actions, error ->
425-
try {
426-
if (error != null) {
427-
throw error
428-
}
429-
430-
browser.postChat(
431-
FlareUiMessage(
432-
command = CHAT_TAB_BAR_ACTIONS,
433-
params = actions
423+
val action = node.params.get("action")
424+
if (action.textValue() == "show_logs") {
425+
runInEdt {
426+
GetAmazonQLogsAction.showLogCollectionWarningGetLogs(project)
427+
}
428+
} else {
429+
handleChat(AmazonQChatServer.tabBarActions, node) { params, invoke ->
430+
invoke()
431+
.whenComplete { actions, error ->
432+
try {
433+
if (error != null) {
434+
throw error
435+
}
436+
437+
browser.postChat(
438+
FlareUiMessage(
439+
command = CHAT_TAB_BAR_ACTIONS,
440+
params = actions
441+
)
434442
)
435-
)
436-
} catch (e: Exception) {
437-
val cause = if (e is CompletionException) e.cause else e
438-
439-
// dont post error to UI if user cancels export
440-
if (cause is ResponseErrorException && cause.responseError.code == ResponseErrorCode.RequestCancelled.getValue()) {
441-
return@whenComplete
442-
}
443-
LOG.error { "Failed to perform chat tab bar action $e" }
444-
params.tabId?.let {
445-
browser.postChat(chatCommunicationManager.getErrorUiMessage(it, e, null))
443+
} catch (e: Exception) {
444+
val cause = if (e is CompletionException) e.cause else e
445+
446+
// dont post error to UI if user cancels export
447+
if (cause is ResponseErrorException && cause.responseError.code == ResponseErrorCode.RequestCancelled.getValue()) {
448+
return@whenComplete
449+
}
450+
LOG.error { "Failed to perform chat tab bar action $e" }
451+
params.tabId?.let {
452+
browser.postChat(chatCommunicationManager.getErrorUiMessage(it, e, null))
453+
}
446454
}
447455
}
448-
}
456+
}
449457
}
450458
}
451459

plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ amazonqInlineChat.popup.editCode = Edit Code
66
amazonqInlineChat.popup.generating = Generating...
77
amazonqInlineChat.popup.reject=Reject \u238B
88
amazonqInlineChat.popup.title=Enter Instructions for Q
9+
amazonq.getLogs=Get Amazon Q logs
10+
amazonq.getLogs.tooltip.text=Show Logs
11+
amazonq.logs.error=Cannot retrieve logs. Please try Help-> Collect Logs and Diagnostic data
12+
amazonq.logs.warning=Log files may contain sensitive information such as account IDs, resource names, and other data. Please be careful when sharing these logs.
913
amazonq.refresh.panel=Refresh Chat Session
1014
amazonq.title=Amazon Q
1115
amazonq.workspace.settings.open.prompt=Workspace index is now enabled. You can disable it from Amazon Q settings.

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/flareChat/AwsServerCapabilitiesProvider.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class AwsServerCapabilitiesProvider {
3737
mcpServers = true,
3838
// Seems like this is the only way to bounce reroute back to the LSP?
3939
reroute = true,
40+
showLogs = true
4041
)
4142
}
4243
}
@@ -51,6 +52,7 @@ data class ChatOptions(
5152
val export: Boolean,
5253
val mcpServers: Boolean,
5354
val reroute: Boolean,
55+
val showLogs: Boolean,
5456
)
5557

5658
data class QuickActions(

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/ExtendedClientMetadata.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ data class DeveloperProfiles(
3232

3333
data class WindowSettings(
3434
val showSaveFileDialog: Boolean,
35+
val showLogs: Boolean,
3536
)
3637

3738
data class ClientInfoMetadata(
@@ -73,7 +74,8 @@ fun createExtendedClientMetadata(project: Project): ExtendedClientMetadata {
7374
workspaceFilePath = project.workspaceFile?.path,
7475
),
7576
window = WindowSettings(
76-
showSaveFileDialog = true
77+
showSaveFileDialog = true,
78+
showLogs = true,
7779
)
7880
),
7981
contextConfiguration = ContextConfiguration(
Lines changed: 7 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)