# 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:
Inject
is meant to pick out the context keys of interest from a Go context.Context (opens new window) object and write that into the headers using the HeaderWriter (opens new window) interfaceInjectFromWorkflow
is the same as above, but operates on a workflow.Context (opens new window) objectExtract
reads the headers and places the information of interest back into the context.Context (opens new window) objectExtractToWorkflow
is the same as above, but operates on a workflow.Context (opens new window) object
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.