☕️ Как я баг исправил, который не могли найти два годаРешил попробовать новый формат постов, где буду иногда делиться опытом решения интересных и нестандартных задач.
Я всегда ищу интересные задачи: помогаю коллегам на работе; менти; беру небольшие подработки, если мне интересен проект. Так я улучшаю карму, повышаю навыки, выходя за границы привычных задач и, конечно, зарабатываю
🤡На одном из сложных проектов, который я помогаю делать, крайне неприятный редкий баг, которому уже несколько лет. Зависания главного потока, что воспроизводился раз в месяц у разработчиков. Но, по закону подлости, раз в день у директоров, что сильно пекло им пятую точку. Да и разрабы, которые воспроизводили проблему, не понимали в чем суть
Какие есть решения в этом случае? Предыдущие разработчики старались пойти решением в лоб: перебирали устройства и ждали пока у них воспроизведения проблемы на
их окружении. Что, конечно же, приводило к критичному оттягиванию сроков исправления.
Я считаю такой подход немного неэффективным и долгим. К тому же это мессенджер. Его флоу нелинейные. Многое зависит от типа юзера, его активности, чатов и многих других эвентов. Одним перебором устройств не решишь эту проблему. Поэтому мне пришло очевидное решение, которое часто используется в крупных компаниях.
🌟 Добавить логи. Зачем мне стараться воспроизвести редкий баг, если я сделаю систему трекинга, которая при воспроизведении у кого-то, даст мне полезную информацию самым быстрым способом.
Окей. С логами понятно, но что будем трекать?
Если зависание главного потока, то здесь на помощь приходит Watchdog. О стандартном механизме мы уже когда-то писали, но я напомню. Watchdog — это механизм, который помогает отслеживать проблему блокировки потока. Я же написал свою реализацию, чем-то похожую на эту.
Так. Мы научились понимать когда main thread завис. Теперь нам нужно как-то понимать что
стало причиной его зависания.
Тут тоже все тривиально. Мы берем Stack Trace и записываем его в файл и отправляем в Firebase. Стандартный
Thread.callStackSymbols
мне не подходил, так как не давал понятной информации. Да и мне хотелось сделать универсальный механизм, который может принимать любой поток и получать его колстэк.
Опять же для вдохновения я взял код из похожей библиотеки и переделал его под себя. Теперь мы легко можем видеть до какой точки исполнения мы дошли перед зависанием приложения.
Дополнительно сделал экран в дебаг меню, который записывает в формате "Date -> Thread.callstack" логи. Чтобы можно было сразу мне отправить лог, как только получили зависание.
После релиза, спустя десяток минут, я получил первый лог. В нем сразу была показана причина зависания. Это был мертвый код, давно ушедшего разраба. Связан он был с расширения кэша картинок для либы SDWebImage
💎 Вывод. Задача была несложная, но требовала ряда компетенций, которые формируются с опытом и насмотренностью. Это понимание работы потоков, специфики кодовой базы и основ логирования.
Не имея этих базовых навыков можно очень сильно накопить раздражение у своих клиентов.
Делитесь своими метриками, которые помогли решить редкие баги