別のブレークパッドサーバー。 パート1

前四半期、クラッシュを処理するためのMVPサービスを作成しました。 MozillaのSocorroに類似していますが、その要件を考慮しています。 サービスコードはリファクタリングとして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
      
      





クラッシュレポートを取得するには、breakpadからminidump_stackwalkユーティリティを使用できます。







 $ minidump_stackwalk path_to_crash base_dir
      
      





このユーティリティは、人間が読める形式と機械が読める形式の両方で出力できます。







しかし、それはあまり便利ではありません。 Mozilla Socorroには、jsonを発行するstackwalkerユーティリティが含まれてます( crash-stats.mozilla.comの例)







Emscripten



グローバルwindow.onerrorハンドラーを使用してクラッシュをキャッチできます。 ブラウザによって、メッセージは異なります。







 Uncaught abort() at Error at jsStackTrace (http://...) at Object.abort (http://...) at _abort (http://...) at _free (...) at __ZN2F28ViewMain13setFullscreenEb (...) at Array.__ZNSt3__210__function6__funcIZN2F28ViewMainC1EvE4__13NS_9allocatorIS4_EEFbPNS2_9UIElementEEEclEOS8_ (http://...) at __ZNKSt3__28functionIFllEEclEl (http://...) at __ZNK2F26detail23multicast_function_baseIFbPNS_9UIElementEENS_24multicast_result_reducerIFbRKNSt3__26vectorIbNS6_9allocatorIbEEEEEXadL_ZNS_10atLeastOneESC_EEEEiLin1EEclERKS3_ (http://...) at __ZN2F29UIElement14processTouchUpERKNS_6vec2_tIfEE (http://...) 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://... abort@http://... _abort@http://... _free@http://... __ZN2F28ViewMain13setFullscreenEb@http://... __ZNSt3__210__function6__funcIZN2F28ViewMainC1EvE4__13NS_9allocatorIS4_EEFbPNS2_9UIElementEEEclEOS8_@http://... __ZNKSt3__28functionIFllEEclEl@http://... __ZNK2F26detail23multicast_function_baseIFbPNS_9UIElementEENS_24multicast_result_reducerIFbRKNSt3__26vectorIbNS6_9allocatorIbEEEEEXadL_ZNS_10atLeastOneESC_EEEEiLin1EEclERKS3_@http://... __ZN2F29UIElement14processTouchUpERKNS_6vec2_tIfEE@http://... __ZN2F29UIElement17processTouchEventERNSt3__26vectorINS1_4pairIPS0_NS_6vec2_tIfEEEENS1_9allocatorIS7_EEEEjNS_15UI_TOUCH_ACTIONE@http://... __ZN2F29UIElement5touchEffNS_15UI_TOUCH_ACTIONEj@http://... __ZN2F213MVApplication5touchEffNS_15UI_TOUCH_ACTIONEj@http://... at stackTrace (http://... glengine.js?v=1485951440.84:360629:11 __ZN2F27UIInput7processEj@http://... __Z14on_mouse_eventiPK20EmscriptenMouseEventPv@http://... dynCall_iiii@http://... dynCall@http://... handlerFunc@http://... jsEventHandler@http://... If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.
      
      





コンパイル中に-gスイッチを使用すると、このようなメッセージが作成されます。 このプロジェクトでは、出力asm.jsコードのサイズは3倍大きくなっています。 したがって、 --emit-symbol-mapを使用します

出力は、単純なキーの文字を含むファイルです:値の形式:







 $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://...) at stackTrace (http://...) at Object.abort (http://...) at _abort (http://...) at Eb (http://...) at Xc (http://...) at rc (http://...) at Array.$c (http://...) at Pc (http://...) at Array.Wb (http://...) If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.
      
      





呼び出しスタックを取得するために、補助ユーティリティが作成されました。







webstackwalker
 #include <map> #include <set> #include <list> #include <regex> #include <fstream> #include <iostream> #include <cxxabi.h> #include <rapidjson/writer.h> #include <rapidjson/stringbuffer.h> namespace { struct Deleter { void operator()(char *data) const { free((void *) data); } }; using CharPtr = std::unique_ptr<char, Deleter>; } std::string demangle(const std::string &mangledName) { int status = 0; int shift = 0; if (mangledName[1] == '_') { shift = 1; } CharPtr realname(abi::__cxa_demangle(mangledName.data() + shift, 0, 0, &status)); if (status == 0) { return std::string(realname.get()); } else { if (mangledName[0] == '_') { const auto str = mangledName.substr(1, mangledName.size() - 1); int status = 0; CharPtr realname(abi::__cxa_demangle(str.data(), 0, 0, &status)); if (status == 0) { return std::string(realname.get()); } return mangledName; } return mangledName; } } void printUsage() { std::cout << "webstackwalker crash_dump symbol_file" << std::endl; } std::map<std::string, std::string> SYMBOL_MAP; void readSymbols(const std::string &path); void flushUnParseLine(const std::string &line); int main(int argc, char **argv) { if (argc < 2) { printUsage(); return 1; } readSymbols(std::string(argv[2])); const std::string inputFile(argv[1]); std::ifstream input(inputFile); const std::regex re("^(?:\\s{4}at\\s){0,1}(?:Array\\.){0,1}([\\w\\d\\$]+)(?: \\(|@).+\\){0,1}"); rapidjson::StringBuffer buffer; rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); writer.StartArray(); const std::set<std::string> skip = {"jsStackTrace", "stackTrace", "abort"}; while (!input.eof()) { std::smatch match; std::string line; std::getline(input, line); if (std::regex_search(line, match, re)) { if (skip.count(match[1])) { continue; } auto iter = SYMBOL_MAP.find(match[1]); std::string function; if (iter != SYMBOL_MAP.cend()) { function = demangle(iter->second); } else { function = demangle(match[1]); } writer.String(function.c_str()); } } writer.EndArray(); std::cout << buffer.GetString() << std::endl; return 0; } void readSymbols(const std::string &path) { std::ifstream input(path); if (!input.is_open()) { std::cerr << "Can't open symbols file: " << path << std::endl; exit(2); } const std::regex re("^([\\d\\w$]+):([\\d\\w]+)$"); while (!input.eof()) { std::smatch match; std::string line; std::getline(input, line); if (std::regex_search(line, match, re)) { SYMBOL_MAP[match[1]] = match[2]; } } }
      
      





ユーティリティはデマングルを使用して変換します:







 _ZN2F211recognizers24UIPinchGestureRecognizer6updateEPNS_9UIElementERKNS_6vec2_tIfEEj
      
      











 F2::recognizers::UIPinchGestureRecognizer::update(F2::UIElement*, F2::vec2_t<float> const&, unsigned int)
      
      





UI



Elasticsearchの秋のレポートを追加するので、弾性コンテンツの視覚化と分析の手段として初めてKibanaを使用します。







kibanaを使用する場合、ボックスから取得します。









ダッシュボードグループは、プラットフォーム、ビルド、署名ごとにクラッシュします。 フィルターシステムを使用すると、次のことがわかります。









適用されたフィルターを検出タブに移動すると、秋の詳細を確認できます。 判明したように、kibanaはモジュール構造を備えているため、機能を拡張できます。 シンプルなプラグインが作成され、レポートのレンダリングが追加されました。これは、標準のテーブルやJSonよりもはるかに便利です。


























All Articles