Honeybadgerのブレッドクラム機能とは?エラー調査を効率化する使い方と拡張術
本番環境でエラーが発生し、どんなに試しても開発環境やステージング環境でその問題を再現できない——そんな経験はありませんか?多くの場合、次のステップとして本番環境にデバッグログを仕込んでデータを集めることになります。しかし、ログとリクエストを紐付ける適切な手段がないと、特にインシデント対応中は非常に苦労します。
そこで私たちは、この課題を解決する機能「ブレッドクラム(Breadcrumbs)」を追加しました。

ブレッドクラムはログイベントによく似ていますが、エラーとともに保存・レポートされる点が特徴です。ログと同様にメッセージを含むだけでなく、ハッシュマップ形式のメタデータを持たせることもできます。ブレッドクラムはリクエスト(またはジョブ実行)のライフサイクル全体を通じて収集され、エラーが報告されない限り即座に破棄されます。
独自のブレッドクラムをスタックに追加するのは簡単です。コード内の任意の場所で Honeybadger.add_breadcrumb を呼び出すだけです。
Honeybadger.add_breadcrumb("Loading User", metadata: {
user_name: user_name,
})
その呼び出しの後にエラーが報告されれば、ブレッドクラムスタックの中で確認できます。

おっと、user_name が空になっていますね。「これが原因で問題が起きそうだ」とすぐ気づけるのが魅力です。
自動ブレッドクラム
HoneybadgerのRubyライブラリには、RubyやRailsにフックして自動的にブレッドクラムを収集する仕組みが組み込まれています。例えば、本番環境で Logger クラス経由で出力されるすべてのログメッセージはキャプチャされ、ブレッドクラムとして記録されます。さらにRailsのインストゥルメンテーションとも連携しており、コントローラアクション、SQLクエリ、Active Jobの実行などに関するブレッドクラムも自動的に収集します。
利用方法
ブレッドクラムは現在、Rubyクライアントから利用できます。4.4.0 以降へアップデートし、設定で明示的に有効化してください。gemの 5.0.0 版をリリースするまでは、不具合を洗い出す期間としてデフォルトで無効になっています。
ぜひ試してみて、問題に遭遇した場合はフィードバックをお寄せください。
ブレッドクラムを拡張する
ブレッドクラムが正式に登場したところで、拡張方法の簡単な例を見てみましょう。Railsアプリでブレッドクラムを有効にすれば、標準的なインストゥルメンテーションによるブレッドクラムが自動的に付与されますが、それ以上の情報を記録したい場面もあるでしょう。
例えば、アプリがHTTPリクエストを送信するたびにブレッドクラムを作成したいとします。この情報はデバッグの際にきっと役立つはずです。
最もシンプルなのは、リクエストを送る箇所それぞれで Honeybadger.add_breadcrumb を呼び出す方法です。
def send_a_message
res = conn.post("/message", { user: user.id, body: "Hey!" }.to_json)
Honeybadger.add_breadcrumb("Request: /message", metadata: { user: user.id })
res
end
ここでは /message へのPOSTごとにブレッドクラムを記録しています。次にこのメッセージ送信の後でアプリがエラーを投げれば、どのユーザーがいつメッセージを送ったのか、エラーとの前後関係まで含めて把握できます。便利ですね!
ただしこの方法は、リクエストを送るすべての場所に add_breadcrumb を書く必要があり、少し手間がかかります。とはいえ、あえて補足しておくと、このやり方にも確かな利点があります。キャプチャしたいメタデータを非常に細かく制御できるのです。本番環境で見つかったバグをもとに、狙いを定めた情報を集めたい場合には最適なアプローチといえます。
個人的に知りたいのは、リクエストが「いつ」「どこへ」飛んだのかという一点だけです。できればライブラリ側に大部分の処理を任せたいところですよね ;)
Faradayでインストゥルメンテーション
ここでは少々強引に、人気のHTTPクライアントライブラリ「Faraday」を使っていることを前提に進めます。
独自のミドルウェアを自作することもできますが、今回はRailsのインストゥルメンテーションを仲介役として活用したいと思います。幸い、faraday_middleware gemにはイベントを発行してくれるミドルウェアが用意されています。Gemfile にgemを追加し、instrumentation ミドルウェアがコネクションに組み込まれていることを確認してください。
connection = Faraday.new do |conn|
conn.use :instrumentation
conn.adapter Faraday.default_adapter
end
アプリ内でコネクションを共有していない場合、この設定には多少の手間がかかるかもしれません。楽をするなら、ConnectionOptionsを先頭に差し込んで、すべてのリクエストでミドルウェアを有効にする方法もあります。ただし注意が必要です。この方法では、アプリ本体だけでなく、組み込んだgem内部で発生するFaradayリクエストまでも計測対象になります(むしろそれを望む場合もあるでしょう!)。
Railsのインストゥルメンテーションを使うメリットは他にもあります。たとえば、別のユースケース(汎用的なログ記録など)のために複数のサブスクリプションを登録できる点です。
送信リクエストをまとめて監視
Faradayリクエストの計測準備が整ったので、イベントを購読してブレッドクラムを作成してみましょう。
ActiveSupport::Notifications.subscribe "request.faraday" do |_, _, _, _, data|
method = data[:method].to_s.upcase
metadata = data.to_h.slice(:url, :status).merge({method: method})
Honeybadger.add_breadcrumb("#{method}: #{metadata[:url]}", category: "request", metadata: metadata)
end
これでHoneybadgerが、送信リクエストごとにブレッドクラムを自動記録するようになります!

ここで注目してほしいのは、リクエストから取得するデータポイントを少数に絞っている点です。送信ボディやレスポンスボディのペイロードは意図的に除外しています。機密データがブレッドクラムのメタデータに混入するリスクがあるためです。
ぜひ試してフィードバックを!
ブレッドクラムが皆さんのデバッグツールボックスに加わる頼もしい存在になることを願っています。さっそく試してみて、「こんな機能が欲しい」という要望があればぜひお聞かせください。
-
ObjectRocketのメトリックダッシュボード徹底解説:Grafanaで実現するデータベース監視
本記事は、2019年9月9日にObjectRocket.com/blogで公開された内容をもとにしています。 Rackspace ObjectRocketのミッションは、お客様のデータベースを「オートパイロット」状態にすること。つまり、データ管理の手間からお客様を解放し、優れたアプリケーション開発に集中していただける環境を提供することです。しかし、データベースが自動化されていても、システムの可観測性(オブザーバビリティ)を維持することは依然として重要な課題です。 データストア内で何が起きているのか、そして直近のアプリケーションの変更がデータベースのパフォーマンスにどのような影響を与えているの
-
Linuxテスト用の新ラップトップ登場:Lenovo G50
これは大きなイベントです。最近、レビューとテストに使用していた4台のノートPC(T61やT400といった有名機種を含む)を引退させました。つまり、Linuxのインストール作業などをこなすための新しいマシンが必要になったわけです。そこで選んだのが、Lenovo G50です。旧式のLGハードウェアについては、Nvidiaカードを搭載しているため、スペックは古く弱いものの、引き続き使用していきます。しかし、これからのディストリビューションテストの大部分は、この新品のマシンに集中することになります。ここには重要な意味があります。UEFIやSecure Bootといった技術が絡んでくるからです。今までの