Using OpenTelemetry with Go

You can enable Cloud Trace for Go applications by using OpenTelemetry. OpenTelemetry is a set of instrumentation libraries for collecting trace and metric data that work with multiple backends. For the latest details about OpenTelemetry for Go, along with additional documentation and examples, go to https://opentelemetry.io/.

Installation and configuration

To collect traces, you need to do the following:

  • Install the OpenTelemetry client libraries.
  • Import the OpenTelemetry trace packages.
  • Configure OpenTelemetry to export spans to Cloud Trace.
  • Enable the Cloud Trace API access scope.

Installing, initializing, and using the client

See the following instructions to instrument your Go applications on Compute Engine and Google Kubernetes Engine.

Compute Engine

Install the OpenTelemetry package:

go get -u go.opentelemetry.io/otel
go get -u 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/api/global"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

Create the exporter and the trace provider:

func main() {
	// Create exporter.
	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
	exporter, err := texporter.NewExporter(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
	// ProbabilitySampler set at the desired probability.
	// Example:
	//   config := sdktrace.Config{DefaultSampler:sdktrace.ProbabilitySampler(0.0001)}
	//   tp, err := sdktrace.NewProvider(sdktrace.WithConfig(config), ...)
	tp, err := sdktrace.NewProvider(sdktrace.WithSyncer(exporter))
	if err != nil {
		log.Fatal(err)
	}
	global.SetTraceProvider(tp)

	// Create custom span.
	tracer := global.TraceProvider().Tracer("example.com/trace")
	tracer.WithSpan(context.Background(), "foo",
		func(_ context.Context) error {
			// Do some work.
			return nil
		})
}

Here, example.com/trace refers to the name of the tracer instance, and foo is the name of the span. The tracer instance should be named after the component being traced because you could have multiple tracer instances.

GKE

Add the following to your Dockerfile:

RUN go get -u 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/api/global"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

Create the exporter and the trace provider:

func main() {
	// Create exporter.
	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
	exporter, err := texporter.NewExporter(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
	// ProbabilitySampler set at the desired probability.
	// Example:
	//   config := sdktrace.Config{DefaultSampler:sdktrace.ProbabilitySampler(0.0001)}
	//   tp, err := sdktrace.NewProvider(sdktrace.WithConfig(config), ...)
	tp, err := sdktrace.NewProvider(sdktrace.WithSyncer(exporter))
	if err != nil {
		log.Fatal(err)
	}
	global.SetTraceProvider(tp)

	// Create custom span.
	tracer := global.TraceProvider().Tracer("example.com/trace")
	tracer.WithSpan(context.Background(), "foo",
		func(_ context.Context) error {
			// Do some work.
			return nil
		})
}

Here, example.com/trace refers to the name of the tracer instance, and foo is the name of the span. The tracer instance is named after the component being traced to make it identifiable; you might have multiple tracer instances.

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, add the following to the source code:

// Create custom span.
tracer := global.TraceProvider().Tracer("example.com/trace")
tracer.WithSpan(context.Background(), "foo",
	func(_ context.Context) error {
		// Do some work.
		return nil
	})

Here, example.com/trace refers to the name of the tracer instance, and foo is the name of the span. The tracer instance is named after the component being traced to make it identifiable; you might have multiple tracer instances.

Configuring 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 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

If you use custom access scopes, then you must ensure that Cloud Trace API access scope is enabled. 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"

Performance optimization

To reduce the performance impact of reporting trace data, use a background process to send this data. To configure background reporting of trace data, include transport=AsyncTransport when initializing the StackdriverExporter.

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.