Setting up Cloud Trace for Go

You can enable Cloud Trace for Go applications by using OpenCensus. OpenCensus is a set of instrumentation libraries for collecting trace and metric data that work with multiple backends. For the latest details about OpenCensus for Go, along with additional documentation and examples, see opencensus-go.

Installing the package

Retrieve the OpenCensus trace package:

go get go.opencensus.io/trace

Configuring the Stackdriver exporter

In order to export the collected Trace data, use a Stackdriver exporter:


import (
	"log"
	"os"

	"contrib.go.opencensus.io/exporter/stackdriver"
	"go.opencensus.io/trace"
)

func main() {
	// Create and register a OpenCensus Stackdriver Trace exporter.
	exporter, err := stackdriver.NewExporter(stackdriver.Options{
		ProjectID: os.Getenv("GOOGLE_CLOUD_PROJECT"),
	})
	if err != nil {
		log.Fatal(err)
	}
	trace.RegisterExporter(exporter)
}

If you are running on Google Cloud infrastructure, then you don't need to set the ProjectID field to your Google Cloud project ID because the client library for Go automatically gathers this data from a Google Cloud metadata server.

If you aren't running on Google Cloud infrastructure, then you must set the ProjectID field to your Google Cloud project ID. In the example code, an environment variable is used and the application has been modified to read this variable.

Configuring integration with Cloud Logging

For information on how to send Cloud Trace data to Cloud Logging, see Integrating with Cloud Logging.

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 can provide these credentials in one of three ways:

  • Run gcloud auth application-default login

  • Place the service account in a default path for your operating system. The following lists the default paths for Windows and Linux:

    • Windows: %APPDATA%/gcloud/application_default_credentials.json

    • Linux: $HOME/.config/gcloud/application_default_credentials.json

  • Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path to your service account:

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"

Sample Trace application for Go


// Sample trace_quickstart traces incoming and outgoing requests.
package main

import (
	"log"
	"net/http"
	"os"

	"contrib.go.opencensus.io/exporter/stackdriver"
	"contrib.go.opencensus.io/exporter/stackdriver/propagation"
	"go.opencensus.io/plugin/ochttp"
	"go.opencensus.io/trace"
)

func main() {
	// Create and register a OpenCensus Stackdriver Trace exporter.
	exporter, err := stackdriver.NewExporter(stackdriver.Options{
		ProjectID: os.Getenv("GOOGLE_CLOUD_PROJECT"),
	})
	if err != nil {
		log.Fatal(err)
	}
	trace.RegisterExporter(exporter)

	// By default, traces will be sampled relatively rarely. To change the
	// sampling frequency for your entire program, call ApplyConfig. Use a
	// ProbabilitySampler to sample a subset of traces, or use AlwaysSample to
	// collect a trace on every run.
	//
	// Be careful about using trace.AlwaysSample in a production application
	// with significant traffic: a new trace will be started and exported for
	// every request.
	trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})

	client := &http.Client{
		Transport: &ochttp.Transport{
			// Use Google Cloud propagation format.
			Propagation: &propagation.HTTPFormat{},
		},
	}

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		req, _ := http.NewRequest("GET", "https://www.google.com", nil)

		// The trace ID from the incoming request will be
		// propagated to the outgoing request.
		req = req.WithContext(r.Context())

		// The outgoing request will be traced with r's trace ID.
		resp, err := client.Do(req)
		if err != nil {
			log.Fatal(err)
		}
		// Because we don't read the resp.Body, need to manually call Close().
		resp.Body.Close()
	})
	http.Handle("/foo", handler)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	log.Printf("Listening on port %s", port)

	// Use an ochttp.Handler in order to instrument OpenCensus for incoming
	// requests.
	httpHandler := &ochttp.Handler{
		// Use the Google Cloud propagation format.
		Propagation: &propagation.HTTPFormat{},
	}
	if err := http.ListenAndServe(":"+port, httpHandler); err != nil {
		log.Fatal(err)
	}
}

Viewing the traces

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

Go to the Trace Viewer page

Troubleshooting

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

Upload of spans for the Go OpenCensus exporter fails

The following are examples of errors that occur when the bundler library used by the exporter is unable to manage the number of spans the application is generating and uploading:

OpenCensus Stackdriver exporter: failed to upload span: buffer full
OpenCensus Stackdriver exporter: failed to upload 183 spans: buffer full

To resolve this situation, try one or more of the following:

  • In the Options struct passed to the traceExporter constructor, increase the value of the TraceSpansBufferMaxBytes field. This optional field specifies the maximum number of bytes used for buffering spans. The default value is 8MB.

  • In the Options object passed to the traceExporter constructor, decrease the values for the following fields:

    • BundleDelayThreshold: This optional field specifies the maximum time the exporter can wait before uploading trace spans. The default value of this field is two seconds.

    • BundleCountThreshold: This optional field specifies the number of spans that can be buffered. The default value of this field is 50.

  • Export fewer spans. To reduce the number of spans you export, configure a global sampler or pass a sampler to each StartSpan. For sample code and more information about these configurations, see OpenCensus Sampling.

Resources