LoginSignup
10
4

More than 3 years have passed since last update.

OpenTelemetryを使ったGoのアプリケーションのトレーシング

Last updated at Posted at 2019-12-19

この記事は Go5 Advent Calendar 2019 20日目の記事です。

はじめに

以前Kubernetes環境でのGoのアプリケーションのトレーシングという記事を書きました。
この記事を書いた際にはOpenCensusJaeger用のexpoterを使ってJaegerにデータを送信してアプリケーションのトレーシングをするということを試しました。

今回はOpenCensusOpenTracingの2つのプロジェクトが統合されたOpenTelemetryというOSSを使ってアプリケーションのトレーシングをしていきたいと思います。

やってみる

Jaegerの起動

まず最初にJaegerを起動します。
今回は検証用にローカル環境でDockerのAll-in-oneイメージを使います。起動の手順は下記を参考にしました。
https://www.jaegertracing.io/docs/1.16/getting-started/

$ docker run -d --name jaeger \
  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
  -p 5775:5775/udp \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 9411:9411 \
  jaegertracing/all-in-one:1.16

http://localhost:16686/search にアクセスすると下記のようにJaegerのUIが表示されるのが確認できるかと思います。

スクリーンショット 2019-12-20 4.49.50.png

アプリケーション側の設定

OpenTelemetryのリポジトリのsampleを参考にGoのアプリケーションをトレーシングする設定を入れて行きます。

コードの全体はGitの下記のレポジトリにあげています。
https://github.com/amber-lamp/opentelemetry-sample/blob/master/main.go

最初にinitTracer関数でexporterとsamplerの設定をします。

main.go
func initTracer() func() {
    // Create Jaeger Exporter
    exporter, err := jaeger.NewExporter(
        jaeger.WithCollectorEndpoint("http://localhost:14268/api/traces"),
        jaeger.WithProcess(jaeger.Process{
            ServiceName: "opentelemetry-sample",
            Tags: []core.KeyValue{
                key.String("exporter", "jaeger"),
                key.Float64("float", 312.23),
            },
        }),
    )
    if err != nil {
        log.Fatal(err)
    }

    tp, err := sdktrace.NewProvider(
        sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),
        sdktrace.WithSyncer(exporter))
    if err != nil {
        log.Fatal(err)
    }
    global.SetTraceProvider(tp)
    return func() {
        exporter.Flush()
    }
}

今回は検証なので、samplerの設定はアクセスした情報をすべてサンプルとして取得するように設定しています。

sdktrace.WithConfig(sdktrace.Config{DefaultSampler: sdktrace.AlwaysSample()}),

プロダクション等で利用する場合はリクエストの一部をサンプルとして取得する設定に変更したほうが良いでしょう。

次にmain関数を見てみます。
今回もKubernetes環境でのGoのアプリケーションのトレーシングという記事と同様におみくじの結果を返すようなアプリケーションを書いたので、リクエストに対しておみくじの結果を返すようになっています。

main.go
func main() {
    fn := initTracer()
    defer fn()

    tr := global.TraceProvider().Tracer("component-main")
    fortuneHandler := func(w http.ResponseWriter, req *http.Request) {
        attrs, entries, spanCtx := httptrace.Extract(req.Context(), req)

        req = req.WithContext(distributedcontext.WithMap(req.Context(), distributedcontext.NewMap(distributedcontext.MapUpdate{
            MultiKV: entries,
        })))

        ctx, span := tr.Start(
            req.Context(),
            "fortune",
            trace.WithAttributes(attrs...),
            trace.ChildOf(spanCtx),
        )
        defer span.End()

        span.AddEvent(ctx, "handling this...")
        omikuji := omikuji(ctx)

        _, _ = io.WriteString(w, "運勢は" + omikuji + "です")
    }

    http.HandleFunc("/fortune", fortuneHandler)
    err := http.ListenAndServe(":7777", nil)
    if err != nil {
        panic(err)
    }
}

下記のTraceProviderの部分でTracerの設定をしています。

tr := global.TraceProvider().Tracer("component-main")

fortuneHandlerの中でfortuneというSpanの設定をしています。

ctx, span := tr.Start(
            req.Context(),
            "fortune",
            trace.WithAttributes(attrs...),
            trace.ChildOf(spanCtx),
        )

最後におみくじの結果を返すomikuji関数の部分です。
こちらもmain関数と同様に関数の最初でTracerとSpanの設定をしています。

main.go
func omikuji(ctx context.Context) string {
    tr := global.TraceProvider().Tracer("component-omikuji")
    _, span := tr.Start(ctx, "omikuji")
    defer span.End()

~~省略~~
}

アプリケーションを起動してアクセスしてみます。

# 起動
$ go run main.go

下記のURLにアクセスするとおみくじの結果が返ってきます。
http://localhost:7777/fortune

スクリーンショット 2019-12-20 5.38.28.png

Jaegerにして検索をするとアプリケーションの情報が取れているのがわかると思います。

スクリーンショット 2019-12-20 5.41.38.png

スクリーンショット 2019-12-20 5.41.55.png

今回はシンプルなアプリケーションなのでメリットがわかりずらいですが、マイクロサービスアーキテクチャで作られているようなサービスの場合にはOpenTelemetryのような技術を使うことでサービス全体がどうなっているか把握しやすくなるのではないかと思います。

まとめ

OpenTelemetryを使ってGoのアプリケーションのトレーシングをしてみました。
今回はOpenTelemetryのサンプルをもとに動かしてみたというだけですので、機会があればOpenTelemetryについてもう少し深堀りして行ければと思っています。

10
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4