Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add error submitter for user feedback #1429

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/ISSUE_TEMPLATE/error_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Quarkus Tools Plugin Error Report
description: "File a bug report for Quarkus Tool Plugin for IntelliJ"
title: "bug: "
labels:
- bug
projects:
- redhat-developer/37
body:
- type: markdown
attributes:
value: |
Thanks for reporting this issue!! Please include as much information as possible in the Bug Description
**Please make sure to search for the title of this report** before submitting a new issue to avoid duplicates.
Tip: You can attach images, videos, or log files by dragging it into the text box.
- id: report
type: textarea
attributes:
label: Bug Description
description: Please describe the error. Include steps for reproducing the behavior and actual results.
value: |
### Steps to reproduce
1.
1.

### Actual results
Actual result

### Screenshots or screencast
Please attach screenshots or a screencast that helps to understand the issue.
Make sure these screenshots or screencast have no sensitive information.
validations:
required: false
- id: info
type: textarea
attributes:
label: IDE Information
description: This information is automatically gathered.
validations:
required: true
- id: stacktrace
type: textarea
attributes:
label: Stacktrace and user message
description: |
This information is automatically gathered from IntelliJ Error Report Screen.
validations:
required: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.quarkus.error;

import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.SubmittedReportInfo;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.util.NlsActions;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.Consumer;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.Component;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Optional;

public class QuarkusPluginIssueReporter extends ErrorReportSubmitter {

private static final String GITHUB_ISSUE_BASE_URL =
"https://github.com/redhat-developer/intellij-quarkus/issues/new?template=error_report.yml";

private static final String SYSTEM_INFO_TEMPLATE = """
| Attribute | Value |
|----------------------------|-------|
| **OS** | %s |
| **IDE** | %s |
| **JDK** | %s |
| **Quarkus Tools Version** | %s |
""";

public static final int MAX_URL_LENGTH = 8191;

final String ideVersion;
String pluginVersion;
final String operatingSystem;
final String jdkVersion;

public QuarkusPluginIssueReporter(){
ApplicationInfo applicationInfo = ApplicationInfo.getInstance();
operatingSystem = SystemInfo.getOsNameAndVersion() + "-" + SystemInfo.OS_ARCH;
ideVersion = String.join(" ", applicationInfo.getVersionName(),
applicationInfo.getFullVersion(), applicationInfo.getBuild().asString() );
jdkVersion = String.join(" ", System.getProperty("java.vm.name"),
SystemInfo.JAVA_VERSION, SystemInfo.JAVA_RUNTIME_VERSION, SystemInfo.JAVA_VENDOR );
}

@Override
public @NlsActions.ActionText @NotNull String getReportActionText() {
return "Create GitHub Issue";
}

@Override
public boolean submit(IdeaLoggingEvent @NotNull [] events,
@Nullable String userMessage,
@NotNull Component parentComponent,
@NotNull Consumer<? super SubmittedReportInfo> consumer) {
try {
IdeaLoggingEvent event = events[0];
String url = generateUrl(event.getThrowableText(), userMessage);
BrowserUtil.browse(url);
consumer.consume(new SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.NEW_ISSUE));
} catch (Exception e) {
consumer.consume(new SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED));
return false;
}
return true;
}

String generateUrl(String throwableText, @Nullable String userMessage) {
PluginDescriptor pluginDescriptor = getPluginDescriptor();
pluginVersion = pluginDescriptor!=null? pluginDescriptor.getVersion() : "Unknown";
String systemInfo = encode(formatSystemInfo());
String titleLine = encode(throwableText.lines()
.findFirst().orElse("Unable to get exception message"));
String url = GITHUB_ISSUE_BASE_URL +"&title=" + titleLine + "&info=" + systemInfo + "&stacktrace=";
int available = MAX_URL_LENGTH - url.length();
String stackTrace = truncateStacktrace(throwableText, userMessage, available);
return url + stackTrace;
}

private String truncateStacktrace(String throwableText, @Nullable String userMessage, int available) {
String stackTrace = encode(formatStacktrace(throwableText,
Optional.ofNullable(userMessage).orElse("User didn't provide any message")));
if (stackTrace.length() > available) {
stackTrace = stackTrace.substring(0, available-1);
}
return stackTrace;
}

private String formatSystemInfo() {
return SYSTEM_INFO_TEMPLATE.formatted(operatingSystem, ideVersion, jdkVersion, pluginVersion);
}

private String formatStacktrace(String stackTrace, String userMessage) {
return """
**User message**: *%s*
**Stacktrace:**
```
%s
```
""".formatted(userMessage, stackTrace);
}

private String encode(final String text) {
return URLEncoder.encode(text, StandardCharsets.UTF_8);
}

}
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@
<lang.substitutor language="yaml"
implementationClass="com.redhat.devtools.intellij.qute.lang.QuteLanguageSubstitutor"/>
<typedHandler implementation="com.redhat.devtools.intellij.qute.editor.QuteTypedHandler"/>
<errorHandler implementation="com.redhat.devtools.intellij.quarkus.error.QuarkusPluginIssueReporter" />
</extensions>

<extensionPoints>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.quarkus.error;

import com.intellij.testFramework.fixtures.BasePlatformTestCase;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static com.redhat.devtools.intellij.quarkus.error.QuarkusPluginIssueReporter.MAX_URL_LENGTH;
import static org.assertj.core.api.Assertions.assertThat;

public class QuarkusPluginIssueReporterTest extends BasePlatformTestCase {
private QuarkusPluginIssueReporter reporter;

@Override
protected void setUp() throws Exception {
super.setUp();
reporter = new QuarkusPluginIssueReporter();
}

private static final String STACKTRACE =
"""
java.lang.NullPointerException: Cannot invoke "javax.swing.JCheckBox.setSelected(boolean)" because "platformCheckbox" is null
at com.redhat.devtools.intellij.quarkus.projectWizard.QuarkusExtensionsStep.getComponent(QuarkusExtensionsStep.java:150)
at com.intellij.ide.wizard.AbstractWizard.updateStep(AbstractWizard.java:483)
""";

public void testEncodedUrlWithExceptionAndMessage() {
String userMessage = "I ran into this error with quarkus project wizard";
String url = URLDecoder.decode(reporter.generateUrl(STACKTRACE, userMessage), StandardCharsets.UTF_8);
assertThat(url).as("Stacktrace not found in decoded url").contains(STACKTRACE);
assertThat(url).as("userMessage not found in decoded url").contains(userMessage);
List<String> systemInfo = List.of(reporter.ideVersion, reporter.jdkVersion,
reporter.operatingSystem, reporter.pluginVersion);
assertThat(systemInfo).allSatisfy(attribute -> assertThat(url).contains(attribute));
}

public void testLongStacktraceIsTruncated() {
String stackTrace = STACKTRACE.concat("A".repeat(MAX_URL_LENGTH));
String url = reporter.generateUrl(stackTrace, "Hallo");
String decodedUrl = URLDecoder.decode(url, StandardCharsets.UTF_8);
assertThat(decodedUrl).as("Initial Stacktrace not found in decoded url").contains(STACKTRACE);
assertThat(url.length()).isLessThan(MAX_URL_LENGTH);
}
}
Loading