Observability
オブザーバビリティとは、システムが出力するログ、メトリクス、トレースから内部状態を説明できる能力です。OpenTelemetryとMLオブザーバビリティを解説します。
可観測性とは、ソフトウェアシステムが出力するテレメトリ、主にログ、メトリクス、トレースから、コードを新たにデプロイせずにシステムの動作について新たな疑問に答えられる程度まで、内部で何が起きているかを理解できる性質です。この用語は制御理論に由来します。Rudolf Kálmánは1960年、システムの出力から内部状態を特定できる場合、そのシステムは可観測であると定義しました。システムが多数のサービスに分割され、障害が事前に構築されたダッシュボードの想定と一致しなくなった2010年代に、ソフトウェアチームがこの概念を取り入れました。機械学習システムでは、可観測性はデータと予測も対象とします。モデルがどのような入力を受け取り、何を出力し、どれほど確信しているか、そしてそれらが時間とともにどう変化するかを把握します。
ログ、メトリクス、トレース#
可観測性の3本柱とも呼ばれる3種類のテレメトリは、それぞれ異なる疑問に答えます。
- メトリクス: リクエスト率、エラー率、レイテンシのパーセンタイル、メモリ、GPU使用率などの数値時系列です。保存コストが低く、ダッシュボードやアラートに適しています。Googleのサイト信頼性エンジニアリングの書籍では、すべてのサービスで測定すべき4つのゴールデンシグナルとして、レイテンシ、トラフィック、エラー、飽和度を挙げています。
- ログ: 個々のイベントを時刻付きで記録したものです。リクエストID、モデルバージョン、入力サイズなどのフィールドを持つJSON形式にすると、フィルタリングや集計がしやすくなります。
- トレース: 1つのリクエストが通過するすべてのサービスをたどった記録です。各スパンに名前、開始時刻、所要時間、属性を持たせたツリーとして記録することで、リクエストがどこで時間を費やしたかが分かります。
2019年にOpenTracingプロジェクトとOpenCensusプロジェクトを統合して設立されたOpenTelemetryは、3種類すべてのシグナルに対応するベンダー中立のAPI、SDK、ワイヤープロトコル(OTLP)を提供します。Prometheus、Grafana、Jaegerなどのバックエンドは、それらを保存して表示します。次の例では、OpenTelemetry Python SDKを使って1件の画像分類リクエストをトレースし、リクエストの親スパンと各処理段階の子スパンを記録します。
import torch
import torchvision
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter
# Keep finished spans in memory; a production service exports them over OTLP instead
exporter = InMemorySpanExporter()
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(exporter))
tracer = provider.get_tracer("classifier")
model = torchvision.models.resnet18().eval()
frame = torch.rand(3, 1080, 1920)
# Trace one request as a parent span with a child span for each stage
with tracer.start_as_current_span("predict", attributes={"model.name": "resnet18", "image.height": 1080}):
with tracer.start_as_current_span("preprocess"):
batch = torchvision.transforms.functional.resize(frame, [224, 224]).unsqueeze(0)
with tracer.start_as_current_span("inference"), torch.inference_mode():
logits = model(batch)
spans = exporter.get_finished_spans()
names = {span.context.span_id: span.name for span in spans}
for span in spans:
parent = names[span.parent.span_id] if span.parent else "-"
print(f"{span.name:<11} {(span.end_time - span.start_time) / 1e6:5.1f} ms parent: {parent}")Apple M5 Pro CPUでは、preprocessスパンが1.0~1.4ミリ秒、inferenceスパンが7~9ミリ秒と出力されます。どちらも親スパンはpredictです。また、predictスパンは8~10ミリ秒で、トレースからリクエスト時間の大半をモデルが占めていることが分かります。スパンがOTLP経由でエクスポートされると、リクエストを処理する各サービスが同じトレースIDの下にスパンを追加し、Jaegerなどのバックエンドがそれらを1つのタイムラインとして表示します。
可観測性とモニタリング#
モデルモニタリングは、エラー率が1%を超える、または推論レイテンシが目標値を超えるといった、既知の障害パターンを事前定義したメトリクス、ダッシュボード、アラートしきい値で監視します。可観測性はより広い概念で、顧客、モデルバージョン、カメラなど、任意の属性で詳細なテレメトリを事後に切り分けることで、想定外の障害を調査できるようにします。Google SREの書籍では、モニタリングが答えるべき質問を「何が壊れているか」と「なぜか」の2つとし、調査では3種類すべてのシグナルをたどって、最初の答えから次の答えへ進みます。
説明可能なAIは別の分野で、入力特徴や内部活性化から、モデルが特定の出力を生成した理由を説明します。その寄与度を、追加のシグナルとしてログに記録することもできます。
機械学習における可観測性#
機械学習システムでは、障害が表面化しないことがよくあります。コンピュータービジョンモデルは、カメラの移動、照明の変化、新製品の登場によって予測精度が低下していても、すべてのリクエストにHTTP 200を返すことがあります。そのため、MLの可観測性では、通常のサービスシグナルにデータと予測のテレメトリを加えます。チームは、画像サイズや明るさなどの入力統計を記録してデータドリフトを検出し、クラス数、空の結果、平均信頼度などの予測分布を追跡します。また、多くの場合は数日後にグラウンドトゥルースラベルが届いてから、セグメントごとの精度を算出します。学習中は、コールバックが各実行の損失曲線、メトリクス、システム使用状況を実験トラッキングツールに送信します。ツールにはTensorBoardやMLflowなどがあります。AIエージェントや大規模言語モデルのアプリケーションでは、トレースに各プロンプト、検索段階、ツール呼び出し、応答が記録されます。OpenTelemetry GenAIのセマンティック規約は、gen_ai.usage.input_tokensなどの属性を標準化し、トークン数やコストをツール間で比較できるようにします。
Ultralytics Platformの専用エンドポイントには、デプロイメントモニタリングが組み込まれています。リクエスト数、エラー率、p95レイテンシのカード、重大度レベルとエラー・警告エントリー用のErrorsフィルターを備えたLogsタブ、上位クラス、時間経過に伴う平均信頼度、画像あたりの予測数、リクエストレイテンシとは別に表示されるモデル推論時間の予測統計が含まれます。すべてのリクエストが成功していても、信頼度の低下や上位クラスの変化はこれらのグラフに現れます。










