Go and OpenTelemetry

This page is designed for application developers who want to collect Cloud Trace data for Go applications by using OpenTelemetry. OpenTelemetry is a set of instrumentation libraries for collecting trace and metric data; these libraries work with multiple backends. To collect traces with OpenTelemetry and Go, you do the following, as described on this page:

  • Install the OpenTelemetry packages.
  • Configure your application to export spans to Cloud Trace.
  • Configure your platform.

For release information, see the following:

For the latest details about OpenTelemetry for Go, along with additional documentation and examples, see OpenTelemetry.

Before you begin

Verify that the Cloud Trace API is enabled for your Google Cloud project:

  1. Click the following button or, in the Google Cloud Console, select APIs & Services, and then select Cloud Trace API:

    Go to Trace API

  2. On the Cloud Trace API page, if a button labeled Enable is displayed, then click it. If this button isn't displayed, then the Cloud Trace API is enabled for the selected project.

Installing, initializing, and using the client

See the following instructions to instrument your Go applications on Compute Engine and Google Kubernetes Engine. For a general example of using OpenTelemetry, see the OpenTelemetry GitHub repository for Go.

Compute Engine

Install the OpenTelemetry package:

go get go.opentelemetry.io/otel
go get github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace

Import OpenTelemetry and Cloud Trace export packages:

import (
	"context"
	"log"
	"os"

	texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
	"go.opentelemetry.io/otel"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

Create the exporter and the trace provider:

func main() {
	// Create exporter.
	ctx := context.Background()
	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
	exporter, err := texporter.New(texporter.WithProjectID(projectID))
	if err != nil {
		log.Fatalf("texporter.NewExporter: %v", err)
	}

	// Create trace provider with the exporter.
	//
	// By default it uses AlwaysSample() which samples all traces.
	// In a production environment or high QPS setup please use
	// probabilistic sampling.
	// Example:
	//   tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.TraceIDRatioBased(0.0001)), ...)
	tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
	defer tp.ForceFlush(ctx) // flushes any pending spans
	otel.SetTracerProvider(tp)

	// Create custom span.
	tracer := otel.GetTracerProvider().Tracer("example.com/trace")
	err = func(ctx context.Context) error {
		ctx, span := tracer.Start(ctx, "foo")
		defer span.End()

		// Do some work.

		return nil
	}(ctx)
}

When you create the exporter, you provide information about your Google Cloud project identifier. In this example, the identifier is stored in the environment variable GOOGLE_CLOUD_PROJECT.

The example application calls the function WithBatcher to configure the trace provider to send spans to Cloud Monitoring by using a background process. The example is also configured to call the exporter's Shutdown function on application exit. When Shutdown executes, it sends all pending spans to Cloud Monitoring. The configuration shown in the sample is the recommended implementation for all operating environments, including for Cloud Run where containers can be shutdown at any time.

When you create the Tracer instance, you provide it with a name. In the example, the name is example.com/trace. We recommend that you name these instances after the component being traced as this strategy lets you have multiple instances.

When the example is executed, a single trace named foo is created.

GKE

Add the following to your Dockerfile:

RUN go get go.opentelemetry.io/otel

Import OpenTelemetry and Cloud Trace export packages:

import (
	"context"
	"log"
	"os"

	texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
	"go.opentelemetry.io/otel"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

Create the exporter and the trace provider:

func main() {
	// Create exporter.
	ctx := context.Background()
	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
	exporter, err := texporter.New(texporter.WithProjectID(projectID))
	if err != nil {
		log.Fatalf("texporter.NewExporter: %v", err)
	}

	// Create trace provider with the exporter.
	//
	// By default it uses AlwaysSample() which samples all traces.
	// In a production environment or high QPS setup please use
	// probabilistic sampling.
	// Example:
	//   tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.TraceIDRatioBased(0.0001)), ...)
	tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
	defer tp.ForceFlush(ctx) // flushes any pending spans
	otel.SetTracerProvider(tp)

	// Create custom span.
	tracer := otel.GetTracerProvider().Tracer("example.com/trace")
	err = func(ctx context.Context) error {
		ctx, span := tracer.Start(ctx, "foo")
		defer span.End()

		// Do some work.

		return nil
	}(ctx)
}

When you create the exporter, you provide information about your Google Cloud project identifier. In this example, the identifier is stored in the environment variable GOOGLE_CLOUD_PROJECT.

The example application calls the function WithBatcher to configure the trace provider to send spans to Cloud Monitoring by using a background process. The example is also configured to call the exporter's Shutdown function on application exit. When Shutdown executes, it sends all pending spans to Cloud Monitoring. The configuration shown in the sample is the recommended implementation for all operating environments, including for Cloud Run where containers can be shutdown at any time.

When you create the Tracer instance, you provide it with a name. In the example, the name is example.com/trace. We recommend that you name these instances after the component being traced as this strategy lets you have multiple instances.

When the example is executed, a single trace named foo is created.

How to create a custom span

You can add additional information to the system-created trace by creating a custom span.

To create a custom span with the name foo, add the following to the source code:

// Create custom span.
tracer := otel.GetTracerProvider().Tracer("example.com/trace")
err = func(ctx context.Context) error {
	ctx, span := tracer.Start(ctx, "foo")
	defer span.End()

	// Do some work.

	return nil
}(ctx)

Here, example.com/trace refers to the name of the tracer instance.

Configure your platform

You can use Cloud Trace on Google Cloud and other platforms.

Running on Google Cloud

When your application is running on Google Cloud, you don't need to provide authentication credentials in the form of a service account to the client library. However, you do need to ensure that your Google Cloud platform has the Cloud Trace API access scope enabled.

For a list of supported Google Cloud environments, see Environment support.

For the following configurations, the default access-scope settings enable the Cloud Trace API:

  • App Engine flexible environment
  • App Engine standard environment

  • Google Kubernetes Engine (GKE)

  • Compute Engine

  • Cloud Run

If you use custom access scopes, then you must ensure that Cloud Trace API access scope is enabled:

  • For information about how to configure the access scopes for your environment by using the Google Cloud Console, see Configuring your Google Cloud project.

  • For gcloud users, specify access scopes using the --scopes flag and include the trace.append Cloud Trace API access scope. For example, to create a GKE cluster with only the Cloud Trace API enabled, do the following:

    gcloud container clusters create example-cluster-name --scopes=https://www.googleapis.com/auth/trace.append

Running locally and elsewhere

If your application is running outside of Google Cloud, then you must provide authentication credentials in the form of a service account to the client library. The service account must contain the Cloud Trace agent role. For instructions, see Creating a service account.

Google Cloud client libraries use Application Default Credentials (ADC) to find your application's credentials. You provide these credentials by setting the GOOGLE_APPLICATION_CREDENTIALS environment variable:

Linux/macOS

    export GOOGLE_APPLICATION_CREDENTIALS=path-to-your-service-accounts-private-key

Windows

    set GOOGLE_APPLICATION_CREDENTIALS=path-to-your-service-accounts-private-key

PowerShell:

    $env:GOOGLE_APPLICATION_CREDENTIALS="path-to-your-service-accounts-private-key"

Viewing the traces

After deployment, you can view the traces in the Cloud Console Trace Viewer.

Go to the Trace Viewer page

Troubleshooting

For information on troubleshooting issues with Cloud Trace, go to the Troubleshooting page.