Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TSKaigi 2026 TypeScriptバックエンドのオブザーバビリティ戦略 — Dat...

TSKaigi 2026 TypeScriptバックエンドのオブザーバビリティ戦略 — Datadog × NestJSの実践

Avatar for Taisei Yamamoto

Taisei Yamamoto

May 22, 2026

Other Decks in Programming

Transcript

  1. ⾃⼰紹介 2 • エンジニア歴 9 年⽬, TypeScript 歴 5 年⽬

    • Java/PHP/Vue.js 4 年 → React/NestJS 5 年 • ⼤⼿通信事業者でWebアプリ&バーチャルオフィスSaaS → any (現職 2 年半前) • 機能開発の傍ら 約 2 年前に Datadog 導⼊PJを推進 • 直近: 技術的負債解消/パフォーマンス, DX改善の専任チーム ⼭本 ⼤星 any 株式会社
  2. 3 ユーザー数 80,000 ⼈突破 BOXIL SaaS AWARD 2021 ⼤企業賞 IVS

    Launchpad 5位 ⼊賞 社内に埋もれている情報や⼈のノウハウを蓄積し、 RAGを使っていつでも引き出せるようにすることで、 組織全体の⽣産性向上と組織の壁を超えるサービス。 ナレッジの資産化が、 企業の未来をつくり出す。 AIナレッジプラットフォーム
  3. 2つのセクションに分けて話します 17 1. ⼊⾨者向け オブザーバビリティこれからやっていき 2. Datadog初級者向けTIPS 💪 👀 Datadog

    を導⼊検討中、運⽤はじめた ばかりの⼈ プラグイン有効化の罠 ちょうど良い dd-trace 依存のすゝめ ログを構造化する エラーの情報量を増やす ❶ ❷ ❶ ❷
  4. 2つのセクションに分けて話します 18 1. ⼊⾨者向け オブザーバビリティこれからやっていき ログを構造化する エラーの情報量を増やす ❶ ❷ 💪

    Datadog を導⼊検討中、運⽤はじめた ばかりの⼈ プラグイン有効化の罠 ちょうど良い dd-trace 依存のすゝめ ❶ ❷ 👀 2. Datadog初級者向けTIPS
  5. 1. ログの “構造化” とは 19 Before: ⾮構造化(⼈間向け) After: JSON 構造化(機械向け)

    なぜ嬉しいか • フィールド単位で検索‧集計やアラート構築できる⼟台 • 後の trace_id 連携‧プロパティ付与の⼟台
  6. 1. ログの “構造化” > 設定コード例 — NestJS の場合 21 NestJS

    docs: Logger # json-logging のサンプルを参考に • 本番では JSON、ローカルでは⾊付き text • これだけでログの フィールド検索‧集計 がしやすくなる
  7. 2. エラーのプロパティを増やす 22 Before: スタックトレースとメッセージだけ After: エラークラス名 / context /

    cause を追加 • エラークラスにこれらのプロパティを適切に保持、Loggerで出⼒されるようにする • エラー発⽣時の状況 が⾒えやすくなる
  8. 2. エラーのプロパティを増やす > コード例 23 • cause チェーンで発⽣源クラスを特定, context にエラー発⽣時の状況を保持

    • ログ出⼒時に toJSON が呼び出されると各種エラー情報がログで確認できるように
  9. 次にいきましょう 24 オブザーバビリティこれからやっていき ログを構造化する エラーの情報量を増やす ❶ ❷ 💪 2. Datadog初級者向けTIPS

    👀 Datadog を導⼊検討中、運⽤はじめた ばかりの⼈ プラグイン有効化の罠 ちょうど良い dd-trace 依存のすゝめ ❶ ❷ 1. ⼊⾨者向け
  10. TIPS1: Datadogライブラリに巻き込まれてアプリが落ちた話 25 1.ドキドキのリリース完了 2.鳴り⽌まないアラート 3. リバートするしか... 事前検証もOKだったし、 ライブラリ⼊れて APM

    動かすぞ! えっ落ちるはずない… 事前にちゃんと調べたし… 他に原因なさそうだし仕⽅ない …あれ、アラート⽌まったぞ
  11. TIPS1: APMプラグインが悪さをしていた模様 26 • 後⽇調べたら Maximum call stack size exceededエラー

    が直接的な原因であることが判明 • SQLクエリなどを確認できる APMのDBプラグインを無効化することで事象を抑⽌ できた • APMのプラグインは⾃動で全て有効化される仕様 • 根本原因ははっきり特定できなかったが、おそらく GraphQL の Field Resolver による深いネスト再帰処理 とアプリのDBライブラリが関係してそう ※APMプラグイン=各種ミドルウェア/ライブラリの詳細をトレーシングできる機能
  12. TIPS1: APMプラグインが悪さをしていた模様 27 • 後⽇調べたら Maximum call stack size exceededエラー

    が直接的な原因であることが判明 • SQLクエリなどを確認できる APMのDBプラグインを無効化することで事象を抑⽌ できた • APMのプラグインは⾃動で全て有効化される仕様 • 根本原因ははっきり特定できなかったが、おそらく GraphQL の Field Resolver による深いネスト再帰処理 とアプリのDBライブラリが関係してそう ※APMプラグイン=各種ミドルウェア/ライブラリの詳細をトレーシングできる機能 APMプラグインの有効化は慎重に!
  13. 29 1.書き込み 投稿の作成/更新/削除 投稿データの永続化 変更イベントを キューイング 2.イベント発⾏ 3.メッセージ取得 4.インデックス 更新

    インデックス 更新作業 ⾼速な全⽂検索を実現 dd-trace が関知してくれない TIPS2: dd-trace に “ちょうど良く” 依存する SQS編
  14. 30 1.書き込み 投稿の作成/更新/削除 投稿データの永続化 変更イベントを キューイング 2.イベント発⾏ 3.メッセージ取得 4.インデックス 更新

    インデックス 更新作業 ⾼速な全⽂検索を実現 dd-trace が関知してくれない TIPS2: dd-trace に “ちょうど良く” 依存する SQS編 独⾃に APM のトレースを開始するような処理を書かないといけない 書き⽅によっては “dd-trace にがっつり依存するようなコード” に⚠
  15. TIPS2: dd-trace に “ちょうど良く” 依存する SQS編 31 アプリ層 ⾃作ライブラリ層 Datadog -

    ビジネスロジックに集中 - - @qast/sqs-helpers - tracer は import しない × SQS受信/メッセージ処理の抽象化 span の⽣成‧タグづけ Datadog依存をライブラリ内で完結 dd-trace による トレース情報の作成 APM / Trace @EventPattern('updateEntry') async handle(@Payload() msg) { // ビジネスロジック } handler を書くだけ await tracer.trace( `processMessage ${pattern}`, async span => { span.addTags({ 'sqs.body': message.Body }); await handleMessage(); }); ⾃作 SQS Transport内
  16. TIPS2: dd-trace に “ちょうど良く” 依存する Logger編 33 アプリ層 ⾃作ライブラリ層 Datadog -

    ビジネスロジックに集中 - - @qast/logger - tracer は import しない × trace_id / span_id が⾃動付与 Logs (構造化ログ) APM / Trace this.logger.log( ‘User updated entry’, { entryId, userId } ); logger を呼び出すだけ const span = tracer.scope().active(); if (span) { tracer.inject( span.context(), formats.LOG, output ); } ⾃作 Logger 内 対応するリクエスト‧処理にジャンプ trace_id / span_id で紐付け ..., "dd": { "trace_id": "1234567890...", "span_id": "9876543210..." }
  17. まとめ 34 1. ⼊⾨者向け オブザーバビリティこれからやっていき 2. Datadog初級者向けTIPS Datadog を導⼊検討中、運⽤はじめた ばかりの⼈

    プラグイン有効化の罠 ちょうど良い dd-trace 依存のすゝめ ログを構造化する エラーの情報量を増やす ❶ ❷ ❶ ❷ 💪 👀
  18. 35

  19. おまけ. ログに共通コンテキストを載せる 36 Before: 「何が起きた」だけ After: 「誰の何の処理か」が全ログ共通でわかる • 単発ログ →

    requestId などをベースに一連の 追跡可能なログへ • 顧客からの問い合わせに対応しやすくなる
  20. おまけ. 共通コンテキスト > コード例 37 • 呼び出し側は何も意識せず logger を呼び出せば適切な context

    がセットされる • NestJSでは nestjs-cls ライブラリを使うのが慣⽤だったりする
  21. 38