Skip to content

Commit 71d123f

Browse files
authored
Add ability to run a query from log group window (#2245)
* Add ability to run a query from log group window * Fixing UI test * Adding close dialog to UI tests * Fix telemetry * Fixing merge issues * Fixing merge issues * Upgrading to new telemetry after pushing types upstream
1 parent 46e5cce commit 71d123f

File tree

8 files changed

+117
-120
lines changed

8 files changed

+117
-120
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ awsSdkVersion=2.17.19
1616
coroutinesVersion=1.3.3
1717
detektVersion=1.17.1
1818
jacksonVersion=2.11.1
19-
telemetryVersion=1.0.9
19+
telemetryVersion=1.0.13
2020
commonsMarkVersion=0.17.1
2121
jgitVersion=5.11.0.202103091610-r
2222

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudwatch/logs/CloudWatchLogWindow.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import software.aws.toolkits.jetbrains.services.cloudwatch.logs.editor.CloudWatc
1818
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.editor.CloudWatchLogStream
1919
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.DetailedLogRecord
2020
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.QueryDetails
21-
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.QueryResultList
21+
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.QueryResultPanel
2222
import software.aws.toolkits.jetbrains.utils.getCoroutineUiContext
2323
import software.aws.toolkits.resources.message
2424
import software.aws.toolkits.telemetry.CloudwatchlogsTelemetry
@@ -91,10 +91,10 @@ class CloudWatchLogWindow(private val project: Project) {
9191
return
9292
}
9393

94-
val queryResult = QueryResultList(project, fields, queryId, queryDetails)
94+
val panel = QueryResultPanel(project, fields, queryId, queryDetails)
9595
val title = message("cloudwatch.logs.query_tab_title", queryId)
9696
withContext(edtContext) {
97-
toolWindow.addTab(title, queryResult.resultsPanel, activate = true, id = queryId, disposable = queryResult)
97+
toolWindow.addTab(title, panel, activate = true, id = queryId, disposable = panel)
9898
}
9999
}
100100

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudwatch/logs/editor/CloudWatchLogGroup.kt

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,29 @@ package software.aws.toolkits.jetbrains.services.cloudwatch.logs.editor
66
import com.intellij.icons.AllIcons
77
import com.intellij.openapi.Disposable
88
import com.intellij.openapi.actionSystem.ActionManager
9-
import com.intellij.openapi.actionSystem.AnAction
109
import com.intellij.openapi.actionSystem.AnActionEvent
1110
import com.intellij.openapi.actionSystem.DefaultActionGroup
12-
import com.intellij.openapi.project.DumbAware
11+
import com.intellij.openapi.project.DumbAwareAction
1312
import com.intellij.openapi.project.Project
1413
import com.intellij.openapi.ui.SimpleToolWindowPanel
1514
import com.intellij.openapi.util.Disposer
1615
import com.intellij.ui.SearchTextField
1716
import kotlinx.coroutines.launch
1817
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient
19-
import software.aws.toolkits.jetbrains.core.awsClient
18+
import software.aws.toolkits.jetbrains.core.AwsClientManager
19+
import software.aws.toolkits.jetbrains.core.credentials.AwsConnectionManager
20+
import software.aws.toolkits.jetbrains.core.credentials.ConnectionSettings
21+
import software.aws.toolkits.jetbrains.core.credentials.ConnectionState
2022
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.CloudWatchLogsActor
23+
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights.QueryEditorDialog
2124
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
2225
import software.aws.toolkits.jetbrains.utils.getCoroutineUiContext
2326
import software.aws.toolkits.jetbrains.utils.ui.onEmpty
2427
import software.aws.toolkits.jetbrains.utils.ui.onEnter
2528
import software.aws.toolkits.resources.message
29+
import software.aws.toolkits.telemetry.CloudwatchinsightsTelemetry
2630
import software.aws.toolkits.telemetry.CloudwatchlogsTelemetry
31+
import software.aws.toolkits.telemetry.InsightsDialogOpenSource
2732
import javax.swing.JPanel
2833

2934
class CloudWatchLogGroup(
@@ -41,8 +46,9 @@ class CloudWatchLogGroup(
4146
private lateinit var searchField: SearchTextField
4247
private lateinit var breadcrumbHolder: JPanel
4348

44-
val client: CloudWatchLogsClient = project.awsClient()
45-
private val groupTable: LogGroupTable = LogGroupTable(project, client, logGroup, LogGroupTable.TableType.LIST)
49+
private val client: CloudWatchLogsClient
50+
private val connection: ConnectionSettings
51+
private val groupTable: LogGroupTable
4652
private var searchGroupTable: LogGroupTable? = null
4753

4854
private fun createUIComponents() {
@@ -53,6 +59,14 @@ class CloudWatchLogGroup(
5359
}
5460

5561
init {
62+
63+
connection = when (val state = AwsConnectionManager.getInstance(project).connectionState) {
64+
is ConnectionState.ValidConnection -> ConnectionSettings(state.credentials, state.region)
65+
else -> throw IllegalStateException(state.shortMessage)
66+
}
67+
client = AwsClientManager.getInstance().getClient(connection.credentials, connection.region)
68+
groupTable = LogGroupTable(project, client, logGroup, LogGroupTable.TableType.LIST)
69+
5670
val locationCrumbs = LocationCrumbs(project, logGroup)
5771
locationInformation.crumbs = locationCrumbs.crumbs
5872
breadcrumbHolder.border = locationCrumbs.border
@@ -99,13 +113,21 @@ class CloudWatchLogGroup(
99113
private fun addToolbar() {
100114
val actionGroup = DefaultActionGroup()
101115
actionGroup.addAction(
102-
object : AnAction(message("general.refresh"), null, AllIcons.Actions.Refresh), DumbAware {
116+
object : DumbAwareAction(message("general.refresh"), null, AllIcons.Actions.Refresh) {
103117
override fun actionPerformed(e: AnActionEvent) {
104118
CloudwatchlogsTelemetry.refreshGroup(project)
105119
refreshTable()
106120
}
107121
}
108122
)
123+
actionGroup.addAction(
124+
object : DumbAwareAction(message("cloudwatch.logs.query"), null, AllIcons.Actions.Find) {
125+
override fun actionPerformed(e: AnActionEvent) {
126+
QueryEditorDialog(project, connection, logGroup).show()
127+
CloudwatchinsightsTelemetry.openEditor(project, InsightsDialogOpenSource.LogGroup)
128+
}
129+
}
130+
)
109131
tablePanel.toolbar = ActionManager.getInstance().createActionToolbar("CloudWatchLogStream", actionGroup, false).component
110132
}
111133

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudwatch/logs/insights/QueryEditorDialog.kt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import java.time.temporal.ChronoUnit
3030
import javax.swing.Action
3131
import javax.swing.JComponent
3232

33-
class QueryEditorDialog(
33+
class QueryEditorDialog internal constructor(
34+
// TODO: Exposed for testing only, should be refactored to be private
3435
private val project: Project,
3536
private val initialQueryDetails: QueryDetails
3637
) : DialogWrapper(project) {
@@ -60,7 +61,8 @@ class QueryEditorDialog(
6061
// Do nothing, close logic is handled separately
6162
}
6263

63-
suspend fun setView(queryDetails: QueryDetails) {
64+
// TODO: Exposed for testing only, should be refactored to be private
65+
internal suspend fun setView(queryDetails: QueryDetails) {
6466
when (val timeRange = queryDetails.timeRange) {
6567
is TimeRange.AbsoluteRange -> {
6668
view.setAbsolute()
@@ -111,7 +113,8 @@ class QueryEditorDialog(
111113
}
112114
}
113115

114-
fun getQueryDetails(): QueryDetails {
116+
// TODO: Exposed for testing only, should be refactored to be private
117+
internal fun getQueryDetails(): QueryDetails {
115118
val timeRange = if (view.absoluteTimeRadioButton.isSelected) {
116119
TimeRange.AbsoluteRange(
117120
startDate = view.startDate.date,
@@ -154,7 +157,8 @@ class QueryEditorDialog(
154157
}
155158
}
156159

157-
fun validateEditorEntries(view: QueryEditor): ValidationInfo? {
160+
// TODO: Exposed for testing only, should be refactored to be private
161+
internal fun validateEditorEntries(view: QueryEditor): ValidationInfo? {
158162
if (!view.absoluteTimeRadioButton.isSelected && !view.relativeTimeRadioButton.isSelected) {
159163
return ValidationInfo(message("cloudwatch.logs.validation.timerange"), view.absoluteTimeRadioButton)
160164
}
@@ -176,7 +180,8 @@ class QueryEditorDialog(
176180
return null
177181
}
178182

179-
fun startQueryAsync(queryDetails: QueryDetails) = coroutineScope.async {
183+
// TODO: Exposed for testing only, should be refactored to be private
184+
internal fun startQueryAsync(queryDetails: QueryDetails) = coroutineScope.async {
180185
val (credentials, region) = queryDetails.connectionSettings
181186
val client = AwsClientManager.getInstance().getClient<CloudWatchLogsClient>(credentials, region)
182187
val timeRange = queryDetails.getQueryRange()
@@ -211,14 +216,15 @@ class QueryEditorDialog(
211216
}
212217

213218
companion object {
214-
private fun defaultQuery(connectionSettings: ConnectionSettings, logGroupName: String) = QueryDetails(
215-
connectionSettings,
219+
private fun defaultQuery(connection: ConnectionSettings, logGroupName: String) = QueryDetails(
220+
connection,
216221
mutableListOf(logGroupName),
217222
TimeRange.RelativeRange(10, ChronoUnit.MINUTES),
218223
QueryString.InsightsQueryString(DEFAULT_INSIGHTS_QUERY_STRING)
219224
)
220225

221-
fun getFields(query: String): List<String> {
226+
// TODO: Exposed for testing only, should be refactored to be private
227+
internal fun getFields(query: String): List<String> {
222228
val fieldsIdentifier = "fields"
223229
val fieldList = mutableListOf<List<String>>()
224230
query.replace("\\|", "")

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudwatch/logs/insights/QueryResultList.form

Lines changed: 0 additions & 45 deletions
This file was deleted.

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudwatch/logs/insights/QueryResultList.kt

Lines changed: 0 additions & 56 deletions
This file was deleted.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.cloudwatch.logs.insights
5+
6+
import com.intellij.icons.AllIcons
7+
import com.intellij.openapi.Disposable
8+
import com.intellij.openapi.actionSystem.ActionManager
9+
import com.intellij.openapi.actionSystem.AnAction
10+
import com.intellij.openapi.actionSystem.AnActionEvent
11+
import com.intellij.openapi.actionSystem.DefaultActionGroup
12+
import com.intellij.openapi.project.Project
13+
import com.intellij.openapi.ui.SimpleToolWindowPanel
14+
import com.intellij.openapi.util.Disposer
15+
import kotlinx.coroutines.launch
16+
import software.aws.toolkits.jetbrains.services.cloudwatch.logs.InsightsQueryResultsActor
17+
import software.aws.toolkits.jetbrains.utils.ApplicationThreadPoolScope
18+
import software.aws.toolkits.resources.message
19+
import software.aws.toolkits.telemetry.CloudwatchinsightsTelemetry
20+
import software.aws.toolkits.telemetry.InsightsDialogOpenSource
21+
22+
class QueryResultPanel(
23+
private val project: Project,
24+
fields: List<String>,
25+
queryId: String,
26+
private val queryDetails: QueryDetails
27+
) : SimpleToolWindowPanel(false, true), Disposable {
28+
private val coroutineScope = ApplicationThreadPoolScope(ID, this)
29+
init {
30+
val resultsTable = QueryResultsTable(project, queryDetails.connectionSettings, fields, queryId)
31+
Disposer.register(this, resultsTable)
32+
setContent(resultsTable.component)
33+
toolbar = ActionManager.getInstance().createActionToolbar(
34+
ID,
35+
DefaultActionGroup(
36+
object : AnAction(message("cloudwatch.logs.open_query_editor"), null, AllIcons.Actions.EditSource) {
37+
override fun actionPerformed(e: AnActionEvent) {
38+
QueryEditorDialog(project, queryDetails).show()
39+
CloudwatchinsightsTelemetry.openEditor(project, InsightsDialogOpenSource.ResultsWindow)
40+
}
41+
}
42+
),
43+
false
44+
).component
45+
coroutineScope.launch { resultsTable.channel.send(InsightsQueryResultsActor.Message.StartLoadingAll) }
46+
}
47+
48+
override fun dispose() {
49+
}
50+
51+
private companion object {
52+
const val ID = "QueryResultPanel"
53+
}
54+
}

ui-tests/tst/software/aws/toolkits/jetbrains/uitests/tests/InsightsQueryTest.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import software.aws.toolkits.jetbrains.uitests.fixtures.IdeaFrame
2929
import software.aws.toolkits.jetbrains.uitests.fixtures.JTreeFixture
3030
import software.aws.toolkits.jetbrains.uitests.fixtures.awsExplorer
3131
import software.aws.toolkits.jetbrains.uitests.fixtures.findAndClick
32+
import software.aws.toolkits.jetbrains.uitests.fixtures.findByXpath
3233
import software.aws.toolkits.jetbrains.uitests.fixtures.idea
3334
import software.aws.toolkits.jetbrains.uitests.fixtures.waitUntilLoaded
3435
import software.aws.toolkits.jetbrains.uitests.fixtures.welcomeFrame
@@ -178,6 +179,21 @@ class InsightsQueryTest {
178179
assertThat(find<ComboBoxFixture>(byXpath("//div[@class='ComboBox']")).selectedText()).isEqualTo("Hours")
179180
}
180181
}
182+
step("Open query from log group") {
183+
step("Open log group") {
184+
awsExplorer {
185+
doubleClickExplorer(cloudWatchExplorerLabel, logGroupName)
186+
}
187+
find<ComponentFixture>(byXpath("//div[@accessiblename='View Log Streams']")).click()
188+
}
189+
step("Click query button") {
190+
findAndClick("//div[@accessiblename='Query']")
191+
}
192+
step("Verify dialog and close it") {
193+
findByXpath("//div[@accessiblename='Query Log Groups' and @class='MyDialog']")
194+
findAndClick("//div[@text='Cancel']")
195+
}
196+
}
181197
}
182198
}
183199

@@ -199,7 +215,7 @@ class InsightsQueryTest {
199215
}
200216

201217
private fun ContainerFixture.openInsightsQueryDialogFromResults() = step("Open query editor") {
202-
findAndClick("//div[@text='Open Query Editor']")
218+
findAndClick("//div[@accessiblename='Open Query Editor']")
203219
}
204220

205221
private fun CloudWatchLogsClient.verifyDeletedLogGroup(logGroup: String) {

0 commit comments

Comments
 (0)