go: cloud.google.com/go/trace Index | Examples | Files | Directories

package trace

import "cloud.google.com/go/trace"

Package trace is a Google Stackdriver Trace library.

This package is still experimental and subject to change.

See https://cloud.google.com/trace/api/#data_model for a discussion of traces and spans.

To initialize a client that connects to the Stackdriver Trace server, use the NewClient function. Generally you will want to do this on program initialization.

import "cloud.google.com/go/trace"
...
traceClient, err = trace.NewClient(ctx, projectID)

Calling SpanFromRequest will create a new trace span for an incoming HTTP request. If the request contains a trace context header, it is used to determine the trace ID. Otherwise, a new trace ID is created.

func handler(w http.ResponseWriter, r *http.Request) {
  span := traceClient.SpanFromRequest(r)
  defer span.Finish()
  ...
}

SpanFromRequest and NewSpan returns nil if the *Client is nil, so you can disable tracing by not initializing your *Client variable. All of the exported functions on *Span do nothing when the *Span is nil.

If you need to start traces that don't correspond to an incoming HTTP request, you can use NewSpan to create a root-level span.

span := traceClient.NewSpan("span name")
defer span.Finish()

Although a trace span object is created for every request, only a subset of traces are uploaded to the server, for efficiency. By default, the requests that are traced are those with the tracing bit set in the options field of the trace context header. Ideally, you should override this behaviour by calling SetSamplingPolicy. NewLimitedSampler returns an implementation of SamplingPolicy which traces requests that have the tracing bit set, and also randomly traces a specified fraction of requests. Additionally, it sets a limit on the number of requests traced per second. The following example traces one in every thousand requests, up to a limit of 5 per second.

p, err := trace.NewLimitedSampler(0.001, 5)
traceClient.SetSamplingPolicy(p)

You can create a new span as a child of an existing span with NewChild.

childSpan := span.NewChild(name)
...
childSpan.Finish()

When sending an HTTP request to another server, NewRemoteChild will create a span to represent the time the current program waits for the request to complete, and attach a header to the outgoing request so that the trace will be propagated to the destination server.

childSpan := span.NewRemoteChild(&httpRequest)
...
childSpan.Finish()

Alternatively, if you have access to the X-Cloud-Trace-Context header value but not the underlying HTTP request (this can happen if you are using a different transport or messaging protocol, such as gRPC), you can use SpanFromHeader instead of SpanFromRequest. In that case, you will need to specify the span name explicility, since it cannot be constructed from the HTTP request's URL and method.

func handler(r *somepkg.Request) {
  span := traceClient.SpanFromHeader("span name", r.TraceContext())
  defer span.Finish()
  ...
}

Spans can contain a map from keys to values that have useful information about the span. The elements of this map are called labels. Some labels, whose keys all begin with the string "trace.cloud.google.com/", are set automatically in the following ways:

- SpanFromRequest sets some labels to data about the incoming request.

- NewRemoteChild sets some labels to data about the outgoing request.

- Finish sets a label to a stack trace, if the stack trace option is enabled in the incoming trace header.

- The WithResponse option sets some labels to data about a response. You can also set labels using SetLabel. If a label is given a value automatically and by SetLabel, the automatically-set value is used.

span.SetLabel(key, value)

The WithResponse option can be used when Finish is called.

childSpan := span.NewRemoteChild(outgoingReq)
resp, err := http.DefaultClient.Do(outgoingReq)
...
childSpan.Finish(trace.WithResponse(resp))

When a span created by SpanFromRequest or SpamFromHeader is finished, the finished spans in the corresponding trace -- the span itself and its descendants -- are uploaded to the Stackdriver Trace server using the *Client that created the span. Finish returns immediately, and uploading occurs asynchronously. You can use the FinishWait function instead to wait until uploading has finished.

err := span.FinishWait()

Using contexts to pass *trace.Span objects through your program will often be a better approach than passing them around explicitly. This allows trace spans, and other request-scoped or part-of-request-scoped values, to be easily passed through API boundaries. Various Google Cloud libraries will retrieve trace spans from contexts and automatically create child spans for API requests. See https://blog.golang.org/context for more discussion of contexts. A derived context containing a trace span can be created using NewContext.

span := traceClient.SpanFromRequest(r)
ctx = trace.NewContext(ctx, span)

The span can be retrieved from a context elsewhere in the program using FromContext.

func foo(ctx context.Context) {
  span := trace.FromContext(ctx).NewChild("in foo")
  defer span.Finish()
  ...
}

Index

Examples

Package Files

grpc.go http.go sampling.go trace.go

Constants

const (
    // ScopeTraceAppend grants permissions to write trace data for a project.
    ScopeTraceAppend = "https://www.googleapis.com/auth/trace.append"

    // ScopeCloudPlatform grants permissions to view and manage your data
    // across Google Cloud Platform services.
    ScopeCloudPlatform = "https://www.googleapis.com/auth/cloud-platform"
)

Variables

var EnableGRPCTracing option.ClientOption = option.WithGRPCDialOption(grpc.WithUnaryInterceptor(GRPCClientInterceptor()))

EnableGRPCTracing automatically traces all outgoing gRPC calls from cloud.google.com/go clients.

The functionality in gRPC that this relies on is currently experimental.

Deprecated: Use option.WithGRPCDialOption(grpc.WithUnaryInterceptor(GRPCClientInterceptor())) instead.

func GRPCClientInterceptor Uses

func GRPCClientInterceptor() grpc.UnaryClientInterceptor

GRPCClientInterceptor returns a grpc.UnaryClientInterceptor that traces all outgoing requests from a gRPC client. The calling context should already have a *trace.Span; a child span will be created for the outgoing gRPC call. If the calling context doesn't have a span, the call will not be traced.

The functionality in gRPC that this feature relies on is currently experimental.

func GRPCServerInterceptor Uses

func GRPCServerInterceptor(tc *Client) grpc.UnaryServerInterceptor

GRPCServerInterceptor returns a grpc.UnaryServerInterceptor that enables the tracing of the incoming gRPC calls. Incoming call's context can be used to extract the span on servers that enabled this option:

span := trace.FromContext(ctx)

The functionality in gRPC that this feature relies on is currently experimental.

func NewContext Uses

func NewContext(ctx context.Context, s *Span) context.Context

NewContext returns a derived context containing the span.

type Client Uses

type Client struct {
    // contains filtered or unexported fields
}

Client is a client for uploading traces to the Google Stackdriver Trace server.

func NewClient Uses

func NewClient(ctx context.Context, projectID string, opts ...option.ClientOption) (*Client, error)

NewClient creates a new Google Stackdriver Trace client.

func (*Client) HTTPHandler Uses

func (c *Client) HTTPHandler(h http.Handler) http.Handler

HTTPHandler returns a http.Handler from the given handler that is aware of the incoming request's span. The span can be extracted from the incoming request in handler functions from incoming request's context:

span := trace.FromContext(r.Context())

The span will be auto finished by the handler.

Code:

handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    client := traceClient.NewHTTPClient(nil)

    req, _ := http.NewRequest("GET", "https://metadata/users", nil)
    req = req.WithContext(r.Context())

    // The outgoing request will be traced with r's trace ID.
    if _, err := client.Do(req); err != nil {
        log.Fatal(err)
    }
})
http.Handle("/foo", traceClient.HTTPHandler(handler)) // traceClient is a *Client

func (*Client) NewHTTPClient Uses

func (c *Client) NewHTTPClient(orig *http.Client) *HTTPClient

NewHTTPClient creates a new HTTPClient that will trace the outgoing requests using tc. The attributes of this client are inherited from the given http.Client. If orig is nil, http.DefaultClient is used.

func (*Client) NewSpan Uses

func (c *Client) NewSpan(name string) *Span

NewSpan returns a new trace span with the given name.

A new trace and span ID is generated to trace the span. Returned span need to be finished by calling Finish or FinishWait.

func (*Client) SetSamplingPolicy Uses

func (c *Client) SetSamplingPolicy(p SamplingPolicy)

SetSamplingPolicy sets the SamplingPolicy that determines how often traces are initiated by this client.

func (*Client) SpanFromHeader Uses

func (c *Client) SpanFromHeader(name string, header string) *Span

SpanFromHeader returns a new trace span, based on a provided request header value. See https://cloud.google.com/trace/docs/faq.

It returns nil iff the client is nil.

The trace information and identifiers will be read from the header value. Otherwise, a new trace ID is made and the parent span ID is zero.

The name of the new span is provided as an argument.

If a non-nil sampling policy has been set in the client, it can override the options set in the header and choose whether to trace the request.

If the header doesn't have existing tracing information, then a *Span is returned anyway, but it will not be uploaded to the server, just as when calling SpanFromRequest on an untraced request.

Most users using HTTP should use SpanFromRequest, rather than SpanFromHeader, since it provides additional functionality for HTTP requests. In particular, it will set various pieces of request information as labels on the *Span, which is not available from the header alone.

func (*Client) SpanFromRequest Uses

func (c *Client) SpanFromRequest(r *http.Request) *Span

SpanFromRequest returns a new trace span for an HTTP request.

It returns nil iff the client is nil.

If the incoming HTTP request contains a trace context header, the trace ID, parent span ID, and tracing options will be read from that header. Otherwise, a new trace ID is made and the parent span ID is zero.

If a non-nil sampling policy has been set in the client, it can override the options set in the header and choose whether to trace the request.

If the request is not being traced, then a *Span is returned anyway, but it will not be uploaded to the server -- it is only useful for propagating trace context to child requests and for getting the TraceID. All its methods can still be called -- the Finish, FinishWait, and SetLabel methods do nothing. NewChild does nothing, and returns the same *Span. TraceID works as usual.

type Decision Uses

type Decision struct {
    Trace  bool    // Whether to trace the request.
    Sample bool    // Whether the trace is included in the random sample.
    Policy string  // Name of the sampling policy.
    Weight float64 // Sample weight to be used in statistical calculations.
}

Decision is the value returned by a call to a SamplingPolicy's Sample method.

type FinishOption Uses

type FinishOption interface {
    // contains filtered or unexported methods
}

func WithResponse Uses

func WithResponse(resp *http.Response) FinishOption

WithResponse returns an option that can be passed to Finish that indicates that some labels for the span should be set using the given *http.Response.

type HTTPClient Uses

type HTTPClient struct {
    http.Client
    // contains filtered or unexported fields
}

HTTPClient is an HTTP client that enhances http.Client with automatic tracing support.

func (*HTTPClient) Do Uses

func (c *HTTPClient) Do(req *http.Request) (*http.Response, error)

Do behaves like (*http.Client).Do but automatically traces outgoing requests if tracing is enabled for the current request.

If req.Context() contains a traced *Span, the outgoing request is traced with the existing span. If not, the request is not traced.

Code:

client := traceClient.NewHTTPClient(nil) // traceClient is a *Client

req, _ := http.NewRequest("GET", "https://metadata/users", nil)
if _, err := client.Do(req); err != nil {
    log.Fatal(err)
}

type Parameters Uses

type Parameters struct {
    HasTraceHeader bool // whether the incoming request has a valid X-Cloud-Trace-Context header.
}

Parameters contains the values passed to a SamplingPolicy's Sample method.

type SamplingPolicy Uses

type SamplingPolicy interface {
    // Sample returns a Decision.
    // If Trace is false in the returned Decision, then the Decision should be
    // the zero value.
    Sample(p Parameters) Decision
}

func NewLimitedSampler Uses

func NewLimitedSampler(fraction, maxqps float64) (SamplingPolicy, error)

NewLimitedSampler returns a sampling policy that randomly samples a given fraction of requests. It also enforces a limit on the number of traces per second. It tries to trace every request with a trace header, but will not exceed the qps limit to do it.

type Span Uses

type Span struct {
    // contains filtered or unexported fields
}

Span contains information about one span of a trace.

func FromContext Uses

func FromContext(ctx context.Context) *Span

FromContext returns the span contained in the context, or nil.

func (*Span) Finish Uses

func (s *Span) Finish(opts ...FinishOption)

Finish declares that the span has finished.

If s is nil, Finish does nothing and returns nil.

If the option trace.WithResponse(resp) is passed, then some labels are set for s using information in the given *http.Response. This is useful when the span is for an outgoing http request; s will typically have been created by NewRemoteChild in this case.

If s is a root span (one created by SpanFromRequest) then s, and all its descendant spans that have finished, are uploaded to the Google Stackdriver Trace server asynchronously.

func (*Span) FinishWait Uses

func (s *Span) FinishWait(opts ...FinishOption) error

FinishWait is like Finish, but if s is a root span, it waits until uploading is finished, then returns an error if one occurred.

func (*Span) Header Uses

func (s *Span) Header() string

Header returns the value of the X-Cloud-Trace-Context header that should be used to propagate the span. This is the inverse of SpanFromHeader.

Most users should use NewRemoteChild unless they have specific propagation needs or want to control the naming of their span. Header() does not create a new span.

func (*Span) NewChild Uses

func (s *Span) NewChild(name string) *Span

NewChild creates a new span with the given name as a child of s. If s is nil, does nothing and returns nil.

func (*Span) NewRemoteChild Uses

func (s *Span) NewRemoteChild(r *http.Request) *Span

NewRemoteChild creates a new span as a child of s.

Some labels in the span are set from the outgoing *http.Request r.

A header is set in r so that the trace context is propagated to the destination. The parent span ID in that header is set as follows: - If the request is being traced, then the ID of s is used. - If the request is not being traced, but there was a trace context header

in the incoming request for this trace (the request passed to
SpanFromRequest), the parent span ID in that header is used.

- Otherwise, the parent span ID is zero. The tracing bit in the options is set if tracing is enabled, or if it was set in the incoming request.

If s is nil, does nothing and returns nil.

func (*Span) SetLabel Uses

func (s *Span) SetLabel(key, value string)

SetLabel sets the label for the given key to the given value. If the value is empty, the label for that key is deleted. If a label is given a value automatically and by SetLabel, the automatically-set value is used. If s is nil, does nothing.

SetLabel shouldn't be called after Finish or FinishWait.

func (*Span) TraceID Uses

func (s *Span) TraceID() string

TraceID returns the ID of the trace to which s belongs.

Directories

PathSynopsis
apiv1Package trace is an experimental, auto-generated package for the trace API.

Package trace imports 22 packages (graph) and is imported by 7 packages. Updated 2017-05-25. Refresh now. Tools for package owners.