Введение в отчеты об ошибках

Отчеты об ошибках – важнейший инструмент разработчика программного обеспечения. Очень жаль, что далеко не все программисты знают и полностью используют это средство тестирования и отладки.

Сколько раз Вы писали своим пользователям: «сделайте пожалуйста скриншот сообщения об ошибке и пришлите его мне»? И ведь периодически оказывается, что ошибка возникает очень редко и вызвать ее повторное появление пользователь не в силах. Автоматическая отправка отчетов об ошибках – великолепное решение этой проблемы.

Автоматические отчеты об ошибках полезны не только при открытом бета-тестировании или при поддержке после релиза, они крайне удобны и во время внутренних тестов и даже в случае, когда Вы – единственный разработчик и пользователь программы в одном лице. Если все ошибки Вашей программы автоматически будут попадать в базу данных, Вы не забудете о появившейся всего лишь однажды ошибке, работа Ваших тестировщиков станет легче, Вы сможете с легкостью узнать, какие ошибки возникают чаще других и т.д.

Как это работает

При возникновении ошибки, выполняется специальная функция программы, собирающая сведения о состоянии программы, конфигурации оборудования, опрашивающая пользователя о его последних действиях и т.п. и передающая эти сведения на сайт разработчика, где подобные сообщения от различных программ сохраняются, сортируются, подсчитываются и отображаются разработчику с применением фильтров и поиска.

Как правило, для передачи отчета используется протокол HTTP (возникает меньше проблем с межсетевыми экранами), а из отправляемых сведений наибольшую ценность представляют сведения о типе ошибки, состоянии стека вызовов, дате и времени возникновения, версии программы, значениях некоторых переменных, объеме свободной памяти, версии операционной системы и используемых библиотек, иногда подробные сведения об аппаратном обеспечении.

Пример реализации на C#

Рассмотрим умышленно простой пример, на сервере будем исользовать веб-сервис на WCF, получающий сообщение об ошибке и сохраняющий его в файл, на клиентской стороне займемся отправкой сообщений при возникновении необработанных исключений (будем без лишних вопросов передавать время и текст исключения на сервер).

Для начала – серверная сторона.
Интерфейс веб-сервиса

namespace ErrorReportingService
{
[System.ServiceModel.ServiceContract]
public interface IErrorReporting
{
[System.ServiceModel.OperationContract]
string PostErrorInfo(string info);
}
}

Реализация этого интерфейса

namespace ErrorReportingService
{
public class ErrorReporting : IErrorReporting
{
public string PostErrorInfo(string info)
{
System.IO.File.AppendAllText(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "\\App_Data\\reports.txt",
"\n\n"+info);
return "ok";
}
}
}

Теперь напишем обработчики исключений для вставки в тело Вашей программы и подключение их при запуске программы — класс Program может выглядеть вот так:

static class Program
{
public static void SendDataAndShowMessage(System.Exception ex)
{
string text = DateTime.Now.ToShortDateString()+" "+
DateTime.Now.ToLongTimeString()+"\n"+
ex.ToString();// тут хорошо бы его отформатировать, скажем, в XML, добавить данные о времени, дате, железе и софте...
try
{
(new ErrorReportingService.ErrorReportingClient()).PostErrorInfo(text);
MessageBox.Show("Произошла ошибка. Информация об ошибке отправлена разработчику.\n\n" + text, "Ошибка программы", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (System.Exception ex2)
{
MessageBox.Show("Произошла ошибка. Информацию об ошибке отправить разработчику не удалось.\n\n" + text, "Ошибка программы", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public static void AppDomain_CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
SendDataAndShowMessage((Exception)e.ExceptionObject);
Application.Exit();
}
public static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
SendDataAndShowMessage(e.Exception);
//на этом месте можно предложить "попытать продолжить работу" (ну-ну) или закрыть приложение
Application.Exit();
}
[STAThread]
static void Main()
{
//Установка обработчика
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(Program.AppDomain_CurrentDomain_UnhandledException);
Application.ThreadException +=
new System.Threading.ThreadExceptionEventHandler(Program.Application_ThreadException);

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

Вот и весь код.

Это действительно очень простая задача. Конечно, гораздо интереснее помещать информацию об ошибках в настоящую базу данных, сделать нормальный веб-интерфейс к этой базе, использовать надежную аутентификацию, а, возможно, и шифрование данных при отправке отчетов об ошибках, но это уже выходит за рамки данной хабростатьи.

Морально-этическая сторона вопроса

С одной стороны, многих беспокоит, что в отчет об ошибке попадут их персональные данные, в связи с чем, правилом хорошего тона является демонстрация пользователю полного текста отчета об ошибке до его отправки, вывод запроса «можно ли отправить сообщение об ошибке?» и тому подобное. Увы, подавляющее большинство моих знакомых утверждают, что ни разу в жизни не нажали кнопку «да, отправить» при появлении соответствующего запроса.

С другой стороны, средний пользователь, как правило, ничего не понимает в «этих ваших отчетах» и лучше его не спрашивать, а уведомить о том, что «идет отправка отчета об ошибке» и спокойно слать. Конечно, во избежание претензий стоит описать такое поведение в лицензионном соглашении и, пожалуй, следует добавить возможность отключения отправки отчетов об ошибках, (чтобы не потерять страдающих паранойей пользователей).

Надеюсь, описанное выше поможет Вам в работе и облегчит организацию тестирования и сбора информации об ошибках.

http://habrahabr.ru/sandbox/20005/

Share