> Source: https://www.ymotongpoo.com/works/oteps/otep-0001/


# OTEP-0001: 手動計装をしない（オープン）テレメトリー

_ソースコードの変更なしでポータブルなテレメトリーデータを抽出するための自動化されたアプローチのための言語横断的要件_

## 動機

OpenTelemetryの目的は、ロバストでポータブルなテレメトリーを、クラウドネイティブソフトウェアのビルトイン機能にすることです。
ソフトウェアや状況によっては、その計装は文字通りソースコードの一部になり得ます。
他の状況では、それほど単純ではありません。
たとえば、私たちは必ずしもソフトウェアを修正したり、再コンパイルすることさえできませんし、OpenTelemetryの計装はプラグインとしてしか存在しない、あるいは、計装がサービスオーナーにとって優先順位のトップに上がることはありません。
さらに、開発者がソースコードに変更を加えることなく、ときには単一のプラグインやモジュールの計装を実行時に無効にしたいことがあります。

このような状況を回避する一つの方法は、サービスのソースコードを変更することなく、OpenTelemetryの計装をサービスに追加するソフトウェアレイヤーを使うことです。
（従来のAPMの世界では、このようなソフトウェアレイヤーはしばしば「エージェント」と呼ばれますが、この用語は多義で曖昧なので、このドキュメントでは使用を避けています。）

### なぜ「言語横断的」なのか

多くの人が、「エージェント」 のデザインは非常に言語に依存するものだと正しく認識しています。
たしかにそれは事実です。
しかし、それでもなお、私たちが言語を超えて行う設計の指針となり、OpenTelemetryが何を提供するのか（そして何を提供しないのか）について、ユーザーが一貫した印象を形成する助けとなる、より高い次元でのOpenTelemetryの「製品」としての目的があります。

### 推薦参考文書

* このGitHub Issue: [Propose an "Auto-Instrumentation SIG"](https://github.com/open-telemetry/community/pull/87)
* 上のイシューに関する[2019年6月11日のミーティングノート](https://docs.google.com/document/d/1ix0WtzB5j-DRj1VQQxraoqeUuvgvfhA6Sd8mF5WLNeY/edit)
* コメントを含めた[このRFCのドラフト](https://docs.google.com/document/d/1sovSQIGdxXtsauxUNp4qUMEIJZzObdukzPT52eyPCHM/edit#)

## ガイドライン案

### 必要条件

前置きはこれくらいにして、「公式な」OpenTelemetryの取り組みが、任意の言語で、ソースコードの変更なしの計装（すなわち、「OpenTelemetryエージェント」）を達成するために必要な一連の要件を示します。

* _手作業_ によるソースコードの改変は「非常に強く推奨しません」。
  ただし、信頼できる代替手段がない言語や環境については例外とします。
  コードの変更は些細なもので、ソースファイルごとに（関数ごとなどではなく）`O(1)` でなければなりません。
* ライセンスは寛容でなければなりません。（例：ASL / BSD）
* パッケージングによって、ベンダーはポータブルな（OpenTelemetryの）ライブラリを「ラップ」したり、顧客に提供される単一のアセットにリパッケージすることができなければなりません。
  * つまり、ベンダーはユーザーにOpenTelemetryパッケージとベンダー固有のパッケージの両方を理解することを要求したくないのです。
* 明示的な、ホワイトボックスのOpenTelemetry計装は、「自動」/ソースコードの変更なし/ブラックボックスの計装と相互運用しなければなりません。
  * ブラックボックスな計装がスパンを開始する場合、ホワイトボックスな計装はそれをアクティブなスパンとして検出できなければなりません（逆も同様）。
  * 関連して、明示的なホワイトボックスな計装と、同じライブラリ／パッケージのブラックボックスな計装との潜在的な競合／重複／冗長性を発見し、回避する方法も必要です。
    * つまり、ある開発者が、たとえばgRPCのための「公式な」OpenTelemetryプラグインをすでに追加している場合、ブラックボックスな計装の取り組みがgRPCサポートを追加するとき、「二重の計装」をして、余分なスパンなどの混乱を生じさせるべきでは _ありません_ 。
* 実際に収集されるテレメトリーの観点からは、「ホワイトボックス」計装と自動計装には、同じ標準と期待（タグ付け、メタデータなど）が適用されます。
* OpenTelemetryパッケージのコードは、特定のベンダーに強く依存してはなりません（その種の機能は、プラグインやレジストリのメカニズムで動作するはずです）。
  * さらに、OpenTelemetryパッケージのコードは、ホストアプリケーションとの衝突の可能性を避けるために分離されていなければなりません（たとえば、Javaでのシェーディングなど）。

### 追加条件

* ランタイムでの統合（対コンパイルタイムでの統合）
* 個々のライブラリやパッケージプラグインの自動化されモジュール化されたテスト
  * これは、任意のライブラリの異なる複数バージョンに対してテストを実施することが容易になるということでもあります。
* 完全にプラガブルなアーキテクチャ。
  これは github.com/open-telemetry という中央のリポジトリに変更を加えなくてもプラグインがランタイムに登録できるというアーキテクチャです。
  * 例: 再コンパイルできないレガシーなソフトウェアのプロプライエタリな部分に対するプラグインを書きたい運用チームのための機能
* ブラックボックスな計装によるホワイトボックスな計装の拡張（あるいは、その逆）。
  つまり、トレースコンテキストをこれらの異なる種類の計装で共有できるだけでなく、処理中のスパンオブジェクトのようなものでさえも共有し、共同修正することができます（たとえば、ランタイム介入を使用してローカル変数を取得し、手動で計装されたスパンにアタッチする）。

## トレードオフと緩和策

このような言語固有の問題に言語横断的にアプローチすることは、「言語が異なれば異なる」ため、本質的に困難です。
たとえば、Goでは、PythonやRuby、あるいはJavaで可能なようなランタイム介入を実行する方法はありません。

また、実行中のプロセスから実際にエスケープされるビットとバイトだけに注目し、それが実際にどのように達成されるかは無視すべきだという考え方もあります。
これにはある種の上品さがありますが、特に（共有された）分散コンテキストそのものに関しては、ゼロタッチの計装と相互運用するための手動計装の必要性にも反しています。

## 提案

### OpenTelemetryのエンドユーザーが望む最終状態とは

上記の多くを繰り返すと、望ましいのは次のような状態です。

* 何よりもまず、**ポータブルなOpenTelemetry計装は、手動でソースコードを修正することなくインストールできます**。
* ポータブルな自動計装に関しては、「明確な勝者」がいます。
  OpenTracingやOpenCensusと同じように、これは選択肢があることが必ずしも良いことではないという状況なのです。
  計装・プラグインを貢献したいと願うエンドユーザーは、その熱意と寛大さを競合するプロジェクト間で希釈させるべきではありません。
* そのようなことが可能である限り、言語間の一貫性があります。
* 幅広いカバレッジ／「プラグイン対応」があります。
* OpenTelemetryの幅広いベンダーサポートがあります。
* 他の条件がすべて同じであれば、速やかにこれらの利点すべてを手に入れましょう！

### 基本的な提案とは

望ましい最終状態を考えると、Datadogのトレーサーは、現在ある中で、もっとも適合し、寛容にライセンスされた選択肢のように思えます。
私たちはDatadogのリーダーシップに、そのコードをOpenTelemetryに提供することに興味があるかどうか尋ね、そして彼らはそのアイデアを受け入れてくれました。
(つまり、これは永遠に並行して維持されなければならない「ハードフォーク」ではありません)

### 言語ごとの包括的（技術的）プロセス

* [Datadog `dd-trace-foo` トレーサー](https://github.com/DataDog) から始めます。
* 各言語ごとに次のような手続きを踏みます。
  * Datadogの `datadog/dd-trace-foo` リポジトリを `open-telemetry/auto-instr-foo` というOpenTelemetryリポジトリにフォークします（正確な命名は未定）。
  * 並行して次のような作業をします。
    * `dd-trace-foo` コードベースはすでにDatadog固有の機能と汎用的な機能をうまく分離しています。
      必要であれば、API（または「SPI」）を通してその境界をより明確にします。
    * `auto-instr-foo` をラップし、上記で因子分解したDatadog固有の部分を含む新しい `dd-trace-foo` ライブラリを作成します。
    * 上記のAPI/SPIに任意のOpenTelemetryベースのトレーサーをバインドすることも可能であることを示します。
  * フォークした `auto-instr-foo` リポジトリをベータ版として使用できるようにします。
  * 一定期間（理想的には短期間）過ぎた後に次を実施します。
    * 新しいプラグインがDatadogの（オリジナルの）リポジトリに追加されたら、それらを `auto-instr-foo` リポジトリにマージします。
    * Datadogエンドユーザーが一定期間、どちらでもバインドできるようにします（最終的なタイムラインはDatadogが決めますが、これは他のトレーサーが `auto-instr-foo` を使うことを妨げるものではありません）。
    * 最終的に、`auto-instr-foo` とDatadogラッパーの組み合わせが `dd-trace-foo` メインラインと機能的に同等になったとき、後者を前者に置き換えても安全になります。
      * 設計上、これはDatadogのエンドユーザーには影響しないと思われます。
  * 移動したリポジトリがGAされたとき、すべての新しいプラグイン（と自動計装コアの改良）は `auto-instr-foo` リポジトリで行われます。

Datadogの `dd-trace-foo` のサポートが始まる前にOpenTelemetryのサポートが始まる言語もあります。
そのような状況では、このOTEPの要求事項に戻り、技術的な決定は言語SIGとOpenTelemetry TCに委ねます。

### 自動計装ライブラリのガバナンス

それぞれの `auto-instr-foo` リポジトリには、メインの `opentelemetry-foo` 言語リポジトリと共通の [メンテナー](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer) が少なくとも1人いなければなりません。
メインの言語リポジトリとそれぞれの自動計装リポジトリのメンテナー/承認者のセットについて、他の要件や制約はありません。
特に、メインの言語リポジトリのメンテナー/承認者が、自動計装リポジトリのメンテナー/承認者ではないかもしれませんし、その逆かもしれません。

### 本提案に関する小FAQ集

**これはOpenTelemetryのための唯一の自動計装ストーリーになるのでしょうか。**
そうである必要はありません。
上記の自動計装ライブラリは、OpenTelemetry APIへの特権的なアクセスは持っていませんので、他の自動計装ライブラリに対する排他的な優位性はありません。

**_プロジェクトX_ の自動計装はどうなりますか。なぜそちらを使わないのですか。**
まず第一に、私たちの誰かが _プロジェクトX_ から素晴らしいアイデアを得て、これらの自動計装ライブラリに組み込むことを妨げるものは何もありません。
私たちは、Datadogのコードベースから始めて、必要に応じてそこから反復することを提案します。
どの言語であれ、改善すべき点があれば、それは誰にでも歓迎されるでしょう。

## 先行技術と代替技術

プロプライエタリなAPM言語エージェントは多く存在します。
ここですべてを挙げる必要はありません。
「APMエージェント」（またはその他の自動計装の取り組み）のリストは、もっと少ないですが、それらはすでにOSSとして寛容にライセンスされています。
たとえば、私たちがJVMのオプションについて議論したとき（より長いメモは[こちら](https://docs.google.com/document/d/1ix0WtzB5j-DRj1VQQxraoqeUuvgvfhA6Sd8mF5WLNeY/edit#heading=h.kjctiyv4rxup)）、私たちは以下のリストを作成しました。

* [HoneycombのJava beeline](https://github.com/honeycombio/beeline-java)
* [DatadogのJavaトレーサー](https://github.com/datadog/dd-trace-java)
* [Glowroot](https://glowroot.org/)
* [SpecialAgent](https://github.com/opentracing-contrib/java-specialagent)

もっとも明白な「代替アプローチ」は、各言語で独立して「出発点」を選ぶことでしょう。
これにはいくつかの問題があります。

* 「ハードフォーク」の可能性が高くなります。
  2つのプロジェクト（OpenTelemetryバージョンとオリジナルバージョン）が独立して進化し、分岐するような最終状態は避けたいところです。
* 言語間の「コンセプトの分岐」の可能性が高くなります。
  各言語が独自の要件と課題を提示する一方で、Datadogの自動計装ライブラリは、共通のコンセプトとアーキテクチャ要件を持つ単一の組織によって書かれています（それらはまた、OpenTracingと互換性があるように書かれており、OpenTelemetryとの類似性を考えると、成功の確率を大幅に高めています）。
* Datadogはここでも統一した方針を望んでおり、この寄付には彼らの同意が必要です（ハードフォークをしない限り、誰にとっても最適とは言えません）。
  そのため、Datadogのライブラリを「1つを除くすべて」（あるいは「2つを除くすべて」など）の言語で開始することは、彼らにとってあまり好ましいことではありません。

