mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
report exceptions in the backgroud (IDEA-33675)
This commit is contained in:
@@ -17,6 +17,7 @@ package com.intellij.openapi.diagnostic;
|
||||
|
||||
import com.intellij.openapi.extensions.PluginAware;
|
||||
import com.intellij.openapi.extensions.PluginDescriptor;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@@ -57,4 +58,8 @@ public abstract class ErrorReportSubmitter implements PluginAware {
|
||||
* @return submission result status.
|
||||
*/
|
||||
public abstract SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent);
|
||||
|
||||
public void submitAsync(IdeaLoggingEvent[] events, Component parentComponent, Consumer<SubmittedReportInfo> consumer) {
|
||||
consumer.consume(submit(events, parentComponent));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Date;
|
||||
public abstract class AbstractMessage {
|
||||
|
||||
private boolean myIsRead = false;
|
||||
private boolean myIsSubmitting = false;
|
||||
private SubmittedReportInfo mySubmissionInfo;
|
||||
private String myScrID;
|
||||
|
||||
@@ -52,6 +53,14 @@ public abstract class AbstractMessage {
|
||||
return mySubmissionInfo;
|
||||
}
|
||||
|
||||
public boolean isSubmitting() {
|
||||
return myIsSubmitting;
|
||||
}
|
||||
|
||||
public void setSubmitting(boolean isSubmitting) {
|
||||
myIsSubmitting = isSubmitting;
|
||||
}
|
||||
|
||||
public boolean isSubmitted() {
|
||||
return mySubmissionInfo != null &&
|
||||
(mySubmissionInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.NEW_ISSUE ||
|
||||
|
||||
@@ -23,6 +23,9 @@ import com.intellij.errorreport.error.NoSuchEAPUserException;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.idea.IdeaLogger;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -32,12 +35,10 @@ import com.intellij.openapi.diagnostic.SubmittedReportInfo;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.util.net.IOExceptionDialog;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -52,98 +53,110 @@ public class ITNReporter extends ErrorReportSubmitter {
|
||||
}
|
||||
|
||||
public SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent) {
|
||||
return sendError(events[0], parentComponent);
|
||||
// obsolete API
|
||||
return new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submitAsync(IdeaLoggingEvent[] events, Component parentComponent, Consumer<SubmittedReportInfo> consumer) {
|
||||
sendError(events [0], parentComponent, consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @noinspection ThrowablePrintStackTrace
|
||||
*/
|
||||
private static SubmittedReportInfo sendError(IdeaLoggingEvent event, Component parentComponent) {
|
||||
private static void sendError(IdeaLoggingEvent event, final Component parentComponent, final Consumer<SubmittedReportInfo> callback) {
|
||||
String newBuild = ErrorReportSender.checkNewBuild();
|
||||
if (newBuild != null) {
|
||||
Messages.showMessageDialog(parentComponent,
|
||||
DiagnosticBundle.message("error.report.new.eap.build.message", newBuild), CommonBundle.getWarningTitle(),
|
||||
Messages.getWarningIcon());
|
||||
return new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED);
|
||||
callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
|
||||
}
|
||||
|
||||
ErrorBean errorBean = new ErrorBean(event.getThrowable(), IdeaLogger.ourLastActionId);
|
||||
|
||||
int threadId = 0;
|
||||
SubmittedReportInfo.SubmissionStatus submissionStatus = SubmittedReportInfo.SubmissionStatus.FAILED;
|
||||
String description = "";
|
||||
|
||||
doSubmit(event, parentComponent, callback, errorBean, description);
|
||||
}
|
||||
|
||||
private static void doSubmit(final IdeaLoggingEvent event,
|
||||
final Component parentComponent,
|
||||
final Consumer<SubmittedReportInfo> callback,
|
||||
final ErrorBean errorBean, final String description) {
|
||||
final DataContext dataContext = DataManager.getInstance().getDataContext(parentComponent);
|
||||
Project project = PlatformDataKeys.PROJECT.getData(dataContext);
|
||||
|
||||
String description = "";
|
||||
do {
|
||||
// prepare
|
||||
try {
|
||||
EAPSendErrorDialog dlg = new EAPSendErrorDialog();
|
||||
dlg.setErrorDescription(description);
|
||||
dlg.show();
|
||||
|
||||
@NonNls String login = ErrorReportConfigurable.getInstance().ITN_LOGIN;
|
||||
@NonNls String password = ErrorReportConfigurable.getInstance().getPlainItnPassword();
|
||||
if (login.trim().length() == 0 && password.trim().length() == 0) {
|
||||
login = "idea_anonymous";
|
||||
password = "guest";
|
||||
}
|
||||
|
||||
description = dlg.getErrorDescription();
|
||||
@NonNls StringBuilder descBuilder = buildDescription(event, description);
|
||||
errorBean.setDescription(descBuilder.toString());
|
||||
|
||||
if (dlg.isShouldSend()) {
|
||||
threadId = ErrorReportSender.sendError(project, login, password, errorBean);
|
||||
previousExceptionThreadId = threadId;
|
||||
wasException = true;
|
||||
submissionStatus = SubmittedReportInfo.SubmissionStatus.NEW_ISSUE;
|
||||
|
||||
Messages.showInfoMessage(parentComponent,
|
||||
DiagnosticBundle.message("error.report.confirmation"),
|
||||
ReportMessages.ERROR_REPORT);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
catch (NoSuchEAPUserException e) {
|
||||
if (Messages.showYesNoDialog(parentComponent, DiagnosticBundle.message("error.report.authentication.failed"),
|
||||
ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (InternalEAPException e) {
|
||||
if (Messages.showYesNoDialog(parentComponent, DiagnosticBundle.message("error.report.posting.failed", e.getMessage()),
|
||||
ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (!IOExceptionDialog.showErrorDialog(DiagnosticBundle.message("error.report.exception.title"),
|
||||
DiagnosticBundle.message("error.report.failure.message"))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (Messages.showYesNoDialog(JOptionPane.getRootFrame(), DiagnosticBundle.message("error.report.sending.failure"),
|
||||
ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final EAPSendErrorDialog dlg = new EAPSendErrorDialog();
|
||||
dlg.setErrorDescription(description);
|
||||
dlg.show();
|
||||
if (!dlg.isShouldSend()) {
|
||||
return;
|
||||
}
|
||||
while (true);
|
||||
|
||||
return new SubmittedReportInfo(submissionStatus != SubmittedReportInfo.SubmissionStatus.FAILED ? URL_HEADER + threadId : null,
|
||||
String.valueOf(threadId),
|
||||
submissionStatus);
|
||||
@NonNls String login = ErrorReportConfigurable.getInstance().ITN_LOGIN;
|
||||
@NonNls String password = ErrorReportConfigurable.getInstance().getPlainItnPassword();
|
||||
if (login.trim().length() == 0 && password.trim().length() == 0) {
|
||||
login = "idea_anonymous";
|
||||
password = "guest";
|
||||
}
|
||||
|
||||
errorBean.setDescription(buildDescription(event, dlg.getErrorDescription()));
|
||||
|
||||
ErrorReportSender.sendError(project, login, password, errorBean, new Consumer<Integer>() {
|
||||
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
|
||||
@Override
|
||||
public void consume(Integer threadId) {
|
||||
previousExceptionThreadId = threadId;
|
||||
wasException = true;
|
||||
callback.consume(new SubmittedReportInfo(URL_HEADER + threadId, String.valueOf(threadId),
|
||||
SubmittedReportInfo.SubmissionStatus.NEW_ISSUE));
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Notification notification = new Notification(ReportMessages.ERROR_REPORT, ReportMessages.ERROR_REPORT,
|
||||
DiagnosticBundle.message("error.report.confirmation"),
|
||||
NotificationType.INFORMATION);
|
||||
Notifications.Bus.notify(notification);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, new Consumer<Exception>() {
|
||||
@Override
|
||||
public void consume(final Exception e) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String msg;
|
||||
if (e instanceof NoSuchEAPUserException) {
|
||||
msg = DiagnosticBundle.message("error.report.authentication.failed");
|
||||
}
|
||||
else if (e instanceof InternalEAPException) {
|
||||
msg = DiagnosticBundle.message("error.report.posting.failed", e.getMessage());
|
||||
}
|
||||
else {
|
||||
msg = DiagnosticBundle.message("error.report.sending.failure");
|
||||
}
|
||||
if (Messages.showYesNoDialog(parentComponent, msg,
|
||||
ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) {
|
||||
callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doSubmit(event, parentComponent, callback, errorBean, dlg.getErrorDescription());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static StringBuilder buildDescription(IdeaLoggingEvent event, String description) {
|
||||
private static String buildDescription(IdeaLoggingEvent event, String description) {
|
||||
String message = event.getMessage();
|
||||
|
||||
@NonNls StringBuilder descBuilder = new StringBuilder();
|
||||
@@ -171,6 +184,6 @@ public class ITNReporter extends ErrorReportSubmitter {
|
||||
if (wasException) {
|
||||
descBuilder.append("There was at least one exception before this one.\n");
|
||||
}
|
||||
return descBuilder;
|
||||
return descBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -182,11 +183,11 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
|
||||
if (message.isSubmitted()) {
|
||||
final SubmittedReportInfo info = message.getSubmissionInfo();
|
||||
if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.FAILED) {
|
||||
txt.append(DiagnosticBundle.message("error.list.message.submission.failed"));
|
||||
txt.append(" ").append(DiagnosticBundle.message("error.list.message.submission.failed"));
|
||||
}
|
||||
else {
|
||||
if (info.getLinkText() != null) {
|
||||
txt.append(DiagnosticBundle.message("error.list.message.submitted.as.link", info.getLinkText()));
|
||||
txt.append(" ").append(DiagnosticBundle.message("error.list.message.submitted.as.link", info.getLinkText()));
|
||||
if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.DUPLICATE) {
|
||||
txt.append(DiagnosticBundle.message("error.list.message.duplicate"));
|
||||
}
|
||||
@@ -197,6 +198,9 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
|
||||
}
|
||||
txt.append(". ");
|
||||
}
|
||||
else if (message.isSubmitting()) {
|
||||
txt.append(" Submitting...");
|
||||
}
|
||||
else if (!message.isRead()) {
|
||||
txt.append(" ").append(DiagnosticBundle.message("error.list.message.unread"));
|
||||
}
|
||||
@@ -508,7 +512,21 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
|
||||
ErrorReportSubmitter submitter = getSubmitter(logMessage.getThrowable());
|
||||
|
||||
if (submitter != null) {
|
||||
logMessage.setSubmitted(submitter.submit(getEvents(logMessage), getContentPane()));
|
||||
logMessage.setSubmitting(true);
|
||||
updateControls();
|
||||
submitter.submitAsync(getEvents(logMessage), getContentPane(), new Consumer<SubmittedReportInfo>() {
|
||||
@Override
|
||||
public void consume(SubmittedReportInfo submittedReportInfo) {
|
||||
logMessage.setSubmitting(false);
|
||||
logMessage.setSubmitted(submittedReportInfo);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateControls();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,24 +17,24 @@ package com.intellij.errorreport;
|
||||
|
||||
import com.intellij.diagnostic.DiagnosticBundle;
|
||||
import com.intellij.errorreport.bean.ErrorBean;
|
||||
import com.intellij.errorreport.error.InternalEAPException;
|
||||
import com.intellij.errorreport.error.NoSuchEAPUserException;
|
||||
import com.intellij.errorreport.itn.ITNProxy;
|
||||
import com.intellij.ide.reporter.ConnectionException;
|
||||
import com.intellij.idea.IdeaLogger;
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.updateSettings.impl.BuildInfo;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateChannel;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.net.HttpConfigurable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: stathik
|
||||
@@ -44,7 +44,9 @@ import java.io.IOException;
|
||||
*/
|
||||
public class ErrorReportSender {
|
||||
@NonNls public static final String PREPARE_URL = "http://www.intellij.net/";
|
||||
//public static String REPORT_URL = "http://unit-038:8080/error/report?sender=i";
|
||||
|
||||
private ErrorReportSender() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String checkNewBuild() {
|
||||
@@ -64,74 +66,51 @@ public class ErrorReportSender {
|
||||
private String myLogin;
|
||||
private String myPassword;
|
||||
private ErrorBean errorBean;
|
||||
private int myThreadId;
|
||||
|
||||
public SendTask(final Project project, ErrorBean errorBean) {
|
||||
myProject = project;
|
||||
this.errorBean = errorBean;
|
||||
}
|
||||
|
||||
public int getThreadId () {
|
||||
return myThreadId;
|
||||
}
|
||||
|
||||
public void setCredentials(String login, String password) {
|
||||
myLogin = login;
|
||||
myPassword = password;
|
||||
}
|
||||
|
||||
public void sendReport() throws Exception {
|
||||
final Ref<Exception> err = new Ref<Exception>();
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
public void sendReport(final Consumer<Integer> callback, final Consumer<Exception> errback) {
|
||||
Task.Backgroundable task = new Task.Backgroundable(myProject, DiagnosticBundle.message("title.submitting.error.report")) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
try {
|
||||
HttpConfigurable.getInstance().prepareURL(PREPARE_URL);
|
||||
|
||||
if (!StringUtil.isEmpty(myLogin)) {
|
||||
myThreadId = ITNProxy.postNewThread(
|
||||
int threadId = ITNProxy.postNewThread(
|
||||
myLogin,
|
||||
myPassword,
|
||||
errorBean,
|
||||
IdeaLogger.getOurCompilationTimestamp());
|
||||
callback.consume(threadId);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
err.set(ex);
|
||||
errback.consume(ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (myProject == null) {
|
||||
runnable.run();
|
||||
task.run(new EmptyProgressIndicator());
|
||||
}
|
||||
else {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable,
|
||||
DiagnosticBundle.message("title.submitting.error.report"),
|
||||
false, myProject);
|
||||
}
|
||||
if (!err.isNull()) {
|
||||
throw err.get();
|
||||
ProgressManager.getInstance().run(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int sendError(Project project, String login, String password, ErrorBean error)
|
||||
throws IOException, NoSuchEAPUserException, InternalEAPException {
|
||||
|
||||
public static void sendError(Project project, String login, String password, ErrorBean error,
|
||||
Consumer<Integer> callback, Consumer<Exception> errback) {
|
||||
SendTask sendTask = new SendTask (project, error);
|
||||
sendTask.setCredentials(login, password);
|
||||
|
||||
try {
|
||||
sendTask.sendReport();
|
||||
return sendTask.getThreadId();
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (NoSuchEAPUserException e) {
|
||||
throw e;
|
||||
} catch (InternalEAPException e) {
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
sendTask.sendReport(callback, errback);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user