Topik ini menjelaskan fitur Analisis Tracing dalam lingkungan runtime Go.
Latar Belakang
Alibaba Cloud Analisis Tracing mengadopsi standar OpenTracing dan kompatibel dengan komunitas sumber terbuka. Analisis Tracing menyediakan berbagai fitur bagi pengembang aplikasi terdistribusi, seperti kemampuan untuk melakukan kueri dan diagnostik jejak terdistribusi, menemukan topologi terdistribusi secara dinamis, serta merangkum kinerja aplikasi secara real time.
Function Compute terintegrasi dengan Analisis Tracing. Anda dapat menggunakan Jaeger SDK atau OpenTelemetry untuk mengunggah informasi jejak sehingga dapat melacak pemanggilan fungsi. Analisis Tracing membantu menganalisis dan mendiagnosis hambatan kinerja dalam arsitektur serverless, sehingga meningkatkan efisiensi pengembangan dan diagnostik dalam skenario serverless.
Ikhtisar
Anda dapat mengonfigurasi Analisis Tracing di Konsol Function Compute. Untuk informasi selengkapnya, lihat Aktifkan Analisis Tracing.
Setelah mengaktifkan Analisis Tracing untuk suatu layanan, Function Compute secara otomatis mencatat waktu yang dikonsumsi dalam sistem, termasuk waktu cold start, waktu eksekusi Fungsi inisialisasi, dan waktu eksekusi fungsi. Untuk informasi selengkapnya tentang rentang sistem pada gambar berikut, lihat Deskripsi nama rentang. 
Anda juga dapat mencatat waktu yang dikonsumsi oleh fungsi di sisi bisnis, misalnya waktu yang diperlukan untuk mengakses layanan seperti ApsaraDB RDS dan Penyimpanan File NAS dalam fungsi, dengan menggunakan Buat rentang kustom.
Kode Contoh
Analisis Tracing untuk Function Compute dalam lingkungan runtime Go memungkinkan Anda membuat rentang kustom menggunakan metode berikut berdasarkan implementasi Jaeger dari spesifikasi OpenTracing.
Gunakan SDK untuk OpenTelemetry (disarankan)
Dalam kode Go, Anda dapat menggunakan SDK untuk OpenTelemetry untuk melakukan instrumentasi kode dan melaporkan data ke Analisis Tracing. Untuk kode contoh lengkap, lihat golang-tracing-openTelemetry.
Daftar berikut menjelaskan detail kode contoh.
Tambahkan dependensi.
go get github.com/aliyun/fc-runtime-go-sdk go get go.opentelemetry.io/otel go get go.opentelemetry.io/otel/sdk go get go.opentelemetry.io/otel/exporters/jaegerLaporkan data ke Analisis Tracing.
func HandleRequest(ctx context.Context, event MyEvent) (string, error) { // Obtain the tracing information of the context in Function Compute. fctx, ok := fccontext.FromContext(ctx) if !ok { return "", fmt.Errorf("failed to get FcContext") } spanCtx, endpoint, err := getFcTracingInfo(fctx) if err != nil { return "", fmt.Errorf("failed to getFcTracingInfo, error: %v", err) } // Create a tracer provider. tp, err := NewTracerProvider(endpoint) if err != nil { return "", fmt.Errorf("OpenTracingJaegerEndpoint: %s, error: %v", fctx.Tracing.JaegerEndpoint, err) } // Set the tracer provider to a global tracer provider. otel.SetTracerProvider(tp) if err != nil { return "", fmt.Errorf("failed to getFcSpanCtx, error: %v", err) } // Create a custom span. startMySpan(trace.ContextWithSpanContext(ctx, spanCtx)) return fmt.Sprintf("hello world! Hello, %s!", event.Name), nil }Buat
tracerProvideryang menyediakan akses ke tracer.func tracerProvider(url string) (*tracesdk.TracerProvider, error) { // Create a Jaeger exporter. exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url))) if err != nil { return nil, err } tp := tracesdk.NewTracerProvider( // Register an exporter. tracesdk.WithBatcher(exp), // Record the application information in the resource. tracesdk.WithResource(resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String("FCTracer"), attribute.String("environment", "production"), attribute.Int64("ID", 1), )), ) return tp, nil }Peroleh informasi tracing dari Context dan konversikan OpenTracing SpanContext menjadi OpenTelemetry SpanContext.
func getFcTracingInfo(fctx *fccontext.FcContext) (trace.SpanContext, string, error) { // Obtain the tracing information. spanContext := trace.SpanContext{} endpoint := fctx.Tracing.JaegerEndpoint OpenTracingSpanContext := fctx.Tracing.OpenTracingSpanContext if len(endpoint) == 0 { return spanContext, endpoint, fmt.Errorf("invalid jaeger endpoint") } spanContextSlice := strings.Split(OpenTracingSpanContext, ":") // Pad zeros in front of the trace ID. tid, err := trace.TraceIDFromHex("0000000000000000" + spanContextSlice[0]) if err != nil { return spanContext, endpoint, err } fid := trace.FlagsSampled spanContext = spanContext.WithTraceID(tid).WithTraceFlags(fid).WithRemote(true) return spanContext, endpoint, nil }Buat
tracerdan gunakan OpenTelemetry SpanContext yang telah dikonversi untuk membuat rentang anak. Rentang merepresentasikan potongan kode yang dapat dieksekusi secara berkelanjutan yang diberi nama dan diukur waktunya dalam jejak pemanggilan. Anda juga dapat membuat rentang anak dari rentang tersebut.func startMySpan(ctx context.Context) { // Use a global tracer provider. tr := otel.Tracer("fc-Trace") ctx, parentSpan := tr.Start(ctx, "fc-operation") defer parentSpan.End() parentSpan.SetAttributes(attribute.Key("version").String("fc-v1")) time.Sleep(150 * time.Millisecond) child(ctx) } func child(ctx context.Context) { tr := otel.Tracer("fc-Trace") _, childSpan := tr.Start(ctx, "fc-operation-child") defer childSpan.End() time.Sleep(100 * time.Millisecond) childSpan.AddEvent("timeout") }
Gunakan SDK untuk Jaeger
Anda dapat menggunakan SDK untuk Jaeger untuk melakukan instrumentasi kode dan melaporkan data ke Analisis Tracing. Untuk kode contoh lengkap, lihat golang-tracing.
Daftar berikut menjelaskan detail kode contoh.
Tambahkan dependensi.
go get github.com/aliyun/fc-runtime-go-sdk go get github.com/opentracing/opentracing-go go get github.com/uber/jaeger-client-goLaporkan data ke Analisis Tracing.
func HandleRequest(ctx context.Context, event MyEvent) (string, error) { // Obtain the tracing information of the context in Function Compute. fctx, _ := fccontext.FromContext(ctx) endpoint := fctx.Tracing.JaegerEndpoint OpenTracingSpanContext := fctx.Tracing.OpenTracingSpanContext if len(endpoint) == 0 { return "", fmt.Errorf("invalid jaeger endpoint") } // Create a tracer. tracer, closer := NewJaegerTracer("FCTracer", endpoint) defer closer.Close() // Restore the SpanContext. spanContext, err := jaeger.ContextFromString(OpenTracingSpanContext) if err != nil { return "", fmt.Errorf("OpenTracingSpanContext: %s, error: %v", fctx.Tracing.OpenTracingSpanContext, err) } // Create a custom span. startMySpan(spanContext, tracer) return fmt.Sprintf("hello world! Hello, %s!", event.Name), nil }Buat objek
traceryang menyediakan akses ke tracer.func NewJaegerTracer(service, endpoint string) (opentracing.Tracer, io.Closer) { sender := transport.NewHTTPTransport(endpoint) tracer, closer := jaeger.NewTracer(service, jaeger.NewConstSampler(true), jaeger.NewRemoteReporter(sender)) return tracer, closer }Konversikan SpanContext dan buat rentang kustom. Anda juga dapat membuat rentang anak dari rentang tersebut.
func startMySpan(context jaeger.SpanContext, tracer opentracing.Tracer) { parentSpan := tracer.StartSpan("MyFCSpan", opentracing.ChildOf(context)) defer parentSpan.Finish() parentSpan.SetOperationName("fc-operation") parentSpan.SetTag("version", "fc-v1") time.Sleep(150 * time.Millisecond) // Enable a child span. childSpan := tracer.StartSpan("fc-operation-child", opentracing.ChildOf(parentSpan.Context())) defer childSpan.Finish() time.Sleep(100 * time.Millisecond) childSpan.LogFields( log.String("type", "cache timeout"), log.Int("waited.millis", 100)) }