使用 OpenTelemetry 向应用添加自定义跟踪记录和指标

本文档介绍如何使用 OpenTelemetry 向应用添加可观测性代码。OpenTelemetry 提供了用于为常用框架生成遥测数据的插桩库。您可以添加用于测量应用特有行为的自定义插桩,以增强库生成的遥测数据。

本文档中介绍的原则和概念可应用于以 OpenTelemetry 支持的所有语言编写的应用。 如需详细了解插桩,请参阅以下文档:

示例代码是使用 Go 生成跟踪记录和指标中介绍的同一个 Go 应用,可在 GitHub 中找到。如需查看完整示例,请点击 更多,然后选择在 GitHub 上查看

准备工作

Enable the Cloud Logging, Cloud Monitoring, and Cloud Trace APIs.

Enable the APIs

创建自定义跟踪记录

如需从应用生成自定义跟踪记录,请添加用于创建 OpenTelemetry span 的插桩代码。在 OpenTelemetry 中,span 是跟踪记录的组成要素。

如需创建 span,请执行以下操作:

  1. 修改您的应用以获取 OpenTelemetry Tracer。在 OpenTelemetry 中,跟踪器是 span 的创建者。您可以获取跟踪器,如以下代码所示:

    const scopeName = "github.com/GoogleCloudPlatform/golang-samples/opentelemetry/instrumentation/app/work"
    
    var (
    	meter                = otel.Meter(scopeName)
    	tracer               = otel.Tracer(scopeName)
    	sleepHistogram       metric.Float64Histogram
    	subRequestsHistogram metric.Int64Histogram
    )
    

    跟踪器名称(由 scopeName 表示)标识所生成的跟踪记录的插桩范围

  2. 使用 tracer 实例可创建 span。在以下代码示例中,computeSubrequests 函数在每次被调用时都会生成一个 span:

    func computeSubrequests(r *http.Request, subRequests int) error {
    	// Add custom span representing the work done for the subrequests
    	ctx, span := tracer.Start(r.Context(), "subrequests")
    	defer span.End()
    
    	// Make specified number of http requests to the /single endpoint.
    	for i := 0; i < subRequests; i++ {
    		if err := callSingle(ctx); err != nil {
    			return err
    		}
    	}
    	// record number of sub-requests made
    	subRequestsHistogram.Record(ctx, int64(subRequests))
    	return nil
    }
    

    在前面的代码示例中,从 computeSubrequests 函数生成的 span 表示整个函数完成的工作。这是因为该函数的第一步是使用 tracer.Start 启动新的 span,并且 span.End() 前面的 defer 关键字可确保该 span 就在函数退出之前结束。

创建自定义指标

如需从应用生成指标,您需要添加用于记录应用执行期间所进行的测量的插桩代码。

如需创建指标,请执行以下操作:

  1. 修改您的应用以获取 OpenTelemetry Meter。在 OpenTelemetry 中,计量器提供对指标插桩的访问权限,以便记录指标。您可以获取计量器,如以下代码所示:

    const scopeName = "github.com/GoogleCloudPlatform/golang-samples/opentelemetry/instrumentation/app/work"
    
    var (
    	meter                = otel.Meter(scopeName)
    	tracer               = otel.Tracer(scopeName)
    	sleepHistogram       metric.Float64Histogram
    	subRequestsHistogram metric.Int64Histogram
    )
    

    计量器名称(由 scopeName 表示)标识所生成的指标的插桩范围

  2. 使用 meter 实例可创建可以记录指标的插桩。例如,在以下代码中,我们使用 meter 创建 OpenTelemetry 直方图

    sleepHistogram, err = meter.Float64Histogram("example.sleep.duration",
    	metric.WithDescription("Sample histogram to measure time spent in sleeping"),
    	metric.WithExplicitBucketBoundaries(0.05, 0.075, 0.1, 0.125, 0.150, 0.2),
    	metric.WithUnit("s"))
    if err != nil {
    	panic(err)
    }

    上面这段代码会生成一个名为 sleepHistogram 的直方图。

  3. 使用 sleepHistogram 实例可记录睡眠时间(该时间在调用函数 randomSleep 时确定):

    func randomSleep(r *http.Request) time.Duration {
    	// simulate the work by sleeping 100 to 200 ms
    	sleepTime := time.Duration(100+rand.Intn(100)) * time.Millisecond
    	time.Sleep(sleepTime)
    
    	hostValue := attribute.String("host.value", r.Host)
    	// custom histogram metric to record time slept in seconds
    	sleepHistogram.Record(r.Context(), sleepTime.Seconds(), metric.WithAttributes(hostValue))
    	return sleepTime
    }
    

    这些插桩记录的指标会根据 OpenTelemetry 导出器配置从您的应用中导出。

后续步骤