コードを一行も変更することなく、Golangアプリケーションにおけるトレーシング、メトリクス、およびログについて学ぼう

> 本記事は[こちらのブログ](https://www.alibabacloud.com/blog/learn-about-tracing-metrics-and-logs-in-the-golang-application-without-changing-a-single-line-of-code_602070?spm=a2c65.11461433.0.0.4ee35355MSxyUr)を参考にしています。
> 翻訳にはアリババクラウドの[ModelStudio](https://www.alibabacloud.com/en/product/modelstudio)([Qwen](https://www.alibabacloud.com/en/solutions/generative-ai/qwen))を使用しております。

# Golangアプリケーションの観測性を向上させるAlibaba CloudのGolang Agent

## 著者: Musi

## 背景
従来、Golangアプリケーションの監視には特定のコード修正が必要でした。たとえば、[OpenTelemetry](https://github.com/open-telemetry/opentelemetry-go)のようなSDKを導入する必要があります。このような修正は、運用（O&M）チームと開発（R&D）チームの間でしばしば意見の対立を引き起こしました。O&Mチームは「R&Dチームが関連する監視にアクセスしないと、アプリケーションの実行状況を把握し、適切な操作を行うのが難しい」と言います。一方、R&Dチームは「すでに多くのビジネス要件があり、コードにさまざまな計装を追加する必要がある。SDKのバージョンが変わると、コードを再調整しなければならない」と不満を訴えます。これにより、Golangアプリケーションが観測性にアクセスする効率が低下しました。

この記事では、Alibaba Cloudのオープンソース[Golang Agent](https://github.com/alibaba/opentelemetry-go-auto-instrumentation)を使用して、1行たりともコードを変更せずにアプリケーションが生成するさまざまな観測データを取得する方法を紹介します。このアプローチにより、O&MチームとR&Dチームの満足度が向上します。

## クイックスタート
Golang開発者は通常、`go build`コマンドを使用してソースコードをバイナリパッケージにビルドします。これはアプリケーション開発時に実行されます。Alibaba CloudのオープンソースGolang Agentは、`go build`の代替手段と考えることができます。Golangアプリケーションをコンパイルする際、ユーザーは`go build`の代わりにGolang Agentのバイナリパッケージを使用して、観測性機能を持つバイナリGolangプログラムをコンパイルできます。以下では、Golang Agentのビルドおよび使用プロセスについて詳しく説明します。

### ステップ1: Golang Agentバイナリパッケージのダウンロード/ビルド
まず、[https://github.com/alibaba/opentelemetry-go-auto-instrumentation](https://github.com/alibaba/opentelemetry-go-auto-instrumentation)のページにアクセスして、最新バージョンのGolang Agentバイナリパッケージをダウンロードします。
![1](https://yqintl.alicdn.com/67b853b73f589d4550f763fb91a962ae464114e4.png)
![2](https://yqintl.alicdn.com/1b8c43484750c23480a843cd959f981871b621ff.png)

最新の未リリース機能を試したい場合、次のコマンドを使用してメインブランチから最新のGolang Agentバイナリパッケージをコンパイルすることもできます：bash
# プロジェクトをローカルコンピュータにダウンロードします。
git clone https://github.com/alibaba/opentelemetry-go-auto-instrumentation.git
# エージェントのルートディレクトリに移動します。
cd opentelemetry-go-auto-instrumentation
# Golang Agentバイナリパッケージをコンパイルします。
make clean && make build
chmod u+x ./otel
上記のコマンドを実行すると、プロジェクトのルートディレクトリに「Otel」という名前のバイナリファイルが生成されます。これにより、Golang Agentバイナリパッケージが正常にコンパイルされたことが確認できます。

### ステップ2: Golang Agentバイナリパッケージを使用してGolangアプリケーションをコンパイル
Golang Agentバイナリパッケージを取得したら、`go build`の代わりにそれを使用してGolangアプリケーションのバイナリプログラムをコンパイルできます。Golang Agentは、[https://github.com/alibaba/opentelemetry-go-auto-instrumentation/tree/main/example](https://github.com/alibaba/opentelemetry-go-auto-instrumentation/tree/main/example)ディレクトリに対応するGolangデモを提供しています：bash
cd ./example/demo
../../otel go build .
例として、`example`ディレクトリ下の`demo`ディレクトリをビルドします。元のビルドコマンドは`go build`だったものが、今後はコンパイルプレフィックスとして`../../otel go build`を追加する必要があります。これはLinuxシステムで元のコマンドの前に`sudo`を追加するのに似ています。上記のコマンドを実行すると、対応するアプリケーションのルートディレクトリに観測性を持つGolangバイナリプログラムが生成されます。

### ステップ3: 報告エンドポイントの設定とGolangアプリケーションの起動
#### トレース報告
まず、ステップ2を参照して`example/demo`ディレクトリ内のバイナリファイル`demo`をコンパイルします。報告前に、アプリケーションのいくつかの依存関係を起動できます。このアプリケーションはMySQLとRedisを呼び出すため、これら2つの依存関係を最初に起動します：bash
docker run -d -p 3306:3306 -p 33060:33060 -e MYSQL_USER=test -e MYSQL_PASSWORD=test -e MYSQL_DATABASE=test -e MYSQL_ALLOW_EMPTY_PASSWORD=yes mysql:8.0.36
docker run -d -p 6379:6379 redis:latest
次に、Jaegerを起動してトレース情報を受信および表示します：bash
docker run --rm --name jaeger \
  -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 14250:14250 \
  -p 14268:14268 \
  -p 14269:14269 \
  -p 9411:9411 \
  jaegertracing/all-in-one:1.53.0
関連する依存関係を起動した後、[Otelの仕様](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/)に従って関連する報告エンドポイントを設定し、アプリケーションを起動します：bash
cd example/demo
export OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318 
export OTEL_EXPORTER_OTLP_INSECURE=true 
export OTEL_SERVICE_NAME=demo 
./demo
アプリケーションが起動したら、アプリケーションに対して継続的にリクエストを行い、関連するトレース情報を生成します：bash
curl_disabled localhost:9000/http-service
最後に、http://localhost:16686/jaeger/ui/search にアクセスしてJaegerでトレース情報を検索します。トレースが生成され、正常に接続されていることが確認できます。これにより、リクエストの全体的な実行パスを完全にトレースできます。
![3](https://yqintl.alicdn.com/6f43ebaba18d69672658a1f95a28dedf8a8b93c9.png)

#### メトリック報告
まず、ステップ2を参照して`example/metrics`ディレクトリ内のバイナリファイル`metrics`をコンパイルします。同様に、報告前にアプリケーションのいくつかの依存関係を起動できます。このアプリケーションはOtel Collectorを介してPrometheusにメトリック情報を報告するため、以下のコマンドを実行してOtel CollectorとPrometheusを起動します：bash
# metricsディレクトリに移動します。
cd example/metrics
# Otel CollectorとPrometheusを起動します。
docker compose up --force-recreate --remove-orphans --detach
関連する依存関係が起動した後、Otelの仕様に従って関
cd example/log
./test
アプリケーションが起動した後、関連するログを出力するためにアプリケーションに継続的にリクエストします:
curl_disabled localhost:9999/log
アプリケーションが以下のようにログを出力することを確認できます。ログの先頭には対応するtraceIDとspanID情報が表示されます:
{level:debug,msg:this is debug message,trace_id:d62a8fea286cc66de9c68ca17d4faa88,span_id:7cb6d692769ffd32}
{level:info,msg:this is info message,trace_id:d62a8fea286cc66de9c68ca17d4faa88,span_id:7cb6d692769ffd32}
{level:warn,msg:this is warn message,trace_id:d62a8fea286cc66de9c68ca17d4faa88,span_id:7cb6d692769ffd32}
{level:error,msg:this is error message,trace_id:d62a8fea286cc66de9c68ca17d4faa88,span_id:7cb6d692769ffd32}
{level:debug,msg:this is debug message,trace_id:e56a6f1e7ed7af48cce8f64d045ed158,span_id:def0b8cf10fe8844}
{level:info,msg:this is info message,trace_id:e56a6f1e7ed7af48cce8f64d045ed158,span_id:def0b8cf10fe8844}
{level:warn,msg:this is warn message,trace_id:e56a6f1e7ed7af48cce8f64d045ed158,span_id:def0b8cf10fe8844}
{level:error,msg:this is error message,trace_id:e56a6f1e7ed7af48cce8f64d045ed158,span_id:def0b8cf10fe8844}
手動ログ関連付け
さらに、Otel SDKを使用してtraceIDとspanIDを手動で取得し、それらをログに出力することができます。関連するサンプルコードは以下の通りです:
package main

import (
  go.opentelemetry.io/otel/sdk/trace
  go.uber.org/zap
  net/http
)

func main() {
  http.HandleFunc(/logwithtrace, func(w http.ResponseWriter, r *http.Request) {
    logger := zap.NewExample()
      // SDKを通じて対応するtraceIDとspanIDを取得します。// 注意: この使用法はGolang Agentが正常にコンパイルされることを前提としています。 traceId, spanId := trace.GetTraceAndSpanId()
    logger.Info(this is info message with fileds,
      zap.String(traceId, traceId),
      zap.String(spanId, spanId),
    )
  })
  http.ListenAndServe(:9999, nil)
}
ステップ2を参照してexample/logディレクトリ内のバイナリファイルtestをコンパイルしてください。アプリケーションがコンパイルされた後、それを起動することができます。 # metricsディレクトリに入ります。 cd example/log
./test
アプリケーションが起動した後、関連するログを出力するためにアプリケーションに継続的にリクエストします:
curl_disabled localhost:9999/logwithtrace
アプリケーションが以下のようにログを出力することを確認できます。ログの先頭には対応するtraceIDとspanID情報が表示されます:
{level:info,msg:this is info message with fileds,traceId:92d63797010a2040484222a74c5ce304,spanId:5a2c84c807a6e12c}
まとめと展望
Golang Agentは、Golangアプリケーションの監視における手動インスツルメンテーションの煩雑な問題を成功裏に解決し、アリババクラウドのパブリッククラウドで商用利用が開始され、顧客に強力な監視機能を提供しています。この技術は元々、既存のコードを変更せずにユーザーが簡単に監視コードを挿入できるように設計されました。これにより、アプリケーションのパフォーマンスをリアルタイムで監視および分析することが可能になります。しかし、その適用範囲は予想以上に広がり、サービスガバナンス、コード監査、アプリケーションセキュリティ、コードデバッグなどにも活用されています。また、まだ未踏の分野でも潜在的な可能性を示しています。私たちはこの革新的なソリューションをオープンソース化し、<a href=https://github.com/open-telemetry/community/issues/1961 target=_blank>OpenTelemetryコミュニティ</a>に寄付することを決定しました。今後、私たちのコードはOpenTelemetryコミュニティのリポジトリに移行されます。このソリューションのオープンソース化は技術共有と改善を促進し、コミュニティの助けを借りてより多くの分野での潜在能力を継続的に探求するのに役立ちます。</div>