Skip to content

Commit 3d49bc6

Browse files
[DQL] Improving DQL execution services
Introducing a root level for all services spawned from this plugin. It allows the user to open main settings. Tenant-level groups show options related to tenants. Double-clicking the service opens the related file or query console.
1 parent e860fb2 commit 3d49bc6

17 files changed

+382
-143
lines changed

CHANGELOG.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
- Adding predefined timeframes to the DQL execution toolbar (user can still define a custom one)
1212
- The DQL execution result will show an empty cell for a boolean column that had a `null` value (instead of the
1313
unchecked checkbox). This change helps to differentiate between `false` and `null` values.
14-
- Executed DQL queries will now be grouped by the tenant they were executed on in the Services tab
14+
- All executed DQL queries will be grouped in the `Services` tab. The root group allows the user to easily access the
15+
most common settings related to DQL execution. All queries will be additionally grouped by the tenant they were
16+
executed with, allowing the user to easily find the query they are looking for in case of using multiple connected
17+
tenants.
18+
- Double-clicking the executed DQL query in the `Services` tab will now either open the related file (if possible),
19+
or open a new DQL query console with the execution context.
1520
- The "Show DQL query" option when executing DQL will now try to show the parsed query instead of the raw one, if
1621
possible.
1722
- Adding support for "Expression DQL" file (with `.dqlexpr` extension), which allows to define a DQL expression without
@@ -30,23 +35,24 @@
3035
- Support for `.partial.dql` files will be removed in the future, so it's recommended to migrate to the new extension
3136
as soon as possible.
3237
- **Breaking**: Changing the approach to the default Dynatrace tenant used for connections - it will be the first tenant
33-
specified in the list (previously the user needed to specifically select the default one).
38+
specified in the list (previously the user needed to specifically select the default one). Please update the tenants
39+
order if you wish to change the default tenant.
3440
- Created Wiki pages with documentation for the plugin features
3541
- DQL now supports complex sorting expressions (for example, `sort abs(field) > 10 desc`)
42+
- DQL now supports `/* language=X */` comments in strings
3643
- Added missing quick fixes for inspections:
3744
- Dropping DQL commands and functions for unknown & experimental expressions
3845
- Renaming the DQL file to `.dqlpart` when an invalid command context is detected (only for `.dql` files)
39-
- DQL now supports `/* language=X */` comments in strings
4046
- Adding a Dynatrace Query Console view that allows the user to execute DQL queries without opening a DQL file.
41-
You can open the console via the `Tools` -> `Services` -> `Dynatrace Query Console` menu or by clicking the `+` button
42-
in the `Services` tab.
47+
You can open the console via the `Tools` -> `Services` -> `Dynatrace Query Console` menu or by clicking the dedicated
48+
button in the `Services` tab.
4349

4450
### Bug fixes
4551

4652
- Creating an empty DQL variable using the `$type: dql` syntax will now create a multiline comment instead of causing an
4753
error
48-
- When modifying or deleting a Dynatrace tenant that was already used, files using it will ask the user to select a new
49-
tenant.
54+
- When modifying or deleting a Dynatrace tenant that was already used, files using it will require the user to select
55+
a new tenant.
5056

5157
## [1.4.0] - 2026-01-28
5258

docs/wiki/DQL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ displayed at the bottom part of the result view.
236236
#### Query console
237237

238238
The plugin also adds support for executing DQL queries without the need of creating a `.dql` file.
239-
The console can be opened via the `Tools` -> `Services` -> `Dynatrace Query Console` menu or by clicking the `+` button
240-
in the `Services` tab.
239+
The console can be opened via the `Tools` -> `Services` -> `Dynatrace Query Console` menu or by clicking the dedicated
240+
button in the `Services` tab.
241241

242242
### Partial DQL
243243

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
package pl.thedeem.intellij.common.services;
22

3-
import com.intellij.execution.services.ServiceViewDescriptor;
4-
import com.intellij.openapi.Disposable;
5-
6-
public interface ManagedServiceGroup extends ServiceViewDescriptor, Disposable {
3+
public interface ManagedServiceGroup extends ManagedService {
74
}

src/main/java/pl/thedeem/intellij/dql/DQLIcon.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ public interface DQLIcon extends Icons {
2828
Icon GUTTER_EXECUTE_DQL = IntelliJUtils.scaleToBottomRight(AllIcons.Actions.Execute, DYNATRACE_LOGO, 0.5f);
2929
Icon GUTTER_EXECUTE_SETTINGS = IntelliJUtils.scaleToBottomRight(AllIcons.General.GearPlain, DYNATRACE_LOGO, 0.5f);
3030
Icon QUERY_CONSOLE = IntelliJUtils.scaleToBottomRight(AllIcons.General.ProjectTab, DYNATRACE_LOGO, 0.5f);
31+
Icon MANAGE_TENANTS = IntelliJUtils.scaleToBottomRight(AllIcons.Actions.Annotate, DYNATRACE_LOGO, 0.5f);
3132
}

src/main/java/pl/thedeem/intellij/dql/actions/ManageTenantsAction.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@
22

33
import com.intellij.openapi.actionSystem.AnAction;
44
import com.intellij.openapi.actionSystem.AnActionEvent;
5-
import com.intellij.openapi.options.ShowSettingsUtil;
6-
import com.intellij.openapi.project.ProjectManager;
75
import org.jetbrains.annotations.NotNull;
86
import pl.thedeem.intellij.dql.settings.tenants.DynatraceTenantsConfigurable;
97

108
public class ManageTenantsAction extends AnAction {
119
@Override
1210
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
13-
ShowSettingsUtil.getInstance().editConfigurable(
14-
ProjectManager.getInstance().getDefaultProject(),
15-
new DynatraceTenantsConfigurable()
16-
);
11+
DynatraceTenantsConfigurable.showSettings();
1712
}
1813
}

src/main/java/pl/thedeem/intellij/dql/actions/OpenDQLQueryConsoleAction.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,12 @@
33
import com.intellij.openapi.actionSystem.AnAction;
44
import com.intellij.openapi.actionSystem.AnActionEvent;
55
import com.intellij.openapi.actionSystem.DataKey;
6-
import com.intellij.openapi.fileEditor.FileEditorManager;
76
import com.intellij.openapi.project.DumbAware;
87
import com.intellij.openapi.project.Project;
98
import org.jetbrains.annotations.NotNull;
10-
import pl.thedeem.intellij.dql.DQLBundle;
119
import pl.thedeem.intellij.dql.fileProviders.DQLQueryConsoleVirtualFile;
1210

13-
import java.util.concurrent.atomic.AtomicInteger;
14-
1511
public class OpenDQLQueryConsoleAction extends AnAction implements DumbAware {
16-
public static final AtomicInteger COUNTER = new AtomicInteger(0);
1712
public static final DataKey<String> INITIAL_TENANT = DataKey.create("DQL.INITIAL_TENANT_FOR_QUERY_CONSOLE");
1813

1914
@Override
@@ -22,12 +17,7 @@ public void actionPerformed(@NotNull AnActionEvent e) {
2217
if (project == null) {
2318
return;
2419
}
25-
26-
DQLQueryConsoleVirtualFile vf = new DQLQueryConsoleVirtualFile(
27-
DQLBundle.message("action.DQL.OpenDQLQueryConsole.ServiceViewAction.consoleName", COUNTER.incrementAndGet()),
28-
e.getData(INITIAL_TENANT)
29-
);
30-
FileEditorManager.getInstance(project).openFile(vf, true);
20+
DQLQueryConsoleVirtualFile.openForTenant(project, e.getData(INITIAL_TENANT));
3121
}
3222
}
3323

src/main/java/pl/thedeem/intellij/dql/editor/DQLMissingTenantNotificationProvider.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package pl.thedeem.intellij.dql.editor;
22

33
import com.intellij.openapi.fileEditor.FileEditor;
4-
import com.intellij.openapi.options.ShowSettingsUtil;
54
import com.intellij.openapi.project.Project;
65
import com.intellij.openapi.vfs.VirtualFile;
76
import com.intellij.ui.EditorNotificationPanel;
@@ -32,7 +31,7 @@ public class DQLMissingTenantNotificationProvider implements EditorNotificationP
3231
panel.setText(DQLBundle.message("notifications.noDynatraceTenants.info"));
3332

3433
panel.createActionLabel(DQLBundle.message("notifications.noDynatraceTenants.actions.add"), () -> {
35-
ShowSettingsUtil.getInstance().showSettingsDialog(project, DQLSettingsConfigurable.class);
34+
DQLSettingsConfigurable.showSettings(project);
3635
panel.setVisible(shouldShowToolbar(tenantsService));
3736
EditorNotifications.getInstance(project).updateNotifications(virtualFile);
3837
});

src/main/java/pl/thedeem/intellij/dql/exec/DQLExecutionService.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99
import com.intellij.openapi.command.WriteCommandAction;
1010
import com.intellij.openapi.diagnostic.Logger;
1111
import com.intellij.openapi.fileEditor.FileEditorManager;
12+
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
1213
import com.intellij.openapi.project.Project;
1314
import com.intellij.openapi.util.Computable;
15+
import com.intellij.openapi.vfs.VirtualFile;
16+
import com.intellij.pom.Navigatable;
1417
import com.intellij.util.concurrency.AppExecutorUtil;
1518
import org.jetbrains.annotations.NotNull;
1619
import org.jetbrains.annotations.Nullable;
1720
import org.jsoup.internal.StringUtil;
21+
import pl.thedeem.intellij.common.IntelliJUtils;
1822
import pl.thedeem.intellij.common.StandardItemPresentation;
1923
import pl.thedeem.intellij.common.components.InformationComponent;
2024
import pl.thedeem.intellij.common.sdk.DynatraceRestClient;
@@ -31,9 +35,11 @@
3135
import pl.thedeem.intellij.dql.editor.actions.QueryConfigurationAction;
3236
import pl.thedeem.intellij.dql.exec.panel.DQLExecutionErrorPanel;
3337
import pl.thedeem.intellij.dql.exec.panel.DQLExecutionResult;
38+
import pl.thedeem.intellij.dql.fileProviders.DQLQueryConsoleVirtualFile;
3439
import pl.thedeem.intellij.dql.fileProviders.DQLResultVirtualFile;
3540
import pl.thedeem.intellij.dql.services.query.DQLQueryConfigurationService;
3641
import pl.thedeem.intellij.dql.services.query.DQLQueryParserService;
42+
import pl.thedeem.intellij.dql.services.ui.ConnectedTenantsServiceGroup;
3743
import pl.thedeem.intellij.dql.services.ui.TenantServiceGroup;
3844
import pl.thedeem.intellij.dql.settings.tenants.DynatraceTenant;
3945
import pl.thedeem.intellij.dql.settings.tenants.DynatraceTenantsService;
@@ -93,9 +99,9 @@ public void dispose() {
9399
public @NotNull List<ManagedServiceGroup> getParentGroups() {
94100
String tenant = configuration.tenant();
95101
if (tenant == null) {
96-
return List.of();
102+
return List.of(ConnectedTenantsServiceGroup.getInstance());
97103
}
98-
return List.of(new TenantServiceGroup(tenant));
104+
return List.of(ConnectedTenantsServiceGroup.getInstance(), new TenantServiceGroup(tenant));
99105
}
100106

101107
public void startExecution() {
@@ -362,4 +368,17 @@ public int hashCode() {
362368
getServiceId()
363369
);
364370
}
371+
372+
@Override
373+
public @Nullable Navigatable getNavigatable() {
374+
String originalFile = configuration.originalFile();
375+
VirtualFile virtualFile = null;
376+
if (originalFile != null) {
377+
virtualFile = IntelliJUtils.getProjectRelativeFile(originalFile, project);
378+
}
379+
if (virtualFile == null) {
380+
virtualFile = new DQLQueryConsoleVirtualFile(this.name, this.configuration.query());
381+
}
382+
return new OpenFileDescriptor(project, virtualFile);
383+
}
365384
}

src/main/java/pl/thedeem/intellij/dql/fileProviders/DQLQueryConsoleVirtualFile.java

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
package pl.thedeem.intellij.dql.fileProviders;
22

3+
import com.intellij.openapi.fileEditor.FileEditorManager;
34
import com.intellij.openapi.fileTypes.FileType;
45
import com.intellij.openapi.project.Project;
56
import org.jetbrains.annotations.NotNull;
67
import org.jetbrains.annotations.Nullable;
8+
import pl.thedeem.intellij.dql.DQLBundle;
79
import pl.thedeem.intellij.dql.DQLFileType;
810
import pl.thedeem.intellij.dql.exec.panel.DQLQueryConsolePanel;
911

1012
import javax.swing.*;
13+
import java.util.Objects;
14+
import java.util.concurrent.atomic.AtomicInteger;
1115

1216
public class DQLQueryConsoleVirtualFile extends DQLVirtualFile<String> {
13-
private final String initialTenant;
17+
public static final AtomicInteger COUNTER = new AtomicInteger(0);
18+
private String initialTenant;
1419

15-
public DQLQueryConsoleVirtualFile(@NotNull String name, @Nullable String initialTenant) {
20+
public DQLQueryConsoleVirtualFile(@NotNull String name) {
1621
super(name, "");
17-
this.initialTenant = initialTenant;
22+
}
23+
24+
public DQLQueryConsoleVirtualFile(@NotNull String name, @NotNull String content) {
25+
super(name, content);
1826
}
1927

2028
@Override
@@ -31,4 +39,36 @@ public boolean isWritable() {
3139
public @NotNull JComponent createComponent(@NotNull Project project) {
3240
return new DQLQueryConsolePanel(project, content, this, initialTenant);
3341
}
42+
43+
public @NotNull DQLQueryConsoleVirtualFile setInitialTenant(@Nullable String initialTenant) {
44+
this.initialTenant = initialTenant;
45+
return this;
46+
}
47+
48+
public static void open(@NotNull Project project) {
49+
open(project, DQLBundle.message("editor.queryConsole.consoleName", COUNTER.incrementAndGet()), null);
50+
}
51+
52+
public static void openForTenant(@NotNull Project project, @Nullable String tenant) {
53+
open(project, DQLBundle.message("editor.queryConsole.consoleName", COUNTER.incrementAndGet()), tenant);
54+
}
55+
56+
public static void open(@NotNull Project project, @NotNull String name, @Nullable String initialTenant) {
57+
DQLQueryConsoleVirtualFile vf = new DQLQueryConsoleVirtualFile(name)
58+
.setInitialTenant(initialTenant);
59+
FileEditorManager.getInstance(project).openFile(vf, true);
60+
}
61+
62+
@Override
63+
public boolean equals(Object o) {
64+
if (this == o) return true;
65+
if (o == null || getClass() != o.getClass()) return false;
66+
DQLVirtualFile<?> casted = this.getClass().cast(o);
67+
return Objects.equals(getName(), casted.getName());
68+
}
69+
70+
@Override
71+
public int hashCode() {
72+
return getName().hashCode();
73+
}
3474
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package pl.thedeem.intellij.dql.services.ui;
2+
3+
import com.intellij.icons.AllIcons;
4+
import com.intellij.navigation.ItemPresentation;
5+
import com.intellij.openapi.actionSystem.*;
6+
import com.intellij.openapi.project.Project;
7+
import org.jetbrains.annotations.NotNull;
8+
import org.jetbrains.annotations.Nullable;
9+
import pl.thedeem.intellij.common.StandardItemPresentation;
10+
import pl.thedeem.intellij.common.services.ManagedServiceGroup;
11+
import pl.thedeem.intellij.dql.DQLBundle;
12+
import pl.thedeem.intellij.dql.DQLIcon;
13+
import pl.thedeem.intellij.dql.fileProviders.DQLQueryConsoleVirtualFile;
14+
import pl.thedeem.intellij.dql.settings.DQLSettingsConfigurable;
15+
import pl.thedeem.intellij.dql.settings.tenants.DynatraceTenantsConfigurable;
16+
17+
import java.util.List;
18+
19+
public class ConnectedTenantsServiceGroup implements ManagedServiceGroup {
20+
private static final ConnectedTenantsServiceGroup INSTANCE = new ConnectedTenantsServiceGroup();
21+
private DefaultActionGroup actions;
22+
23+
protected ConnectedTenantsServiceGroup() {
24+
}
25+
26+
public static ConnectedTenantsServiceGroup getInstance() {
27+
return INSTANCE;
28+
}
29+
30+
@Override
31+
public @NotNull ItemPresentation getPresentation() {
32+
return new StandardItemPresentation(
33+
DQLBundle.message("services.connectedTenants.groupName"),
34+
null,
35+
DQLIcon.DYNATRACE_LOGO
36+
);
37+
}
38+
39+
@Override
40+
public void dispose() {
41+
}
42+
43+
@Override
44+
public @Nullable ActionGroup getToolbarActions() {
45+
if (actions == null) {
46+
actions = new DefaultActionGroup();
47+
actions.add(new AnAction(
48+
DQLBundle.message("services.connectedTenants.actions.openConsole.title"),
49+
null,
50+
DQLIcon.QUERY_CONSOLE
51+
) {
52+
@Override
53+
public void actionPerformed(@NotNull AnActionEvent e) {
54+
Project project = e.getProject();
55+
if (project == null) {
56+
return;
57+
}
58+
DQLQueryConsoleVirtualFile.open(project);
59+
}
60+
});
61+
actions.add(new AnAction(
62+
DQLBundle.message("services.connectedTenants.actions.allSettings.title"),
63+
null,
64+
AllIcons.General.GearPlain
65+
) {
66+
@Override
67+
public void actionPerformed(@NotNull AnActionEvent e) {
68+
Project project = e.getProject();
69+
if (project == null) {
70+
return;
71+
}
72+
DQLSettingsConfigurable.showSettings(project);
73+
}
74+
});
75+
actions.addAction(new AnAction(
76+
DQLBundle.message("services.connectedTenants.actions.manageTenants.title"),
77+
null,
78+
DQLIcon.MANAGE_TENANTS
79+
) {
80+
@Override
81+
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
82+
DynatraceTenantsConfigurable.showSettings();
83+
}
84+
85+
@Override
86+
public @NotNull ActionUpdateThread getActionUpdateThread() {
87+
return ActionUpdateThread.BGT;
88+
}
89+
});
90+
}
91+
return actions;
92+
}
93+
94+
@Override
95+
public @NotNull String getServiceId() {
96+
return "DynatraceTenants";
97+
}
98+
99+
@Override
100+
public @NotNull List<ManagedServiceGroup> getParentGroups() {
101+
return List.of();
102+
}
103+
}

0 commit comments

Comments
 (0)