# 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`

in Cats-Effect 2 this is likely the best choice. However for 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.

*The examples on this page use the following imports:*

```
import cats.{ Applicative, Monad }
import cats.data.Kleisli
import cats.effect.MonadCancel
import cats.mtl.Local
import cats.syntax.all._
import natchez.{ Span, Trace }
import natchez.mtl._
```

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.

```
def wibble[F[_]: Monad: Trace](name: String, age: Int): F[Unit] =
Trace[F].span("wibble") {
for {
_ <- Trace[F].put("name" -> name, "age" -> age)
// ... actual method logic in F
} yield ()
}
```

By adding a `Trace`

constraint to our abstract we gain this capability.

Now that we have written a program in `F[_]: Trace`

we need a way to satisfy this constraint. There are several ways to do this.

## No-Op Instance

There is a no-op `Trace[F]`

instance available for all `F[_]: Applicative`

. This instance does as you might expect: nothing. This can be useful for development and for testing (where trace data is typically not necessary).

```
object NoTraceForYou {
// In this scope we will ignore tracing
import natchez.Trace.Implicits.noop
// So this compiles fine
def go[F[_]: Monad]: F[Unit] =
wibble("bob", 42)
}
```

## Kleisli Instance

Given `MonadCancel[F, Throwable]`

there is a `Trace[F]`

instance for `Kleisli[F, Span[F], *]`

. This allows us to discharge a `Trace`

constraint, given an initial `Span`

.

```
// Given MonadCancel[F, Throwable] and a Span[F] we can call `wibble`
def go[F[_]](span: Span[F])(
implicit ev: MonadCancel[F, Throwable]
): F[Unit] =
wibble[Kleisli[F, Span[F], *]]("bob", 42).run(span)
```

This strategy works if we write in tagless style. Our outer effect is instantiated as some effect `F`

and the effect for the traced part of our program is instantiated as `Kleisli[F, Span[F], *]`

.

It is not always possible instantiate arbitrary `F`

as `Kleisli`

, depending on the additional constraints on `F`

. In particular it would be impossbile to call `wibble[F[_]: ConcurrentEffect: Trace]`

in this way.

## Cats-MTL Local Instance

By first adding the `natchez-mtl`

module (which pulls in Cats-MTL), given `MonadCancel[F, Throwable]`

and `Local[F, Span[F]]`

there is an instance `Trace[F]`

.

```
def goLocal[F[_]](
implicit ev0: MonadCancel[F, Throwable],
ev1: Local[F, Span[F]]
): F[Unit] =
wibble("bob", 42)
```

This is more general than the `Kleisli`

instance above and allows you to instantiate `F`

as `RWST`

for example, at the cost of an additional dependency.

## Cats-Effect 3 IO Instance

Given a `Span[F]`

you can construct a `Trace[IO]`

for **Cats-Effect 3** (for Cats-Effect 2 you will need to use `Kleisli`

or `Local`

above). This uses `FiberLocal`

to pass the span around.

TODO: Example