The Span trait represents an individual tracing operation. There are two types of span lifecycle management: manual and auto.
Type Signature
Lifecycle Management
Manual Lifecycle
A manual span requires to be ended explicitly by invoking end. This strategy can be used when it’s necessary to end a span outside of the scope (e.g., async callback).
Leaked span (incorrect):
val tracer: Tracer[F] = ???
val leaked: F[Unit] =
tracer.spanBuilder("manual-span").build.startUnmanaged.flatMap { span =>
span.setStatus(StatusCode.Ok, "all good")
} // span is never ended!
Properly ended span (correct):
val tracer: Tracer[F] = ???
val ok: F[Unit] =
tracer.spanBuilder("manual-span").build.startUnmanaged.flatMap { span =>
span.setStatus(StatusCode.Ok, "all good") >> span.end
}
Auto Lifecycle
The auto strategy has a fully managed lifecycle. The span is started upon resource allocation and ended upon finalization.
Automatically ended span:
val tracer: Tracer[F] = ???
val ok: F[Unit] =
tracer.spanBuilder("auto-span").build.use { span =>
span.setStatus(StatusCode.Ok, "all good")
} // span automatically ended when resource is released
Core Properties
backend
def backend: Span.Backend[F]
The backend implementation of the span.
context
Returns the SpanContext associated with this span.
isRecording
def isRecording: F[Boolean]
Returns true if this span is recording.
A recording span captures data passed through operations like addAttributes, addEvent, recordException, and setStatus.
Returns: F[Boolean] - Whether the span is recording
updateName
def updateName(name: String): F[Unit]
Updates the name of the span.
Note: If used, this will override the name provided via the SpanBuilder.
Caution: Upon this update, any sampling behavior based on span’s name will depend on the implementation.
Status Management
setStatus (with status code only)
def setStatus(status: StatusCode): F[Unit]
Sets the status of the span.
The status code (e.g., StatusCode.Ok, StatusCode.Error)
setStatus (with description)
def setStatus(status: StatusCode, description: String): F[Unit]
Sets the status of the span with a description.
A description of the status
Adding Data to Spans
addAttributes
def addAttributes(attributes: immutable.Iterable[Attribute[_]]): F[Unit]
Adds attributes to the span.
attributes
immutable.Iterable[Attribute[_]]
required
The attributes to add
Example:
span.addAttributes(
Attribute("http.method", "GET"),
Attribute("http.url", "https://example.com")
)
addEvent (with attributes)
def addEvent(
name: String,
attributes: immutable.Iterable[Attribute[_]]
): F[Unit]
Adds an event to the span with attributes.
attributes
immutable.Iterable[Attribute[_]]
required
The attributes associated with the event
addEvent (with timestamp)
def addEvent(
name: String,
timestamp: FiniteDuration,
attributes: immutable.Iterable[Attribute[_]]
): F[Unit]
Adds an event to the span with a custom timestamp and attributes.
The explicit timestamp from the epoch
attributes
immutable.Iterable[Attribute[_]]
required
The attributes associated with the event
Note: The timestamp should be based on Clock[F].realTime. Using Clock[F].monotonic may lead to issues.
addLink
def addLink(
spanContext: SpanContext,
attributes: immutable.Iterable[Attribute[_]]
): F[Unit]
Adds a link to another span.
The context of the span to link to
attributes
immutable.Iterable[Attribute[_]]
required
The attributes associated with the link
recordException
def recordException(
exception: Throwable,
attributes: immutable.Iterable[Attribute[_]]
): F[Unit]
Records an exception as an event on the span.
attributes
immutable.Iterable[Attribute[_]]
required
Additional attributes to associate with the exception
Ending a Span
end
Marks the end of span execution.
Only the timing of the first end call for a given span will be recorded; subsequent calls will be ignored.
The end timestamp is based on Clock[F].realTime.
end (with timestamp)
def end(timestamp: FiniteDuration): F[Unit]
Marks the end of span execution with a specified timestamp.
The explicit timestamp from the epoch
Only the timing of the first end call for a given span will be recorded; subsequent calls will be ignored.
Note: The timestamp should be based on Clock[F].realTime. Using Clock[F].monotonic may lead to a missing span.
mapK
def mapK[G[_]](f: F ~> G): Span[G]
Modifies the context F using the transformation f.
Natural transformation from F to G
Returns: Span[G] - A span with the transformed effect type
liftTo
def liftTo[G[_]](implicit kt: KindTransformer[F, G]): Span[G]
Modifies the context F using an implicit KindTransformer from F to G.
Returns: Span[G] - A span with the transformed effect type
Span Backend
The Span.Backend trait provides the low-level implementation of span operations.
Creating Backends
// No-op backend
Span.Backend.noop[F]
// Propagating backend (holds SpanContext but operations are no-op)
Span.Backend.propagating[F](meta, context)
See Also