Как известно, программ без ошибок не бывает, и существует очень много инструментов и подходов, призванных улучшить качество выпускаемых приложений, от юнит тестов до анализаторов кода. Однако, даже если использовать все их одновременно, никто не даст гарантии, что ваши приложения лишены каких-либо ошибок. И если проблемы, возникающие во время разработки и тестирования, видны нам сразу, ну или почти сразу, и мы имеем возможность получить подробную информацию, что произошло и оперативно это исправить, то ошибки после выпуска, происходящие на пользовательской стороне, являются более коварными.
Самое главное, что, скорее всего, вам о них просто не сообщат. Как часто вы отправляли ошибки в Microsoft, когда вас об этом просили? :) Пользователи, как правило, либо просто перезапускают приложение, матерятся и продолжают пользоваться дальше, либо удаляют его полностью. Если вам повезет, и о падении вам сообщат, то зачастую это выглядит как-то так:
и это не вносит абсолютно никакой ясности в понимание проблемы. В результате у пользователей формируется негативный опыт от использования вашей программы, а вы не имеете никакой возможности что-то с этим сделать.
Ну а коль на пользователей надежды нет, то придется брать дело в свои руки. Для начала мы знаем, что все исключительные ситуации в своих программах мы можем обработать. Например, в .NET мы можем повесить глобальный обработчик всех эксепшенов. Самое простое, что можно сделать дальше, это писать в лог все эксепшены, которые нам прилетают в этот обработчик. Это уже хоть что-то.
Однако, просто лог сам себя не отошлет, и нам приходится ждать сообщения от пользователя, чтобы узнать о проблеме и попросить его этот лог отправить, а это лишняя трата времени, да и вообще, пользователь может и вовсе не написать. Как вариант, мы можем отправлять наш лог сами по электронной почте, но страшно представить, во что превратится наш почтовый ящик, если нам придет достаточно большое количество оповещений. А это достаточно реально на крупных проектах. Да и вообще, разбирать, что там написано в текстовом лог файле на 100500 строк, не совсем приятное занятие.
В результате мы приходим к тому, что самое адекватное решение — это сервис, который будет крутиться в облаке и принимать информацию о произошедших ошибках, обрабатывать ее, структурировать и показывать нам через web интерфейс в удобном виде. Ну и почему бы нам для себя подобный сервис не написать?
Изначально мы сделали простейший сборщик падений в наших демках, чтобы получать данные об этих падениях, и на их основании исправлять проблемы в наших компонентах, тем самым улучшая их качество. Это были всего лишь кол-стек и имя модуля демки, однако, мы быстро поняли, что этих данных недостаточно, и стали их расширять. В результате в данный момент мы собираем очень подробную информацию об окружении, где произошла ошибка, начиная со списка загруженных библиотек и версии студии и фреймворка, и заканчивая версией ОС и текущей установленной культурой. При этом, если нам надо, мы всегда можем добавить любую дополнительную информацию через механизм CustomData. Для примера, можно посмотреть на тестовый репорт.
Когда информации для нахождения проблемных мест стало достаточно, мы столкнулись с тем, что порой репортов приходит очень много. Ведь, если проблема достаточно тривиальна, то велика вероятность, что много пользователей на нее наткнется. А в такой ситуации мы получаем по репорту от каждого из них. В результате мы имеем кучу репортов, которые если не идентичны, то крайне похожи:
Понятное дело, что работать со всем этим, мягко говоря, затруднительно, плюс, среди всех этих одинаковых репортов могут потеряться и уникальные, оповещающие о других проблемах. Чтобы избавиться от этого, мы реализовали поиск дубликатов по определенному набору ключевых полей и схлопывание их в один репорт:
Да, так уже гораздо лучше.
Однако, помимо дубликатов, во входящих оказывалось достаточно много репортов, которые нам просто не интересны, например, это могут быть репорты об уже пофикшеных проблемах. Это подтолкнуло нас к задаче реализации автоматического игнорирования входящих репортов по каким-либо условиям, а условий нам дали уйму: и чтобы по версии можно было игнорировать, и чтобы по ключевым словам в колстеке, и чтобы по определенным строкам колстека, и чтобы ошибка без наших компонентов в колстеке нам не приходили и т.д и т.п. В результате мы выделили 4 основных вида правил игнора, и это покрыло все наши задачи. Вообще, данная тема заслуживает отдельной статьи, поэтому здесь я приведу ссылку на документацию, чтобы можно было составить общее впечатление об этом механизме: Ignoring Filters
В процессе работы с сервисом мы нашли ему еще одно необычное применение: он отлично может помогать отделу поддержки. Нередко пользователи пишут, что у них произошла какая-то проблема, но она воспроизводится только на машине их пользователя, и подебажить или получить какую-то подробную информацию о самой ошибке возможности нет. Или, например, ошибки происходят на программах, которые ограничены в правах и не могут записать лог файл. Во всех этих ситуациях нам успешно помогает Logify, ибо сбор данных о падениях на развернутых приложениях и есть его основная задача.
В результате Logify был внедрен во множество наших продуктов, и сейчас приносит ощутимую пользу. В процессе развития Logify уже явно перестал быть просто проектом для внутреннего пользования, и мы решили выпустить его как отдельный сервис. Он был причесан и представлен публике с переделанным UI сначала в виде бета тестирования, и в данный момент он уже полноценно запущен в продакшен. Так что кому интересно, приглашаю попробовать: Logify. Клиенты доступны на GitHub.
Автор: Mirimon