Natchez provides interfaces that abstract over many distributed tracing back-ends. Span, EntryPoint, and Trace are the most important of these interfaces.


The central interface in Natchez is the Span, which is a managed resource that records timing information and other details about its own lifetime. We perform computations within the lifetime of a span and thus gather timing information about these computations.

A Span can create child spans, whose lifetimes are bounded (usually!) by the lifetime of the parent. We can thus gather timing information for various phases of computation within a larger computation. Concurrent computations may have many active child spans.

Spans thus form a tree.

Each Span (in addition to a parent, name, intrinisic timing information, and other back-end-specific data) contains a string-keyed map of TraceValues (strings, booleans, and numbers) for arbitrary user-defined information.

A Span can provide a hunk of data called a Kernel, which can be sent to a remote computer, typically via HTTP headers. The remote computer can then create child spans that will be linked with the originating span by the tracing back-end. Tracing is thus distributed.

See the reference for more information on spans.

Entry Points

Before we can add fields to a Span or create child spans, we must have a span! The chicken-and-egg problem is resolved by the EntryPoint, which provides us with an initial span.

An initial span can be a root span (with no parent) or a continued span (with a parent on another computer). To construct a continued span we must provide the Kernel from a parent span, typically received via HTTP headers.

See the reference for more information on entry points.

Trace Constraint

We must be aware of the current Span if we wish to add fields or create child spans, which means we must pass the current span around.

It is perfectly fine to pass the current span around explicitly, and if you are working in a concrete effect type like IO from Cats-Effect 2 this may be the best choice. However for IO in Cats-Effect 3, as well as the increasingly common case of applications constructed in tagless style (where computations are peformed in some abstract effect) we have a Trace constraint that ensures an ambient span is always available.

Given an effect F[_]: Trace we can add fields to the ambient span, gets its kernel, or run a computation in a child of the ambient span, without referencing the underlying Span directly.

See the reference for more information on the Trace constraint.

The source code for this page can be found here.