Mackerel ã§ã¯ OpenTelemetry ã®ä¸»è¦ãªã·ã°ãã«ã®ãã¡ã®ãã¬ã¼ã¹ã«å¯¾å¿ããåæ£ãã¬ã¼ã·ã³ã°æ©è½ã§ãã Vaxila ã使ããããã«ãªãã¾ãããWeb ã¢ããªã±ã¼ã·ã§ã³ã®ãã³ãã©ãã©ãããããã¨ã§ç°¡åã«è¨è£ ããã©ã¤ãã©ãªãªã©ã¯ä½¿ã£ããã¨ãããã®ã§ãããä»åã¯èªåã§ã¹ãã³ãä½ããã¬ã¼ã¹ãè¨è£ ãããã¨ã§ããç解ãæ·±ãã¦ã¿ããã¨æãã¾ãã
- åæ£ãã¬ã¼ã·ã³ã°ãµã¼ãã¹ Vaxilaï¼ã´ã¡ãã·ã©ï¼ã Mackerel ã®æ©è½ã¨ãã¦ä½¿ããããã«ãªãã¾ãã - Mackerel ããã° #mackerelio
- åæ£ãã¬ã¼ã·ã³ã°ãµã¼ãã¹ Vaxila(ã´ã¡ãã·ã©)ã£ã¦ã©ããªãµã¼ãã¹ï¼ - Mackerel Tech Dayéå¬è¨å¿µé£è¼ #2 - Mackerel ããã° #mackerelio
ä»å㯠HTTP ãªã¯ã¨ã¹ããéä¿¡ããã¦ããã¬ã¹ãã³ã¹ãè¿ã£ã¦ããã¾ã§ã®æéããã¬ã¼ã¹ãã¦ã¿ããã¨æãã¾ããMackerel ã®å¤å½¢ç£è¦ã§ã¯ã¹ãã¼ã¿ã¹ã³ã¼ãã証ææ¸ã®æå¹æéãã¬ã¹ãã³ã¹ããã£ã®ãã§ãã¯ãã¬ã¹ãã³ã¹ã¿ã¤ã ã®å¯è¦åãªã©ã¯ã§ãã¾ãããDNS ã®åå解決ãã³ãã¯ã·ã§ã³ã®ç¢ºç«ãTLS ãã³ãã·ã§ã¤ã¯ã®æéãªã©ãè¦ããã¨ãã§ããªãããããããã¹ãã³ã¨ãã¦éä¿¡ãã¦ã¿ã¾ãã
æ¦å¿µã®ãããã
ãã¬ã¼ã¹ã®æ¦å¿µã«é¢ãã¦ã¯ OpenTelemetry ã®ããã¥ã¡ã³ããç°¡æ½ã«ã¾ã¨ã¾ã£ã¦ãã¦ããããããã§ãã - ãã¬ã¼ã¹ | OpenTelemetry - Overview | OpenTelemetry
HTTP ãªã¯ã¨ã¹ãå é¨ã®è¨è£
åç´ã« HTTP ãªã¯ã¨ã¹ããè¨è£
ããã ããªã otelhttp package ã使ç¨ããæ¢åã® handler ã middleware ãã©ããããã ãã§å®çµãã¾ãããä»å㯠DNS ã®åå解決ãªã©ãè¨è£
ãããã®ã§ otelhttp.NewTransport
ãç¨ã㦠Transport
ãå·®ãæ¿ãã¾ããGo 㧠DNS ã®åå解決ãªã©ã® HTTP ãªã¯ã¨ã¹ãå
é¨ã®ã¤ãã³ãããã¬ã¼ã¹ããã«ã¯ httptrace package ã使ç¨ã§ãã¾ãï¼ç¨èªãæ··ãã£ã¦ãããããã§ãããã¡ã㯠OTel ã®ãã¬ã¼ã¹ã¨ã¯å¥ç©ï¼ãClientTrace ã®å®ç¾©ãè¦ãã¨ãããããã«ãåå解決ã®éå§ã¨çµäºãTLS ãã³ãã·ã§ã¤ã¯ã®éå§ã¨çµäºãªã©æ§ã
ãªã¿ã¤ãã³ã°ã«ããã¯ãä»è¾¼ããã¨ãã§ãã¾ãã
trace package ã¨ä¸è¨ã®ããã¯ãçµã¿åãã㦠HTTP ã®å
é¨å¦çã®ã¹ãã³ãä½æãã¾ããtracer.Start
/ tracer.End
ã«ãªãã·ã§ã³ã渡ããã¨ã§ã¿ã¤ã ã¹ã¿ã³ããå±æ§ãªã©æ§ã
ãªè¨å®ãã§ãã¾ããå®éã«ãã£ã¦ã¿ãã®ã以ä¸ã®ã³ã¼ãã
package main import ( "context" "crypto/tls" "log" "net/http" "net/http/httptrace" "time" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" ) func initTracer() func() { exporter, err := otlptracegrpc.New(context.Background()) if err != nil { log.Fatalf("failed to initialize exporter: %v", err) } tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter)) otel.SetTracerProvider(tp) return func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("failed to shut down tracer provider: %v", err) } } } func main() { shutdown := initTracer() defer shutdown() url := "https://example.com" client := http.Client{ Transport: otelhttp.NewTransport( http.DefaultTransport, otelhttp.WithClientTrace(func(ctx context.Context) *httptrace.ClientTrace { tracer := otel.Tracer("example/client") var dnsStart, handShakeStart, connStart time.Time var host string return &httptrace.ClientTrace{ DNSStart: func(info httptrace.DNSStartInfo) { dnsStart = time.Now() host = info.Host }, DNSDone: func(info httptrace.DNSDoneInfo) { dnsEnd := time.Now() _, span := tracer.Start(ctx, "DNS Lookup", trace.WithTimestamp(dnsStart), trace.WithAttributes(attribute.String("host", host)), trace.WithSpanKind(trace.SpanKindClient), ) span.End(trace.WithTimestamp(dnsEnd)) }, TLSHandshakeStart: func() { handShakeStart = time.Now() }, TLSHandshakeDone: func(state tls.ConnectionState, err error) { handShakeEnd := time.Now() _, span := tracer.Start(ctx, "TLS Handshake", trace.WithTimestamp(handShakeStart), trace.WithAttributes(attribute.Int("CipherSuite", int(state.CipherSuite))), trace.WithSpanKind(trace.SpanKindClient), ) if err != nil { span.RecordError(err) } span.End(trace.WithTimestamp(handShakeEnd)) }, ConnectStart: func(network, addr string) { connStart = time.Now() }, ConnectDone: func(network, addr string, err error) { connEnd := time.Now() _, span := tracer.Start(ctx, "Connection Establishment", trace.WithTimestamp(connStart), trace.WithAttributes( attribute.String("network", network), attribute.String("address", addr), ), trace.WithSpanKind(trace.SpanKindClient), ) if err != nil { span.RecordError(err) } span.End(trace.WithTimestamp(connEnd)) }, } }), ), } ctx := context.Background() req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { log.Fatalf("failed to create request: %v", err) } resp, err := client.Do(req) if err != nil { log.Fatalf("failed to perform request: %v", err) } defer resp.Body.Close() log.Printf("Response status: %s", resp.Status) }
åããã¯ãã¤ã³ãã§ã¿ã¤ã ã¹ã¿ã³ãããã¹ãåãIP ã¢ãã¬ã¹ãªã©ãå±æ§ã¨ãã¦è¨å®ãã¦ãã¾ããã¾ããã¨ã©ã¼ãèµ·ããå ´åã¯ã¹ãã³ã®ã¨ã©ã¼ãè¨å®ãã¦ãã¾ãã以ä¸ã®éã HTTP ãªã¯ã¨ã¹ãã親ã¨ãã¦åå é¨å¦çãã¹ãã³ã¨ãã¦æ§é åããã¦ãããã¨ããããã¾ãã
otelhttp.WithClientTrace
ã使ã
ããç¨åº¦ã³ã¼ããæ¸ãã¦ããããã¥ã¡ã³ãã®è£ã©ããä¸ã®ä¸ã§åããã¨ããã¦ãã人ãããªãããæ¹ãã¦èª¿ã¹ã¦ã¿ãã¨ãã otelhttptrace ã¨ããããã±ã¼ã¸ãç¨æããã¦ãããã¨ãç¥ãã¾ããã1
ãã®ããã±ã¼ã¸ã使ã㨠http.Client
ãä½ãé¨åã¯ããã ãã§æ¸ã¿ã¾ãã
client := http.Client{ Transport: otelhttp.NewTransport( http.DefaultTransport, otelhttp.WithClientTrace(func(ctx context.Context) *httptrace.ClientTrace { return otelhttptrace.NewClientTrace(ctx) }), ), }
åå¾ããæ å ±ãå¢ãã¦ãã¦ãããé©åã«æ§é åããã¦ãã¾ããã
åãããããã使ãã°ããã£ãããâ¦ã¨ããæ°æã¡ã«ãªãã¾ããããä»åã¯æã§ã¹ãã³ãä½ã£ã¦ã¿ãã¨ãããã¨ãç®çã ã£ãã®ã§ã°ãã¨ãã®æ°æã¡ã飲ã¿è¾¼ã¿ã¾ãããã£ããã©ã¤ãã©ãªããããã¨ãè¦ã¤ããã®ã§ãã¡ãã§ã¯ã©ããã£ããã¨ããã¦ããã®ããå°ãè¦ã¦ã¿ã¾ããã
åå®ç¾©ãè¦ã¦ããã¨ããã¬ã¼ãµã¼ãããã¤ãã¼ãæå®ããããåéããæ å ±ã®ã«ã¹ã¿ãã¤ãºãã§ããããã§ããããã©ã«ãã§ã¯èªè¨¼ç¨ã®ãããã¼ãè½ã¨ãããã®ã§ãããåå¾ããããã«ããããè¦ã¤ãã£ãæ å ±å ¨ã¦ãã¹ãã³ã«ãªããã¨ãæå¶ã§ããããããã
clienttrace.go ãã®ããã¦ã¿ãã¨ãããã¯ã®éå§ã»çµäºå¦çãå
±éåãã¦åã¿ã¤ãã³ã°ã§è¨å®ãããå±æ§ã¨ä¸ç·ã«ãããå¼ã°ãã¦ãã¾ããèªåã§æ¸ããå®è£
ã§ã¯ WithTimestamp
ã使ã£ã¦æã«ã¿ã¤ã ã¹ã¿ã³ããè¨å®ãã¦ãã¾ããããcontext ããã¹ãã³ãåå¾ãã¦éå§ã»çµäºã®ã¿ã¤ãã³ã°ã§åãã¹ãã³ã® Start
/End
ãå¼ãã§ããããã§ããåå®ç¾©ã®ã¨ããã§è¦ãuseSpans
ãã©ã°ã«ãã£ã¦ã¤ãã³ãã¨å±æ§ã®ã¿è¨å®ããã¨ããå¦çãããã¾ããã
Vaxila ã«éä¿¡ãã¦ã¿ã
æå¾ã« Vaxila ã«ãã¬ã¼ã¹ãéä¿¡ãã¦ã¿ã¾ããã¨ã¯ã¹ãã¼ã¿ã¼ã®è¨å®ã以ä¸ã®ããã«å¤ããã ãã§ããæ¨æºåããããããã³ã«ã®ä¾¿å©ããæ¹ãã¦æãã¾ããã
exporter, err := otlptracehttp.New(context.Background(), otlptracehttp.WithEndpointURL("https://otlp-vaxila.mackerelio.com"), otlptracehttp.WithHeaders(map[string]string{ "Mackerel-Api-Key": os.Getenv("MACKEREL_APIKEY"), }), )
ããæãã«è¡¨ç¤ºããã¾ããã
å®éã«æãåããã¦ãã¬ã¼ã¹ãè¨è£ ãããã¨ã«ãããã¹ãã³ã®è¦ªåé¢ä¿ã®è¨å®ãå±æ§ãã¤ãã³ãã®æ¦å¿µã®ãããããã§ããã®ã¨ãã¹ãã³ã®ç¨®é¡ãï¼ä»åã®å®è£ ã«ã¯åºã¦ãã¾ããã§ãããï¼ãªã³ã¯ãªã©è§¦ãããã¨ã®ãªãæ¦å¿µãããã¨ãããã¨ãç¥ããã¨ãã§ãã¾ããã
ãã®è¨äºã¯ Mackerel Advent Calendar 2024 7æ¥ç®ã®è¨äºã§ããã
- åèã«ããã¦ããã£ãè¨äº OpenTelemetryã¨httptrace.ClientTraceã使ã£ã¦HTTPãªã¯ã¨ã¹ãã®latencyãå¯è¦åãã - oinume journal↩