Reckoner における Datadog Error Tracking の活用事例
この記事は、3-shake Advent Calendar 2024 の 15 日目の記事です。
はじめに
私の所属する株式会社スリーシェイクでは、Reckoner というデータパイプライン構築の SaaS を開発しています。
「SaaSをつなぐ。業務が変わる。ビジネスが進化する。」
直感的なユーザーインターフェイスで、多種多様な SaaS のデータをつなぎ合わせることで、データ活用・データの民主化を実現します。
Reckoner では多種多様な連携先に対応しているため、様々なエラーが発生する可能性があります。そのため、エラーの迅速な発見と解決が重要です。
本記事では、Datadog の Error Tracking という機能を活用して、Reckoner におけるエラーの追跡方法について紹介します。
また、本記事の内容は Reckoner で実際のデータ処理を扱う Scala 製バッチアプリケーションの例を元にしており、関連する以下のスライドも合わせてご参照ください。
Datadog Error Tracking の概要
Datadog Error Tracking は、アプリケーション内で発生したエラーを簡単に追跡し、分析することができるツールです。これにより、デバッグ時間の短縮や、問題解決までのプロセスが円滑になります。主に以下の機能を備えています。
- エラーのグルーピング: 発生パターンの分析、よく発生するエラーの要素の絞り込み
- トレースとの連携: エラーが発生したコンテキストの特徴をトレースとして追跡
- レポート機能: 情報収集の自動化と記録の可視化
エラー情報の記録
Error Tracking は Datadog APM のトレースからエラー情報を取得するため、トレースにエラー情報を記録することで自動でエラー情報を取得することができます。
Reckoner では OpenTelemetry を採用しており、以下のような OpenTelemetry Java API のラッパーを用意して Span にエラー情報を記録しています。
trait OpenTelemetryOps {
@SuppressWarnings(Array("scalafix:DisableSyntax.defaultArgs"))
def tracingWithSpan[A](spanName: String, attributes: Attributes = Attributes.empty())(body: Span => A): A = {
val span = tracer.spanBuilder(spanName).setAllAttributes(attributes).startSpan()
val scope = span.makeCurrent()
try body(span)
catch {
case NonFatal(e) =>
val sw = new StringWriter()
val _ = e.printStackTrace(new PrintWriter(sw))
val _ = span
.setStatus(StatusCode.ERROR)
// https://docs.datadoghq.com/ja/tracing/trace_explorer/trace_view/?tab=spantags
.setAttribute("error.type", e.getClass.getName)
.setAttribute("error.msg", e.getMessage)
.setAttribute("error.stack", sw.toString)
// 実装エラーではない無害なエラーを無視するためのマーク。詳細は後述。
.setAttribute("error.ignored", e.isInstanceOf[AlertIgnoreMark])
throw e
} finally {
scope.close()
span.end()
}
}
}
記録されたエラーの詳細
記録されたエラーは Datadog の Web UI から確認することができます。以下はエラーの詳細画面の一例です。
エラーの発生頻度を表すグラフやスタックトレース
Span に記録された属性 (Span Attributes) の一覧
Error Tracking 活用 Tips
Error Tracking をより活用していくうえで実践している Tips を紹介します。
Span Attributes の充実化
Span に記録する属性 (Span Attributes) を充実させることで、エラーの発生状況をより詳細に把握することができます。
例えば、Reckoner では以下のような情報を記録しています。
実行環境
- 環境名 (dev, stg, prd)
- Google Cloud の実行リージョン
- k8s の Node, Pod 情報
計算資源上のどこでエラーが発生しているのかを確認できます。
バッチジョブの情報
- チームID・プロジェクトID
- ワークフロー ID
- タスク ID
- タスクの設定情報
- 社内向け管理画面の URL
どのユーザーが、どのワークフローで、どのような設定でタスクを実行したのかを確認できます。
タスクの設定情報は、実装エラーなのか、設定ミスなのかを判断するために重要です。
また、社内向け管理画面の URL を記録することで、ワークフローの設定情報や依存タスクの状況を確認できます。
バージョン情報
- git のリポジトリ URL、コミットハッシュ、タグ
どのバージョンでエラーが発生しているのかを確認できます。
また、これを記録しておくことで、Error Tracking の UI 上から直接ソースコードを確認することが可能です。
関心のないエラーを除外する
ユーザー側の設定ミスなど、アプリケーション実装のエラーではない無害なエラーが発生することがあります。
このようなエラーを除外するために、独自に AlertIgnoreMark
というマーカー trait を用意して、バリデーションエラーなどの例外クラスに mix-in しています。
trait AlertIgnoreMark { self: Throwable => }
// バリデーションでの例
fields.get("hoge") match {
case Some(field) => field
case None =>
throw new NoSuchElementException(s"指定されたフィールド名 hoge が見つかりません") with AlertIgnoreMark
}
エラーの一覧画面で @error.ignored:false
を使いフィルタリングすることで、関心のないエラーを除外することができます。
エラーを通知する
Error Tracking に記録されたエラーは、Datadog の Monitor 機能を使って通知することができます。
Reckoner では以下のような通知を設定しています。
新しく発見されたエラーの通知
新規にグルーピングされたエラーが発生した場合に通知を送信しています。
Error Tracking 導入以前は、既知のエラーかにも関わらず通知を送信していたため、アラート疲れが発生していましたが、これにより関心のあるエラーに絞って通知を受け取ることができるようになりました。
高頻度で発生しているエラーの通知
一定期間内に高頻度で発生しているエラーがある場合に通知を送信しています。
インシデントの早期発見に役立ちます。
エラーを振り返る機会を設ける
エラーを収集するだけでは品質の向上にはつながりません。エラーが発生したあとにその原因を振り返ることが重要です。
Reckoner では週に一回、チーム定例の際に「エラーを見る会」を開催しており、直近で発生したエラーの内容をチーム全員で確認することで、エラーの対応有無の判断や、品質向上のためのナレッジ共有の場として活用しています。
修正の必要なエラーについては、Datadog の Case Management 機能を使って Case を作成し、対応が必要なエラーのリスト化と進捗管理を行っています。
まとめ
Datadog Error Tracking を活用することで、アプリケーションエラーの追跡が効率化され、品質向上につながっています。
単にエラーを収集するだけ終わるのではなく、エラーの詳細情報を記録し、通知を設定し、エラーを振り返ることでより効果的に活用しましょう。
おわりに
Reckoner ではエンジニアを募集しています!
株式会社スリーシェイクの採用情報はこちらをご覧ください。
Discussion