OTEP-0147: OpenTelemetryにおけるアップグレードの考え方

広く分散されたソフトウェアを大規模に管理するには、後方互換性、バージョニング、アップグレードに関する慎重な設計が必要です。 OpenTelemetryのアプローチを以下で説明します。 OpenTelemetryの利用を検討している方は、私たちがこの問題にどのように取り組んでいるかを理解しておくと役に立つでしょう。

コンポーネントの概要

スムーズなアップグレードと長期的なサポートを実現するため、OpenTelemetryクライアントはいくつかのコンポーネントに分割されています。 このドキュメントの以降の部分では、次の用語を使用します。

パッケージ(Packages)とは、何らかの依存関係管理の仕組みを通じて互いを参照するコード単位を指す一般的な用語です。 プログラミング言語ごとに依存関係管理へのアプローチは異なり、この概念を表すのにモジュール(module)やライブラリ(library)といった別の用語が使われることもあります。

API とは、OpenTelemetryの計装を書くために必要なすべてのインターフェースと定数を含むソフトウェアパッケージ群を指します。 APIの実装は、アプリケーションの起動時に登録できます。 他の実装が登録されていない場合、APIはデフォルトでno-op実装を登録します。

SDK とは、OpenTelemetryプロジェクトが提供する、APIを実装するフレームワークを指します。 特殊なケースを扱うために代替のAPI実装が書かれることもありますが、ほとんどのユーザーはOpenTelemetryを実行する際にSDKをインストールすることを想定しています。

プラグインインターフェース(Plugin Interfaces)とは、SDKが提供する拡張ポイントを指します。 これには、サンプリングの制御、データのエクスポート、その他さまざまなライフサイクルフックのためのインターフェースが含まれます。 なお、これらのインターフェースはAPIの一部ではありません。SDKの一部です。

計装(Instrumentation)とは、APIを呼び出すすべてのコードを指します。 これには、OpenTelemetryプロジェクトが提供する計装、サードパーティの計装、さらにはアプリケーションコードやライブラリ自身がネイティブに行う計装が含まれます。

プラグイン(Plugins)とは、SDKのプラグインインターフェースを実装するあらゆるパッケージを指します。 これには、OpenTelemetryプロジェクトが提供するプラグインと、サードパーティのプラグインが含まれます。

プラグインと計装の間には重要な違いがあります。 プラグインはプラグインインターフェースを実装します。計装はAPIを呼び出します。 この違いは、OpenTelemetryのアップグレードへのアプローチに関係しています。

OpenTelemetryのアップグレードパス

設計要件について説明する前に、実際のアップグレードがどのように機能するかを説明します。 なお、OpenTelemetryのすべてのコンポーネント(API、SDK、プラグイン、計装)は、それぞれ独立したバージョン番号を持っています。

APIの変更

OpenTelemetry APIに新しい機能が追加されると、APIの新しいマイナーバージョンがリリースされます。 これらのAPIの変更は常に追加的なものであり、以前のバージョンをインポートして呼び出す既存の計装パッケージの視点から見て後方互換性があります。 以前のすべてのマイナーバージョンのAPIに対して書かれた計装は動作し続け、依存関係の競合を発生させることなく同じアプリケーションに組み合わせることができます。

API実装は、常にAPIの最新バージョンを対象とすることが期待されています。 APIの新しいバージョンがリリースされると、そのAPIをサポートするバージョンのSDKが並行してリリースされます。 APIの新しいバージョンが、古いバージョンのSDKをサポートすることは想定されていません。

SDKの変更

バグ修正、セキュリティパッチ、パフォーマンス改善は、SDKのパッチバージョンとしてリリースされます。 APIの新しいバージョンへのサポートは、マイナーバージョンとしてリリースされます。 新しいプラグインインターフェースや設定オプションも、マイナーバージョンとしてリリースされます。

プラグインインターフェースに対する破壊的変更は、非推奨化を通じて処理されます。 プラグインインターフェースを破壊する代わりに、新しいインターフェースが作成され、既存のインターフェースは非推奨としてマークされます。 非推奨のインターフェースを対象とするプラグインは動作し続け、SDKは不足している機能のデフォルト実装を提供します。 1年後、非推奨のプラグインインターフェースは、SDKのメジャーバージョンリリースとして削除されます。

設計要件とその説明

このアップグレードへのアプローチは、レガシーコードに関連する保守オーバーヘッドを最小限に抑えつつ、2つの重要な設計要件を解決します。

  • APIの呼び出し元が壊れることは決してありません。
  • SDKのユーザーは、最新バージョンへ簡単にアップグレードできます。

既存の計装を無期限にサポートすることは、OpenTelemetryの重要な機能です。 何百万行ものコードがAPIに対して書かれることが見込まれています。 これには、OpenTelemetryの計装が組み込まれた状態で出荷される共有ライブラリも含まれます。 これらのライブラリは、OpenTelemetryが依存関係の競合を生じさせることなく、アプリケーションに組み合わせて使用できなければなりません。 OpenTelemetryプロジェクトが提供するものなど、一部の計装は最新バージョンのAPIに更新されますが、それ以外の計装は決して更新されないこともあります。

新しい計装を利用するには、ユーザーが最新バージョンのSDKにアップグレードする必要が生じることがあります。 このアップグレードを容易に行えないとすると、OpenTelemetryプロジェクトは、古いバージョンのSDKや、計装エコシステム全体の古いバージョンをサポートせざるを得なくなってしまいます。

これは、最善のケースでも膨大な保守作業になります。 しかも、OpenTelemetryプロジェクトはそのエコシステムの一部しか管理していないため、そもそも実現不可能です。 OpenTelemetryは、ネイティブな計装を持つライブラリに対して、複数バージョンのAPIをサポートすることを要求できません。 アプリケーションのオーナーやオペレーターが最新バージョンのSDKにアップグレードできることを保証することで、この問題は解決されます。

SDKのアップグレードを妨げる主な要因は、古くなったプラグインです。 新しいバージョンのSDKが既存のプラグインインターフェースを破壊してしまうと、依存しているプラグインがアップグレードされるまで、ユーザーは誰もSDKをアップグレードできなくなります。 ユーザーは、依存する計装が必要とするAPIのバージョンと、自分のプラグインをサポートするSDKのバージョンとの間で板挟みになる可能性があります。

プラグインインターフェースについて非推奨化のパターンに従うことで、新しいSDKのリリース後にプラグインエコシステムがアップグレードできる1年間の猶予期間が生まれます。 私たちは、これは積極的にメンテナンスされているプラグインがアップグレードを行うのに十分な期間であり、また使われなくなったプラグインを識別して置き換えるのにも十分な期間であると考えています。

SDKを簡単にアップグレードできるようにすることで、アプリケーションのオーナーやオペレーターが、多数の以前のSDKバージョンにわたってパッチをバックポートする必要なく、重要なバグ修正やセキュリティパッチを迅速に取り込めるようにする道も提供されます。