モバイル向けセッションリプレイが一般公開!ユーザー体験を簡単に改善する方法を徹底解説

Article by: Jasmin Kassas, Sarah Guthals   モバイル向けセッションリプレイがついに一般公開されました。 セッションリプレイの偉大さについて大袈裟に語ることもできますが、今回は趣向を変えて、A…I…があなたのために一句詠みます。   画面が固まる 開発者はため息 リプレイ明かす犯人は…… .addListener 忘れていた   俳句になっているかどうかはさておき、要するに Sentry はユーザーの操作を動画のように再現できるため、どのデバイスで問題が発生しているのか、他の端末を使って再現確認しなくても、不具合の箇所や体験が途切れているポイントをすぐに確認できます。 今どき iPhone 12 Mini が家に転がっている人なんてそうそういませんよね?少なくとも、私たちの手元にはありません。あなたのところはいかがですか? さて、本題に移ります。もし実際の問題をセッションリプレイでどのようにデバッグできるのか知りたい方は、この先をご覧ください。そうでない場合は、iOS、Android、Flutter、React Nativeのセットアップ方法をまとめたドキュメントをぜひご覧ください。   セッションリプレイでどう解決するのか 奇妙なバグの通知を受け取り、クラッシュダンプを見てもなぜユーザーがその状態に至ったのかわからなかった… 開発者であればそんな経験はよくあるでしょう。 その度に状態を把握するためランダムなログを無闇に差し込み、それを再リリースしてユーザーにアップデートを強制するも的が外れてまたやり直し… そんなことを繰り返していませんか? しかしセッションリプレイならそんな手間を省くことができます。エラーや操作の流れも含めて確認することができるため、ユーザーがエラーに至るまでに何をしていたのかが正確に確認できます。 ここからは、過去6ヶ月間のベータ期間に Sentry のお客様が実際に体験された事例をご紹介していきます。   モバイルアプリの状態を正確に把握する モバイルアプリは実にさまざまな形式があり、その多くは複雑なUIフローや状態を保持しています。セッションリプレイを使用することで、アプリがどのような状態なのかを正確に把握することができ、問題の原因になっているUIフローを見つけることができます。 以下の画像のように、バックエンドのエラーも含めて全体像を掴むのにとても役立ちました。 セッションリプレイがなければ、問題が起きた時の再現手順を特定するのに不要な手間がかかります。これは複雑な条件(手順や状態)をデバッグする際に特に役立ちます。   バックエンドのエンドポイントエラーにも対応 ユーザーがどのような操作をしていたか分からない状態で、サーバーのエラーをデバッグするのは本当に骨が折れます。 しかしセッションリプレイを使えば、エンドポイントに到達するまでのユーザー操作をそのまま見ることができます。またタイムラインビューを使うことでサーバーエラーが発生した正確なタイミングに一瞬でジャンプすることもできます。 とあるお客様の事例を挙げると、アプリがフォアグラウンドに戻った際にプロフィールを更新しようとして、400エラーが発生していたことがありました。 原因はその時点でユーザーがログアウトしていたからでした。修正はシンプルで、今では AppState イベントを監視しユーザーがログアウト状態ならすぐにログイン画面へリダイレクトするように修正しています。   モバイル特有の問題も見逃さない セッションリプレイのパンくずリストを使えば、ユーザーの操作履歴とともにデバイスに関する重要な情報も取得できます。どの瞬間に、どのような操作や理由によって問題が起きたのかを正確に特定します。 例えば「コードに問題はなかったのに、ネットワークが突然切れてオフラインになったこと」が原因だった(調査する開発者にとっては、これほど最悪なケースはありません)としても、セッションリプレイを見れば一目瞭然です。 このパンくずリストは、従来のログでは見えない部分に光を当ててくれる貴重な手掛かりになります。   モバイル向けセッションリプレイ導入手順 セッションリプレイをアプリに組み込むためのステップは以下の通りです。 […]

モバイル向けセッションリプレイを発表 – オープンβ開始

iOS、Android、React Native用のSession Replayがオープンβになりました。 もしあなたがSession Replayをすでに知っているなら、素晴らしいことです。 リンクをクリックし、あなたのSDKをアップデートすれば、あなたのユーザーが怒りを引き起こすような問題を経験している場所をビデオのように再現してくれるようになります。 もし私が何を言っているのか分からないなら、なおさらです。お話をしましょう。 クラッシュ、悪ふざけ、一般的な無反応は、⭐1つのレビューにつながり、人々はアンインストールし、成長ハックを売り込むPMにつながり、誰もそれを望んでいません。このような悪ふざけを先回りするにはどうすればいいのでしょうか? 昨年、私たちは、Webアプリのユーザーセッションの完全匿名化されたビデオのような複製をキャプチャする機能 – Webベースのアプリケーションのためのセッションリプレイ – を発表しました。現在、40,000を超えるチームが、チェックアウトの不具合、ページの読み込みの遅さ、予期せぬクラッシュなど、あらゆるデバッグにこの機能を使用しています。 何が問題なのかを実際に見ることで、デバッグがより簡単になるとは誰が考えたでしょうか???? モバイル開発者(GitHubで400以上のアップヴォートを提供し、500以上のアーリーアダプターのサインアップに貢献した)もこの機能を望んでいます。 だから、私たちはここにいます。モバイル向けセッション・リプレイは現在オープンベータ版で、アーリーアダプターは無料で使用できます。 コードとUXのギャップを埋める モバイル向けセッションリプレイは、アプリ上のユーザーセッションを視覚的に再現することで、モバイルアプリケーションの可視性を拡大します。これにより、いつ、どこで、どのようにエラーがアプリに影響を及ぼしているかを、自分で再現したり顧客と会話したりすることなく理解することができます。リプレイを使用すると、タップやピンチによるズームなどのジェスチャーがリプレイビューに含まれるため、ユーザーとのインタラクションをより深く理解し、アプリのどこで問題が発生しているかを特定することができます。リプレイには、デバイスタグ、ネットワークリクエストの詳細、スローされた例外などのデバッグコンテキストも含まれています。 当社の全製品と同様に、セッションリプレイはSentryワークフローに統合されています。Issue Detailsでスタックトレースを検査しながら関連するリプレイを見たり、User Feedbackでバグレポートを提出したユーザからのリプレイを見たりすることができます。また、サンプリング設定を構成して、エラーが発生したときのみリプレイをキャプチャし、データのインジェストを減らすことができます。また、UIへの影響やユーザーの反応(アプリを閉じたかどうかなど)によって、問題の深刻度を評価することもできます。 モバイルエラーの根本原因を確認する モバイル用のSentryのセッションリプレイを使用すると、ユーザーがエラーに遭遇したときにサンプリングセッションを優先するオプションがあります。 これは、クラッシュが発生したときに、その特定のエラーに遭遇した実際のユーザーからの関連するリプレイが、問題の詳細ページで関連するSentryの問題に便利にリンクされていることを意味します。エラーの発生前、発生中、発生後に、OSのバージョンや名前などの有用なコンテキストとともに何が起こったかを見ることで、エラーがどのように発生し、ユーザーにどれほどの影響を与えたかを素早く特定することができます。さらに、エラー時のサンプリングにより、必要なデータを待つ時間や、イベントクォータを監視する不安も軽減されます。 ゲーミフィケーションを使用し、UXに重点を置き、素晴らしいイラストやアニメーションがある、派手なライフスタイル・アプリを開発しているとしましょう。アプリケーション・パフォーマンス・モニタリング(APM)製品は、サードパーティのライブラリでクラッシュが発生していることを警告します。この問題を調査し解決するためにセッションリプレイを使用する方法を説明します。 エラーを特定する: エラー追跡システムで、あなたはエラーメッセージ “NullPointerException in run_animation() “で繰り返し起こるクラッシュを分析します。スタック・トレースは、あなたが使っているサードパーティのアニメーション・ライブラリを指していますが、あなたはその意味を理解していません。 関連するセッションのリプレイを探す: リプレイをフィルタリングして、この特定のクラッシュに関連するものだけを表示します。 リプレイを見る: リプレイの1つを選択すると、達成を祝う画面から始まり、達成ポイントが与えられます。かなり長いです)リワードアニメーションが再生される間に、ユーザーは「次へ」ボタンをタップし、アプリがクラッシュします。 コンソールログを調べる: コンソールログの中で、アニメーションライブラリから「onAnimationCancelled」コールバックが呼び出されていることに気づきます。 このコールバックを実装しそこねていたことに気づきます。対策として、アニメーションの時間も短くします。アップデートをデプロイした後、アプリをアップデートするにつれてクラッシュの数が減少していることを監視します。 この例では、Session Replayにより、クラッシュに至ったユーザーアクションを正確に可視化し、エラーの根本原因としてアニメーションライブラリのコールバックの欠落を特定し、この問題を解決するために的を絞った修正を実装することができます。セッション リプレイがなければ、イベントの正確なシーケンスを理解し、このクラッシュの原因を特定することははるかに困難であったでしょう。 アプリのペインポイントの特定 誤解を招くラベル、リンク切れ、パーミッションの問題 – ユーザーが例外を発生させない問題にぶつかることがありますが、それでもユーザー体験に影響を与えます。セッションリプレイは、ユーザーがどこで立ち往生したり、アプリから脱落したりするかを確認することで、アプリ内でこれらのペインポイントが発生する場所を特定するのに役立ちます。 例えば、モバイル e コマースアプリを開発していて、チェックアウト中にアプリが反応しなくなるという悪いレビューが増えているとします。この問題を調査し解決するためにセッションリプレイをどのように利用できるかを説明しましょう。 アプリのパフォーマンスに問題があると思われます。しかし、パフォーマンスKPIはまだ良好で、APM製品はチェックアウト画面で問題を示しません。 関連するセッション・リプレイを見つける:リプレイをフィルタリングして、チェックアウト画面に関連するリプレイのみを表示し、継続時間の長いリプレイにも注目します。 リプレイを見る:リプレイの1つを選択し、ユーザーのアクションを観察します。ユーザーがチェックアウトページの「次へ」ボタンをタップし、サーバーへのAPIコールが開始されるのを確認します。 ネットワークリクエストを確認する: ネットワーク・タブを調べると、APIコールが正常かつ適切な時間で終了していることがわかります。これで、これが根本的な原因ではないことがわかりました。 パンくずを調べる:アプリのUI状態管理でごく最近の状態変更があり、APIコールが返された後に状態が衝突してUIが更新されないことに気づきます。この時点で、ユーザーは激怒してクリックし、最終的にアプリを終了します。 修正と検証:UI状態管理のバグを処理するための修正を実装します。アップデートをデプロイした後、後続のセッションリプレイを監視して、ユーザーがチェックアウトプロセス中に進めるようになったことを確認します。 […]

Trace Viewを使用してAPIコールを22.3秒短縮した方法

Dan Mindruはフロントエンド開発者兼デザイナーで、モーニング・メーカー・ショーの共同司会者でもあります。 現在、PageUI、Clobbr、CronToolなどのアプリケーションを開発しています。 開発者として、遅いAPIほどイライラさせられるものはありません。 コードが動くことは分かっていても、それがもう良いユーザー体験にならないことは分かっているはずです。 私にもそのようなことがあり、2週間ほど見て見ぬふりをしていました。 しかししばらくすると、いくつかの問題は個人的なものになります。 問題は、どこから手をつければいいのか見当もつかなかったことです。 Sentryの新しいトレース・ビューを発見するまでは。 もちろん、トレースこそ、パフォーマンス低下の根本原因を突き止めるために必要なものです。では、このトレース・ビューのトリックひとつで、APIコールのロード時間を22.3秒短縮した方法をお教えしましょう。 この投稿で詳細を説明し、トレースを使って自分のAPIコールのボトルネックを見つける方法を紹介します。うまくいけば、あなた自身のレスポンスタイムを数秒短縮できるかもしれません。さあ、始めましょう! トレースビューとは? ほとんどの人は、Sentryのエラー監視機能を知っています。しかし、それだけではありません。実際、Sentryはパフォーマンスのボトルネックを見つけるのにも役立ちます! Sentryのセットアップがいかに簡単かは前にも述べました。その後、Sentryはパフォーマンス・メトリクスも収集してくれます。 トレース・ビューはその重要な一部で、トランザクションとスパンを滝のように可視化します。ご想像の通り、これはアプリケーションのパフォーマンスに影響を与える遅延、関連するエラー、ボトルネックの特定に役立ちます。 次に、私のユースケースでこれをどのようにセットアップしたかをお見せしましょう。 面白いことに、Sentryは自社のパフォーマンス測定機能を活用したことで、年間16万ドルを節約しました! ファイルI/Oのトレースビューの設定 私がデバッグしているエンドポイントは、普通のボトルネックではありません。長いHTTPコール、ファイルI/O、サードパーティ・コール(AI生成)、そして最後にDBクエリーがいくつかあります。 問題のエンドポイントはShipixenというアプリのもので、コードベース全体、リポジトリ、コンテンツを生成し、Vercelにデプロイまでしてくれます。 見ての通り、通常のCRUDエンドポイントではありません。 このような状況は、影響を測定することなく毎月毎月機能を増やし続けるエンドポイントによく見られます。 最終的なエンドポイントのボスと呼んでもいいでしょう。 目の前の問題を理解する ただひとつわかっていたのは、このリクエストのすべてのステップが必要だということでした。バックグラウンド処理にしたり、キューに分けたり、他のアーキテクチャを応用することも考えたが、実際のところは以下の通りです。 ユーザーが利益を得るのは、すべてのタスクが完了してから。 ユーザーは王様/女王様であり、私のアーキテクチャなど気にも留めない。 私は行動を共にし、リクエストを完了するのにかかる時間を半分にするよう努力する必要がある。 これが、44.94秒という短い処理時間の理由です。 あるいは、平均的なシナリオでこのリクエストを完了するのにかかった時間です。 さっそくデバッグシューズを履いて、トレースビューを開いてみました。驚いた! SentryはネットワークI/Oの検出はうまくやりましたが、それ以外はすべてブラックボックスでした。 そしてそれは理にかなっています。 実行中の様々なファイルI/Oをすべてトレースする必要があることを、どうやって知ることができるでしょうか? 54秒かかったという事実は無視して、目の前の問題に集中しましょう。どのタスクに一番時間がかかるのか、さらに重要なのは、どの順番でタスクが完了するのかがわからなかったのです。 カスタム計装の設定 幸運なことにSentryはカスタムインスツルメンテーションを行うメソッドを公開しているので、ファイルシステム上であれ、https上であれ、その中間であれ、あらゆる操作を追跡することができます。 スパンを作成する関数呼び出しで、問題の操作をラップする必要があります。スパンとは、基本的に時間の計測値であり、「起こること」です。”thing “と呼ぶのは少し抽象的なので、スパンと呼ぶことにしました。 お使いの言語やフレームワークにもよりますが、以下のようになります。 そして、メソッドをスパンで囲み始めると、いつの間にかトレース・ビューワーはこのようになっていました。 ボトルネックを特定する方法を探ってみましょう。 ボトルネックの特定 この見方をよく見てみましょう。一般的に、これらは最も注意すべき問題です。 ロング・ラン・スパン ペイロードを減らすことができるか? 複数の並列タスクに分割できるか? バックグラウンドで実行できるか? より高速で効率的な新しいAPIはないか? 互いに待機するウォーターフォール型スパン(並列化可能) 互いに待機しなければならない非効率的なスパンオーダー スパン間の依存関係 最初のバイトまでの時間が遅い / ネットワーク依存のコールドスタート […]

Sentryのメトリクスで、16万ドル節約した方法

私をご存知の方は知っているでしょうが、私はいつも高速に動作するコードかどうか気にしています。 最近、簡単なクエリーを実行したところ、1つのタスクに年間16万ドル近く費やしていることが判明しました。 幸運なことに、私たちは3月にメトリクス・ベータを立ち上げました。 ここ1ヶ月ほど10人のSentryエンジニアは、カスタム・データ・ポイントを追跡するためにMetricsを活用し、この無駄なインジェスト・コストにつながる問題を突き止めるために、多くの機能にわたって協力しました。 解決すべき重要な問題の特定 save_event_transaction 私はSentryのSearch and Ingestチームにいます。 同僚のJernej Strasnerと私は、Sentryのインジェストパイプラインを最適化できるかどうかを調べたいと思いました。最近のクエリで、save_event_transaction タスクに週に6,000ドル近く費やしていることがわかりました。 パフォーマンスとメトリクスが、どのように問題特定に役立ったか これはMetricsの完璧なユースケースだと思いました。 このタスクの計算時間を可視化するためにMetricsをセットアップしたところ、save_event_transaction タスクに過去7日間で1.37週間の計算を費やしたことがわかりました。 save_event_transationタスクから始めるべきだということがわかったので、このオーバーヘッドを減らす方法を特定するために、発見の旅に出ました。 トレース・ビューは、どの関数が最大の違反者であるかのヒントを与えてくれました。下のスクリーンショットでわかるように、この特定のトレースでは 8.00s秒のうち7.37s秒がset_subkeysに費やされていることが分かります。 set_subkeys 関数はmemcachedを通してキャッシュを設定し、私たちのインフラストラクチャで重要な役割を果たしている。 この時点で、 set_subkeysの実際の影響を突き止めたいと思いました。 そこで、Metricsを使用して、抽出されたトランザクションとスパンのメトリクスをプロットし、save_event_transaction. に関連してset_subkeysが費やす時間の割合を得ました。実際には、インジェストされたトランザクションごとに、最小で27%、最大で81%をキャッシュの設定に費やしていることになります。 要約すると、トランザクションの処理時間の平均51%をキャッシュの設定に費やしているということです。 財務用語で言えば、私たちはキャッシュの設定に1週間あたりおよそ3060ドル(年間16万ドル)を費やしていることになります。 セーブイベントからSentryを保存する save_event_transaction:によって引き起こされる時間(とお金)のコストを削減するのに役立つ、Metricsの助けを借りて特定した主な方法は4つありました。 キャッシュを設定するタイミングを慎重にする。 memcacheサーバー間のトラフィックのバランス配分を改善する。 サードパーティツールのバックグラウンドスレッドを有効にする。 Twemproxyから代替へ移行する。 これらの変更により、Sentryのコードベース全体のパフォーマンスが向上し、全体的なコスト削減につながりました。 インパクトのある変更は一行で可能 慎重に検討した結果、トランザクションごとにキャッシュを設定し、別の書き込み操作を必要とする代わりに、最初の読み取り操作の際にキャッシュを設定すればよいことにしました。この変更はGitHubでご覧いただけます。 このマイナーチェンジを行った直後から、平均で300msから100ms以下に短縮されたのがお分かりいただけると思います。 そしてこの変更は、他のceleryタスクにも大きな影響を与えました。 トラフィック配分を改善するためにオペレーション・チームを巻き込む オペレーションの2人の同僚、Anton OvchinnikovとAlex TarasovもSentryのmemcachedサーバーの前にあるロードバランサー、twemproxyのKubernetes設定に問題があることを発見しました。彼らはtwemproxy-saveサービスをclusterIP Noneから通常のclusterIPに切り替えて、memcacheサーバ間のトラフィックを適切にバランスよく分散させる実験を行いました。 その結果、ユーザースペースに費やされるCPU時間の割合が大幅に減少し、接続がより均等に分散されたため、CPU使用率が安定しました。 実験の結果、sentry.tasks.store.save_eventのp95が大幅に減少しました。 C また、sentry.tasks.store.save_eventの時間が10ms(~13%)短縮しました。 さらに、sentry.tasks.store.save_event_transaction p95も減少しました。 サードパーティツールからのブロック解除 メトリクスを詳細に分析した結果、インフラ監視ツールのSDKがstatsdプロキシに逐次的なリクエストを送信し、ブロックしていたため、Sentryのホットパスで高い実行回数が発生していることがわかりました。 私たちはクライアントを更新し、メインのスレッドをブロックしないように別のスレッドでメトリクスを送信するバックグラウンドスレッド機能を有効にしました。 一部のプロファイルでは、インフラ・モニタリング・ツールがプロキシにイベントを送信するのに非常に時間がかかり、トランザクション全体の30%を占めていました。 この変更により、sentry.tasks.store.save_event_transaction.が11ms改善されました。 Twemproxy […]

【Beta版公開中】Metricsで重要指標を測定し、問題を迅速に解決する方法

4年前、私たちは開発者を第一優先したパフォーマンス監視で大きな一歩を踏み出しました。 それ以来、数千ものソフトウェアチームが当社の最新APMソリューションを採用しています。 しかし、パフォーマンスについてチェックすべき項目が多くある一方で、開発チーム内で別々のツールで管理しているところもあり、監視が分断されてしまっているケースもあります。 エラーの根本原因や、パフォーマンスの問題を結びつけるのは、不必要に難しくさせます。SentryのMetricsは現在ベータ版で公開されています。 最初の立ち上げの週に予告したように、Metricsはまだ開発途中でした。 今回、ベータ版がリリースされ、無料で使用できるようになりました(ローンチウィークのアナウンスはこちら)。 これは単なるツールではなく、あなたにとって最も重要なデータポイントを長期にわたって追跡するための新しいパートナーとなるでしょう。 Metricsを使えば、製品・サービス・コードが常に意図したとおりに動作していることを確認しながら、相関するトレースで問題を特定し、解決することができます。 チームは、処理時間・チェックアウトのコンバージョン率・ユーザーのサインアップなどのカスタムメトリクスを監視して視覚化したり、トランザクションの継続時間などの既成のメトリクスを探索したりすることが可能になります。 また、問題を発見した場合、問題の原因を解決するために相関トレースを使用することができます(もちろん、このような機能はありません)。 メトリクスでクリティカルパスを監視 あなたがショッピングカートとチェックアウトの機能を持つ製品やサービスに取り組んでいるとします。 その処理フローは、あなたの会社の収益に直結しています。ですから、巨大なeコマースチェーンや、ユーザーがクレジットカード情報を入力しなければ続行できないSentry’sのようなSaaSビジネスを思い浮かべてください。 ユーザーがハッピーパスを通して成功できるようにすることは、貴社の成功にとって非常に重要です。このパスに遅延が生じると、収益が失われ、おそらく(間違いなく)多くの顧客が離脱することになります。 以下の例では、チェックアウトのレートを注視し、ユーザーがホームページから配送先住所の追加、チェックアウトへとスムーズに移動できるようにします。 仮想のチェックアウトフローのGIFをご覧いただくとわかるように、訪問者は3つのステップを完了する必要があります。 ホームページでスワッグをリクエストし、住所を入力し、注文を送信します。 Sentryの新しいメトリクスを使用すると、カスタムメトリクスを作成して、チェックアウトプロセスを完了したユーザー数をカウントし、視覚化することができます。 チェックアウトフローの3つのステップを追跡するためにカスタムメトリクスを作成し、何人のユーザーがホームページでスワッグをリクエストし、住所を入力、そして注文を送信したかどうかを可視化できるようになりました。 Metricsのおかげで、チェックアウトのコンバージョン率が安定していることが可視化することが出来るようになりました。 メトリクスが合わないとアラートを受け取る また、アラートを作成して、重大な変更があった場合にSlack、Discord、Teams、Emailで通知を受け取ることもできます。チェックアウトフローですべてがうまくいっていることを確認するために、チェックアウト率が20%下がったら発動する閾値アラートを設定しました。 アラートが表示される場合は、以下の画像のように表示されます。 コンバージョン率が下がったのでしょう。 結果をチェックすると、それを確認することができます。 訪問者が購入者に転換していないようです。 カスタムメトリクスによると、注文を正常に送信するユーザーが明らかに減少している。 一般的な製品の旅はここで終わりです。 しかし、Sentryの場合はまだ始まりに過ぎません。 【メトリクスとトレース】デバッグの強化 問題を特定できたので、当然の次のステップは解決策を見つけ出すことです。 問題がどこにあるのか直感的に分かるかもしれませんし、特定のAPIに問題があるかどうかを確認するために、レスポンスタイムのような他のメトリクスを引き出すかもしれません。 それで十分な場合もありますが、それ以上に厄介な場合もあります。 そんな時こそ、1つのツールでアプリケーションに関する様々な種類のデータにアクセスできるのが本当に便利です。 Metricsは、アプリケーションの幅広いデータを見るのに適しています。 一方、トレースは、フロントエンドからバックエンドまで、アプリケーションの深部を見るのに役立ち、根本原因を見つけるための豊富なトラブルシューティングデータを提供します。 あなたが注目しているメトリクスと相関のあるトレースイベントを表示することで、2つのシグナルを簡単に結びつけることができます。 イベント・サンプル・テーブルから、特定のトレース・ビューにドリルダウンすることができます。 ウォーターフォールを見ると、このトレースに非常に時間がかかっていることがわかります。サードパーティのフルフィルメントAPIが原因です。 これで、問題を解決し、ショップを復旧させるために何をすべきかがはっきりしました。 数えるだけじゃない『分布・ゲージ・セット』 上記の例では、カウント(”インクリメント “できるものをトラッキング)の例を示していますが、以下のようなさまざまなメトリックタイプを作成することができます。 分布: 最大値、最小値、平均値のように、時間にわたって集計できる値のリストを追跡します(たとえば、ページのロード時間)。プロセスの開始時間やキューの健全性やターンアラウンドタイムのように、アプリケーションの健全性を明らかにするようなことをレポートするために分布を使用することができます。 例えば、Sentryでは、イベントマネージャがイベントを保存するのにかかる時間の分布を測定するために、Dogfood Metricsを使用しています。そして、通常95パーセンタイルを監視し、イベント・インジェスト・パイプラインに影響を与える可能性のあるリグレッションをチェックします。 以下のように、青い点はこのメトリクスで収集されたサンプルです。 サンプルテーブルを使用して単一のサンプルを選択するか、直接ドットをクリックしてトレースの詳細を表示することができます。 ゲージ: 増減する値を追跡します(例えば、使用可能なディスク容量や使用メモリなど)。 セット: count_unique(ユニーク・ユーザー数など)のように、時間の経過とともに集計される値のセットを追跡します。 さあ、始めましょう! Metricsを追加する以前の場合は、SentryのPerformance機能を使えば、すべての典型的なパフォーマンス・メトリクスを測定することは可能でした。 […]

Cron監視の拡張

この1年間、我々はCronを構築してきました。 小さなプロトタイプから始まったこの機能は、Sentryのエラー、パフォーマンス、信頼性モニタリングツールの本格的な機能へと生まれ変わりました。 この機能自体はまだベータ版ではありますが、すでに1日あたり700万以上のチェックインを受け付けています。 このような規模が大きくなった機能なので、信頼性を保証する方法について慎重な決断が必要でした。 早期実施 Sentryの新しいCron監視機能とは、スケジュールされたジョブ(例:古典的なcronjobs、celery beatタスク、Sidekiq、Laravel Scheduled Tasks、あるいはsystemdタイマー)が通常通り動作しているか、あるいは実行に失敗したシナリオを検証し、アラートを出す方法のことです。 これは、スケジュールされたタスクが “check-in “イベントを介して私たちに通知することで機能します。 Missed:予定時刻にチェックインしなかった場合、「チェックイン漏れ」となる Timed-Out:進行中のチェックインが完了しなかった場合、「タイムアウト」となる Error:status=errorのチェックインを送信すると、明示的にエラーとしてマークされる 最初のプロトタイプでは、チェックインの取り込みはDjangoアプリケーションに組み込まれたいくつかのAPIエンドポイントによって処理されていました。 物事をシンプルに保つために、チェックインは単に Postgres テーブルのエントリとして記録されます。 チェックイン漏れを検出するために、1分間に1回、celery beatタスクを実行して、予定時刻にチェックインがなかったモニターを探すだけです。タイムアウトの検出も同様です。 しかし、この最初のプロトタイプをアーリーアクセスユーザーに提供できるようにしたのは、今年に入ってからでした。 アルファ版の機能であっても、私たちはすぐに勢いを取り戻し、信頼性とスケーリングについて考える時が来たということです。 インジェスト・インフラストラクチャー 私たちが最初に解決しようとした問題は、チェックインの取り込みでした。 私たちのSDKが使用するAPIエンドポイントは、可用性が高く分散されています(私たちの分散取り込みインフラであるRelayを使用しています)。 しかし、私たちのフロントエンドを駆動し、プロトタイプのエンドポイントが実装されたSentry製品のAPIは、このような保証がありません。 Relayが可用性を向上させるだけでなく、Relay経由でチェックインを実装するもう一つの大きな利点は、私たちのSDK群全体でCronチェックインを作成するためのサポートを迅速に実装できることです。 これはRelayが統一された「エンベロープシリアライゼーションスキーマ」を使用しており、SDKが任意のイベント(もちろん最も一般的なのはエラーとトランザクションです)をRelayのポイント・オブ・プレゼンスに簡単に渡すことができるためです。 Cronのチェックイン・インジェストをRelayに移行するのは当然のことでしたが、プロトタイプのインフラを大きく変更する必要がありました。 この改良された世界では、Relay は SDK からのチェックインイベントを受け付けます。これは従来の curl スタイルでのチェックイン用の API エンドポイントも提供します。 これらのチェックインは検証され、正規化され、Kafkaトピックに入れられます。 これにより、処理できるチェックインの量をスケールアップするためのノブをすぐに回すことができます。以下のようなイメージです。 このアーキテクチャにより、ユーザーのチェックインを失うことなく、コンシューマーの問題を確実に回復することができます。Kafkaは問題のあるシナリオでもチェックインのバックログを維持することができ、負荷の要求に応じてコンシューマーの数を微調整することができます。 チェックイン漏れを確実に検知 Cronのインジェストインフラストラクチャの可用性が改善されたので、私たちはチェックイン漏れ検出の信頼性に注目しました。 Sentryは通常、プラットフォームに送られたデータを処理します。 未チェックインの検出は、我々のインフラにとって斬新な領域です。 1分間に1回のCelery beatタスクを使ってチェックインを検出するというプロトタイプのアプローチには、2つの大きな問題があることがすぐにわかりました。 Celery beatスケジューラのデプロイ中に、タスクがスキップされる短い期間があります。 これは、1分間に1回のチェックイン・プロデューサ・タスクが、特定の1分間実行されないことがあることを意味します。 このシナリオでは、すべてのユーザに自分のモニタのチェックインミスが通知されません。 Kafkaメッセージのバックログシナリオで、1分以上バックログしている場合、成功したチェックインが単にバックログにあるだけで、まだ処理されていないスケジュールされた時間のチェックインミスが発生する可能性があります。 これらはどちらも問題があるだけでなく、エンドユーザーを混乱させます。 私たちの目標は、モニターが停止したことを確実に伝えることなので、ミスしたチェックインを正しく検出することが重要です。 では、チェックイン漏れをチェックするタスクが、1)毎日毎時毎分、無期限に実行され、2)チェックインが壁掛け時計の時間より遅れても影響を受けないようにするにはどうすればいいのでしょうか? […]

エスカレーションする問題で、トレンドの問題をより早く見つける

どのissueを優先し、最初に解決すべきか判断することは、開発者が共通して直面する問題です。 この問題に対処するため、Sentry は、エスカレーション、進行中およびアーカイブの課題ステータスのような新機能をリリースしました。 さらに、優先度ソートを更新し、最も重要な課題をより簡単かつ迅速に特定できるようになりました。開発者が最も重要な課題を特定するのに役立つ機能を以下で紹介していきます。 新しい問題状態の導入 Sentryは、新しい問題から始まり、進行中の既知の問題、解決またはアーカイブされた問題まで、問題のライフステージに関するより多くのコンテキストを提供するようになりました。修正された問題がいつクローズするか、進行中の問題やアーカイブされた問題がいつ劣化するかを簡単に発見できるように、RegressedとEscalatingという2つの新しいタブが追加されました。 以前は “Regressressed “というステータスがありましたが、それはユーザーが以前に問題を解決(つまり修正)し、その問題が引き続きイベントを受信している場合にのみ表示されるものでした。しかしこのロジックでは、悪化しつつあり、優先されるべきissueが考慮されていませんでした。  このロジックにより、無視のアクションとステータスをアーカイブに置き換えることにしました。 以前は、「無視」機能は開発者が行える正確なアクションではありませんでした。問題を見えなくする最も簡単な方法でした。 しかし、問題が悪化し始めた場合には役に立ちませんでした。 というのも、いつ無視されなくなるかのしきい値を手動で定義しなければならなかったからです。現在では、アーカイブによってissueはアーカイブ・タブに移動し、issueがエスカレートして悪化し始めると、issueはエスカレーションに移動します。issueが以前にアーカイブされたか、一度も対処されなかったかにかかわらず、issueが通常よりも著しく多くのイベントを受信した場合に、新しいエスカレーションissueステータスが割り当てられます。 また、その他の要因も考慮されます。これにより、issueフィードを整理しやすくなり、優先度の高いissueをより早く特定することができます。課題のエスカレーションはアルゴリズムに基づいて行われるため、どの課題に焦点を当てるべきかを手動で判断する必要はありません。 ベータテストでは、アルゴリズムによってエスカレーションされた課題は、解決される可能性が3倍高いことがわかりました。 また、エスカレーションのしきい値を手動で設定した場合と比較して、これらの課題が再度アーカイブされる可能性も低くなりました。 ソートと検索の改善 早急な対応が必要な問題を特定するために使用できるもう1つのツールが、課題ストリームの優先順位ソートオプションです。最近、優先順位ソート機能がアップグレードされ、年齢、全体的なイベント量、最近のイベント量に基づいて課題が順番に表示されるようになりました。例えば、イベント件数の多い新しい課題は、イベント件数の少ない進行中の課題よりも優先順位が高くなります。どのような課題を上位に表示すべきか、ご意見があればGitHub のディスカッションスレッドに投稿してください。 また、重要な問題をより簡単に見つけるという精神に基づき、問題検索バーに人気フィルターを導入しました。 問題への迅速な対応 注意が必要な問題を素早く見つけることは、Sentryにおける良いユーザー体験の核心であると言えます。上記の改善は、Sentryにログインするたびに、「ホットフィックスに値する」問題を簡単に見つけられるようにするためのほんの始まりにすぎません。 IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談はこちらのフォームからお気軽にお問い合わせください。

Node.jsのプロファイリングでコードレベルのボトルネックを解決する

Node.jsのプロファイリング

プロファイリングは、最も重要なツールです。 プロファイリングを利用することで、本番環境で実行中のプログラム情報を詳しく見ることができます。 パフォーマンスのボトルネックは、ローカルで再現するのが非常に困難であったり、不可能であったりすることがよくあります。そのため、この機能はとても重要であるといえます。 再現が困難である理由は、外部制約や本番環境特有の負荷が理由にあります。 Sentryでは、iOSとAndroidのプロファイリングのサポートをリリースした後、他のプラットフォームもサポートするように取り組んできました。そのうちの一つがNode.jsです。Node.jsのプロファイリングは、現在ベータ版です。 Node.jsのプロファイリングのセットアップ Node.jsのプロファイリングを設定するには、@sentry/profiling-node パッケージをインストールする必要があります。次に、パッケージをインポートします。その後、プロファイルに必要なサンプリングレートを設定します。 プロファイリングは、当社のSentryパフォーマンス上で動作します。 そのため、Sentryパフォーマンスもセットアップする必要があります。 これらのセットアップが完了すると、Sentry.startTransactionとtransaction.finishの間のすべてのコードが自動的にプロファイリングされるようになります。 プロファイリングは実際に何をしているのでしょうか? 本パッケージは、内蔵のV8プロファイラを使用しており、サンプリング周波数が最大100ヘルツでスタックサンプルを取得します。プロファイル結果のスタックサンプルはSentryダッシュボードにアップロードされます。 すると、そのサンプルをフレームチャートの形で可視化することができます。フレイムチャートでは、プロファイラが収集したスタックサンプルを時系列で確認することができます。 これにより、プログラムがどの関数呼び出しに最も多く時間がかかっているのか確認することができます。 自分たちのコードをプロファイリングしてわかったこと まず、Chartcuterie(Slackで共有されるチャートリンクのサムネイル画像を生成するサービス)を実行するExpressサーバーにプロファイリングを導入し、フロントエンドのテストスイート全体と、社内のSlackボットにも導入しました。 コードのプロファイリングを成功させるために、まず、すべてのサービスでSentryの パフォーマンスサービスがインストールされていることを確認します。 Sentryはサービス全体のレイテンシー問題を追跡するので、プロファイルとトランザクションを簡単に関連付けることができます。これにより、リクエストが遅くなっている原因を特定することができます。 パフォーマンスのダッシュボードは、アプリケーションがどのように動作しているかを確認するのに役立ちました。プロファイリングを導入する前と後では、p75の時間を正確に追跡することができました。 パフォーマンスの原因を探る-ネタバレ:テストコードとは限らない Sentryのフロントエンドのコードは、約400のテストファイルにまたがる4000のテストから構成されています。 CI環境からいくつかのプロファイルを確認した後、いくつかのテストでloadFixtures関数呼び出しの内部にかなりの時間がかけられているこることがわかりました。loadFixturesの呼び出しは setup.tsスクリプトの一部で行われます。 これは、テストの実行前に実行され、テストが実行できる環境を準備します。 フレームチャートを見ると、テストのセットアップコードがテスト時間の大部分を占めていることがわかります。そのため、テストセットアップが何を行っているのかを確認することにしました。 擬似的なコードでは、loadFixturesは次のように動作しています。 このコードには何の問題もありません。むしろ、このコードによって、require/import文を書かなくても、テストの内部で一部のコードをスタブ化することができるようになりました。しかし、これはメリットだけではありません。 stubsDir内にあるすべてのコードを(たとえテストで実際に必要とされないものであっても)ロードしてしまいます。 この問題は、Jestがrequire.cacheを採用しないことが原因となり、さらに深刻なものになります。 さらに、setupFilesAfterEnvで定義されたスクリプトが1ファイルにつき一回実行されるということも、問題の原因です。 この問題を解決するために、JavaScriptのプロキシを活用し、require文を遅延ロードさせるようにしました。これにより、パフォーマンスに影響を与えることなく、問題を解決できました。 また、具体的な修正内容はこちらでご覧いただけます。 スローテストを探す Sentryのフロントエンドテストの中には、実行にかなり時間がかかるものがあります(時には数分を超えることもあります)。 その理由はテストによって異なりますが、あるテストは、大きな依存関係グラフを持つ複雑なコンポーネントをテストしているためであったり、すべてのコードを初めてトランスパイル(あるプログラミング言語から、他のプログラミング言語に変換すること)すると、動作に時間がかかったりします。 また、レンダリングに時間がかかるコンポーネントをテストしている場合も同じように動作が遅くなります。 さらに言えば、私たちのテストはデフォルトのGitHub Ubuntuランナー上で実行しています。これはローカル開発で使っているM1チップのmacOS環境とはかなり異なる環境です。 あるコードの実行が遅い理由として、さまざまなことが考えられます。 しかし、プロファイリングがなければ、原因を正確に把握することは難しいでしょう。そのため、実際の本番環境から収集したプロファイルを持つことが非常に重要なのです。 そこで、いくつかのプロファイルがウォーターフォールパターンを示していることに着目しました。 上のフレームグラフでは、keyboardImplementationの呼び出しがウォーターフォール型になっており、テスト実行全体のおよそ7回呼び出されていることがわかります。 これは、テスト時間の大部分を占めています。 また、新しいチームメンバーが招待されたときに、ユーザーに表示されるモーダルをテストしていました。 長文のメールを送信する際に、 userEvent.typeを繰り返し使用していました。そのため、コンポーネント全体の再レンダリングが発生していました。 レンダリングを最適化するためにコンポーネント自体を書き直すことはすぐに対応できることではないため、現実的ではありません。しかし、おそらくそれが最良の解決策だったのでしょう。 私たちは、userEvent.pasteを使用して、ユーザーがメールアドレスを入力することをシミュレートすることで、負荷を軽減することを選びました。これにより、文字列の各文字に対してイベントを発生させることなく、テストの速度を向上させることができました。 当社のサービス以外の問題を発見する Chartcuterieサービスは、Slackのリンクが共有されるたびに、サムネイルを生成します。 これにより、ダッシュボードを開かなくても、Slackですぐにチャートを確認することができます。しばらくの間、このサービスはメモリリークに悩まされており、その都度、再起動させる必要がありました。 最終的に、メモリリークの原因はプロファイリングを活用する前に特定することができ、修正されました。 メモリリークの根本的な原因を調査するのは難しく、簡単な修正作業ではありませんでした。 […]

Pythonのプロファイリングでコードレベルでボトルネックを解決

Pythonのプロファイリング

プロファイリングは、最も重要なツールです。 プロファイリングを利用することで、本番環境で実行中のプログラム情報を詳しく見ることができます。 パフォーマンスのボトルネックは、ローカルで再現するのが非常に困難であったり、不可能であったりすることがよくあります。そのため、この機能はとても重要なのです。 再現が困難である理由は、外部制約や本番環境特有の負荷が理由にあります。 Pythonは、最も人気のあるプログラミング言語の一つです。 SentryもPythonをメインに開発しています。Pythonのプロファイリングは現在ベータ版です。しかし、sentry-sdk==1.11.0を利用することでWSGIアプリケーションで利用可能になります。 これにより、実運用でのアプリケーションのパフォーマンスについて、コードレベルで把握することができます。 Pythonのプロファイリングを始めるには、SDK上でprofiles_sample_rateを設定するだけです。 SDKは100ヘルツのサンプリング周波数でサンプルを取得する別スレッドを実行します。 プロファイルが終了すると、サンプルはSentryに送られ、プロファイルがフレームチャートとして可視化されます。 フレームチャートは、エンドポイントや遅いトレースにおいて、頻繁に実行されるコードを素早く見つけ、リソース消費(例:CPU)を最適化することができます。 SentryプロファイリングでSentryを改善する 長い間、Sentry上でPythonプロファイラの内部バージョンを実行することで、Sentryを最適化することができました。 日付時刻と連携 多くの人は、時系列で確認できることほど嬉しいことはありません。そのため、Sentryの様々なところで時系列グラフを用意しています。しかし、時系列グラフの生成には時間がかかります。 処理が重い箇所を調査したら、 discover.discover – timeseries.transform_results が原因である可能性があることがわかりました。 さらに調査を進めると、この関数が本当に原因であることがわかりました。 たまに数百ミリ秒の遅さになることがあり、これはデータ取得のクエリよりも遅いです! 実はクエリよりも後処理の方が遅いんです! コードを見ると、単純な変換をしているだけでした。そのため、根本的な原因はすぐには分かりませんでした。しかし、プロファイルを見ると、リクエストの大半が、ゼロフィル(データが全て0埋めになっている状態のこと)内で日付のパース処理だということがわかりました。 ゼロフィル内の日付時間のパース処理でした! これを知った時は驚きました。 検証するために、いくつかの簡単なベンチマークを行ました。また、日付と時刻の文字列をパースするいくつかの方法を比較してみました。 それは衝撃的事実でした。なぜなら、dateutil.parser.parseからdatetime.datetime.fromisoformatに変更することで、数百倍速くなる可能性があるからです! datetime.datetime.fromisoformatは完全なISO 8601通りのパース関数ではありません(とりあえずはPython 3.11までは)。しかし、我々はdatetime.datetime.isoformatに満足していました。なぜなら、この一行を変更するだけで、最悪な状況が大幅に改善されるからです。 Django:プリフェッチするかしないか プリフェッチはDjangoでよく採用されるテクニックです。 これは、関連するオブジェクトにアクセスする時に、大量にデータベースクエリが発生するのを防いでくれます。 オブジェクトごとに1つのクエリを作る代わりに、プリフェッチすることによって、関連するすべてのオブジェクトを一度に取得する一つのクエリを作ることができます。 Sentryの様々な場所でこの技術を採用しています。しかし、ユーザーのエンドポイントが非常に遅いことに気づきました。大きな影響を与えずに、関連するオブジェクトにプリフェッチを使用するようにしました。 いくつかのトランザクションを見ると、興味深いことがわかりました。 それは監視できていない期間があったのです。さらに最も興味深いのは、それがいくつかのデータベーススパンに散らばっていたことです。 また、コードを調べてみると、これらのデータベーススパンは以下のクエリに対応していることがわかりました。 最初のクエリはOrganizationMemberに対するもので、それに続く3つのクエリはprefetch_related内で指定された3つのルックアップに対するものです。 プロファイルを調べると、prefetch_related_objectsがありました。これはDjangoの内部呼び出しで、リクエストの大部分を占めています。 OrganizationMemberとTeamの間の多対多の関係、そしてTeamとProjectの間の多対多のリレーションクエリをしていたことがわかりました。 prefetch_relatedを使ったクエリは高速でしたが、Djangoは結合処理を実行していました。つまり、一部のチームとプロジェクトを取得しただけですが、 DjangoはすべてのOrganizationMember、Team、Projectを繰り返し、関連するオブジェクトを属性として設定していました。 この知識をもとに、クエリの書き換えに取り掛かりました。 Pythonでこの結合処理を実行したくはなかったのです。prefetch_relatedを削除し、関連するオブジェクトを手動でフェッチし、レスポンスを丁寧に構築することで、これを達成することができました。これにより、p95は50%近く減少しました! プロファイリングはパフォーマンスを補完する プロファイリングは、Sentryパフォーマンスを完璧に補完します。 パフォーマンスが問題を大まかに把握することができますが、プロファイリングは正確なプログラムのコード行番号まで把握することができるので、簡単に問題を解決することができます。 コードのプロファイリングをできるようにするために、まずすべてのサービスをSentryのパフォーマンス製品で接続するようにしました。 Sentryは、サービス全体のレイテンシー問題を把握することができます。 これにより、プロファイルとトランザクションを簡単に関連づけることができ、遅いリクエストの根本原因を特定することができます。 パフォーマンスのダッシュボードは、アプリケーションがどのように動作しているかのを把握するのにも役立ちました。プロファイリングを導入する前と導入した後を比較すると、P75の時間やスループットなどを簡単に把握することができました。 早速いまからプロファイリングを始めてみましょう。 最初に「パフォーマンスを計測する」を確認してください(わずか5行のコードで可能です)。 […]

コードカバレッジインサイト – スタックトレースで確認できるようになりました

コードカバレッジインサイト

その理由 コードカバレッジとは、テスト手法の一つで、どのコードがテストされているかを知らせるもので、パーセントで表示されます。 コードカバレッジは、コードの総行数のうち、全体の何割がテストされているのかを把握することができます。 また、テストを書くことはとても大変です。しかし、コード変更があると、せっかく書いたテストコードも変更内容をテストできているかがわかりません。 このストレスから、共同創業者のイーライ氏と私は、テスト駆動開発で解決したいと思うようになりました。 私たちは、(まだ)存在していないものを作ることが好きです。 また、ほとんどの開発者はエラーが発生するコードのテスト状況を見たいだろうと思っていました。 しかし、SentryがCodecovを買収したとき、次のような反応が最も多かったです。 それは私たちもとても感じていました。 Codecovを使ってコードレビューしても、デプロイ後の作業にはあまり役立ちませんでした。 長い間、ユーザー/顧客向けの製品に携わる開発者は、”OK、でも次の問題は何?”ということに向き合ってきました。 その問題は、おおよそ次のように表現されます。 アプリでエラー・不具合内容を受け取る エラー周辺のデータを開く(アプリケーションのパフォーマンス監視と例外処理) “よし、でも次はどうする?“ 別画面で自分のIDEを開く 2つの画面を見渡し、コードのメンタルモデル(価値観やイメージのこと)を構築する。 そのコードにテストがあるのなら、根本的な原因を修正する方法を考える。 必要であれば、今後同様のエラーが発生するのを防ぐために、基となるソースコードを変更し、テストを記述・編集する。 さらに一歩踏み込むと… もしエラーが発生するコードがテストされていない場合、次のステップは、このケースを中心にテストを書くことかもしれません。 または もしエラーが発生するコードがテストされていた場合、次のステップとして、問題のテストとコードのロジックとの関連性を調査します。例えば、テストケースに見落としがないかを確認します。 SentryのスタックトレースにCodecovを導入することは、本番前とデプロイ後のデータ連携を実現する最初の取り組みです。 これにより、問題が発生した際のデバッグやパッチ適用がより迅速かつ容易になります。 何を? ひとことで言うとCodecovのSentry連携を使えば、Sentry Issueのスタックトレースでエラーの原因となる未テストのコードを直接確認することができます。 この機能を使うことで、さまざまなユーザー操作を考えたり、コードを手動で分析したりする必要はもうなくなります。 SentryにCodecovを導入すれば、テストするべき優先箇所を正確に把握できるので、時間を無駄にすることなく、信頼性の高いコードを維持することができます。   テストカバレッジを改善するために、数ヶ月に一度「カバレッジ週間」を設けて、コードのテストを改善していました。しかし、SentryとCodecovの連携により、コードを分析し、テストカバレッジが必要な箇所を考えることはなくなりました。さらに、Sentryが取り組むべき箇所を正確に教えてくれるので、テストカバレッジの構築に費やしていた時間を約50%ほど削減できました。 – アレックス・ナサネイル(技術担当ディレクター)@vectare.co.jp   Codecovの使用方法 前提条件: Sentryの場合 SentryのGitHubインテグレーションをインストールし、Codecovにテストカバレッジデータがあれば、使い始められます。 また、GitHubインテグレーションにCode Mappingsをセットアップする必要もあります。これはテストカバレッジを表示するためのソースコードファイルを把握するのに必要です。 GitHubを使われていない方は、GitLabとBitbucketは対応中ですので、しばらくお待ちください。 Codecovの場合 Codecovにサインアップするだけです。一度アカウントを取得すれば、テストされていないコードが本番環境でエラーを引き起こしている箇所をワンクリックで確認できます。 コードカバレッジは初めてですか? 大丈夫です。詳しくはこちらをご覧ください。 SentryとCodecov – スタックトレースでコードカバレッジを即座に確認できるようになります。 最も簡単な方法 – 全く何もする必要はありません。両方のサービスでセットアップされたときに、自動連携を有効にする日次ジョブを実行します。 簡単な方法 – すぐにでも始めたい場合は、設定ページに移動し、「コードカバレッジインサイトの有効化」をオンにしてください。 […]

;