すべてのプロダクト
Search
ドキュメントセンター

Function Compute:トレース分析

最終更新日:Nov 09, 2025

このトピックでは、Go ランタイム環境におけるトレース分析機能について説明します。

背景

Alibaba Cloud Tracing Analysis は OpenTracing 標準を採用しており、オープンソースコミュニティと互換性があります。トレース分析は、分散アプリケーションの開発者にさまざまな機能を提供します。たとえば、開発者は分散トレースのクエリと診断、分散トポロジの動的な検出、アプリケーションパフォーマンスのリアルタイムでの集計が可能になります。

Function Compute はトレース分析と統合されています。Jaeger SDK または OpenTelemetry を使用してトレース情報をアップロードし、関数呼び出しを追跡できます。トレース分析は、サーバーレスアーキテクチャにおけるパフォーマンスボトルネックの分析と診断に役立ちます。これにより、サーバーレスシナリオでの開発と診断の効率が向上します。

概要

Function Compute コンソールでトレース分析を設定できます。詳細については、「トレース分析の有効化」をご参照ください。

サービスのトレース分析を有効にすると、Function Compute はシステムで消費された時間を自動的に記録します。この時間には、コールドスタート時間、イニシャライザー関数の実行時間、および関数の実行時間が含まれます。次の図のシステムスパンの詳細については、「スパン名の説明」をご参照ください。Tracing Analysis

ビジネス側の関数で消費された時間を記録できます。たとえば、「カスタムスパンの作成」を使用して、関数内で ApsaraDB RDS や File Storage NAS などのサービスへのアクセスにかかった時間を記録できます。

サンプルコード

Go ランタイム環境の Function Compute のトレース分析では、OpenTracing 仕様の Jaeger 実装に基づいて、次のメソッドを使用してカスタムスパンを作成できます。

SDK for OpenTelemetry の使用 (推奨)

Go コードでは、SDK for OpenTelemetry を使用してコードインストルメンテーションを実行し、データをトレース分析にレポートできます。完全なサンプルコードについては、「golang-tracing-openTelemetry」をご参照ください。

次のリストは、サンプルコードの詳細を説明しています。

  • 依存関係を追加します。

    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/jaeger
  • データをトレース分析にレポートします。

    func HandleRequest(ctx context.Context, event MyEvent) (string, error) {
        // 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)
        }
        // トレーサープロバイダーを作成します。
        tp, err := NewTracerProvider(endpoint)
        if err != nil {
            return "", fmt.Errorf("OpenTracingJaegerEndpoint: %s, error: %v", fctx.Tracing.JaegerEndpoint, err)
        }
        // トレーサープロバイダーをグローバルトレーサープロバイダーに設定します。
        otel.SetTracerProvider(tp)
        if err != nil {
            return "", fmt.Errorf("failed to getFcSpanCtx, error: %v", err)
        }
        // カスタムスパンを作成します。
        startMySpan(trace.ContextWithSpanContext(ctx, spanCtx))
        return fmt.Sprintf("hello world! Hello, %s!", event.Name), nil
    }
  • トレーサーへのアクセスを提供する tracerProvider を作成します。

    func tracerProvider(url string) (*tracesdk.TracerProvider, error) {
        // Jaeger エクスポーターを作成します。
        exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
        if err != nil {
            return nil, err
        }
        tp := tracesdk.NewTracerProvider(
            // エクスポーターを登録します。
            tracesdk.WithBatcher(exp),
            // リソースにアプリケーション情報を記録します。
            tracesdk.WithResource(resource.NewWithAttributes(
                semconv.SchemaURL,
                semconv.ServiceNameKey.String("FCTracer"),
                attribute.String("environment", "production"),
                attribute.Int64("ID", 1),
            )),
        )
        return tp, nil
    }
  • Context からトレース情報を取得し、OpenTracing SpanContext を OpenTelemetry SpanContext に変換します。

    func getFcTracingInfo(fctx *fccontext.FcContext) (trace.SpanContext, string, error) {
        // トレース情報を取得します。
        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, ":")
    
        // トレース 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
    }
  • tracer を作成し、変換された OpenTelemetry SpanContext を使用して子スパンを作成します。スパンは、呼び出しトレースで名前が付けられ、時間が計測される、継続的に実行可能なコードスニペットを表します。スパンから子スパンを作成することもできます。

    func startMySpan(ctx context.Context) {
        // グローバルトレーサープロバイダーを使用します。
        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")
    }

SDK for Jaeger の使用

SDK for Jaeger を使用してコードインストルメンテーションを実行し、データをトレース分析にレポートできます。完全なサンプルコードについては、「golang-tracing」をご参照ください。

次のリストは、サンプルコードの詳細を説明しています。

  • 依存関係を追加します。

    go get github.com/aliyun/fc-runtime-go-sdk
    go get github.com/opentracing/opentracing-go
    go get github.com/uber/jaeger-client-go
  • データをトレース分析にレポートします。

    func HandleRequest(ctx context.Context, event MyEvent) (string, error) {
        // Function Compute のコンテキストのトレース情報を取得します。
        fctx, _ := fccontext.FromContext(ctx)
        endpoint := fctx.Tracing.JaegerEndpoint
        OpenTracingSpanContext := fctx.Tracing.OpenTracingSpanContext
        if len(endpoint) == 0 {
            return "", fmt.Errorf("invalid jaeger endpoint")
        }
        // トレーサーを作成します。
        tracer, closer := NewJaegerTracer("FCTracer", endpoint)
        defer closer.Close()
        // SpanContext を復元します。
        spanContext, err := jaeger.ContextFromString(OpenTracingSpanContext)
        if err != nil {
            return "", fmt.Errorf("OpenTracingSpanContext: %s, error: %v", fctx.Tracing.OpenTracingSpanContext, err)
        }
        // カスタムスパンを作成します。
        startMySpan(spanContext, tracer)
        return fmt.Sprintf("hello world! Hello, %s!", event.Name), nil
    }
  • トレーサーへのアクセスを提供する 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
    }
  • SpanContext を変換し、カスタムスパンを作成します。スパンから子スパンを作成することもできます。

    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)
        // 子スパンを有効にします。
        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))
    }