# Tracing and context propagation

# Tracing

The Go client provides distributed tracing support through OpenTracing (opens new window). Tracing can be configured by providing an opentracing.Tracer (opens new window) implementation in ClientOptions (opens new window) and WorkerOptions (opens new window) during client and worker instantiation, respectively. Tracing allows you to view the call graph of a workflow along with its activities, child workflows etc. For more details on how to configure and leverage tracing, see the OpenTracing documentation (opens new window). The OpenTracing support has been validated using Jaeger (opens new window), but other implementations mentioned here (opens new window) should also work. Tracing support utilizes generic context propagation support provided by the client.

# Context Propagation

We provide a standard way to propagate custom context across a workflow. ClientOptions (opens new window) and WorkerOptions (opens new window) allow configuring a context propagator. The context propagator extracts and passes on information present in the context.Context and workflow.Context objects across the workflow. Once a context propagator is configured, you should be able to access the required values in the context objects as you would normally do in Go. For a sample, the Go client implements a tracing context propagator (opens new window).

# Server-Side Headers Support

On the server side, Cadence provides a mechanism to propagate what it calls headers across different workflow transitions.

struct Header {
    10: optional map<string, binary> fields
}

The client leverages this to pass around selected context information. HeaderReader (opens new window) and HeaderWriter (opens new window) are interfaces that allow reading and writing to the Cadence server headers. The client already provides implementations (opens new window) for these. HeaderWriter sets a field in the header. Headers is a map, so setting a value for the the same key multiple times will overwrite the previous values. HeaderReader iterates through the headers map and runs the provided handler function on each key/value pair, allowing you to deal with the fields you are interested in.

type HeaderWriter interface {
    Set(string, []byte)
}

type HeaderReader interface {
    ForEachKey(handler func(string, []byte) error) error
}

# Context Propagators

Context propagators require implementing the following four methods to propagate selected context across a workflow:

The tracing context propagator (opens new window) shows a sample implementation of context propagation.

type ContextPropagator interface {
    Inject(context.Context, HeaderWriter) error

    Extract(context.Context, HeaderReader) (context.Context, error)

    InjectFromWorkflow(Context, HeaderWriter) error

    ExtractToWorkflow(Context, HeaderReader) (Context, error)
}

# Q & A

# Is there a complete example?

The context propagation sample (opens new window) configures a custom context propagator and shows context propagation of custom keys across a workflow and an activity.

# Can I configure multiple context propagators?

Yes, we recommended that you configure multiple context propagators with each propagator meant to propagate a particular type of context.