Search
Write a publication
Pull to refresh

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

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

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

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

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


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

Как правило, для передачи отчета используется протокол 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());
}
}

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


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

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


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

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

Надеюсь, описанное выше поможет Вам в работе и облегчит организацию тестирования и сбора информации об ошибках.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.