サムライズトップ > APM - アプリケーションパフォーマンスマネージメント > アプリケーション性能問題の解決とDevOpsの高速化 > 開発現場でのデバッグ作業が劇的に楽になるRookout独自の機能

開発現場でのデバッグ作業が劇的に楽になるRookout独自の機能

デバッグのスピードアップと省力化で開発チームの負担を減らし、ビジネスを開発面で支えるRookout
  1. Live Debuggerでスタックトレースにブレークポイントを設定
  2. ログレベルの動的な変更を可能にする新機能Live Logger

この記事では、Rookoutの特長である「止まらないブレークポイント」の活用法のなかでも、オープンソースライブラリなどのサードパーティ製コードをデバッグするときにも便利な、スタックトレースにブレークポイントを設定するテクニックをRookout社のブログ記事の要約としてご紹介します。また、ログ監視のためのTailコマンドや他社のログ監視ソリューションのLive Tail機能に置き換わる画期的な新機能Live loggerについてもブログ記事(12)をもとに解説します。

The Journey To Debugging Other People's Code



Live Debuggerでスタックトレースにブレークポイントを設定


そのバグ、あなたのコードのせいではないかも?

アプリケーションを開発する際は、すべてのコードを自分で書くのでない限り、必要なライブラリやオープンソースの実装を探して自分のコードに組み込みます。そして、アプリケーションで特定のタスクを実行したり、フレームワークを使用したりする必要がある場合、通常はパッケージマネージャを使うのではないでしょうか。Mavenリポジトリのような古参ツールからnpm(英語)やpip(英語)のような新しいツールまで、必要なパッケージのインストールがコマンドライン一発あるいはjsonやxmlを編集するだけで完了します。しかし、そうしたパッケージのほとんどは別の会社や開発チームが開発したもので、オープンソースでない限り(であっても)ソースコードにたどり着くのが困難なときがあります。たとえ同じ会社に属していても部署が違えばコードの共有に積極的でない場合もあるでしょう。また、明示的にサードパーティのパッケージを使っていなくても、最終的にはAWS LambdaやApp EngineなどのPaaS上で他者が書いたコードからあなたのアプリケーションが呼び出されて実行されることになるかもしれません。

そのパッケージにどれだけ信頼を置いているとしても、ソフトウェアである限りそうしたコードにバグが含まれている可能性はゼロではありません。あるいは、バグではなくても、APIのドキュメントが古くて、間違った使い方をしてしまうかもしれません。では、そのソフトウェアのどこかがおかしいとなったとき、どうすればいいのでしょうか?


Rookoutのソリューション

ご存知のように、Rookoutは開発者がオンデマンドであらゆる環境のアプリケーションに「止まらないブレークポイント」を設定することを可能にします。これにより、アプリケーションを一時停止したりパフォーマンスを低下させることなく、デバッガを使用しているかのようにアプリケーションからデータを収集することができます。何々というファイルの何行目のコードがトリガーされたときにアプリケーションのデータのスナップショットを取得するようにRookoutに指示するだけです。Rookoutは、ローカル変数、関数の引数、トレースデータ、コールスタックなど、指示されたものは何でも収集します。

コードを書いたのが自分であれば、どのソースファイルのどの行からデータを収集したいかを一番理解しているのは自分なので、とくに問題はないでしょう。また、ソースコードが手元にあれば、他者が書いたコードでも実行フローを追うことは可能です。しかし、コンパイル済みのコードでソースにアクセスできなかったり、あるいはソースのバージョンが明確にわからない場合はお手上げです。

ソースなしでどうやってデバッグをすればいいのか?私たちは昔ながらのコールスタックに注目しました。サードパーティ製のコードが実行され、自分のコードと相互作用するフローを確実に特定できる場所がそこだからです。コールスタックが連なるスタックトレースを追うことで、それがどの場所で実行されていようと、それを誰が書いたか、ソースファイルにアクセスできるかに関係なく、コードの実行フローを検証することができます。

スタックトレースにブレークポイントを設定する手順

Rookoutでは、止まらないブレークポイントで表示されるスタックトレースに対しても、さらにブレークポイントを設定することができます。下図は「Stack Trace」タブに表示されたスタックトレースで、ここでは自分のコード"TodoController.java"に含まれる"getTodos"がコールされる前に何が起きているのかを確認するために、そのコールスタックにブレークポイント(紫色のドット)を設定しています。


実はここに含まれる他のサードパーティ製コードからのコール、例えば"FrameworkServlet.java"の"doGet"(2つめのドット)で何が起きているのかも簡単にわかります。「Set Breakpoint」をクリックすれば、Rookoutが任意のコールスタックにブレークポイントを設定してくれます。これで、ソースが手元にないコードであってもデータを収集して検証できます。


このようにブレークポイントを設定すれば、次回"FrameworkServlet.java"の"doGet"がコールされたときに、Rookoutが収集したデータを確認することができます。

ご覧のように、"URIConverter"や"ApplicationMapping"など、さまざまなメソッドのローカル変数や引数の値が取得できています。これらはすべて、ウェブサーバー上で稼働するサードパーティ製のフレームワークがアクセスしたオブジェクトです。ソースコードが手元になくても、実行フローを詳細に検証できることがおわかりいただけたでしょうか。

ちなみに、アプリケーションのパフォーマンスに影響を与えないように、Rookoutが取得する変数はブレークポイントを設定したコールスタックのローカルスコープ内のみに制限されています。しかし、ブレークポイントは複数設定でき、その場所も何度でも変更できるので、ピンポイントで問題を絞り込むことが可能です。

Rookoutユーザーなら誰でもこのテクニックを活用し、サードパーティ製コードのデバッグを飛躍的に生産性の高いものにすることができます。ぜひお試しください。

ログレベルの動的な変更を可能にする新機能Live Logger


ログの数、多すぎ?少なすぎ?

次にご紹介するのはRookoutの新機能です。その前に、開発の現場で発生する典型的なログ管理のジレンマについて確認しておきましょう。いにしえの昔から開発者は、信頼がおける直感的でわかりやすいデバッグ方法としてログに頼ってきました。しかし、開発の初期段階からステージング、本番環境へのデプロイメント、そして継続的なバージョンアップまで、ソフトウェアのライフサイクルを通じてアプリケーションログから得たい情報は変化していきます。開発初期にはコードのあらゆる場所に詳細なDEBUGやTRACEレベルのログを追加しますが、製品が成熟するにつれて不要なログをコードから削除あるいは無効化してノイズを減らし、適切な場所にWARNINGやERRORレベルのログを追加して日々の監視や運用に役立てます。これが、開発時や問題発生時にはできるだけ詳細なログを取りたい一方で、運用フェーズではなるべくログを絞りたいという正反対のニーズのジレンマです。これを解決するための調整やログの管理はソフトウェアのパフォーマンスや品質を維持するために欠かせない作業ですが、ログ行の無効化やログレベルの変更は人手でおこなわれ、常に開発チームへの負担となっています。また、その一部を自動化できてもログの変更を反映するためには毎回アプリケーションの再起動が必要になります。

こうしたログ管理の煩雑さをなくし、その時々で必要なログだけを、稼働中のアプリケーションに影響を与えることなく、簡単かつ効率的にオンにできたとしたら?

Rookoutならではのログソリューション

それを現実のものとしてくれるのが、Rookoutの新機能「Live Logger」です。


RookoutのLive Loggerは一見すると、DatadogLogz.ioSumo Logicなどのオブザーバビリティ(可観測性)ツールに搭載されたLive Tail機能とまったく同じに感じるかもしれません。上部に検索ボックス、左側にいくつかのフィルターチェックボックス、暗い背景にログ行が表示されており、ログを使ってデバッグするのが習慣になっている開発者なら、このデザインは違和感なく受け入れられるはずです。しかし、Rookout Live Loggingと他社製品におけるLive Tailの実装との間には大きな違いがあります。

DatadogのLiveTailビュー(出展:https://docs.datadoghq.com/ja/logs/explorer/live_tail/

他社のLive Tail機能のほとんどは、ログが出力順に表示され、リアルタイムに感じられるユーザー体験を提供しています。しかし、実際のところはコード内ですでに有効化されているログラインの出力を見やすいように形式を整えて表示しているだけなのです。

Rookout Live Loggerはこのアプローチを一歩進め、無効化したログ行を後からリアルタイムで有効化させることができます。Rookout SDKがLog4j、Logback、Winstonといったよく使われるログ出力ライブラリと連携することで、バイトコード操作によって無効化されていたログ行を「オン」にすることができるのです。このコア機能により、開発者はボタンをクリックするだけで、コードに含まれていながら本番環境では無効化されていたログ行が取得できたはずのデータをリアルタイムで確認できます。以下で、この機能の詳細を解説します。

Live Loggerの特長1. ログレベルの動的な切り替え

ユーザーの皆さんからよく聞くご要望は、「アプリの再起動やコストへの影響を気にせずに、簡単にDEBUGログを有効化できたらいいのに」というものです。Rookout Live Loggerはまさにそれを実現しました。

Live Loggerでは、ボタンをクリックするだけでINFO、DEBUG、さらにはTRACEとログレベルを切り替えられるため、アプリの動作をより深く理解することができます。一時的にログの冗長性を高め、後述する高度なフィルター機能を使ってデータ収集をピンポイントでおこなえるということは、見たいログを必要なときに有効化できるということに他なりません。

Live Loggerの特長2. テキストベースのフィルタリング

一見同じように見えるログラインの連なりから必要な情報だけを得るための最も直感的な方法は、短いテキストの文字列でフィルタリングすることです。Rookoutは指定された文字列を含むログ行のみを「スイッチオン」することができ、画面に表示されたり、必要に応じてオブザーバビリティプラットフォームにパイプするログ行を、パターンに一致したものだけに制限することができます。

見落としがちなエラーメッセージの捕捉はもちろん、特定のサービスが出力したログを抽出したり、特定の変数の値を追跡するような高度な利用法も可能です。また、冗長性フィルターを使えば、後から有効化したログ行を大まかなレベルで分別することもできます。

Live Logger画面例

Live Loggerの特長3. コンテキストベースのフィルタリング

テキストベースのフィルタリングは開発者にとって最も直感的ですが、制約もあります。例えば、そもそもどの文字列でフィルターすればいいのかがわからない、そんな時に役立つのがコンテキストベースのフィルタリングです。

これは、OpenTracingならびにOpenTelemetry標準を実装したツールとの連携で実現します。Live Loggerはそれらのツールから特定のユーザー、アカウント、サービス、あるいはトランザクションの関連情報などのコンテキストデータを取得し、関連するコードの実行時に出力したログだけを抽出できます。これにより、問題の原因をすばやく特定できます。

Live Loggerの特長4. ログスループットの追跡

アプリが毎日何行のログを出力しているか、そしてそのログをログストレージプロバイダーに送信するためにI/Oリソースをどれだけ消費しているかを把握していますか?DevOpsチームはそうしたオーバーヘッドやストレージのコストを極力減らしたいと思っているはずです。

Rookoutでは、冗長度を上げたことで追加発生するログ行の量を把握することができます。前述のフィルターを活用してログの量を抑えれば、オブザーバビリティプラットフォームに送信するログ行を節約でき、アプリケーションに悪影響を与えたり余計なノイズを加えたりすることなく、より深いインサイトやコンテキストを取得することが可能になります。

Live Loggerの特長5. ログの転送

出力されたログをリアルタイムのLive Tail機能で表示し、適切なフィルターを適用してスループットの増加が許容範囲内であることを確認したら、そのログを「Targets」タブで設定したオブザーバビリティプラットフォームに転送します。

「Targets」タブに追加できる連携サービスには最も一般的なログ管理ツールやAPMツールが含まれており、有効化したDEBUGやTARGETログをログ管理ツールに転送することで、他のソースから収集したデータと見比べながら分析できます。

DatadogへのRookoutメトリクス、ログ転送画面例
Datadog Integration Final Demo(出展:https://www.youtube.com/watch?v=tnA4B1y2mi4

Live Loggerの特長6. エンタープライズおよび本番環境に対応

Rookout Live Loggerは、Rookout Live Debuggerと同じチームが開発したものです。つまり、Rookoutならではの特長がこの新機能にも組み込まれています。Liver Loggerは、本番環境を想定したオブザーバビリティとして設計されており、パフォーマンスへの影響を最小限に抑えながら、セキュアでコンプライアンスに準拠したデータ収集を実現しています。

そして、サポートするプログラミング言語、クラウドベンダー、デプロイメント方法など、現在利用可能なテクノロジーの中で最も広い範囲をカバーします。さらに、他のオブザーバビリティ、ロギング、モニタリングツールとの統合も提供しています。

Live Debuggerを補完するLive Logger

RookoutのLive Loggerは、Live Debuggerと補完関係にあります。前者はコード内にすでに存在するログ行をリアルタイムで有効化しますが、後者はそもそもコード内に存在しないログをリアルタイムで出力させることができます。Live Loggerは、あらゆる場所にあるコードのログ行を一斉に有効化できる一方で、Live Debuggerは既知の特定のコード行をピンポイントで検証することを可能にします。

Live Loggerは、ログ収集とオブザーバビリティのパイプラインをフルにコントロールできる画期的な新機能です。問題が発生したときに必要なログが有効化されておらず、情報が不足しているような場合でも、簡単にログレベルを変更して原因の究明にあたることができます。さらに、高度なフィルター機能の活用とあわせ、オーバーヘッドやコストを最小限に抑えつつ、より効率的なデバッグが可能になります。

Rookoutの新機能Live Loggerにご興味のあるかたはぜひ、こちら(英語)をご覧ください。

ページのトップへ戻る