Tracing and Context Propagation

Tracing

The Go client provides distributed tracing support through OpenTracing. Tracing can be configured by providing an opentracing.Tracer implementation in ClientOptions and WorkerOptions 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. The OpenTracing support has been validated using Jaeger, but other implementations mentioned here 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 and WorkerOptions 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.

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 and HeaderWriter are interfaces that allow reading and writing to the Cadence server headers. The client already provides implementations 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 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 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.