🌌

Transparent Telemetryの概要

2023/02/26に公開

背景

Goのツールチェーンにテレメトリを導入することで、go, gopls, govulncheckなどのコマンドラインツールの使われ方についての情報を収集し、オープンソースであるGo言語の開発に活用しようというDiscussionsがあります。
telemetry in the Go toolchain #58409

本記事は、Goツールチェーンへのテレメトリ導入の展望を理解するために、Discussionsと同じ2023年2月8日にRuss Coxにより投稿されたTransparent Telemetry[1]の3本の記事と、Discussionsを受けて追加された1本の追加記事について概要をまとめます。[2]

Part1: Transparent Telemetry for Open-Source Projects

(Part1については、原文が分かりやすかったためほとんど和訳としています。一部Summaryの省略あり。)

ソフトウェアがどのように使われ、期待するパフォーマンスを発揮しているかを知るためのモダンな手法として、Russはテレメトリを上げています。その上で、それをオープンソース向けにした新たなデザインとして"Transparent Telemetry"を提案しています。

Why Telemetry?

テレメトリ以外にソフトウェアのバグや使われ方の情報を知れる手段としてバグ報告とサーベイをあげ、それぞれでは不十分であることを解説し、テレメトリの必要性を訴えています。

バグ報告だけでは不十分

バグ報告では、ユーザーがバグと判定しその上で報告をされたものしか知ることができないが、ユーザーが気づけない事象についてテレメトリでは統計的に不具合を認識することができるとして、過去のGo開発からの具体例を上げています。

Go 1.14のリリースプロセスにおいて、Appleの署名ツールを使えるようmacOS用のGoディストリビューションのビルド方法を調整したが、それによってすべてのプリコンパイルされた.aファイルが古いと判定される状態で提供されました。
その結果、goコマンドが初回実行時に標準ライブラリを再ビルドし、cgoを使うnetパッケージを利用する際にXcodeが必要となってしまいました。
ユーザー目線では、XcodeがないmacOSの環境でgoclangを実行する際には、Xcodeをインストールするポップアップが表示されるが、ユーザーはそれが必要だと感じたか、goによってXcodeが必要とされているということすら認識できなかった可能性があり、結局このバグは3年以上もの間誰からも報告されずその存在を認知されませんでした。

テレメトリがあれば、1.14移行のバージョンのGoを使っているMacの環境についてプリコンパイルされた標準ライブラリへのキャッシュミス率が100%であることが分かるため、すぐに気づくことができたのではないかと主張しています。

サーベイだけでは不十分

サーベイではユーザーがGoをどんな目的で使いたいかなどを理解できたが、これはあくまで少ないサンプルであり、特に使われる頻度の少ない機能についての情報を集めるためには、精度を高めるためにさらに大きなサンプルを必要とする問題があります。

Goでの使われる頻度の少ない機能への変更例として、Go1.13のNative Client (GOOS=nacl)のサポート終了や、Go1.15の32bit Intel CPUでのSSE2命令セットをサポートしない浮動小数点ハードウェア(GO386=387)のサポート終了が挙げられていますが、いずれも影響範囲の規模感について概ね予測通りの結果であったようです。

しかし失敗例として、Go1.18の-buildmode=sharedの削除についてドラフトに組み込んだが、Go1.18 beta 1のリリース時点で「まだ使ってるから消さないでほしい」とのフィードバックがあり、削除を諦めたという過去もあったようです。

メンテナンスコストを軽減するために検討されているものとして、モダンなアトミック命令のないARMv5 (GOARM=5)サポート終了などもあります。最近で言えばGo1.20でmacOS High Sierraのサポートを終了することも検討されたが、ユーザーから保留してほしいとの意見が上がったようです。

テレメトリも完璧なものではないですが、使わない機能や問題のある機能についてメンテナンスを続けるよりは、大きなサンプルのユーザーへのサーベイをする必要なく、統計的に利用状況を確認できるテレメトリを導入する必要性はあるのかもしれません。

Why Telemetry For Open Source?

テレメトリと聞くと、プライベートな部分まで情報収集されてしまうというようなネガティブなイメージを直感で持たれる方も少なくないのではないでしょうか。

キーボードによる入力の一つ一つまでを収集されるというのは誇張かもしれませんが、あながち間違いでもないと感じるのも以下の現実に起きている例から納得できます。

そのようなイメージもあるのか、オープンソースのソフトウェアプロジェクトでは主に2つの理由からテレメトリを避ける傾向にあります。1つはユーザーに対する大きなプライバシーコストの懸念、もう一つは従来のテレメトリの性質上集めた情報に対するアクセスを制限する必要があり、オープンソースであるプロジェクトの方向性に反するものとなるためです。

テレメトリを導入しない(何もしない)方が簡単ですが、それによって先に述べた、「使われていない機能に関するメンテナンス」や「ユーザー体験を損なう、バグや不具合などを含んだリリース」に対して時間を無駄に割いてしまうデメリットを被ります。

Russは「侵略的なまでのテレメトリによるトラッキング」と「テレメトリを導入せず何もしない」は誤った二分法であり、オープンソースを傷つけていると主張しています。こういった情報収集やそれによるGo言語開発の優先順位付けを行えないことが、メンテナの燃え尽きにつながるのではないかということです。

Eric Raymondは「十分目玉に晒されていれば、すべてのバグは浅い(“given enough eyeballs, all bugs are shallow,”)」と言い、説明として十分なベータテスターと開発者仲間があれば、ほとんどの問題は認識され解決されるとしました。
しかし、現代のオープンソースソフトウェアは昔と比べて、それを開発したりどのように動くのかについて詳しくない人を含む多くの人々から使われるようになったにもかかわらず、認知までに時間を要した先述のmacOSのGoのキャッシュバグの例からも、目玉はスケールしないことがわかります。

オープンソースソフトウェアのための、プライバシーを侵害しない必要最低限のユーザーアクティビティの収集から開発を効率化させられる、新しいテレメトリのデザインを考える必要があるでしょう。

Transparent Telemetry

このシリーズで提案するTransparent Telemetryは、オープンソースのためのテレメトリで、最小限のデータ収集(年間で数キロバイト程度)と、集めた情報のすべてを公開する方針からその名前がついています。(「透過的テレメトリ」)

ここでは、将来的にGoツールチェーンに導入を検討しているTransparent Telemetryの概要を紹介しています。

情報の収集方法

Goツールチェーンのテレメトリにおいては、実行ごとにキャッシュヒット、利用した機能、レイテンシなどの情報を一週間ごとにディスクにファイルとして保存するようです。ユーザーのデータやユーザーを識別するような情報は含まず、一部で簡潔なスタックトレースなども保存するが、引数についての情報は一切保存しない方針です。

GoogleのGoチームがテレメトリの情報収集用のサーバーを管理し、毎週10%の確率でユーザー環境に収集設定(collection configuration)を配布して、サーバーがどの情報を欲しているのかを伝えます。収集設定はGo moduleとして配布されるため、Go checksum databaseでvalidateすることができます。
収集設定のサンプル率に基づいて(大抵2%程度、平均して環境につき年に一回程度)、テレメトリ収集用のサーバーにログを送信します。

先述の通り、データにはIDなどユーザーを識別する情報を含みません。例えば、ユーザー名、マシンID、MACアドレス、IPアドレス及びそのプレフィックス、マシンの位置情報、ランダムに生成された擬似的なIDも含みません。
含まれる想定の情報としては、ツールチェーンのバージョンやビルドターゲットとされたOSやCPUアーキテクチャ、荒い粒度でのホストOSの情報("Windows 8"など)、ツールチェーンが利用したローカルのCコンパイラなどの他のツールの情報("gcc 2.95")などがあります。

集めた情報の公開方法

集めた情報のアクセスとしては、毎日の収集情報の更新、集計結果のグラフなどのgo.devでの公開、集まった情報をすべて誰でもダウンロード可能にする予定のようです。

データを集めるためにTCPコネクションを利用した場合、システムのパブリックIPアドレスがデータに紐付くことになりますが、それらの情報については今後設定されるプライバシーポリシーに基づき、アップロードされ公開される前に切り離されます。
切り離されるというのも、DoS対策などを含むサーバーのメンテナンスのためにIPアドレスを含むログが必要になるため、IPアドレスは削除ではなく保存される必要があるのですが、公開されるデータとは別で保存されるようです(おそらく非公開で、サーバーの運用のためだけに使われる?)。

利用方法

Discussionsでは次の点は議論の対象になっていましたが、記事ではGOTELEMETRY=offが指定されない限りは、デフォルトでテレメトリが収集され、設定により無効化するまでの猶予期間としてツールチェーンのインストールから最低でも一週間はGOTELEMETRYの設定に関わらずデータは送信されないと記述されていました。

※ この点については2023-02-24の追記で、フィードバックを受け再検討した結果デフォルトで無効化する方針に変更し、その詳細について4つ目の記事を投稿しました。

Next Steps

Russはローカルでのプロトタイプの実装から、GoツールチェーンにTransparent Telemetryを組み込むパフォーマンスコストが十分に小さいと確信していて、2023年を通して実装していきたいと表明していました。

Part2: The Design of Transparent Telemetry

Transparent テレメトリのデザイン(設計)について、Goツールチェーンに組み込む予定のものを上げて、5つの要素に分けて詳しく紹介しています。(詳細は省きます)

  • Counting: Goツールチェーンがカウンタの値(メトリクス)を週毎にローカルファイルとして保存する。
  • Configuration: Go公式サイトでのレビューを含むパブリックな意思決定プロセスによって定められる、新たなグラフやメトリクスに対するテレメトリの設定。収集される情報や、サンプルレートを決める情報源となる。
  • Reporting: 週に一度、自動化されたメトリクスの報告プログラムが、現行の収集設定(collection configuration)をダウンロードするかどうか、及びその週のサンプルとしてデータを送信するかを決める。
  • Publishing: 情報を集めたサーバーは、日毎に集まった情報をまとめて圧縮し、表やグラフなどのサマリーと合わせて公開する。
  • Opt-out: デフォルトでテレメトリを使うため、設定によるシンプルで十分な無効化機能(opt-out)を提供する。当初デフォルトで有効とする設計にしていたのは2つの理由があるそうです。
    • 1つは、大多数の人はデフォルトの設定を変更することはないため、デフォルトでテレメトリの収集がされない場合、収集されるサンプルの中でGoやテレメトリのシステムに詳しいユーザーからによるものの割合が増えることでバイアスが生じる危険性があるためです。
    • もう1つの理由として、onに設定するチェックボックスの存在が、必要以上のデータを集める正当化になってしまうことを懸念しています。
    • (2023-02-24の追記で、デフォルトでテレメトリの利用を無効にし、設定により有効化できるopt-inの方式に変更すると書かれています。)

Part3: Use Cases for Transparent Telemetry

Transparent Telemetryによる情報を活かして、現状のGoツールチェーンの持つどのような問題を分析しようとしているのかを紹介しています。(詳細は省きます)

  • Go moduleと比べた、従来のGOPATHモードの利用率
  • Go workspace(go.workファイル)の利用率
  • -buildmode=sharedの利用率
  • GOOS, GOARCHの設定値の比率
  • サポート終了が決まっているWindows7, Windows8と比較した、WSLの利用率
  • 全ビルドの中のクロスコンパイル率と、各クロスコンパイルのホスト<->ターゲットの組み合わせの比率(GOOS, GOARCH)
  • Go全体でのビルドのキャッシュミス率
  • Goのバージョン別のビルドのキャッシュミス率
  • goコマンド実行の中の標準ライブラリのリコンパイル率
  • キャッシュを保持する有効な期間 (現状は最後のキャッシュヒットから5日保持するが、それがより短くなったほうが効率的なのか否か)
  • 世代別GCにインスパイアされた、世代別ビルドキャッシュの導入の有効性
  • Go workspaceが持つモジュール数の分布
  • goコマンド実行毎に読み込まれるgo.modファイルの数の分布
  • モジュールのダウンロードにかかった時間の分布
  • ...などなど[3]

必要最小限の情報収集でも、Go言語の開発における多くの疑問に知見をもたらせることが分かります。

Part4: Opting In to Transparent Telemetry

Discussionsでの議論を受けて追加された記事になります。

Opt-in vs Opt-out

フィードバックとデフォルト無効化(Opt-in)への変更経緯についての記述です。

当初デフォルトで有効化する(opt-out)のがTransparent Telemetryの設計でしたが、デフォルト無効化(opt-in)の提案が強い支持を受けたことから、改めてこの点について比較しています。

フィードバックの例として以下のようなものがありました。

  • 内容は良いし喜んで有効化したいけど、デフォルトで有効化されているなら無効化したい
  • 公開された情報の中で、特殊で頻度の低い設定が特定のプロジェクトや企業に紐付いて、それら組織がどのような機能を使っているのか推測されてしまうのでは?
    • Russ: 攻撃に利用するには限られた情報しか公開されない想定だけど、無視はできない

他にも、これだけ詳細に従来のテレメトリとは異なるTransparent Telemetryを説明しているにも関わらず、多くの人々がそれを混同している状況があり、デフォルトで無効化することにしたそうです。

The Campagin/Privacy Cost of Opt-in

デフォルトでテレメトリを無効化する(Opt-in)とした上で、そのデメリットを2つに分けて議論しています。

  • The Campaign Cost of Opt-In
    • どのような情報が集められ、どのような情報は守られるのかについての認知を広めるためのコスト
    • 以下のような場面で明確に仕様を伝える必要性がある。
      • グラフィカルなGoインストーラーの実行時
      • リリースノート
      • VS Codeで初めてGoを使う時など
  • The Privacy Cost of Opt-In
    • Transparent Telemetryはサンプリングを行うことから、全てのユーザーから常に情報を集める場合と比較して、プライバシーに対するコストを緩和できる。
    • しかし、統計的に優位な結果を得るために一定のサンプル数は必要
      • 1%有意水準を実現するためには、16,000件/週のサンプルが必要と試算
    • 有効化(opt-in)率が低い場合、有効化している環境にサンプリングのしわ寄せが起き、有効化することに対するプライバシーコストが高まる (デフォルト有効化と比べ)

その他

その他、以下の内容が議論されていました(ここらへんの詳細は省きます)

  • 統計的な側面への深堀り
  • テレメトリそのものを無くすことを再度比較対象に入れた、一部のフィードバックに対する反論
  • 将来的な展望としての、PrioProchloなどを活用したよりセキュアなテレメトリ

まとめ

Transparent Telemetryは、ネガティブなイメージのある従来のテレメトリと異なり、オープンソース向けのテレメトリの再定義といった印象を受けました。

Goを皮切りにその他のオープンソースプロジェクトに浸透していき、開発プロセスの効率化や、メンテナの燃え尽きといった問題も改善されていくと良いですね。今後も注目です。

脚注
  1. "Transparent Telemetry" © Russ Cox Licensed under CC BY 4.0 ↩︎

  2. この記事は完全な和訳記事ではなく、個人的な解釈に基づいたまとめで、一部省略や表現の変更などがあります。誤りに気づいた場合はコメント下さい。 ↩︎

  3. What is the latency distribution of a Go workspace load?
    以下省略 ↩︎

GitHubで編集を提案

Discussion