report exceptions in the backgroud (IDEA-33675)

This commit is contained in:
Dmitry Jemerov
2010-10-20 16:22:02 +04:00
parent 8d65cda320
commit 96043c3e1e
5 changed files with 142 additions and 118 deletions
@@ -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);
}
}