Еще один breakpad сервер. Часть 1 |
В прошлом квартале делали MVP сервиса по обработке крешей. Аналог Socorro от Mozilla, но с учетом своих требований. Код сервиса будет выкладываться на GitHub по мере рефакторинга. Утилиты, о которых пойдет речь в этой статье, доступны тут.
У нас были следующие требования:
Содержание:
В составе breakpad есть утилита извлекающая файлы символов из elf/pdb. Вот описание формата файла. Это текстовый файл, но нас интересует первая строка имеет формат MODULE operatingsystem architecture id name
, у нас она выглядит так:
MODULE windows x86 9E8FC13F1B3F448B89FF7C940AC054A21 IQ Option.pdb
MODULE Linux x86_64 4FC3EB040E16C7C75481BC5AA03EC8F50 IQOption
MODULE mac x86_64 B25BF49C9270383E8DE34560730689030 IQOption
Далее эти файлы следует расположить в особом порядке: base_dir/name/id/name.sym
, выглядит это так:
base_dir/IQ Option/9E8FC13F1B3F448B89FF7C940AC054A21/IQ Option.sym
base_dir/IQOption/4FC3EB040E16C7C75481BC5AA03EC8F50/IQOption.sym
base_dir/IQOption/B25BF49C9270383E8DE34560730689030/IQOption.sym
Для получения отчета о падения можно воспользоваться утилитой minidump_stackwalk из поставки breakpad:
$ minidump_stackwalk path_to_crash base_dir
Данная утилита может выводить как в человеко читаемым виде так и в machine-readable формате.
Но это не очень удобно. В Mozilla Socorro входит утилита stackwalker которая выдает json(пример на crash-stats.mozilla.com)
Ловить падения можно через глобальный обработчик window.onerror. В зависимости от браузера, сообщения будут отличаться:
Uncaught abort() at Error
at jsStackTrace (http://localhost/traderoom/glengine.js?v=1485951440.84:1258:13)
at Object.abort (http://localhost/traderoom/glengine.js?v=1485951440.84:776417:44)
at _abort (http://localhost/traderoom/glengine.js?v=1485951440.84:9914:22)
at _free (http://localhost/traderoom/glengine.js?v=1485951440.84:232487:38)
at __ZN2F28ViewMain13setFullscreenEb (http://localhost/traderoom/glengine.js?v=1485951440.84:533436:2)
at Array.__ZNSt3__210__function6__funcIZN2F28ViewMainC1EvE4__13NS_9allocatorIS4_EEFbPNS2_9UIElementEEEclEOS8_ (http://localhost/traderoom/glengine.js?v=1485951440.84:658644:2)
at __ZNKSt3__28functionIFllEEclEl (http://localhost/traderoom/glengine.js?v=1485951440.84:673406:75)
at __ZNK2F26detail23multicast_function_baseIFbPNS_9UIElementEENS_24multicast_result_reducerIFbRKNSt3__26vectorIbNS6_9allocatorIbEEEEEXadL_ZNS_10atLeastOneESC_EEEEiLin1EEclERKS3_ (http://localhost/traderoom/glengine.js?v=1485951440.84:476310:12)
at __ZN2F29UIElement14processTouchUpERKNS_6vec2_tIfEE (http://localhost/traderoom/glengine.js?v=1485951440.84:471241:9)
If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.
uncaught exception: abort() at jsStackTrace@http://localhost/traderoom/glengine.js?v=1485951440.84:1258:13
stackTrace@http://localhost/traderoom/glengine.js?v=1485951440.84:1275:12
abort@http://localhost/traderoom/glengine.js?v=1485951440.84:776417:44
_abort@http://localhost/traderoom/glengine.js?v=1485951440.84:9914:7
_free@http://localhost/traderoom/glengine.js?v=1485951440.84:232487:38
__ZN2F28ViewMain13setFullscreenEb@http://localhost/traderoom/glengine.js?v=1485951440.84:533436:2
__ZNSt3__210__function6__funcIZN2F28ViewMainC1EvE4__13NS_9allocatorIS4_EEFbPNS2_9UIElementEEEclEOS8_@http://localhost/traderoom/glengine.js?v=1485951440.84:658644:2
__ZNKSt3__28functionIFllEEclEl@http://localhost/traderoom/glengine.js?v=1485951440.84:673406:9
__ZNK2F26detail23multicast_function_baseIFbPNS_9UIElementEENS_24multicast_result_reducerIFbRKNSt3__26vectorIbNS6_9allocatorIbEEEEEXadL_ZNS_10atLeastOneESC_EEEEiLin1EEclERKS3_@http://localhost/traderoom/glengine.js?v=1485951440.84:476310:12
__ZN2F29UIElement14processTouchUpERKNS_6vec2_tIfEE@http://localhost/traderoom/glengine.js?v=1485951440.84:471241:9
__ZN2F29UIElement17processTouchEventERNSt3__26vectorINS1_4pairIPS0_NS_6vec2_tIfEEEENS1_9allocatorIS7_EEEEjNS_15UI_TOUCH_ACTIONE@http://localhost/traderoom/glengine.js?v=1485951440.84:468018:35
__ZN2F29UIElement5touchEffNS_15UI_TOUCH_ACTIONEj@http://localhost/traderoom/glengine.js?v=1485951440.84:598797:8
__ZN2F213MVApplication5touchEffNS_15UI_TOUCH_ACTIONEj@http://localhost/traderoom/ at stackTrace (http://localhost/traderoom/glengine.js?v=1485951440.84:1275:12)
glengine.js?v=1485951440.84:360629:11
__ZN2F27UIInput7processEj@http://localhost/traderoom/glengine.js?v=1485951440.84:273450:6
__Z14on_mouse_eventiPK20EmscriptenMouseEventPv@http://localhost/traderoom/glengine.js?v=1485951440.84:446769:5
dynCall_iiii@http://localhost/traderoom/glengine.js?v=1485951440.84:767912:9
dynCall@http://localhost/traderoom/glengine.js?v=1485951440.84:501:14
handlerFunc@http://localhost/traderoom/glengine.js?v=1485951440.84:2526:30
jsEventHandler@http://localhost/traderoom/glengine.js?v=1485951440.84:2429:11
If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.
Такое сообщение создаются если при компиляции использовать ключ -g. На нашем проекте размер выходного asm.js кода раза в 3 больше. Поэтому у нас используется --emit-symbol-map.
На выходе получаем файл с символами в простом формате key:value:
$cc:__ZNSt3__210__function6__funcIZN2F28ViewMain17animateLeftPannelEbE4__36NS_9allocatorIS4_EEFvvEEclEv
f8d:__ZNKSt3__210__function6__funcIZN2F218MVMessageQueueImpl4sendINS2_26EventSocialProfileReceivedEJiEEEvDpRKT0_EUlvE_NS_9allocatorISA_EEFvvEE7__cloneEPNS0_6__baseISD_EE
Z1:__ZN2F211recognizers24UIPinchGestureRecognizer6updateEPNS_9UIElementERKNS_6vec2_tIfEEj
а сообщения теперь имеют вид:
Uncaught abort() at Error
at jsStackTrace (http://10.10.1.247:8080/main.js:1:17947)
at stackTrace (http://10.10.1.247:8080/main.js:1:18118)
at Object.abort (http://10.10.1.247:8080/main.js:12:6480)
at _abort (http://10.10.1.247:8080/main.js:1:37453)
at Eb (http://10.10.1.247:8080/main.js:5:22979)
at Xc (http://10.10.1.247:8080/main.js:5:53767)
at rc (http://10.10.1.247:8080/main.js:5:47782)
at Array.$c (http://10.10.1.247:8080/main.js:5:54228)
at Pc (http://10.10.1.247:8080/main.js:5:52663)
at Array.Wb (http://10.10.1.247:8080/main.js:5:40899)
If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.
Для получения получения стека вызовов была написана вспомогательная утилита:
#include
Утилита использует demangle, для преобразования:
_ZN2F211recognizers24UIPinchGestureRecognizer6updateEPNS_9UIElementERKNS_6vec2_tIfEEj
в
F2::recognizers::UIPinchGestureRecognizer::update(F2::UIElement*, F2::vec2_t const&, unsigned int)
Отчеты о падении складываем в Elasticsearch, поэтому на первое время используем Kibana, как средство визуализации и анализа содержимого эластика.
При использовании кибаны получаем из коробки:
Дашборды группируют креши по платформе, билду, сигнатуре. Система фильтров позволяет узнать:
Примененные фильтры можно перенести на вкладку discover, где можно посмотреть подробности падения. Как оказалось кибана имеет модульную структуру, что позволяет расширять её возможности. Был написан простой плагин, добавляющий рендер отчета, что намного удобней стандартного Table и JSon.
Комментировать | « Пред. запись — К дневнику — След. запись » | Страницы: [1] [Новые] |