Slide 1

Slide 1 text

Webアプリケーションに オブザーバビリティを実装する Rust入門ガイド 2025/9/10 Rustの現場に学ぶ 〜Webアプリの裏側からOS、人工衛星まで〜 @nwiizo 15min #rust_findy

Slide 2

Slide 2 text

nwiizo 株式会社スリーシェイクで プロのソフトウェアエンジニ アをやっているものです 格闘技、読書、グラビアが趣味 でよく本を紹介しています 人生を通して"運動、睡眠、読書"をきちんとやりたい 2

Slide 3

Slide 3 text

about 3-shake 3

Slide 4

Slide 4 text

We are Hiring!! 3-shakeは一緒にSRE界隈を盛り上げてくれる仲間を大募集中です! Mobility、FinTech、通信など大規模SREを存分に経験できます (最近社内はGenAI / GPU / Kubernetesが盛り上がってます) 是非、カジュアル面談しましょう!!!! 4

Slide 5

Slide 5 text

オブザーバビリティとは CNCFの定義から理解する 制御理論において、 「オブザーバビリティとは、シ ステムの外部出力の知識から、そのシステムの内 部状態をどれだけ推測できるかの尺度」という概 念から拝借している CNCF Observability Whitepaper v1.0より 2023年10月リリース TAG Observabilityが主導 コミュニティ主導の包括的なガイド https://github.com/cncf/tag-observability より引用 5

Slide 6

Slide 6 text

オブザーバビリティとは 変化していくシステムを理解するための能力 システムを理解するための能力であり、ソフトウ ェアの複雑性が増すにつれて、オブザーバビリテ ィの必要性も高まっています。 Observability Engineeringの第二版がリリースされ ます。個別に収集されたバラバラなシグナルか ら、統一されたデータワークフローへと進化させ る方法を解説しています。 第二版では、現在の技術動向を踏まえた最新のプ ラクティスが紹介されています。特に最近は生成 AI関連でobservabilityの重要性も在り方も大きく変 わってきています。 https://learning.oreilly.com/library/view/observability-engineering- 2nd/9781098179915/ より引用 6

Slide 7

Slide 7 text

オブザーバビリティの三本柱 CNCFが定義するPrimary Signals ログ (Logs): 何が起きたかの記録 メトリクス (Metrics): どれくらいの量か トレーシング (Traces): どのように流れたか 💡 三本柱を組み合わせて、システムの振る舞いを理 解する https://github.com/cncf/tag-observability より引用 7

Slide 8

Slide 8 text

シグナルの相関関係 オブザーバビリティの真価は相関分析にある 単一のシグナルでは見えない問題も、複数のシグ ナルを相関させることで原因が明らかになる 例: トレースでレイテンシの増加を発見 メトリクスでCPU使用率の急上昇を確認 ログで特定のエラーパターンを特定 https://github.com/cncf/tag-observability より引用 8

Slide 9

Slide 9 text

実装時のシグナル相関 トラブルシューティングでの活用例: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

Slide 10

Slide 10 text

TEMPLE: Six Pillars of Telemetry 三本柱を拡張したTEMPLEフレームワーク Traces - 分散システムでのリクエスト追跡 Events - 重要な状態変化の記録 Metrics - システムの定量的測定 Profiles - パフォーマンス詳細分析 Logs - 詳細なコンテキスト情報 Errors - エラーの包括的な追跡 TEMPLE: Six Pillars of Observability より引用 10

Slide 11

Slide 11 text

ログの実装 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

Slide 12

Slide 12 text

より高度なログ:構造化とファイル出力 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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

構造化ログ:機械可読性の向上 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

Slide 15

Slide 15 text

メトリクスの実装:2つのアプローチ prometheus vs metrics クレート prometheus クレート もともとGoで書かれたPrometheusの正統派Rust版です。 起動時にすべてのメトリクスを定義する必要があるけど、 その分タイプセーフで間違いが起きにくい設計になっています。 use prometheus::{ IntCounter, Registry, Encoder, TextEncoder }; use once_cell::sync::Lazy; static HTTP_REQUESTS: Lazy = 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

Slide 16

Slide 16 text

トレーシング OpenTelemetryの基本概念 📏 Span リクエスト内の各処理の情報 (処理名、実行時間、ステータス等) 🔗 Trace あるリクエストに対する Spanのまとまり 📡 Context Span間の親子関係や リクエストIDの伝播 💡 1つのリクエスト(Trace)は複数の処理(Span)から構成される 各Spanが親子関係を持つことで、処理の流れが可視化される! 16

Slide 17

Slide 17 text

なぜトレーシングが必要なのか 並行処理とマイクロサービスの複雑性に対処 従来のログの問題点 // 複数のリクエストが同時に処理されると... [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

Slide 18

Slide 18 text

Spanの概念を視覚的に理解する 分散トレーシングの実際の姿 画像引用: https://lightstep.com/opentelemetry/spans 親子関係 各Spanが階層構造を持ち、処理の流れを表現 処理時間 各サービスでの処理時間が横幅で表示 ボトルネック 最も時間がかかっている処理が一目瞭然 依存関係 どのサービスがどのサービスを呼び出しているか 💡 Rustの #[instrument] マクロで、 この図のようなトレース情報を自動生成! 18

Slide 19

Slide 19 text

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, store: Store, ) -> Result { 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

Slide 20

Slide 20 text

Tracing関連ライブラリ 用途に応じた選択肢を広げる。足りなかったら自分で作れ! 主要なトレーシングライブラリ tracing-opentelemetry Jaeger/Zipkinへの送信。OpenTelemetry準拠で将来性◎ tracing-bunyan-formatter Bunyan形式(業界標準) 。Elasticsearch/Datadogと相性良し tracing-error エラー時のスタックトレース自動記録。 color-eyre と最強タッグ tracing-appender 非同期ファイル出力。日次ローテーション対応 💡 まずは tracing と tracing-subscriber だけで始めよう! 20

Slide 21

Slide 21 text

実装後の新たな課題 観測可能性の向上がもたらす意図しない影響 技術の進歩と運用の複雑性 観測能力の飛躍的向上 あらゆるデータが取得可能に リアルタイムでの可視化 高度な相関分析が容易に 新たに生まれる課題 情報の洪水への対処 真に重要な指標の選別 チームの認知的負荷 21

Slide 22

Slide 22 text

三本柱で何を測るべきか ビジネス価値に関連する情報を収集していく ログ: エラーの詳細と文脈情報 // エラーが起きたときに詳細情報を記録 error!(user_id = %id, error = ?e, "決済処理失敗"); メトリクス: ビジネスに直結する数値 // 決済完了の回数をカウント counter!("payment_completed_total", "currency" => "JPY"); トレーシング: クリティカルパスの処理時間 // この関数の実行時間を自動で記録(dbは大きいのでスキップ) #[instrument(skip(db), fields(order_id = %id))] 22

Slide 23

Slide 23 text

2025年のオブザーバビリティトレンド OpenTelemetryの成熟と実装の選択肢 OpenTelemetryが実用段階へ opentelemetry-rust がv0.30.0でMetrics API/SDKが安定 版に ログ・メトリクス・トレースを統一的に扱える ベンダー中立で将来の移行が容易 Rustでの実装選択肢 // シンプルに始めるなら tracing + tracing-subscriber // 本格的な実装なら opentelemetry + opentelemetry-otlp 23

Slide 24

Slide 24 text

まとめ 1. Rustでオブザーバビリティを始める ログ・メトリクス・トレーシングの三本柱で内部状態を理解 tracing クレートで簡単に開始、 #[instrument] で自動計測 まずは tracing から始めて、必要に応じて拡張 2. 実装時の重要な考え方 「何でも見える」ではなく「見るべきものを見る」 ビジネス価値とアクションに繋がる情報のみ収集 24

Slide 25

Slide 25 text

最後にメッセージ 測定は手段であって目的ではない オブザーバビリティはあくまでも問題解決のツール システムの健全性を維持するために使う チームの改善を促進するために使う 監視のための数値の収集が目的にならないよう注意 数値の最適化が目的にならないよう注意 25

Slide 26

Slide 26 text

参考文献(1/2) 書籍 『測りすぎ―― なぜパフォーマンス評価は失敗するのか? 』 『入門監視』 『オブザーバビリティエンジニアリング』 『Zero To Production In Rust』 特に推奨 『Zero To Production In Rust』は実践的なRust Webアプリケーショ ン開発とオブザーバビリティの実装を同時に学べる最良の一冊 26

Slide 27

Slide 27 text

参考文献(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

Slide 28

Slide 28 text

ありがとうございました ご質問・ご相談はお気軽にお問い合わせください @nwiizo | https://3-shake.com