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

Webアプリケーションにオブザーバビリティを実装するRust入門ガイド

Avatar for nwiizo nwiizo
September 10, 2025

 Webアプリケーションにオブザーバビリティを実装するRust入門ガイド

2025年9月10日(水)、「Rustの現場に学ぶ〜Webアプリの裏側からOS、人工衛星まで〜」というイベントで登壇させていただきます。

https://findy.connpass.com/event/359456/

他の登壇者の話が聞きたすぎるけど調整能力の圧倒的な不足で登壇したらすぐに帰らなければなりません。

今回の発表内容のベースとなったのはこちらのブログです。
- 「RustのWebアプリケーションにオブザーバビリティを実装するインフラエンジニアのための入門ガイド」

Avatar for nwiizo

nwiizo

September 10, 2025
Tweet

More Decks by nwiizo

Other Decks in Technology

Transcript

  1. オブザーバビリティの三本柱 CNCFが定義するPrimary Signals ログ (Logs): 何が起きたかの記録 メトリクス (Metrics): どれくらいの量か トレーシング

    (Traces): どのように流れたか 💡 三本柱を組み合わせて、システムの振る舞いを理 解する https://github.com/cncf/tag-observability より引用 7
  2. 実装時のシグナル相関 トラブルシューティングでの活用例:ECサイトで深夜3時に注文処理が遅延 1. トレース(OpenTelemetry)で調査開始 注文API: 15秒(通常は500ms) └─ 在庫確認: 200ms ✓

    └─ 決済処理: 14.5秒 └─ DB接続待機: 14秒 2. メトリクス(Prometheus)で状況確認 DB接続プール: 100/100(満杯) 、CPU使用率: 95%(異常高負荷) 、メモリ: 正常範囲 3. ログ(構造化ログ)で根本原因発見 { "level": "ERROR", "time": "03:00:12", "msg": "バッチ処理が大量のDB接続を占有", "batch_id": "daily_report", "connections": 80 } → 原因: 深夜バッチとAPIが接続プールを奪い合い https://github.com/cncf/tag-observability より引用 9
  3. TEMPLE: Six Pillars of Telemetry 三本柱を拡張したTEMPLEフレームワーク Traces - 分散システムでのリクエスト追跡 Events

    - 重要な状態変化の記録 Metrics - システムの定量的測定 Profiles - パフォーマンス詳細分析 Logs - 詳細なコンテキスト情報 Errors - エラーの包括的な追跡 TEMPLE: Six Pillars of Observability より引用 10
  4. ログの実装 log crateを使った基本的なログ実装 use log::{info, warn, error, debug}; // 初期化(env_loggerの場合)

    fn main() { env_logger::init(); // RUST_LOG環境変数で制御 log::error!("This is an error!"); log::info!("This is info!"); log::warn!("This is a warning!"); } // 実行方法 // $ RUST_LOG=info cargo run 💡 もっとも標準的なログで困ったらこれを使っていれば良いと思います log がインターフェース役で、実際の出力は env_logger などが担当。 ログレベルは環境変数で制御できるので、開発と本番で使い分けが簡単。 11
  5. より高度なログ:構造化とファイル出力 2つのアプローチ log4rs - 設定ファイルベース Javaのlog4jを知ってる人なら「あー、あれね」って感じ。 YAMLで細かく設定できるから、運用チームが喜ぶタイプ。 本番環境でログレベルを変えたい時とかに便利。 # log4rs.yaml

    appenders: stdout: kind: console encoder: { kind: json } file: kind: file path: "app.log" root: level: info appenders: [stdout, file] tracing-subscriber - コードベース Rustらしい「型で守る」アプローチです。 レイヤーを重ねてカスタマイズできるのが特徴的です。 非同期処理のログを追うならこちらが圧倒的に便利です。 use tracing_subscriber::{ fmt::writer::MakeWriterExt, layer::SubscriberExt }; let file_appender = tracing_appender::rolling::daily( "logs", "app.log" ); // 非同期・非ブロッキング出力 12
  6. HTTPリクエストのログ実装 Warpのカスタムログ機能でリクエスト情報を自動記録 フレームワーク側でロギングの機構を用意していることも多いので機能と限界を知っておくことが大切です 「APIが遅い」と言われた時、これがないと原因特定が困難になります。レスポンスタイムとステータスコードは最低限記録しておこう。 let log = warp::log::custom(|info| { log::info!(

    "{} {} {} {:?} from {}", info.method(), info.path(), info.status(), info.elapsed(), info.remote_addr().unwrap() ); }); let routes = get_questions .or(update_question) .or(add_question) .with(cors) .with(log) // ログフィルタを追加 .recover(return_error); 💡 メソッド、パス、ステータス、処理時間、クライアントIPを構造化して記録 出力例: `GET /questions 200 OK 254.528µs from 127.0.0.1:51439` 13
  7. 構造化ログ:機械可読性の向上 JSON形式での出力例 { "time": "2024-03-15T10:30:45.123Z", "message": "GET /questions 200 OK

    254.528µs from 127.0.0.1:51439", "module_path": "practical_rust_book", "file": "src/main.rs", "line": 20, "level": "INFO", "target": "practical_rust_book", "thread": "tokio-runtime-worker", "thread_id": 123145515622400, "request_id": "5da2bc97-e960-4984-be8a-d75be4728119" } 💡 JSONで出力さえしていれば、どんなログ収集サービスでも助かる。CloudWatch Logs、Datadog、Elasticsearch、どこでも対応可能です。 構造化ログは「クラウド時代の当たり前」です。というか、これがないとログの解析が大変です。 14
  8. メトリクスの実装:2つのアプローチ prometheus vs metrics クレート prometheus クレート もともとGoで書かれたPrometheusの正統派Rust版です。 起動時にすべてのメトリクスを定義する必要があるけど、 その分タイプセーフで間違いが起きにくい設計になっています。

    use prometheus::{ IntCounter, Registry, Encoder, TextEncoder }; use once_cell::sync::Lazy; static HTTP_REQUESTS: Lazy<IntCounter> = Lazy::new(|| { IntCounter::new( "http_requests_total", "Total HTTP requests" ).unwrap() }); // 使用 HTTP_REQUESTS.inc(); metrics クレート logクレートと同じ思想で作られた新しいアプローチです。 実行時に動的にメトリクスを作れるので柔軟性が高くなっています。 バックエンドを自由に選べます(Prometheus、StatsD等) 。 use metrics::{counter, histogram}; // よりシンプルなAPI counter!("http_requests_total").increment(1); histogram!("request_duration_seconds") .record(duration.as_secs_f64()); // metrics-prometheusで // Prometheus形式にエクスポート 15
  9. トレーシング OpenTelemetryの基本概念 📏 Span リクエスト内の各処理の情報 (処理名、実行時間、ステータス等) 🔗 Trace あるリクエストに対する Spanのまとまり

    📡 Context Span間の親子関係や リクエストIDの伝播 💡 1つのリクエスト(Trace)は複数の処理(Span)から構成される 各Spanが親子関係を持つことで、処理の流れが可視化される! 16
  10. なぜトレーシングが必要なのか 並行処理とマイクロサービスの複雑性に対処 従来のログの問題点 // 複数のリクエストが同時に処理されると... [2025-01-28 10:00:01] INFO: リクエスト開始 [2025-01-28

    10:00:01] INFO: リクエスト開始 // どっちがどっち? [2025-01-28 10:00:02] ERROR: DB接続エラー // どのリクエストの? Tracingで解決 // 各リクエストにIDが自動付与される [span_id=abc123] INFO: リクエスト開始 user_id=42 [span_id=def456] INFO: リクエスト開始 user_id=99 [span_id=abc123] ERROR: DB接続エラー // user_id=42のリクエストだ! 🎯 非同期処理でもリクエストの流れを追跡できる APIゲートウェイ → 認証サービス → ビジネスロジック → DBと 複数のマイクロサービスを横断する処理も一貫して追える! 17
  11. Tracingの実装例 関数の処理時間を自動で記録する仕組み use tracing::{instrument, info}; use std::collections::HashMap; #[instrument( skip(store), //

    大きなデータはスキップ fields( user_id = %params.get("user_id").unwrap_or(&String::from("anonymous")), method = "GET" ) )] pub async fn get_questions( params: HashMap<String, String>, store: Store, ) -> Result<impl warp::Reply, warp::Rejection> { info!("querying questions"); // 処理... } // {"level":"INFO","span":{"name":"get_questions","user_id":"42"},"message":"querying questions"} // {"level":"INFO","span":{"name":"get_questions"},"message":"close","elapsed_ms":333} 💡 関数の開始/終了時刻と処理時間が自動記録される! 19
  12. 三本柱で何を測るべきか ビジネス価値に関連する情報を収集していく ログ: エラーの詳細と文脈情報 // エラーが起きたときに詳細情報を記録 error!(user_id = %id, error

    = ?e, "決済処理失敗"); メトリクス: ビジネスに直結する数値 // 決済完了の回数をカウント counter!("payment_completed_total", "currency" => "JPY"); トレーシング: クリティカルパスの処理時間 // この関数の実行時間を自動で記録(dbは大きいのでスキップ) #[instrument(skip(db), fields(order_id = %id))] 22
  13. まとめ 1. Rustでオブザーバビリティを始める ログ・メトリクス・トレーシングの三本柱で内部状態を理解 tracing クレートで簡単に開始、 #[instrument] で自動計測 まずは tracing

    から始めて、必要に応じて拡張 2. 実装時の重要な考え方 「何でも見える」ではなく「見るべきものを見る」 ビジネス価値とアクションに繋がる情報のみ収集 24
  14. 参考文献(1/2) 書籍 『測りすぎ―― なぜパフォーマンス評価は失敗するのか? 』 『入門監視』 『オブザーバビリティエンジニアリング』 『Zero To Production

    In Rust』 特に推奨 『Zero To Production In Rust』は実践的なRust Webアプリケーショ ン開発とオブザーバビリティの実装を同時に学べる最良の一冊 26
  15. 参考文献(2/2) オンラインリソース・技術ドキュメント 公式ドキュメント Rust log crate - Rustのロギング標準 tracing クレート

    - 非同期Rust向けトレーシング OpenTelemetry Rust prometheus-rust 技術ブログ・記事 もう一度読むObservability Engineering RustのWebアプリケーションにオブザーバビリティを実装するインフラエンジニアのための入門ガイド 缶つぶし機とソフトウェア移行技術 - Refactoring to Rust の読書感想文 State of the Crates 2025 CNCF Observability Whitepaper 27