OpenCensusはdeprecatedされているので本当はOpenTelemetryを使った方がいいのだけれど、やったのでメモがてらに残しておく。アプリケーションの実行環境はGAEでやった。
追記: OpenTelemetryでやる方法も書きました
izumisy.work
まずはログのグルーピング(Span)をリクエスト毎に開始するためのミドルウェアを作る。
package middleware
import (
"github.com/gin-gonic/gin"
"go.opencensus.io/exporter/stackdriver/propagation"
"go.opencensus.io/trace"
)
func Tracer() gin.HandlerFunc {
return func(c *gin.Context) {
ctxWithSpan, span := trace.StartSpan(c, "yourapp/trace")
defer span.End()
httpFormat := propagation.HTTPFormat{}
if sc, ok := httpFormat.SpanContextFromRequest(c.Request); ok {
ctxWithSpan, span = trace.StartSpanWithRemoteParent(c, c.FullPath(), sc)
}
c.Request = c.Request.WithContext(ctxWithSpan)
c.Next()
}
}
TracerミドルウェアによってContextにグルーピングのために必要な情報がセットされるので、それを取得する関数も用意しておく。
gin.Context
の場合にはRequestからContextを取り出すようにしているのがポイント。
package log
import (
"context"
"github.com/gin-gonic/gin"
"go.opencensus.io/trace"
)
type Tracer struct {
SpanID string
TraceID string
}
func ExtractTracer(ctx context.Context) Tracer {
sc := trace.SpanContext{}
if ginCtx, ok := ctx.(*gin.Context); ok {
sc = trace.FromContext(ginCtx.Request.Context()).SpanContext()
} else {
sc = trace.FromContext(ctx).SpanContext()
}
return Tracer{
SpanID: sc.SpanID.String(),
TraceID: sc.TraceID.String(),
}
}
あとはCloud Loggingにデータを送信するタイミングで、上で作ったExtractTracerを用いてContextからSpanIDとTraceIDを取り出し、それぞれ適切な形でセットしてやればok
package log
import (
"fmt"
"os"
"log"
"cloud.google.com/go/logging"
)
func Log(ctx context.Context, severity logging.Severity, timestamp time.Time, text string) {
projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
client, err := logging.NewClient(ctx, projectID)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
tracer := ExtractTracer(ctx)
logger = client.Logger("ServeHTTP")
logger.Log(logging.Entry{
Timestamp: timestamp,
Severity: severity,
Payload: text,
SpanID: tracer.SpanID,
Trace: fmt.Sprintf("projects/%s/traces/%s", projectID, tracer.TraceID),
})
}
DeNAが出しているaelogというパッケージを使えばこの辺全部よしなにやってくれるっぽい。
Ginでなにもせず使えるかは試してない。ミドルウェアの型定義的に gin.WrapH
とかでラップしてUseしてあげれば使えるような気もするけど、どうなんだろう
github.com
追記: 調べたらこんなのもあった。
github.com
Cloud Loggingとのつなぎこみだけ自分で作ってこういうのを使うでもいいかも。