1. やりたいこと
以前の投稿で、docker-composeを利用して、zipkinサービスを手元で動かすことができるようになったので、golangでも、zipkinにレコードを登録できるかを試してみようと思いました。
下記を一通り読むと、addsrvのセクションで簡単なサンプルが紹介されていました。
2. やってみた
2-1. ソースコードをダウンロード
git clone https://github.com/go-kit/kit.git
cd kit/examples/addsvc/
2-2. 依存するライブラリをgo getする
go get github.com/go-kit/kit/tracing/zipkin
go get github.com/codahale/hdrhistogram
go get github.com/prometheus/client_golang/prometheus
2-3. ビルドしてサーバを起動する
go build
./addsvc --zipkin.collector.addr=*.*.*.*:9410
2-4. curlで、起動したサーバにGETメソッドを送る
curl -H "Content-Type: application/json" -L "http://localhost:8001/sum" -d '{"a":10,"b":12}'
上記を実行すると、下記のようなエラーが出ちゃいました。。
ts=2016-**-**T14:10:40Z caller=stdlib.go:89 file="http: panic serving [::1" msg="]:50391: interface conversion: interface {} is server.SumRequest, not *server.SumRequest"
2-5. でもzipkinのuiを見てみる
addsvc
というサービスがトレースされていることが確認できました。
まだ、コミットが直近でも入っているようなので発展途上なのかもしれません。もうちょっと時間をおいてまた見てみようと思います。
3. ちょっとだけソースも眺めてみた
main.go
を起点に、httpサーバをgolangで立てたときにどのようにトレーサーを仕込んでいくのかを見てみました。
3-1. zipkin collectorの変数を生成
まず、tracer自体については、go-kit/kit/tracing/zipkin
パッケージのzipkin
のzipkin.NewScribeCollector
を読んで生成しているようでした。
main.go
// package tracing
var collector zipkin.Collector
{
zipkinLogger := log.NewContext(logger).With("component", "zipkin")
collector = loggingCollector{zipkinLogger} // TODO(pb)
if *zipkinCollectorAddr != "" {
var err error
if collector, err = zipkin.NewScribeCollector(
*zipkinCollectorAddr,
*zipkinCollectorTimeout,
zipkin.ScribeBatchSize(*zipkinCollectorBatchSize),
zipkin.ScribeBatchInterval(*zipkinCollectorBatchInterval),
zipkin.ScribeLogger(zipkinLogger),
); err != nil {
zipkinLogger.Log("err", err)
os.Exit(1)
}
}
}
3-2. httpリクエストをトレースする
上記を、おそらくhttpのリクエストに食わせていると思い眺めて、とってもざっくりな理解ですが、
-
zipkin.AnnotateServer(newSumSpan, collector)(sum)
で処理実行のサーバとdurationの開始をハンドル -
net/http
のmux.Handlerに、zipkintのtransport/http
パッケージのファンクションをかまして、終了をキャッチ
のような感触を得ました。
main.go
var (
transportLogger = log.NewContext(logger).With("transport", "HTTP/JSON")
tracingLogger = log.NewContext(transportLogger).With("component", "tracing")
newSumSpan = zipkin.MakeNewSpanFunc(*zipkinHostPort, *zipkinServiceName, "sum")
newConcatSpan = zipkin.MakeNewSpanFunc(*zipkinHostPort, *zipkinServiceName, "concat")
traceSum = zipkin.ToContext(newSumSpan, tracingLogger)
traceConcat = zipkin.ToContext(newConcatSpan, tracingLogger)
mux = http.NewServeMux()
sum, concat endpoint.Endpoint
)
sum = makeSumEndpoint(svc)
sum = zipkin.AnnotateServer(newSumSpan, collector)(sum)
mux.Handle("/sum", httptransport.NewServer(
root,
sum,
server.DecodeSumRequest,
server.EncodeSumResponse,
httptransport.ServerBefore(traceSum),
httptransport.ServerErrorLogger(transportLogger),
))
4. 所感
- Golangでもできるんだー、と思いました。Elixir/Phoenixでもできないのかな。
-
net/http
でrouteごとに上記のように実装するのはちょっと冗長かも、と思いました。 - go getが動かずに動作確認できませんでしたが、go-zipkinだと上記のような冗長な箇所が解消されているのかな、とちょっと期待。ソース見てみよー。
- いろいろ眺めてみたけれど満足に動くライブラリとかサンプルが少ないような。。みんなトレーシングはfluentなどのロギングベースでいくのかな。mix inとかDIみたいにさりげなくzipkinのような仕組みをフレームワークに組み込めたら素敵だと思うのだけれども。。。
5. 参考
本日は以上となります。