OpenTelemetry 101

# OpenTelemetryとは

テレメトリデータを収集してバックエンドプラットフォームに転送するための方法を標準化してくれるフレームワーク。OpenCensus・OpenTracingという2つのソフトウェアがマージされて誕生した。[OpenTelemetry](https://opentelemetry.io/docs/)は、SDK・API・ツールの総称であり、バックエンドを担うものでは無い。

分散システム上のアプリケーション・ホスト環境のトラブルシューティング・デバッグに必要なデータを収集することが可能。複雑なシステムのトラブルシューティングを容易にしてくれる。

CNCFでk8sに次いで、2番目に活発なProjectだとか。

## OpenTelemetryのメリット

- 一貫性
    - [ベンダー](https://opentelemetry.io/ecosystem/vendors/)(AWS, GCPなど)・言語に依存せず共通化した方法が提供されている
    - 様々なバックエンドをサポートしている(OTLPに対応していることが前提)
        - Jaeger・Zipkin・Prometheusなど
- 互換性
    - OpenTracing, OpenCensusのどちらとも互換性がある
- 拡張性
    - 用途に応じた拡張性能が高い

## OpenTracing

OpenTracingは、トレーシングを標準化するAPIを提供することを目指していた。トレーシングに特化しており、用途が限られているという課題があった。

## OpenCensus

OpenCensusはGoogleが社内のトレーシングプラットフォームをベースに開発した。収集したメトリクスを任意のバックエンドに転送することをサポートしていた。しかし、OpenCensusをコードに組み込むAPIが提供されていなかった。

## 可観測性(オブザーバビリティ)とは

「監視」と比較されることが多い。監視には積極的な意味合いが強く、システムに設定された閾値を超えたらアラートを鳴らす。一方で可観測性は、システム内の状態を常に包括的に把握することを指す。システムの出力からシステム状態を測定するために利用する。従来の監視は、既存の問題にしか対応できないが、分散システムにおいては、どのような問題が発生するか、事前に予測するのがとても難しい。可観測性は、予測不可能性にアプローチする最適解となり得る。

### 可観測性が誕生した背景
前述したように、分散システムを適切に監視できる手法が求められていた。従来の監視だと以下のような問題に対処できなかった。
- マイクロサービスに分散したログをリクエスト単位で追いづらい
- エラー原因箇所の同定の難しさ
- レスポンス遅延の原因把握

## テレメトリーデータとは
テレメトリーデータは、Log, Metrics, Tracesの3つに分類される。それに加えて、OpenTelemetry特有のBaggageというテレメトリーが存在する。
### Log
- 発生したイベントを各時点で記録するテキスト。プレーンテキスト・構造化・非構造化データがある。
    - エラーログ、アクセスログなど
            
```prolog
I, [2021-02-23T13:26:23.505892 #22473]  INFO -- : [6459ffe1-ea53-4044-aaa3-bf902868f730] Started GET "/" for ::1 at 2021-02-23 13:26:23 -0800
```
            
### Metrics
- 一定の期間にわたって測定された値を指す。タイムスタンプ・イベント名・イベント値などの属性が記録される。構造化データであることが普通
    - CPU使用率、トランザクション量など
    - よりメタ的には、Counter, Gauge, Histogramとして計測する
        - Counter
            - リクエスト数など、測定可能かつ常に増加するMetrics
        - Gauge
            - キューイング数など、時間によって増減するMetrics
        - Histogram
            - 一定期間における値の分布に関するMetrics
### Traces
- 分散システムでのリクエスト処理経路をエンドツーエンドで表すデータ
    - 例：リクエストの処理フローに関するデータ
        - システムがリクエストを処理した場合に、トレースID、スパンID、操作名、開始・終了タイムスタンプ、などの重要情報がエンコードされる
- トレースを利用してMetricsを作成することも可能。RED(ratio, error, time)

```json
{
  "name": "hello",
  "context": {
    "trace_id": "0x5b8aa5a2d2c872e8321cf37308d69df2",
    "span_id": "0x051581bf3cb55c13"
  },
  "parent_id": null,
  "start_time": "2022-04-29T18:52:58.114201Z",
  "end_time": "2022-04-29T18:52:58.114687Z",
  "attributes": {
    "http.route": "some_route1"
  },
  "events": [
    {
      "name": "Guten Tag!",
      "timestamp": "2022-04-29T18:52:58.114561Z",
      "attributes": {
        "event_attributes": 1
      }
    }
  ]
}
```

### Baggages
- spanを介して伝達されるcontext情報のこと。key-value storeとして機能する
- context, propagationという仕組みで、分散トレーシングを効率的に実現する
    - Context
        - service間でのシグナルの連携を把握することができるObject
        - serviceAが serviceBを呼んだ場合に、contextに存在するtrace IDをもとにsignalを後から分析しやすくする
    - Propagation
        - service、process間でのcontextのやりとりをシリアライズ・デシリアライズして実行するメカニズム
        - 例：CustomerIdなど
            
![スクリーンショット 2024-02-04 14.29.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371779/9d559e39-8787-b63e-2f79-4207e434c4d5.png)

            

# OpenTelemetryの機能

## システム構成

![スクリーンショット 2024-02-04 10.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371779/50670245-d5d4-9c7c-61cc-1426222d9e71.png)


### 言語別のOpenTelemetry API
- 各プログラミング言語に対応した、データ収集のためのコードがある
    - Automatic instrumentationといった機能もある（後述）
    - C++, Go, Java, JavaScript, Python, Rust etc
    - [コード例](https://opentelemetry.io/docs/languages/)
### 言語別のOpenTelemetry SDK
- APIとエクスポーターの間の橋渡しとなる
### OpenTelemetry Protocol (OTLP)
- SDKなどからOTLCにテレメトリーデータを渡すためのプロトコル。HTTP or gRPC
### OpenTelemetry Collector (OTLC)
- ベンダーに依存することなくテレメトリーデータをアプリケーション、インフラから受信して、監視バックエンドにデータ連携する。Receiver, Processor, Exporterの3要素から構成される
    - Receiver
        - OpenTelemetryを受け取る。いろいろなデータを受け取ることができる
            - kubernetesにおいては、kubeletstats Receiver, Filelog Receiver, Kubernetes Cluster Receiver, Kubernetes Objects Receiverなどがある
    - Processor
        - 属性に応じて送信先を変えたり、指標を集積してカウンタ値を作成することが可能
            - production・staging, host, serviceなど
    - Exporter
        - HTTP, gRPCなどで送信。あくまでOpenTelemetryはバックエンドに送信するだけで、データ保存はPrometheusなどの下流が担う

## Auto instrumentation (kubernetes operator)

- 従来のトレーシングでは、観測データを出力する部分をコーディングする必要があったが、OpenTelemetryでは、コードを記載しなくてもinstrumentationを行うことができる
    - OpenTelemetry Operatorを[k8s](https://opentelemetry.io/docs/kubernetes/)上にdeployした上でPodにannotationを追加すると、そのPod sidecarからトレーシングデータを自動取得できるようになる
- Auto instrumentationでカバーできないデータは、自分で実装する必要がある
    - どのデータをauto instrumentationするのかは、yaml fileで指定可能

## FaaS
AWS Lambdaのような[Functions as a Service](https://opentelemetry.io/docs/faas/) (FaaS)でも、instrumentationは機能する。


# まとめ
OpenTelemetryの各種仕様がfixしてきているので、今後さらに盛り上がることが期待される。