<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Maksym Ochenashko</title>
    <subtitle>Personal engineering blog</subtitle>
    <link rel="self" type="application/atom+xml" href="https://ochenashko.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://ochenashko.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-01-13T10:00:00+00:00</updated>
    <id>https://ochenashko.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Practical observability: distributed tracing with otel4s</title>
        <published>2026-01-13T10:00:00+00:00</published>
        <updated>2026-01-13T10:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ochenashko.com/practical-observability-distributed-tracing/"/>
        <id>https://ochenashko.com/practical-observability-distributed-tracing/</id>
        
        <content type="html" xml:base="https://ochenashko.com/practical-observability-distributed-tracing/">&lt;p&gt;In this series, we explore how to bring observability into a Scala application
using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;&quot;&gt;OpenTelemetry&lt;&#x2F;a&gt; - the open standard for telemetry data -
and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;otel4s&#x2F;&quot;&gt;otel4s&lt;&#x2F;a&gt;, a purely functional OpenTelemetry library for the
Typelevel (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;cats-effect&#x2F;&quot;&gt;Cats Effect&lt;&#x2F;a&gt;) ecosystem.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        Series roadmap
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;..&#x2F;practical-observability-foundation&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt;: Foundations with OpenTelemetry.&lt;&#x2F;li&gt;
&lt;li&gt;Part 2 (this post): Distributed tracing with otel4s.&lt;&#x2F;li&gt;
&lt;li&gt;Part 3 (coming soon): Implementing metrics with otel4s.&lt;&#x2F;li&gt;
&lt;li&gt;Part 4 (coming eventually): Advanced configuration and operational tips.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This article explains how to implement clear and predictable distributed tracing in Scala with otel4s.&lt;&#x2F;p&gt;
&lt;p&gt;The early sections outline how telemetry signals are identified by resources, instrumentation scopes, and attributes.
They also explain how tracers and tracer providers define boundaries and lifecycle, providing context for span behavior
and the otel4s API structure.&lt;&#x2F;p&gt;
&lt;p&gt;Then we focus on span creation, scoping, and context propagation, detailing how traces cross service boundaries.
These concepts are later demonstrated in a real application to show how explicit instrumentation affects observed
traces.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition tip&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        Tip
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;For practical instrumentation, jump to &lt;a href=&quot;#7-instrumenting-an-application&quot;&gt;section 7&lt;&#x2F;a&gt;. While prior sections cover
fundamentals, they aren&#x27;t necessary to follow the examples.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;&lt;h1 id=&quot;1-identifying-telemetry-signals&quot;&gt;1. Identifying telemetry signals&lt;&#x2F;h1&gt;
&lt;p&gt;When you look at a trace in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;docs&#x2F;tempo&#x2F;latest&#x2F;&quot;&gt;Grafana Tempo&lt;&#x2F;a&gt; or
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.jaegertracing.io&#x2F;&quot;&gt;Jaeger&lt;&#x2F;a&gt;, you&#x27;re not just viewing timings. You&#x27;re seeing information from different parts
of an application, compiled into a single view. Understanding where that information comes from makes the tracing API
much easier to reason about.&lt;&#x2F;p&gt;
&lt;p&gt;OpenTelemetry defines a consistent identification model for all telemetry. Each signal has a &lt;strong&gt;process-level&lt;&#x2F;strong&gt; identity,
a &lt;strong&gt;scope-level&lt;&#x2F;strong&gt; identity, and &lt;strong&gt;operation-level&lt;&#x2F;strong&gt; details. These aspects are kept separate and clearly defined.&lt;&#x2F;p&gt;
&lt;p&gt;The tracing backends, like Grafana Tempo or Jaeger, rely on this information. It determines which service emitted the
signal, which library or subsystem produced it, and what kind of operation it represents.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-1-attributes&quot;&gt;1.1. Attributes&lt;&#x2F;h2&gt;
&lt;p&gt;Attributes are key-value pairs used to describe telemetry data. They are a core concept in OpenTelemetry and are used
with traces, metrics, and logs.&lt;&#x2F;p&gt;
&lt;p&gt;An attribute provides structured context to a signal. In traces, attributes describe what a span represents. In metrics,
they label time series. In logs, they offer structured fields. The same attribute key, such as a &lt;code&gt;service.name&lt;&#x2F;code&gt; or
&lt;code&gt;http.request.method&lt;&#x2F;code&gt;, can appear consistently across all three signals.&lt;&#x2F;p&gt;
&lt;p&gt;Because attributes are structured, backends can index them. This enables filtering traces by
route, grouping metrics by operation, or correlating logs with a specific request. Without attributes, telemetry becomes
difficult to query and analyze.&lt;&#x2F;p&gt;
&lt;p&gt;In tracing, span attributes typically capture &lt;strong&gt;operation-level&lt;&#x2F;strong&gt; details, such as the HTTP method, route template,
database system, or request type. These values explain what kind of work the span represents, rather than how it was
executed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-2-instrumentation-resource&quot;&gt;1.2. Instrumentation resource&lt;&#x2F;h2&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;resources&#x2F;&quot;&gt;resource&lt;&#x2F;a&gt; is a &lt;strong&gt;process-level&lt;&#x2F;strong&gt; identity that defines the
entity generating telemetry. In practice, it describes the running service with attributes like &lt;code&gt;service.name&lt;&#x2F;code&gt;,
&lt;code&gt;service.version&lt;&#x2F;code&gt;, or &lt;code&gt;deployment.environment&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Resource attributes are attached to all telemetry produced by a specific SDK instance. They are intended to remain
constant for the lifetime of the process and do not vary per request.&lt;&#x2F;p&gt;
&lt;p&gt;In otel4s, you configure the resource when creating the SDK, generally through environment variables or system
properties.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition tip&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        Tip
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;If the attribute value can change from one request to another, it does not belong in the resource.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;&lt;h2 id=&quot;1-3-instrumentation-scope&quot;&gt;1.3. Instrumentation scope&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;instrumentation-scope&#x2F;&quot;&gt;instrumentation scope&lt;&#x2F;a&gt; is a &lt;strong&gt;scope-level&lt;&#x2F;strong&gt; identity
that describes the library or module that emitted the telemetry signal. Concretely, it is defined by a name, an optional
version, and an optional schema URL.&lt;&#x2F;p&gt;
&lt;p&gt;In otel4s, this information is attached when you create a &lt;code&gt;Tracer&lt;&#x2F;code&gt;. The tracer name usually corresponds to a library, a
module, or a logical subsystem. For application code, it is common to use something like &lt;code&gt;module.forecast&lt;&#x2F;code&gt; or
&lt;code&gt;module.payments&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Backends use the instrumentation scope to group spans, filter noise, and reason about ownership. When you later see
traces with spans from an HTTP server, a database client, and a Kafka consumer, the instrumentation scope helps you
tell them apart.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition tip&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        Tip
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;If two pieces of code could reasonably be versioned independently, they should not share the same instrumentation scope.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;hr &#x2F;&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;mermaid&quot; style=&quot;display: flex; justify-content: center;&quot;&gt;
---
config:
  look: handDrawn
  layout: elk
---
graph TB
  subgraph R[&amp;quot;Telemetry resource&amp;lt;br&amp;#x2F;&amp;gt;(process wide)&amp;quot;]
    Rdesc[&amp;quot;Attributes:&amp;lt;br&amp;#x2F;&amp;gt;service.name&amp;lt;br&amp;#x2F;&amp;gt;service.version&amp;lt;br&amp;#x2F;&amp;gt;deployment.environment&amp;quot;]

    subgraph S[&amp;quot;Instrumentation scope (library or module)&amp;quot;]
      Sdesc[&amp;quot;name&amp;lt;br&amp;#x2F;&amp;gt;version&amp;lt;br&amp;#x2F;&amp;gt;schema URL&amp;quot;]

      subgraph SIG[&amp;quot;Telemetry signal&amp;quot;]
        Span[&amp;quot;Trace &amp;#x2F; Metric &amp;#x2F; Log record&amp;quot;]
        Attr[&amp;quot;Attributes:&amp;lt;br&amp;#x2F;&amp;gt;operation.type&amp;lt;br&amp;#x2F;&amp;gt;http.request.method&amp;lt;br&amp;#x2F;&amp;gt;user.id&amp;quot;]
        Span --&amp;gt; Attr
      end
    end

end
&lt;&#x2F;pre&gt;

&lt;p style=&quot;text-align: center&quot;&gt;Telemetry signal identification layers&lt;&#x2F;p&gt;
&lt;!-- @formatter:on --&gt;
&lt;p&gt;The telemetry resource identifies the running service or process for all SDK output. The instrumentation scope refers
to a specific library, module, or subsystem.&lt;&#x2F;p&gt;
&lt;p&gt;A span, metric point, or log record always belongs to a single instrumentation scope and the telemetry resource.
Attributes are attached at the signal level. They describe what the specific span, metric, or log represents and serve
as the main mechanism for querying, grouping, and correlating telemetry.&lt;&#x2F;p&gt;
&lt;p&gt;This nesting, from resource to instrumentation scope to individual signals, explains why OpenTelemetry can maintain
ownership, identity, and meaning separation while still presenting everything as a single, coherent trace or view in the
backend.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;2-initializing-the-sdk&quot;&gt;2. Initializing the SDK&lt;&#x2F;h1&gt;
&lt;p&gt;Before creating tracers or spans, an SDK must be initialized. The instrumentation API used by the application is
exposed through this instance.&lt;&#x2F;p&gt;
&lt;p&gt;In most applications, you create one instance at startup. You keep it for the entire lifetime of the process.
Treat it as a shared dependency to make ownership clear and keep configuration centralized.&lt;&#x2F;p&gt;
&lt;p&gt;First, we need to add a few dependencies and configuration options:&lt;&#x2F;p&gt;




&lt;div class=&quot;tool-tabs&quot; data-tool-tabs&gt;
  &lt;div class=&quot;tool-tabs__controls&quot; role=&quot;tablist&quot; aria-label=&quot;Build tool&quot;&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;sbt&quot;&gt;
        sbt
      &lt;&#x2F;button&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;scala-cli&quot;&gt;
        scala-cli
      &lt;&#x2F;button&gt;
    
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;tool-tabs__panels&quot;&gt;
    &lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;sbt&quot;&gt;
  &lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;libraryDependencies &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;++=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Seq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.typelevel&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;   %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;otel4s-oteljava&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                           %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.0.0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;io.opentelemetry&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;opentelemetry-exporter-otlp&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;               %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Runtime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;io.opentelemetry&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;opentelemetry-sdk-extension-autoconfigure&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Runtime&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;run &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; fork  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;javaOptions &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.java.global-autoconfigure.enabled=true&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;javaOptions &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.service.name=weather-service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;scala-cli&quot;&gt;
  &lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;org.typelevel::otel4s-oteljava:1.0.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;io.opentelemetry:opentelemetry-exporter-otlp:1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; javaOpt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.java.global-autoconfigure.enabled=true&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; javaOpt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.service.name=weather-service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Here we add otel4s with the &lt;code&gt;oteljava&lt;&#x2F;code&gt; backend, which uses the official
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;open-telemetry&#x2F;opentelemetry-java&quot;&gt;OpenTelemetry Java SDK&lt;&#x2F;a&gt; under the hood. We include the SDK
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;languages&#x2F;java&#x2F;configuration&#x2F;#zero-code-sdk-autoconfigure&quot;&gt;autoconfiguration&lt;&#x2F;a&gt; module and
the OTLP exporter. These components allow the SDK to configure resources, exporters, and sampling using environment
variables and JVM (system) properties rather than hard-coded values.&lt;&#x2F;p&gt;
&lt;p&gt;With the dependencies in place, we can create an autoconfigured instance:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IOApp&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Otel4s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;oteljava&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;OtelJava&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TracerProvider&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IOApp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Simple&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    OtelJava&lt;&#x2F;span&gt;&lt;span&gt;.autoConfigured[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]().use { otel4s &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; otel4s.tracerProvider&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      program&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; program&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;My program&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;OtelJava.autoConfigured&lt;&#x2F;code&gt; builds an SDK instance using environment variables, JVM properties, and defaults. It
returns a &lt;code&gt;Resource&lt;&#x2F;code&gt;, so the lifecycle is managed for you. When released, exporters flush and shut down gracefully.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-1-autoconfigured-versus-global&quot;&gt;2.1. Autoconfigured versus global&lt;&#x2F;h2&gt;
&lt;p&gt;otel4s offers two main ways to integrate with the OpenTelemetry Java SDK.&lt;&#x2F;p&gt;
&lt;p&gt;The first option is &lt;code&gt;OtelJava.autoConfigured&lt;&#x2F;code&gt;, the default for most applications. It creates an isolated, non-global SDK
instance configured by the environment. Exporters, sampling strategies, resource detectors, and context storage are
automatically configured.&lt;&#x2F;p&gt;
&lt;p&gt;This instance is not registered as the global OpenTelemetry SDK. Multiple autoconfigured instances are completely
independent and do not see each other&#x27;s spans. Usually, you create a single instance for the lifetime of the process.
This model suits functional applications built with &lt;code&gt;IOApp&lt;&#x2F;code&gt;, where resource ownership and shutdown are explicit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;OtelJava.autoConfigured&lt;&#x2F;code&gt; also accepts an optional customization function. This allows you to tweak the underlying SDK
builder while still relying on autoconfiguration for most settings:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;OtelJava&lt;&#x2F;span&gt;&lt;span&gt;.autoConfigured[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;] { builder &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  builder.addResourceCustomizer { (resource, _)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    resource.toBuilder.put(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;custom.attribute&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;value&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).build()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The second option is &lt;code&gt;OtelJava.global&lt;&#x2F;code&gt;, which configures otel4s to use the global OpenTelemetry instance. The global SDK
must be initialized before &lt;code&gt;OtelJava.global&lt;&#x2F;code&gt; is materialized. Because otel4s does not manage the lifecycle, the owner of
the global SDK is responsible for flushing and shutting down.&lt;&#x2F;p&gt;
&lt;p&gt;This approach is useful when an IO-based code runs inside a larger application that already relies on a global
OpenTelemetry setup, and you want otel4s to participate in it.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition warning&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        Warning
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;Neither &lt;code&gt;OtelJava.autoConfigured&lt;&#x2F;code&gt; nor &lt;code&gt;OtelJava.global&lt;&#x2F;code&gt; work with the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;zero-code&#x2F;java&#x2F;agent&#x2F;&quot;&gt;OpenTelemetry Java Agent&lt;&#x2F;a&gt; seamlessly. However, there are
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;otel4s&#x2F;oteljava&#x2F;agent.html&quot;&gt;experimental options&lt;&#x2F;a&gt; to let otel4s work with the agent.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;&lt;h2 id=&quot;2-2-configuration-through-the-environment&quot;&gt;2.2. Configuration through the environment&lt;&#x2F;h2&gt;
&lt;p&gt;Autoconfiguration uses environment variables and JVM options. For example, variables like &lt;code&gt;OTEL_TRACES_EXPORTER&lt;&#x2F;code&gt; select
exporters, &lt;code&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;&#x2F;code&gt; sets endpoints, and &lt;code&gt;OTEL_TRACES_SAMPLER&lt;&#x2F;code&gt; chooses sampling strategies.&lt;&#x2F;p&gt;
&lt;p&gt;By default, the SDK builds a telemetry resource using detectors. These usually include process information, host
details, and any attributes provided through &lt;code&gt;OTEL_RESOURCE_ATTRIBUTES&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In a minimal setup, the only required configuration is the service name. You can provide it using the
&lt;code&gt;otel.service.name&lt;&#x2F;code&gt; system property or the &lt;code&gt;OTEL_SERVICE_NAME&lt;&#x2F;code&gt; environment variable. All other settings can be
configured later without modifying application code.&lt;&#x2F;p&gt;
&lt;p&gt;This approach scales across environments. You can deploy the same service to development, staging, or production with
varied observability. Traces remain structurally identical. Differences in origin, environment, or region are reflected
in telemetry resource attributes, not in code paths.&lt;&#x2F;p&gt;
&lt;p&gt;Here are a few examples of common settings:
&lt;div class=&quot;box&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;System property&lt;&#x2F;th&gt;&lt;th&gt;Environment variable&lt;&#x2F;th&gt;&lt;th&gt;Example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;otel.service.name&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;OTEL_SERVICE_NAME&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;weather-service&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;otel.traces.exporter&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;OTEL_TRACES_EXPORTER&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;otlp&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;otel.exporter.otlp.endpoint&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;http:&#x2F;&#x2F;localhost:4317&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;otel.propagators&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;OTEL_PROPAGATORS&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tracecontext,baggage&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can check the full list of supported settings in the OpenTelemetry Java
SDK &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;languages&#x2F;java&#x2F;configuration&#x2F;#properties-general&quot;&gt;documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;3-creating-a-tracer&quot;&gt;3. Creating a Tracer&lt;&#x2F;h1&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;mermaid&quot; style=&quot;display: flex; justify-content: center;&quot;&gt;
---
config:
  look: handDrawn
  layout: elk
---
graph TB
subgraph R[&amp;quot;OtelJava&amp;lt;br&amp;#x2F;&amp;gt;(OpenTelemetry Java SDK)&amp;quot;]

    subgraph TracerProvider
      subgraph Tracer
        TracerApi@{ shape: processes, label: &amp;quot;Spans&amp;quot; }
        TracerScope[&amp;quot;Instrumentation scope:&amp;lt;br&amp;#x2F;&amp;gt;name&amp;lt;br&amp;#x2F;&amp;gt;version&amp;lt;br&amp;#x2F;&amp;gt;schema URL&amp;quot;]
      end
    end

    Pipeline[&amp;quot;Telemetry Pipeline&amp;quot;]

    TracerProvider --&amp;gt; Pipeline
end
&lt;&#x2F;pre&gt;

&lt;p style=&quot;text-align: center&quot;&gt;Components hierarchy&lt;&#x2F;p&gt;
&lt;!-- @formatter:on --&gt;
&lt;p&gt;The &lt;code&gt;TracerProvider&lt;&#x2F;code&gt; is the main entry point for tracing in otel4s. It produces &lt;code&gt;Tracer&lt;&#x2F;code&gt; instances for different
instrumentation scopes and connects them to the telemetry pipeline. We can get it from the &lt;code&gt;OtelJava&lt;&#x2F;code&gt; instance.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;code&gt;Tracer&lt;&#x2F;code&gt; represents a single instrumentation scope. Every span is created through a tracer, and the tracer defines
which part of the system those spans belong to. In otel4s, tracers are cheap to create and safe to reuse. You typically
create one tracer per module or logical group and make it available wherever spans are needed.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with a simple example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; checkWeather&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    getForecast(location)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getForecast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Getting forecast for&lt;&#x2F;span&gt;&lt;span&gt; $location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).as(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Sunny&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].tracer(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;module.forecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).withVersion(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;1.2.3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we create a &lt;code&gt;Tracer&lt;&#x2F;code&gt; named &lt;code&gt;module.forecast&lt;&#x2F;code&gt; with version &lt;code&gt;1.2.3&lt;&#x2F;code&gt;. These options identify the instrumentation
scope. In application code, the name typically corresponds to a logical subsystem, such as a domain module, an HTTP
layer, or a background worker.&lt;&#x2F;p&gt;
&lt;p&gt;The version becomes useful when traces from multiple deployments overlap. If span names or attributes change between
releases, the version tells you which code produced which spans. This makes it easier to reason about traces during
rollouts. It also helps when comparing behavior across versions.&lt;&#x2F;p&gt;
&lt;p&gt;The tracer is created once and passed to the module implicitly. All spans produced by &lt;code&gt;ForecastModule&lt;&#x2F;code&gt; now carry the
same scope information. This makes their origin explicit in the trace.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition tip&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        Tip
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;&lt;code&gt;TracerProvider[IO].get(&quot;service&quot;)&lt;&#x2F;code&gt; is a convenience shortcut for &lt;code&gt;TracerProvider[IO].tracer(&quot;service&quot;).get&lt;&#x2F;code&gt;.
Both create a tracer for the given instrumentation scope name.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;A common question at this stage is whether an application should use a single tracer or multiple tracers.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s no strict rule, but a useful guideline: use separate tracers for spans from different layers and use a single
tracer if spans belong to one cohesive unit.&lt;&#x2F;p&gt;
&lt;p&gt;For example, use one tracer for an HTTP layer and another for a domain logic. This helps visually separate transport
concerns from business behavior in a trace. Splitting tracers too aggressively, however, can add noise without
improving clarity.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;4-creating-a-span&quot;&gt;4. Creating a Span&lt;&#x2F;h1&gt;
&lt;p&gt;A span is a unit of work with a name, timing, optional attributes and events, and trace context. In otel4s, spans are
always created via a &lt;code&gt;Tracer&lt;&#x2F;code&gt; to ensure proper instrumentation scope and context association.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Tracer[IO].span&lt;&#x2F;code&gt; is the main API for application code, handling span creation, context management, and cleanup in a
single step, compatible with effectful code.&lt;&#x2F;p&gt;
&lt;p&gt;A minimal example looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; checkWeather&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;checkWeather&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;location&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, location)).use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      getForecast(location)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;*&lt;&#x2F;span&gt;&lt;span&gt; span.addEvent(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;forecast-received&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getForecast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Getting forecast for&lt;&#x2F;span&gt;&lt;span&gt; $location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).as(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Sunny&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code creates a span named &lt;code&gt;checkWeather&lt;&#x2F;code&gt;, makes it current for the duration of the effect, and guarantees that it
is ended when the effect completes.&lt;&#x2F;p&gt;
&lt;p&gt;Several important things happen here.&lt;&#x2F;p&gt;
&lt;p&gt;First, parent selection is automatic: if there&#x27;s an active span, the new one becomes a child; if not, a new trace
starts. This establishes the parent-child relationship that forms the trace structure.&lt;&#x2F;p&gt;
&lt;p&gt;Second, error awareness is built in. If the effect fails, the span is marked as errored, and the exception is recorded.
You do not need to catch exceptions just to annotate the span or remember to set status codes on every failure path.
Span outcome follows effect outcome by default.&lt;&#x2F;p&gt;
&lt;p&gt;When the effect finishes, the previous context is restored. This maintains span nesting and prevents context leaks.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition tip&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        Tip
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;Use &lt;code&gt;Tracer[IO].rootSpan(&quot;span&quot;)&lt;&#x2F;code&gt; when you want to force the creation of a root span, regardless of the current tracing
context.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;&lt;h2 id=&quot;4-1-nesting-spans&quot;&gt;4.1. Nesting spans&lt;&#x2F;h2&gt;
&lt;p&gt;When a span is created inside another span, the inner span automatically becomes a child of the outer one. You do not
need to manage scopes explicitly or pass span references through method signatures.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; checkWeather&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;checkWeather&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;location&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, location)).use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      getForecast(location)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;*&lt;&#x2F;span&gt;&lt;span&gt; span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getForecast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;getForecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).surround {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Getting forecast for&lt;&#x2F;span&gt;&lt;span&gt; $location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).as(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Sunny&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The resulting trace links &lt;code&gt;getForecast&lt;&#x2F;code&gt; as a child of &lt;code&gt;checkWeather&lt;&#x2F;code&gt;, preserving timing and structure. Context
propagates automatically across calls, fibers, and async bounds within the Cats Effect runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Span nesting reflects effect structure, not thread structure. This is critical in fiber-based systems, where execution
can switch threads often.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition tip&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        Tip
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;&lt;code&gt;Tracer[IO].span(&quot;...&quot;).surround(io)&lt;&#x2F;code&gt; is a convenience shortcut for &lt;code&gt;Tracer[IO].span(&quot;...&quot;).use(_ =&amp;gt; io)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;&lt;h2 id=&quot;4-2-accessing-the-current-span&quot;&gt;4.2. Accessing the current span&lt;&#x2F;h2&gt;
&lt;p&gt;While a span is active, it is available through the current tracing context. This allows nested code to interact with
an existing span without owning its lifecycle:&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getForecast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Getting forecast for&lt;&#x2F;span&gt;&lt;span&gt; $location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).as(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Sunny&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].withCurrentSpanOrNoop(_.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;This code doesn&#x27;t create a span. It retrieves the current one from the scope and updates it if present. If no span is
active, a no-op span is used, and &lt;code&gt;setStatus&lt;&#x2F;code&gt; has no effect.&lt;&#x2F;p&gt;
&lt;p&gt;This pattern keeps span ownership at higher levels while still allowing deeper layers to report outcomes, add
attributes, or emit events. Domain code remains loosely coupled to tracing and does not need to know how spans are
created or finalized.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-3-the-spanbuilder-deep-dive&quot;&gt;4.3. The SpanBuilder deep dive&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;Tracer[IO].span&lt;&#x2F;code&gt; covers typical cases, managing lifecycle, context propagation, and errors with minimal API surface.&lt;&#x2F;p&gt;
&lt;p&gt;At system boundaries, you often need advanced control over span creation. Typical scenarios include integrating with
HTTP servers, gRPC handlers, or message consumers, where span creation must align with context or protocols provided by
external systems.&lt;&#x2F;p&gt;
&lt;p&gt;For these cases, otel4s exposes a low-level builder API via &lt;code&gt;Tracer[IO].spanBuilder&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; withSpanBuilder&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;externalParent&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SpanContext&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;linkTo&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SpanContext&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; spanOps&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SpanOps&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;span.name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .addAttributes(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;request.type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;example&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .addLink(linkTo)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .withParent(externalParent)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Internal&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .withFinalizationStrategy(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanFinalizer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Strategy&lt;&#x2F;span&gt;&lt;span&gt;.reportAbnormal)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  spanOps.surround(io)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The builder makes span creation explicit and configurable. It supports overriding parents, attaching links, setting the
span kind, and customizing finalization. These capabilities are intentionally excluded from the high-level API because
the business layer rarely needs them, whereas boundary code often does.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the full list of methods available on the builder:&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;div class=&quot;box&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Method&lt;&#x2F;th&gt;&lt;th&gt;What it does&lt;&#x2F;th&gt;&lt;th&gt;The use case&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;addAttributes&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Adds attributes to the span&lt;&#x2F;td&gt;&lt;td&gt;Describe the operation, protocol, or static identifiers&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;addLink&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Adds a non-hierarchical reference to another span&lt;&#x2F;td&gt;&lt;td&gt;Correlating asynchronous work or fan-in and fan-out patterns&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;root&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Forces the span to be a root span, ignoring any existing parent&lt;&#x2F;td&gt;&lt;td&gt;Deliberately breaking propagation, such as for scheduled jobs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;withParent&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sets an explicit parent span context&lt;&#x2F;td&gt;&lt;td&gt;Joining an existing or extracted trace&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;withSpanKind&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Declares the role the span plays in a distributed interaction&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;Client&lt;&#x2F;code&gt;, &lt;code&gt;Server&lt;&#x2F;code&gt;, &lt;code&gt;Producer&lt;&#x2F;code&gt;, &lt;code&gt;Consumer&lt;&#x2F;code&gt;, or &lt;code&gt;Internal&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;withFinalizationStrategy&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Customizes how the span is finalized based on outcome&lt;&#x2F;td&gt;&lt;td&gt;Attaching additional attributes or status&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;withStartTimestamp&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sets the start time manually&lt;&#x2F;td&gt;&lt;td&gt;Advanced cases where timing must be aligned with external events&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;Use the builder API for advanced integration points where you need to align spans with externally provided context,
correlate work between systems, or customize span attributes or timing. For typical application code, continue using
the high-level API for ease of use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-4-the-context-propagation-model&quot;&gt;4.4. The context propagation model&lt;&#x2F;h2&gt;
&lt;p&gt;You may have noticed that &lt;code&gt;Tracer[IO].spanBuilder(...).build&lt;&#x2F;code&gt; method returns a &lt;code&gt;SpanOps[IO]&lt;&#x2F;code&gt;, not a
&lt;code&gt;Resource[IO, Span[IO]]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Span creation and span propagation management are closely related. A span is not just a value that needs to be acquired
and released. It also needs to be made current so downstream operations can attach to it. This requires careful control
over scope.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Resource&lt;&#x2F;code&gt; is a good fit for managing lifecycles, but it does not model dynamic context propagation well. Resource
acquisition and release can happen on different fibers, which breaks the assumption that a span should be current only
for a specific region of execution.&lt;&#x2F;p&gt;
&lt;p&gt;otel4s solves this by basing the context propagation on
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;cats-mtl&#x2F;mtl-classes&#x2F;local.html&quot;&gt;cats.mtl.Local&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Local&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[_], &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;E&lt;&#x2F;span&gt;&lt;span&gt;] {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ask&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;E&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; local&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;fa&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; E&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; E&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;Instead of binding to threads, context is bound to effect segments. &lt;code&gt;Local&lt;&#x2F;code&gt; ensures the same context is observed
throughout execution of a segment, regardless of how the fiber is scheduled. This is what makes span nesting and access
to the current span work transparently across asynchronous boundaries, without passing &lt;code&gt;Span[IO]&lt;&#x2F;code&gt; explicitly or relying
on thread locals.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;SpanOps&lt;&#x2F;code&gt; bridges this gap by combining lifecycle management with scoped context propagation. It wraps effects, ensuring
tracing context is installed and restored correctly.&lt;&#x2F;p&gt;
&lt;p&gt;This design ensures the tracing API is predictable and safe for concurrent and async code.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;5-explicit-scope-manipulation&quot;&gt;5. Explicit scope manipulation&lt;&#x2F;h1&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;These explicit scope controls are for edge cases. Most application code should rely on the default propagation rules and
high-level &lt;code&gt;Tracer[IO].span&lt;&#x2F;code&gt; API.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;By default, &lt;code&gt;Tracer[IO].span&lt;&#x2F;code&gt; determines parentage automatically based on the currently active tracing context.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes the default behavior is not enough. You may want to suppress tracing for a block of code, start a new trace,
or attach work to a specific parent that is not currently active. These cases often occur at boundaries where execution
semantics change and implicit propagation no longer matches intent.&lt;&#x2F;p&gt;
&lt;p&gt;otel4s provides explicit scope controls for these situations. The intent of a scope is to temporarily redefine the
current tracing context, directly affecting how spans created within it are parented. Rather than creating spans, scopes
determine the parenting relationships for spans created during their lifetime.&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;div class=&quot;box&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Method&lt;&#x2F;th&gt;&lt;th&gt;What it does&lt;&#x2F;th&gt;&lt;th&gt;The use case&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Tracer[IO].noopScope&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Establishes a no-op tracing scope. All tracing operations inside the scope become no-ops&lt;&#x2F;td&gt;&lt;td&gt;Useful for suppressing noise from background maintenance tasks, health checks, or tight internal loops&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Tracer[IO].rootScope&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Establishes a new root tracing scope. Any span created inside it becomes a root span, even if a parent was active before&lt;&#x2F;td&gt;&lt;td&gt;Use when you intentionally want to break trace continuity, such as scheduled jobs, detached background work, or independent workflows&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Tracer[IO].childScope&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Establishes a tracing scope with an explicit parent span context&lt;&#x2F;td&gt;&lt;td&gt;Useful at integration boundaries where you receive a span context externally and want to attach work to it deliberately&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;The following example demonstrates how these scopes affect span parentage in practice:&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; scopeManagement&lt;&#x2F;span&gt;&lt;span&gt;()(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;parent&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).use { parent &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;child-1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).use_ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; a child of the &amp;#39;parent&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].rootScope {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;             Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;child-2&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).use_ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; a root span that is not associated with the &amp;#39;parent&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].noopScope {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;             Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;child-3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).use_ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; a span will not be created&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;child-4&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).surround {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; a child of the &amp;#39;parent&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;             Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].childScope(parent.context).surround {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;               Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;explicit-child&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).use_ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; a child of the &amp;#39;parent&amp;#39;, not &amp;#39;child-4&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;The first span, &lt;code&gt;child-1&lt;&#x2F;code&gt;, is a straightforward child of &lt;code&gt;parent&lt;&#x2F;code&gt;, created under the default propagation rules.&lt;&#x2F;p&gt;
&lt;p&gt;Within &lt;code&gt;rootScope&lt;&#x2F;code&gt;, &lt;code&gt;child-2&lt;&#x2F;code&gt; becomes a root span. This breaks the default continuity, as &lt;code&gt;parent&lt;&#x2F;code&gt; is still active
outside but not within the new scope. The explicit scope here signals the intent to start a new trace context.&lt;&#x2F;p&gt;
&lt;p&gt;Inside &lt;code&gt;noopScope&lt;&#x2F;code&gt;, no span is created. Tracing has no effect here, letting you suppress traces without extra logic.&lt;&#x2F;p&gt;
&lt;p&gt;The last case shows scope interaction. &lt;code&gt;child-4&lt;&#x2F;code&gt; follows &lt;code&gt;parent&lt;&#x2F;code&gt; by normal propagation. Inside, &lt;code&gt;childScope(parent)&lt;&#x2F;code&gt;
overrides the scope, so &lt;code&gt;explicit-child&lt;&#x2F;code&gt; is a direct child of &lt;code&gt;parent&lt;&#x2F;code&gt;, not &lt;code&gt;child-4&lt;&#x2F;code&gt;. This demonstrates that scope
defines intent, apart from the execution structure.&lt;&#x2F;p&gt;
&lt;p&gt;This level of control is powerful but easy to misuse. Overusing explicit scopes can make traces harder to interpret, as
parent-child relationships no longer reflect the execution flow. Scope manipulation should mark meaningful execution
boundaries. Use it where execution meaningfully changes, not as a replacement for the default propagation model.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;6-cross-service-propagation&quot;&gt;6. Cross-service propagation&lt;&#x2F;h1&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;A span never crosses a process boundary. Only tracing context does.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Up to this point, everything has happened within a single process. Spans are created, nested, and propagated
automatically as execution moves across fibers. This model holds as long as all work stays within one runtime.&lt;&#x2F;p&gt;
&lt;p&gt;The moment execution crosses a process boundary, the rules change. A span cannot follow execution into another process.
Instead, only the tracing context is transferred. This happens at explicit boundaries where a service hands work off
to something else, such as an HTTP call, a gRPC request, or a message being published or consumed.&lt;&#x2F;p&gt;
&lt;p&gt;Tracing context represents a small data structure containing the trace ID, parent span ID, and sampling flags. On the
caller side, the tracing context is encoded into request metadata. On the receiver side, it is decoded and set as the
current context, allowing new spans to join the same trace. If decoding succeeds, the trace continues. If decoding
fails, execution proceeds under a new root context.&lt;&#x2F;p&gt;
&lt;p&gt;Encoding and decoding operations are performed
by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;context-propagation&#x2F;#propagation&quot;&gt;propagators&lt;&#x2F;a&gt;. A propagator specifies the
representation of tracing context as a set of key-value pairs and defines its reconstruction on the receiving side.&lt;&#x2F;p&gt;
&lt;p&gt;By default, the OpenTelemetry SDK uses the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;trace-context&#x2F;&quot;&gt;W3C TraceContext&lt;&#x2F;a&gt; propagator.
Propagators are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;languages&#x2F;java&#x2F;configuration&#x2F;#properties-general&quot;&gt;configured&lt;&#x2F;a&gt; at the SDK
level, typically using environment variables or JVM system properties, rather than in application code.&lt;&#x2F;p&gt;
&lt;p&gt;With the W3C TraceContext propagator, injected headers look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;traceparent&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where &lt;code&gt;4bf92f3577b34da6a3ce929d0e0e4736&lt;&#x2F;code&gt; is the trace ID, &lt;code&gt;00f067aa0ba902b7&lt;&#x2F;code&gt; is the span ID, and &lt;code&gt;01&lt;&#x2F;code&gt; is the trace
flags.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;6-1-outgoing-side-propagating-context&quot;&gt;6.1. Outgoing side: propagating context&lt;&#x2F;h2&gt;
&lt;p&gt;On the outgoing side, the goal is to attach the current tracing context to an outbound request.&lt;&#x2F;p&gt;
&lt;p&gt;In otel4s, this starts with &lt;code&gt;Tracer[IO].propagate&lt;&#x2F;code&gt;, which reads the current tracing context and uses the configured
propagators to encode it as text key-value pairs. These pairs are written into a carrier.&lt;&#x2F;p&gt;
&lt;p&gt;A carrier is a data structure that holds string keys and values. At this point, nothing is sent over the wire.
No transport is involved yet. The carrier is simply a container for the encoded tracing context.&lt;&#x2F;p&gt;
&lt;p&gt;The second step is transport-specific. Once you have a populated carrier, you attach it to an outgoing request using
whatever mechanism the protocol provides, such as HTTP headers, gRPC metadata, or message headers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Tracer[IO].propagate&lt;&#x2F;code&gt; works with any carrier that implements &lt;code&gt;TextMapUpdater&lt;&#x2F;code&gt;. This typeclass defines how key-value
pairs are written into a carrier. As long as a data structure can store textual keys and values, it can be
used for propagation.&lt;&#x2F;p&gt;
&lt;p&gt;For example, this is how propagation can be wired into &lt;code&gt;org.http4s.Headers&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;propagation&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TextMapUpdater&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; handleOutgoing&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;request&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    headers  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].propagate(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;.empty)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    response &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; client.expect[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;](request.withHeaders(headers))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TextMapUpdater&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; updated&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;carrier&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    carrier.put(key &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;Here, the current tracing context is written into the &lt;code&gt;Headers&lt;&#x2F;code&gt; instance, which is then attached to the
outgoing request. Downstream services can extract this context and continue the trace.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;6-2-incoming-side-extracting-context&quot;&gt;6.2. Incoming side: extracting context&lt;&#x2F;h2&gt;
&lt;p&gt;On the incoming side, the goal is the inverse. Tracing context must be read from request metadata, decoded using the
configured propagators, and installed as the current context while the request is handled.&lt;&#x2F;p&gt;
&lt;p&gt;In otel4s, this is done with &lt;code&gt;Tracer[IO].joinOrRoot&lt;&#x2F;code&gt;. This call reads encoded context from a carrier, attempts to decode
it, and establishes the resulting context as current for the duration of the effect.&lt;&#x2F;p&gt;
&lt;p&gt;As a result, if decoding succeeds, spans created inside the block become children of the upstream span. If decoding
fails, execution continues under a fresh root context, and the first span you create becomes the root of a new trace.&lt;&#x2F;p&gt;
&lt;p&gt;As on the outgoing side, the same carrier is extracted from the request, and, as before, it is not tied to any
specific transport.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Tracer[IO].joinOrRoot&lt;&#x2F;code&gt; also works with any carrier type that implements &lt;code&gt;TextMapGetter&lt;&#x2F;code&gt;, a typeclass that defines how
key-value pairs are read from a carrier.&lt;&#x2F;p&gt;
&lt;p&gt;For example, this is how context can be extracted directly from &lt;code&gt;org.http4s.Headers&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Response&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ci&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;CIString&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;propagation&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TextMapGetter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; handleIncoming&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;  handler&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Response&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Response&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].joinOrRoot(req.headers) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${req.method} ${req.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .surround(handler(req))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TextMapGetter&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;carrier&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    carrier.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;CIString&lt;&#x2F;span&gt;&lt;span&gt;(key)).map(_.head.value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; keys&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;carrier&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Iterable&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    carrier.headers.view.map(_.name).distinct.map(_.toString).toSeq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, context extraction happens exactly once at the boundary. After that, normal in-process propagation takes over. The
server span is explicitly created using the extracted or fresh context, and all downstream spans automatically attach to
it.&lt;&#x2F;p&gt;
&lt;p&gt;This boundary-focused approach keeps propagation explicit and predictable. Context is injected only when leaving the
process and extracted only when entering it. Everything else relies on the same propagation rules you already use inside
a single service.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;7-instrumenting-an-application&quot;&gt;7. Instrumenting an application&lt;&#x2F;h1&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;For illustrative purposes, this section includes examples that use span names with potentially high cardinality, such as
the HTTP span name. In real systems, you would typically avoid this and prefer low cardinality names to keep tracing
backends efficient and queryable.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Now we apply the earlier concepts to a concrete service: resources and scopes identify layers, and propagation occurs
only at process boundaries, while the rest of the code relies on in-process context flow.&lt;&#x2F;p&gt;
&lt;p&gt;This section applies tracing to a small weather service that fetches the forecast for a given location.
The goal is to show how tracing fits into real code through clear boundaries, deliberate span placement, and explicit
wiring.&lt;&#x2F;p&gt;
&lt;p&gt;The example service has an HTTP endpoint that returns a weather forecast, split into a business module and an HTTP
layer. It is intentionally small, but the structure scales to larger services. Tracing reflects this design: domain
spans are placed around service actions within the business module, while HTTP spans are positioned around request
handling and context propagation in the HTTP layer.&lt;&#x2F;p&gt;
&lt;p&gt;For this example, the dependencies and JVM options look like this:&lt;&#x2F;p&gt;




&lt;div class=&quot;tool-tabs&quot; data-tool-tabs&gt;
  &lt;div class=&quot;tool-tabs__controls&quot; role=&quot;tablist&quot; aria-label=&quot;Build tool&quot;&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;sbt&quot;&gt;
        sbt
      &lt;&#x2F;button&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;scala-cli&quot;&gt;
        scala-cli
      &lt;&#x2F;button&gt;
    
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;tool-tabs__panels&quot;&gt;
    &lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;sbt&quot;&gt;
  &lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;scalaVersion &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;3.7.4&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;libraryDependencies &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;++=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Seq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.http4s&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;       %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;http4s-ember-client&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                      %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;0.23.33&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.http4s&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;       %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;http4s-ember-server&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                      %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;0.23.33&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.http4s&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;       %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;http4s-dsl&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                               %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;0.23.33&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.typelevel&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;otel4s-oteljava&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                          %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.0.0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.typelevel&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;otel4s-semconv&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                           %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.0.0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;io.opentelemetry&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;opentelemetry-exporter-otlp&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;               %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;io.opentelemetry&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;opentelemetry-sdk-extension-autoconfigure&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;ch.qos.logback&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;   %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;logback-classic&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                           %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;1.5.24&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;run &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; fork  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;javaOptions &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.service.name=weather-service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;javaOptions &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.java.global-autoconfigure.enabled=true&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;scala-cli&quot;&gt;
  &lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; scala&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;3.7.4&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;org.http4s::http4s-ember-client:0.23.33&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;org.http4s::http4s-ember-server:0.23.33&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;org.http4s::http4s-dsl:0.23.33&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;org.typelevel::otel4s-oteljava:1.0.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;org.typelevel::otel4s-semconv:1.0.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;io.opentelemetry:opentelemetry-exporter-otlp:1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.58.0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; dep&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;ch.qos.logback:logback-classic:1.5.24&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; javaOpt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.service.name=weather-service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; javaOpt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.java.global-autoconfigure.enabled=true&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        Give me the code
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;The complete, runnable code for this section is available as a
standalone &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;iRevive&#x2F;4362adb50ec5efa2b6f9def2fd3ec676&quot;&gt;example&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;&lt;h2 id=&quot;7-1-instrumenting-the-business-layer&quot;&gt;7.1. Instrumenting the business layer&lt;&#x2F;h2&gt;
&lt;p&gt;In the business layer, tracing describes domain behavior by placing spans around key operations. Use attributes and
events for domain context. This layer ignores headers, carriers, and propagation, assuming tracing context exists and
focusing only on clearly demarcated units of work.&lt;&#x2F;p&gt;
&lt;p&gt;Business logic sits in a dedicated &lt;code&gt;ForecastModule&lt;&#x2F;code&gt; with its own tracer and scope. The tracer, created once, identifies
the module as domain code. Business spans stand apart from HTTP spans in traces and views, making ownership clear.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; checkWeather&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].tracer(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;module.forecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).withVersion(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;1.2.3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;(client)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The business layer spans define the domain-level units of work. In this module, &lt;code&gt;checkWeather&lt;&#x2F;code&gt; is the public entry
point, so a span is placed around it as the top-level business span.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; checkWeather&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;checkWeather&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;location&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, location)).use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    getForecast(location)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;*&lt;&#x2F;span&gt;&lt;span&gt; span.addEvent(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;forecast-received&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Span boundaries are chosen based on domain meaning rather than implementation details. Even if &lt;code&gt;checkWeather&lt;&#x2F;code&gt; later
grows to include caching, retries, or additional calls, the span boundary remains correct.&lt;&#x2F;p&gt;
&lt;p&gt;Attributes capture stable domain inputs. The &lt;code&gt;location&lt;&#x2F;code&gt; attribute is attached to &lt;code&gt;checkWeather&lt;&#x2F;code&gt; because it is central
and helps with grouping and filtering.&lt;&#x2F;p&gt;
&lt;p&gt;Events mark notable moments within a span without adding another span. The &lt;code&gt;forecast-received&lt;&#x2F;code&gt; event records a
meaningful completed step.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;getForecast&lt;&#x2F;code&gt; method is traced separately because it represents a distinct unit of work within the operation.&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getForecast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;getForecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      forecast &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; client.expect[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;wttr.in&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;$location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;?format=3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      _        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; forecast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;Span status reflects the outcome of a domain operation. Explicitly setting status helps when success or failure is part
of a normal control flow and should be immediately visible in the trace.&lt;&#x2F;p&gt;
&lt;p&gt;The business layer does not manage propagation, cancellation, or lifecycle aspects. It assumes context is already
established and focuses only on describing domain work.&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;ForecastModule.scala&lt;&#x2F;summary&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; checkWeather&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;checkWeather&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;location&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, location)).use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      getForecast(location)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;*&lt;&#x2F;span&gt;&lt;span&gt; span.addEvent(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;forecast-received&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getForecast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;getForecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Getting forecast for&lt;&#x2F;span&gt;&lt;span&gt; $location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        forecast &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; client.expect[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;wttr.in&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;$location&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;?format=3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; forecast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].tracer(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;module.forecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).withVersion(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;1.2.3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;(client)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;details&gt;
&lt;h2 id=&quot;7-2-instrumenting-the-http-layer&quot;&gt;7.2. Instrumenting the HTTP layer&lt;&#x2F;h2&gt;
&lt;p&gt;At the HTTP layer, tracing can be centralized at the middleware level. This ensures consistent request lifecycle
tracing without duplicating manual span creation across routes.&lt;&#x2F;p&gt;
&lt;p&gt;On the server, it extracts context, creates server spans, and adds protocol attributes. On the client, it creates client
spans and propagates context for outbound calls.&lt;&#x2F;p&gt;
&lt;p&gt;This approach ensures every request is traced consistently and protocol-specific aspects remain at the HTTP layer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;7-2-1-http-server&quot;&gt;7.2.1. HTTP server&lt;&#x2F;h3&gt;
&lt;p&gt;The server is implemented as a dedicated &lt;code&gt;HttpServer&lt;&#x2F;code&gt; with its own tracer and instrumentation scope. Spans created here
represent transport-level work and the lifecycle of a request, not domain logic.&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;forecastModule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; httpApp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpApp&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;forecastModule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpServer&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].get(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;org.http4s.server&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt;(forecastModule)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;Tracing middleware is applied to the entire &lt;code&gt;HttpApp&lt;&#x2F;code&gt;, wrapped in &lt;code&gt;IO.uncancelable&lt;&#x2F;code&gt; to ensure the server span is always
finalized, even if a request is canceled. This prevents scenarios where canceled requests end tracing prematurely,
leaving spans incomplete and creating diagnostic blind spots. Actual request handling runs inside the &lt;code&gt;poll&lt;&#x2F;code&gt; block
and remains cancelable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;forecastModule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; tracingMiddleware&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;httpApp&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpApp&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpApp&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Kleisli&lt;&#x2F;span&gt;&lt;span&gt; { (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      IO&lt;&#x2F;span&gt;&lt;span&gt;.uncancelable { poll &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;        Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].joinOrRoot(req.headers) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;          Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${req.method} ${req.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              poll(httpApp.run(req)).flatTap { response &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                span.addAttribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpAttributes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpResponseStatusCode&lt;&#x2F;span&gt;&lt;span&gt;(response.status.code))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Tracer[IO].joinOrRoot&lt;&#x2F;code&gt; establishes the parent context at the boundary. Everything downstream relies on normal
in-process propagation. The server span covers the full request lifecycle, and protocol attributes are added once the
response is available.&lt;&#x2F;p&gt;
&lt;p&gt;Routes themselves focus only on request handling and domain logic. They do not explicitly create spans or manage
context.&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; routes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpRoutes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpRoutes&lt;&#x2F;span&gt;&lt;span&gt;.of {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  case&lt;&#x2F;span&gt;&lt;span&gt; req &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GET&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Root&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;weather&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; location &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      forecast &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; forecastModule.checkWeather(location)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Response&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]().withEntity(forecast)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;details&gt;
&lt;summary&gt;HttpServer.scala&lt;&#x2F;summary&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Kleisli&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Resource&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;dsl&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;io&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ember&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;EmberServerBuilder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ci&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;CIString&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;propagation&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TextMapGetter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;semconv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;attributes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpAttributes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;forecastModule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;given&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; start&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    EmberServerBuilder&lt;&#x2F;span&gt;&lt;span&gt;.default[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].withHttpApp(httpApp).build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; httpApp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpApp&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tracingMiddleware(routes.orNotFound)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; routes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpRoutes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpRoutes&lt;&#x2F;span&gt;&lt;span&gt;.of { &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span&gt; req &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GET&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Root&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;weather&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; location &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        forecast &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; forecastModule.checkWeather(location)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Response&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]().withEntity(forecast)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; tracingMiddleware&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;httpApp&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpApp&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpApp&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Kleisli&lt;&#x2F;span&gt;&lt;span&gt; { (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;req&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      IO&lt;&#x2F;span&gt;&lt;span&gt;.uncancelable { poll &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;        Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].joinOrRoot(req.headers) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;          Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${req.method} ${req.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              poll(httpApp.run(req)).flatTap { response &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                span.addAttribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpAttributes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpResponseStatusCode&lt;&#x2F;span&gt;&lt;span&gt;(response.status.code))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;forecastModule&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpServer&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].get(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;org.http4s.server&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpServer&lt;&#x2F;span&gt;&lt;span&gt;(forecastModule)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TextMapGetter&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;carrier&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      carrier.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;CIString&lt;&#x2F;span&gt;&lt;span&gt;(key)).map(_.head.value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; keys&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;carrier&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Iterable&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      carrier.headers.view.map(_.name).distinct.map(_.toString).toSeq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;details&gt;
&lt;h3 id=&quot;7-2-2-http-client&quot;&gt;7.2.2. HTTP client&lt;&#x2F;h3&gt;
&lt;p&gt;The HTTP client is also instrumented as a separate module with its own tracer and instrumentation scope. Client spans
represent outbound calls, and the client is responsible for injecting the active tracing context into request headers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpClient&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The middleware creates a span for each request, propagates context, and records response attributes. It is wrapped in
&lt;code&gt;Resource.uncancelable&lt;&#x2F;code&gt; to ensure the span is finalized even if the caller cancels the request.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; tracingMiddleware&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Client&lt;&#x2F;span&gt;&lt;span&gt; { request &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Resource&lt;&#x2F;span&gt;&lt;span&gt;.uncancelable { poll &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        spanOps &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${request.method} ${request.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          .resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        headers &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.eval(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].propagate(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;.empty))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        response &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; poll(client.run(request.withHeaders(headers)).mapK(spanOps.trace))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.eval(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          spanOps.span.addAttribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpAttributes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpResponseStatusCode&lt;&#x2F;span&gt;&lt;span&gt;(response.status.code))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Tracer[IO].propagate&lt;&#x2F;code&gt; encodes the active span context into request headers so that downstream services can join the
same trace. Client spans are named by HTTP method and URI, and the response status code is recorded upon completion of
the call.&lt;&#x2F;p&gt;
&lt;p&gt;The value returned by &lt;code&gt;.resource&lt;&#x2F;code&gt; is a &lt;code&gt;SpanOps.Res&lt;&#x2F;code&gt;, which contains both the span itself and a trace function. This
distinction is important because span propagation does not happen automatically through &lt;code&gt;Resource&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This matters because the &lt;code&gt;client.run&lt;&#x2F;code&gt; returns a &lt;code&gt;Resource[IO, Response[IO]]&lt;&#x2F;code&gt;. By applying &lt;code&gt;mapK(spanOps.trace)&lt;&#x2F;code&gt;, we
transform the underlying effect so that all actions performed while using the response, including reading the body, run
inside the span context. Without this step, the span would start and end correctly, but the actual HTTP work would not
appear under the client span in the trace.&lt;&#x2F;p&gt;
&lt;p&gt;This pattern ensures that the client span accurately represents the full lifecycle of the outbound request, from sending
headers to consuming the response, while keeping propagation and lifecycle management localized to the HTTP layer.&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;HttpClient.scala&lt;&#x2F;summary&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Resource&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;middleware&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Logger&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;http4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ember&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;EmberClientBuilder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;propagation&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TextMapUpdater&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;semconv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;attributes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpAttributes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpClient&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    EmberClientBuilder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .default[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .map(client &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Logger&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;](logHeaders &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;, logBody &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;)(client))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .evalMap(client &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpClient&lt;&#x2F;span&gt;&lt;span&gt;.traced(client))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; traced&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].get(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;org.http4s.client&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; tracingMiddleware(client)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; tracingMiddleware&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;client&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Client&lt;&#x2F;span&gt;&lt;span&gt; { request &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      Resource&lt;&#x2F;span&gt;&lt;span&gt;.uncancelable { poll &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          spanOps &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${request.method} ${request.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          headers  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.eval(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].propagate(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;.empty))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          response &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; poll(client.run(request.withHeaders(headers)).mapK(spanOps.trace))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.eval(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            spanOps.span.addAttribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpAttributes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpResponseStatusCode&lt;&#x2F;span&gt;&lt;span&gt;(response.status.code))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TextMapUpdater&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Headers&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; updated&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;carrier&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Headers&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      carrier.put(key &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;details&gt;
&lt;h2 id=&quot;7-3-wiring-everything-together&quot;&gt;7.3. Wiring everything together&lt;&#x2F;h2&gt;
&lt;p&gt;The application entry point assembles modules and owns the lifecycle of the tracing infrastructure. No other part of the
codebase needs to know how tracing is configured or how to shut it down.&lt;&#x2F;p&gt;
&lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IOApp&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Resource&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;oteljava&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;OtelJava&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;typelevel&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;otel4s&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;trace&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IOApp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Simple&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      otel4s                   &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; OtelJava&lt;&#x2F;span&gt;&lt;span&gt;.autoConfigured[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      given&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.pure(otel4s.tracerProvider)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      httpClient               &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HttpClient&lt;&#x2F;span&gt;&lt;span&gt;.create&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      forecastModule           &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.eval(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ForecastModule&lt;&#x2F;span&gt;&lt;span&gt;.create(httpClient))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      httpServer               &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.eval(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpServer&lt;&#x2F;span&gt;&lt;span&gt;.create(forecastModule))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      _                        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; httpServer.start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }.useForever&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;p&gt;Tracing initializes once with &lt;code&gt;OtelJava.autoConfigured&lt;&#x2F;code&gt;. All modules share a &lt;code&gt;TracerProvider&lt;&#x2F;code&gt;. Each module derives a
&lt;code&gt;Tracer&lt;&#x2F;code&gt; with a unique instrumentation scope. Configuration and lifecycle remain at the application edge and
infrastructure does not leak into domain code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;7-4-configuration&quot;&gt;7.4. Configuration&lt;&#x2F;h2&gt;
&lt;p&gt;All observability configuration is handled externally. The code does not hardcode exporters, endpoints, or sampling
policies. These are provided through environment variables and system properties.&lt;&#x2F;p&gt;
&lt;p&gt;This allows the same service to run in different environments with different observability setups. Traces remain
structurally identical, but their resource attributes reflect where and how they were produced.&lt;&#x2F;p&gt;
&lt;p&gt;At a minimum, the application defines a service name and enables SDK autoconfiguration.&lt;&#x2F;p&gt;




&lt;div class=&quot;tool-tabs&quot; data-tool-tabs&gt;
  &lt;div class=&quot;tool-tabs__controls&quot; role=&quot;tablist&quot; aria-label=&quot;Build tool&quot;&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;sbt&quot;&gt;
        sbt
      &lt;&#x2F;button&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;scala-cli&quot;&gt;
        scala-cli
      &lt;&#x2F;button&gt;
    
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;tool-tabs__panels&quot;&gt;
    &lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;sbt&quot;&gt;
  &lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;javaOptions &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.service.name=weather-service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;javaOptions &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.java.global-autoconfigure.enabled=true&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;scala-cli&quot;&gt;
  &lt;!-- @formatter:off --&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; javaOpt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.service.name=weather-service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; javaOpt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.java.global-autoconfigure.enabled=true&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;!-- @formatter:on --&gt;
&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;7-5-seeing-traces-in-grafana&quot;&gt;7.5. Seeing traces in Grafana&lt;&#x2F;h2&gt;
&lt;p&gt;To validate the traces, we run the service locally, send a real request, and inspect the resulting trace in Grafana
using a local OpenTelemetry stack.&lt;&#x2F;p&gt;
&lt;p&gt;For local development, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;grafana&#x2F;docker-otel-lgtm&#x2F;&quot;&gt;Grafana LGTM&lt;&#x2F;a&gt; is a convenient option. It provides
a setup with Grafana for data visualization, Tempo for distributed tracing, and an OpenTelemetry Collector, all in a
single Docker container. This keeps the feedback loop short and avoids any custom infrastructure work.&lt;&#x2F;p&gt;
&lt;p&gt;We can run it as a Docker container:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; docker run&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; 3000:3000&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; 4317:4317&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; -p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; 4318:4318&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; --rm -ti&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; grafana&#x2F;otel-lgtm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once the container is running, the OpenTelemetry Collector is ready to receive traces, and Grafana is available to query
them.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we start the application itself:&lt;&#x2F;p&gt;




&lt;div class=&quot;tool-tabs&quot; data-tool-tabs&gt;
  &lt;div class=&quot;tool-tabs__controls&quot; role=&quot;tablist&quot; aria-label=&quot;Build tool&quot;&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;sbt&quot;&gt;
        sbt
      &lt;&#x2F;button&gt;
    
      
      &lt;button class=&quot;tool-tabs__tab&quot; type=&quot;button&quot; role=&quot;tab&quot; data-tool-tab=&quot;scala-cli&quot;&gt;
        scala-cli
      &lt;&#x2F;button&gt;
    
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;tool-tabs__panels&quot;&gt;
    &lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;sbt&quot;&gt;
  &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; sbt run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tool-tabs__panel&quot; role=&quot;tabpanel&quot; data-tool-panel=&quot;scala-cli&quot;&gt;
  &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; scala-cli run Main.scala&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;With both running, we send a request to the service:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; curl localhost:8080&#x2F;weather&#x2F;Kyiv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Kyiv:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; ⛅️&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  -12°C&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From the caller&#x27;s perspective, this is an ordinary HTTP request. Behind the scenes, each request produces a trace made
up of spans that mirror the execution path. Server spans wrap request handling, client spans wrap outbound calls, and
internal spans reflect meaningful application steps.&lt;&#x2F;p&gt;
&lt;p&gt;The application logs confirm that the tracing context was propagated to the outbound request. The injected &lt;code&gt;traceparent&lt;&#x2F;code&gt;
header contains this tracing information and demonstrates successful propagation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;log&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;11:07:11.521&lt;&#x2F;span&gt;&lt;span&gt; [io-compute-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;background-color: #F0FFF4;&quot;&gt;INFO&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; org.http4s.client.middleware.RequestLogger&lt;&#x2F;span&gt;&lt;span&gt; -- &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  HTTP&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; GET &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;https:&#x2F;&#x2F;wttr.in&#x2F;Kyiv?format=3&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span&gt;  Headers(traceparent: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;00-0ceda30d45b3e923b54a853df0762c64-70a2f1612420ee06-01&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  body=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now let&#x27;s open Grafana and inspect the exported trace:&lt;&#x2F;p&gt;



&lt;div class=&quot;image-wrap&quot;&gt;
    &lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;practical-observability-distributed-tracing&#x2F;grafana-traces.png&quot; alt=&quot;Traces in Grafana&quot; class=&quot;no-lightsense&quot; &#x2F;&gt;

    &lt;!-- server span name: GET - &#x2F;weather&#x2F;Kyiv --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 1.5%; top: 21%; width: 9.6%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span&gt;  .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${req.method} ${req.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- service name --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 27.4%; top: 21%; width: 8%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;javaOptions &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Dotel.service.name=weather-service&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- kind = server --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 68.2%; top: 21%; width: 3.7%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${req.method} ${req.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span&gt;  .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- library name = org.http4s.server --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 84.8%; top: 21%; width: 8.5%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].get(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;org.http4s.server&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- http response status code --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 2%; top: 28.6%; width: 13%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;span.addAttribute(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  HttpAttributes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;HttpResponseStatusCode&lt;&#x2F;span&gt;&lt;span&gt;(response.status.code)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- checkWeather span name --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 2.2%; top: 48.1%; width: 7.5%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;checkWeather&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;location&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, location)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- library name = module.forecast --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 75.3%; top: 48.1%; width: 8%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span&gt;  .tracer(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;module.forecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .withVersion(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;1.2.3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- library version = 1.2.3 --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 90.4%; top: 48.1%; width: 2.8%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .tracer(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;module.forecast&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span&gt;  .withVersion(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;1.2.3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- attribute location --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 3%; top: 55.6%; width: 12%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;checkWeather&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;location&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, location)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- event --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 4.3%; top: 62.5%; width: 10%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;span.addEvent(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;forecast-received&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- status = ok --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 67%; top: 71%; width: 2%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- client span name: GET - https:&#x2F;&#x2F;wttr.in&#x2F;Kyiv?format=3 --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 4.2%; top: 85%; width: 16%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span&gt;  .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${req.method} ${req.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- kind = client --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 69%; top: 85%; width: 3.5%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;${req.method} ${req.uri}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot; style=&quot;background-color: #F6F8FA;&quot;&gt;&lt;span&gt;  .withSpanKind(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanKind&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;


&lt;!-- library = org.http4s.client --&gt;





&lt;div class=&quot;hotspot&quot; tabindex=&quot;0&quot; role=&quot;button&quot; aria-label=&quot;Show hotspot details&quot; style=&quot;left: 85%; top: 85%; width: 8.5%; height: 2%;&quot;&gt;
    &lt;div class=&quot;tooltip&quot;&gt;
        &lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TracerProvider&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].get(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;org.http4s.client&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The trace has a clear shape. At the top is the server span, which represents the middleware processing of
the incoming HTTP request and covers the full request lifecycle. Nested beneath are spans from the business logic layer,
each detailing the forecast operation and its internal steps. The outbound HTTP call appears as a client span,
indicating an external request during the trace.&lt;&#x2F;p&gt;
&lt;p&gt;Span names indicate the operations they describe. Parent-child relationships, where one operation triggers another,
follow actual execution. Timing bars show when each operation ran and for how long. HTTP spans represent network
requests, while domain spans relate to specific business logic, making them easy to distinguish. Instrumentation scopes,
or labeled code sections, clarify which application layer generated each span.&lt;&#x2F;p&gt;
&lt;p&gt;Attributes at the HTTP layer, such as &lt;code&gt;http.response.status_code=200&lt;&#x2F;code&gt;, appear only on transport spans and indicate
the request&#x27;s outcome. Domain attributes, specific to business logic, appear only on domain spans. An attribute like
&lt;code&gt;location=Kyiv&lt;&#x2F;code&gt; helps categorize the span by business context. Events indicate significant actions or state
changes and appear as markers within spans.&lt;&#x2F;p&gt;
&lt;p&gt;Even in this small example, the trace already answers practical questions. You see where time was spent and which part
of the request performed the work. You also see how different operations were nested. As the application grows, this
structure scales. Adding more routes increases server spans. More domain logic adds business spans. The overall shape of
the trace stays stable as it grows.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;8-conclusion&quot;&gt;8. Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;Distributed tracing with otel4s works best when it is built into the program rather than an afterthought layered on top.
The API encourages clear ownership and disciplined context flow, which matches how real systems behave under load.&lt;&#x2F;p&gt;
&lt;p&gt;In this article, we looked at how traces are identified, how spans are scoped and propagated, and how otel4s translates
OpenTelemetry concepts onto functional code.&lt;&#x2F;p&gt;
&lt;p&gt;The practical takeaway is simple. Instrument the operations that explain system behavior, keep spans aligned with
meaningful work, and let context propagation do the rest. When tracing is consistent, the resulting traces align with
the work and give you answers rather than more noise.&lt;&#x2F;p&gt;
&lt;p&gt;In the next part of the series, we will apply the same mindset to metrics and examine how to measure system behavior
over time using otel4s.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Practical observability: foundations with OpenTelemetry</title>
        <published>2025-12-14T10:00:00+00:00</published>
        <updated>2025-12-14T10:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ochenashko.com/practical-observability-foundation/"/>
        <id>https://ochenashko.com/practical-observability-foundation/</id>
        
        <content type="html" xml:base="https://ochenashko.com/practical-observability-foundation/">&lt;p&gt;In this series, we explore how to bring observability into a Scala application
using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;&quot;&gt;OpenTelemetry&lt;&#x2F;a&gt; - the open standard for telemetry data -
and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;otel4s&#x2F;&quot;&gt;otel4s&lt;&#x2F;a&gt;, a purely functional OpenTelemetry library for the
Typelevel (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;cats-effect&#x2F;&quot;&gt;Cats Effect&lt;&#x2F;a&gt;) ecosystem.&lt;&#x2F;p&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        Series roadmap
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;ul&gt;
&lt;li&gt;Part 1 (this post): Foundations with OpenTelemetry.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;..&#x2F;practical-observability-distributed-tracing&quot;&gt;Part 2&lt;&#x2F;a&gt;: Distributed tracing with otel4s.&lt;&#x2F;li&gt;
&lt;li&gt;Part 3 (coming soon): Implementing metrics with otel4s.&lt;&#x2F;li&gt;
&lt;li&gt;Part 4 (coming eventually): Advanced configuration and operational tips.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This first post focuses on the conceptual foundation: what observability means, how telemetry signals work, and how they
stay connected in distributed systems.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;&#x2F;h1&gt;
&lt;p&gt;There are countless variables that can affect how your system behaves in production.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe a new marketing collaboration with a popular tech blogger triples your traffic overnight. A minor slowdown, such
as a third-party API call or slow database query, can cascade through your services: threads pile up, external calls
time out, queues overflow, and soon unrelated components start failing. Generally, such things are
just accidents without a clear trail. We may know that &lt;strong&gt;something&lt;&#x2F;strong&gt; is wrong,
&lt;strong&gt;somewhere&lt;&#x2F;strong&gt;, however, logs alone rarely tell the full story.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Why did latency spike last night?&lt;&#x2F;li&gt;
&lt;li&gt;Why does one instance behave differently under the same load?&lt;&#x2F;li&gt;
&lt;li&gt;Where does the time actually go between the request entering the system and the response leaving?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is where &lt;strong&gt;observability&lt;&#x2F;strong&gt; comes into the picture.&lt;&#x2F;p&gt;
&lt;p&gt;Observability isn&#x27;t about collecting &lt;em&gt;more data&lt;&#x2F;em&gt;. It&#x27;s about understanding your system through the data it produces. The
key is capturing structured, correlated signals that let us reason about why something happens, not just what happened.&lt;&#x2F;p&gt;
&lt;p&gt;Traditionally, monitoring told us whether a service was healthy. Observability extends that idea: instead of asking
&lt;code&gt;Is it up?&lt;&#x2F;code&gt;, we ask &lt;code&gt;Why is it behaving this way?&lt;&#x2F;code&gt; even when we didn&#x27;t anticipate the failure mode.&lt;&#x2F;p&gt;
&lt;p&gt;To achieve that, we rely on telemetry - data emitted from our applications in the form of signals: traces, metrics, and
logs. Together, these signals create a complete picture of how our system behaves.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;2-from-monitoring-to-observability&quot;&gt;2. From monitoring to observability&lt;&#x2F;h1&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;What problem are we actually trying to solve?&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Monitoring is great when we know what to expect. We define a few metrics, set thresholds, and get alerts when they are
crossed. Unfortunately, in modern distributed systems, a single user request can cross dozens of services and queues.
Once systems
become that complex, we can&#x27;t predict every possible point of failure.&lt;&#x2F;p&gt;
&lt;p&gt;Monitoring is like a dashboard warning light - it catches a symptom and tells us &lt;strong&gt;something&lt;&#x2F;strong&gt; is wrong, for example,
&lt;code&gt;Latency has increased&lt;&#x2F;code&gt;. Observability is a diagnostic toolkit - it helps uncover the cause and understand &lt;strong&gt;why&lt;&#x2F;strong&gt;
something is wrong, for example, &lt;code&gt;Database connection pool is exhausted in one region&lt;&#x2F;code&gt;. Both are essential, but
observability gives us the context to reason about system behavior, not just detect anomalies.&lt;&#x2F;p&gt;
&lt;p&gt;As Scala engineers, we often work with concurrent and effectful systems built on asynchronous computations across
multiple services. In such environments, failures often have multiple reasons. Monitoring might tell us that a
request is slower than usual, but observability helps us pinpoint the source of the slowdown in the execution chain,
whether it&#x27;s a downstream dependency, a blocked fiber, or an overloaded queue.&lt;&#x2F;p&gt;
&lt;p&gt;Observability solves the problem of having disconnected telemetry signals that, on their own, fail to tell
a coherent story about what happened inside the system. By correlating traces, metrics,
and logs around the execution of a single request, observability turns isolated symptoms into an explanation we can reason about.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;3-understanding-telemetry-signals&quot;&gt;3. Understanding telemetry signals&lt;&#x2F;h1&gt;
&lt;p&gt;Think of your system like a body that ate a questionable gas-station sandwich: when discomfort hits later, you need
different vital signs to explain what happened. Traces, metrics, and logs are those vital signs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Traces show &lt;strong&gt;what&lt;&#x2F;strong&gt; the system did that led to an outcome: &quot;Stopped for gas&quot; -&amp;gt; &quot;bought a sandwich&quot; -&amp;gt; &quot;ate it&quot; -&amp;gt;
&quot;drove to work&quot; -&amp;gt; &quot;digestive regret&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Metrics describe continuous measurements, like a smartwatch reporting a pulse. You might see the moment &lt;strong&gt;when&lt;&#x2F;strong&gt;
the heart rate spiked after lunch, but the metric alone doesn&#x27;t explain why.&lt;&#x2F;li&gt;
&lt;li&gt;Logs capture the context in the moment: &quot;This sandwich looks fine. What bad could happen?&quot;, a few hours later:
&quot;Regret. So much regret&quot;. Logs record real-time perception and events that help us understand &lt;strong&gt;why&lt;&#x2F;strong&gt; this happened.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each signal offers a different perspective - traces supply the sequence, metrics capture the impact over time, and logs
preserve moment-to-moment context. Together they tell us not only that something went wrong, but &lt;strong&gt;what&lt;&#x2F;strong&gt; happened,
&lt;strong&gt;when&lt;&#x2F;strong&gt;, and &lt;strong&gt;why&lt;&#x2F;strong&gt;. That&#x27;s observability: connecting separate telemetry pieces into a cohesive, meaningful view of
system behavior.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-1-traces&quot;&gt;3.1. Traces&lt;&#x2F;h2&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;What happened, step by step.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Traces capture the storyline of a request: a chronological view of how work propagates through a system.&lt;&#x2F;p&gt;
&lt;p&gt;Each trace is made up of &lt;strong&gt;spans&lt;&#x2F;strong&gt;. A span is a building block of a trace - it represents a specific operation and the
time it takes to complete, such as handling an HTTP request or querying a database.&lt;&#x2F;p&gt;
&lt;p&gt;A span records things like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;When the operation started and ended&lt;&#x2F;li&gt;
&lt;li&gt;How it relates to other spans (parent&#x2F;child relationships)&lt;&#x2F;li&gt;
&lt;li&gt;Whether it succeeded or failed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A trace then answers broader questions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What did the request actually do?&lt;&#x2F;li&gt;
&lt;li&gt;Which components were involved?&lt;&#x2F;li&gt;
&lt;li&gt;Where was time spent?&lt;&#x2F;li&gt;
&lt;li&gt;Where did errors occur?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s dive into an example. A user requests a weather forecast:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;gateway-service&lt;&#x2F;code&gt; receives an HTTP GET &lt;code&gt;&#x2F;weather?location=Kyiv&lt;&#x2F;code&gt; request&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;gateway-service&lt;&#x2F;code&gt; calls &lt;code&gt;weather-service&lt;&#x2F;code&gt; to fetch the forecast&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;gateway-service&lt;&#x2F;code&gt; also publishes a Kafka event with request details to the &lt;code&gt;warehouse-service&lt;&#x2F;code&gt; (for analytics
to consume later)&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;weather-service&lt;&#x2F;code&gt; retrieves the forecast and returns it&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When we visualize this trace, we can see the entire journey of the request: how it moves through services, how long each
step took, and where problems occurred.&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid&quot; &gt;
gantt  
title Trace timeline: GET &amp;#x2F;weather?location=Kyiv  
dateFormat HH:mm:ss  
axisFormat %H:%M:%S

section gateway-service
HTTP request handling      :active, 10:00:00, 10s
Send request to weather-service    :         10:00:02, 6s
Publish Kafka event        :         10:00:02, 3s

section weather-service
Fetch forecast             :         10:00:03, 4s

section warehouse-service
Consume Kafka event        :         10:00:11, 2s

Persist analytics record   :         10:00:12, 1s
&lt;&#x2F;pre&gt;
&lt;p&gt;Traces reveal what happened, step by step, allowing us to follow a request across fibers, services, and boundaries.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-2-metrics&quot;&gt;3.2. Metrics&lt;&#x2F;h2&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;How the system behaves over time.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;If traces tell stories, metrics show patterns and &lt;strong&gt;trends&lt;&#x2F;strong&gt;. Metrics are the numbers a system emits continuously, such
as counts, durations, and resource usages, that show how the system performs over time.&lt;&#x2F;p&gt;
&lt;p&gt;They let us spot changes at scale: traffic spikes, regressions, or slow degradation that might not be visible from
individual traces or logs.&lt;&#x2F;p&gt;
&lt;p&gt;Metrics are also essential for alerting and automation. They can detect outages, trigger alerts, or even drive
auto-scaling when demand suddenly increases.&lt;&#x2F;p&gt;
&lt;p&gt;Metrics answer questions like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;How fast are requests being processed on average?&lt;&#x2F;li&gt;
&lt;li&gt;What&#x27;s the 95th percentile latency?&lt;&#x2F;li&gt;
&lt;li&gt;How many errors occurred in the past 5 minutes?&lt;&#x2F;li&gt;
&lt;li&gt;How much CPU or memory is being used right now?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here are the most common types of metrics:
&lt;div class=&quot;box&quot;&gt;
    &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;What it does&lt;&#x2F;th&gt;&lt;th&gt;Example&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Counter&lt;&#x2F;td&gt;&lt;td&gt;Monotonically increasing total; no decrements, reset only on restart.&lt;&#x2F;td&gt;&lt;td&gt;Count successful HTTP requests or emitted events.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;UpDownCounter&lt;&#x2F;td&gt;&lt;td&gt;Value that increments when work starts and decrements when it ends.&lt;&#x2F;td&gt;&lt;td&gt;Track in-flight HTTP requests or queued tasks by incrementing on start, decrementing on finish.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Gauge&#x2F;Observable&lt;&#x2F;td&gt;&lt;td&gt;Snapshot gathered by a callback or poll.&lt;&#x2F;td&gt;&lt;td&gt;Report CPU utilization, heap usage, or queue depth every collection cycle.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Histogram&lt;&#x2F;td&gt;&lt;td&gt;Distribution recorder that powers tail percentiles.&lt;&#x2F;td&gt;&lt;td&gt;Emit latency and payload size metrics to alert on p95 and p99 regressions.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;

&lt;&#x2F;div&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Back to our over-engineered weather service, it might expose metrics like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http.server.active_requests&lt;&#x2F;code&gt; - an &lt;strong&gt;UpDownCounter&lt;&#x2F;strong&gt; tracking the number of active HTTP requests&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;http.server.request.duration&lt;&#x2F;code&gt; - a &lt;strong&gt;Histogram&lt;&#x2F;strong&gt; recording the distribution of request latencies&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;system.cpu.utilization&lt;&#x2F;code&gt; - a &lt;strong&gt;Gauge&lt;&#x2F;strong&gt; reflecting the current CPU usage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;mermaid&quot; &gt;
---
config:
  themeVariables:
    xyChart:
      titleColor: &amp;quot;#ff0000&amp;quot;
---
xychart
title &amp;quot;http.server.request.duration p95 latency&amp;quot;
x-axis [&amp;quot;12:00&amp;quot;, &amp;quot;14:00&amp;quot;, &amp;quot;16:00&amp;quot;, &amp;quot;18:00&amp;quot;, &amp;quot;20:00&amp;quot;, &amp;quot;22:00&amp;quot;]
y-axis &amp;quot;Latency (ms)&amp;quot; 80 --&amp;gt; 260
bar &amp;quot;active requests&amp;quot; [120, 130, 140, 150, 135, 110]
line &amp;quot;p95 duration&amp;quot; [110, 125, 140, 240, 160, 120]
&lt;&#x2F;pre&gt;
&lt;p&gt;The chart shows how the weather-service histogram of request durations changes throughout a stormy afternoon.
A spike around 18:00 signals downstream slowness despite traffic volume remaining roughly the same,
precisely the kind of trend metrics excel at detecting early.&lt;&#x2F;p&gt;
&lt;p&gt;Metrics reveal &lt;strong&gt;how a system is performing over time&lt;&#x2F;strong&gt;, helping us observe long-term trends, spot regressions early,
and detect anomalies.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-3-logs&quot;&gt;3.3. Logs&lt;&#x2F;h2&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;The context around what happened.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;If traces tell stories and metrics show trends, logs are the day-to-day journal of your system - recording events one at
a time.&lt;&#x2F;p&gt;
&lt;p&gt;Logs capture what&#x27;s happening inside your code: messages, events, and context. They&#x27;re timestamped, detailed, and
usually the first place to look when something goes wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Logs answer questions such as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What specific event occurred?&lt;&#x2F;li&gt;
&lt;li&gt;What values or state were involved?&lt;&#x2F;li&gt;
&lt;li&gt;What errors or exceptions were thrown?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For example, our trusty weather service might log something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;log&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;2025-10-03 15:14:18.123&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;background-color: #F0FFF4;&quot;&gt; INFO&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  trace_id=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;4bf92f3577b34da6a3ce929d0e0e4736&lt;&#x2F;span&gt;&lt;span&gt; span_id=00f067aa0ba902b7 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Checking forecast for location [Kyiv]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, the &lt;code&gt;trace_id&lt;&#x2F;code&gt; and &lt;code&gt;span_id&lt;&#x2F;code&gt; link this log entry to a specific span within a trace, allowing us to see all related
operations and understand them in context. When logs are tied to traces, they stop being isolated lines of text and
instead help explain what the system was doing when something happened.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-4-baggage&quot;&gt;3.4. Baggage&lt;&#x2F;h2&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;A global context along the path.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;There&#x27;s also &lt;strong&gt;baggage&lt;&#x2F;strong&gt; - not a separate telemetry signal, but metadata that rides inside the same context payload as the
trace identifiers. Baggage is a lightweight key-value map that propagates across services and threads, so every
instrumentation can read the same request-level hints, such as tenant, plan, experiment flag, and so on.&lt;&#x2F;p&gt;
&lt;p&gt;Think of it as a sticky note attached to the trace context: invisible to users yet available to each instrument.
Because it travels with every outbound call, baggage should stay small and focused on attributes that truly help explain
or partition the work.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;4-context-propagation&quot;&gt;4. Context propagation&lt;&#x2F;h1&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;The invisible glue that makes distributed tracing possible.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Now that we&#x27;ve looked at &lt;em&gt;what&lt;&#x2F;em&gt;, &lt;em&gt;when&lt;&#x2F;em&gt;, and &lt;em&gt;why&lt;&#x2F;em&gt; of telemetry signals, one question remains: &lt;strong&gt;How do these signals
stay
connected?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The answer is &lt;strong&gt;context propagation&lt;&#x2F;strong&gt; - the invisible glue that makes distributed tracing possible. The context carries
metadata, such as trace and span IDs, that identify the current span and link it to the overall trace. With context
propagation, spans can be correlated and assembled into a single trace, regardless of where each span originated.&lt;&#x2F;p&gt;
&lt;p&gt;Modern applications are highly asynchronous and distributed. A single HTTP request might trigger a Kafka message, spawn
a background fiber, and make a gRPC call before completing. Without context propagation, each of those operations would
start a new trace, making it impossible to reconstruct the timeline of an individual request.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, context propagation means passing along the trace context: serializing it before an outbound call and
deserializing it on the other side.&lt;&#x2F;p&gt;
&lt;p&gt;Depending on the protocol, the serialized context travels in different carriers:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP - passed via request headers&lt;&#x2F;li&gt;
&lt;li&gt;gRPC - passed via metadata entries (the gRPC equivalent of headers)&lt;&#x2F;li&gt;
&lt;li&gt;Messaging (Kafka, RabbitMQ) - attached to message headers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For example, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;trace-context&#x2F;#traceparent-header&quot;&gt;W3C Trace Context&lt;&#x2F;a&gt; standard defines the
&lt;code&gt;traceparent&lt;&#x2F;code&gt; header that carries tracing information in HTTP:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where &lt;code&gt;4bf92f3577b34da6a3ce929d0e0e4736&lt;&#x2F;code&gt; is the trace ID, &lt;code&gt;00f067aa0ba902b7&lt;&#x2F;code&gt; is the span ID, and &lt;code&gt;01&lt;&#x2F;code&gt; is the trace flags.&lt;&#x2F;p&gt;
&lt;p&gt;When a downstream service receives a request with this header, it extracts the context, restores the trace state, and
starts a new child span linked to its parent, continuing the same trace seamlessly across service boundaries.&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid&quot; &gt;
sequenceDiagram
    autonumber
    actor User
    participant G as gateway
    participant WS as weather-service
    participant WH as warehouse

    User-&amp;gt;&amp;gt;G: HTTP GET &amp;#x2F;weather?location=Kyiv
    activate G

    G-&amp;gt;&amp;gt;WS: gRPC: Fetch forecast (location=Kyiv)
    activate WS
    WS--&amp;gt;&amp;gt;WS: Retrieve forecast
    WS--&amp;gt;&amp;gt;G: gRPC: OK + Forecast
    deactivate WS

    G--&amp;gt;&amp;gt;WH: Publish event to Kafka (request details)
    
    #Note over WH: Consumed for analytics later

    G--&amp;gt;&amp;gt;User: 200 OK + Forecast
    deactivate G
&lt;&#x2F;pre&gt;
&lt;p&gt;In this example, the gateway service starts a new root trace and creates a child span for the gRPC request. When the
weather-service handles a gRPC call, it extracts the trace context from the gRPC metadata and restores the trace state so
the new span is linked to the parent. Warehouse consumes the Kafka event, extracts the context from the message headers,
and either continues the parent or links to it depending on the ingestion style. That way, we can track the full journey
of the request from start to finish.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;5-opentelemetry&quot;&gt;5. OpenTelemetry&lt;&#x2F;h1&gt;

&lt;div class=&quot;admonition note&quot;&gt;
    &lt;div class=&quot;admonition-title&quot;&gt;
        
        
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;admonition-content&quot;&gt;
        &lt;p&gt;The standard behind it all.&lt;&#x2F;p&gt;

    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;imgs.xkcd.com&#x2F;comics&#x2F;standards.png&quot; alt=&quot;Standards XKCD Comics&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;Obligatory &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;927&#x2F;&quot; target=&quot;_blank&quot;&gt;XKCD&lt;&#x2F;a&gt; comics&lt;&#x2F;p&gt;
&lt;p&gt;At this point, we&#x27;ve explored the &lt;em&gt;what&lt;&#x2F;em&gt;, &lt;em&gt;when&lt;&#x2F;em&gt;, &lt;em&gt;why&lt;&#x2F;em&gt;, and &lt;em&gt;how&lt;&#x2F;em&gt; of observability signals. Now it&#x27;s time to look at
the
standard that ties all these ideas together.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;&quot;&gt;OpenTelemetry&lt;&#x2F;a&gt; is an open-source, vendor-neutral framework for collecting, processing, and exporting telemetry data
(traces, metrics, logs) from applications. It defines how telemetry data is structured, correlated, and exchanged between
services so that your observability setup doesn&#x27;t depend on any single vendor or tool.&lt;&#x2F;p&gt;
&lt;p&gt;Before OpenTelemetry, each observability vendor provided its own SDKs, APIs, and data formats. For application
developers, that often meant choosing one monitoring stack and sticking with it. For library authors, it was more
problematic: you&#x27;d have to provide instrumentation for every possible backend or force users into one ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;OpenTelemetry provides a set of standards and conventions that all languages and vendors can follow. Each language ships
an API (the abstraction instrumentation code targets) and an SDK (the concrete implementation that manages exporters,
processors, and context propagation). With that split, application code depends only on the stable API while the SDK can
evolve or be swapped without touching business logic. On top of the API&#x2F;SDK split, the project defines surrounding
components that keep telemetry portable:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Common APIs and data models - consistent interfaces and data structures for generating telemetry signals in any
language.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;context-propagation&#x2F;&quot;&gt;Context propagation standards&lt;&#x2F;a&gt; - a unified
approach (e.g., the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;TR&#x2F;trace-context&#x2F;&quot;&gt;W3C Trace Context&lt;&#x2F;a&gt;) to share trace context across service boundaries.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;collector&#x2F;&quot;&gt;OpenTelemetry Collector&lt;&#x2F;a&gt; - a standalone service that receives,
processes (transforms&#x2F;filters), and routes telemetry data between your applications and observability backends.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;semantic-conventions&#x2F;&quot;&gt;Semantic conventions&lt;&#x2F;a&gt; - standardized naming and
attributes for common operations, such as HTTP requests, database calls,
messaging systems, and more.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;specs&#x2F;otel&#x2F;protocol&#x2F;&quot;&gt;OTLP (OpenTelemetry Protocol)&lt;&#x2F;a&gt; - a standard wire protocol for
transmitting telemetry data between SDKs, collectors,
and backend systems.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Together, these parts form an ecosystem that keeps your telemetry consistent and portable, regardless of language,
framework, or vendor. For example, you might collect traces in your services and send them to a tracing backend
like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;oss&#x2F;tempo&#x2F;&quot;&gt;Grafana Tempo&lt;&#x2F;a&gt;, export metrics to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;&quot;&gt;Prometheus&lt;&#x2F;a&gt;, and forward
logs to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;oss&#x2F;loki&#x2F;&quot;&gt;Grafana Loki&lt;&#x2F;a&gt;. The OpenTelemetry Collector can route and export data to each of
these systems using the standard OTLP format.&lt;&#x2F;p&gt;
&lt;p&gt;Concepts stick once you see the API surface. The following sections show the same tiny span&#x2F;metric examples first with the
OpenTelemetry Java SDK, then with otel4s, so you can see the trade-offs between thread-local and effect-aware approaches.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;6-opentelemetry-java-overview&quot;&gt;6. OpenTelemetry Java overview&lt;&#x2F;h1&gt;
&lt;p&gt;The official &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;open-telemetry&#x2F;opentelemetry-java&quot;&gt;OpenTelemetry Java&lt;&#x2F;a&gt;
comes with instrumentation for many popular frameworks (e.g., Spring) and
libraries (e.g., JDBC connection pools, HTTP clients). That works well for traditional Java or Kotlin applications.&lt;&#x2F;p&gt;
&lt;p&gt;However, it doesn&#x27;t play nicely with purely functional Scala apps built on top of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;cats-effect&#x2F;&quot;&gt;Cats Effect&lt;&#x2F;a&gt;.
The reason is that the Java SDK relies on thread-local context propagation, which doesn&#x27;t align with how Cats Effect manages fiber-based concurrency and
context.&lt;&#x2F;p&gt;
&lt;p&gt;Below, we can peek at the API and compare it with the otel4s counterparts later.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;6-1-tracing-api&quot;&gt;6.1. Tracing API&lt;&#x2F;h2&gt;
&lt;p&gt;The OpenTelemetry Java API keeps instrumentation explicit: you build spans manually, push them into the current &lt;code&gt;Scope&lt;&#x2F;code&gt;,
run the work, and close the span yourself. Thread-local context propagation links the span to the current thread, so
&lt;code&gt;Span.current()&lt;&#x2F;code&gt; retrieves whatever you placed in scope.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;static void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWorkWithSpan&lt;&#x2F;span&gt;&lt;span&gt;(Tracer tracer) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Span span&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; tracer.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;spanBuilder&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;do-work&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;setAttribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;example.attribute&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;startSpan&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  try&lt;&#x2F;span&gt;&lt;span&gt; (Scope scope&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; span.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;makeCurrent&lt;&#x2F;span&gt;&lt;span&gt;()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    doWork&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;setStatus&lt;&#x2F;span&gt;&lt;span&gt;(StatusCode.OK);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt; (Throwable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;setStatus&lt;&#x2F;span&gt;&lt;span&gt;(StatusCode.ERROR);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;recordException&lt;&#x2F;span&gt;&lt;span&gt;(e);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;setAttribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;error.type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getClass&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getName&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; finally&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;static void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWork&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Span current&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Span.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;current&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Doing some work: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; current.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getSpanContext&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;toString&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;6-2-metrics-api&quot;&gt;6.2. Metrics API&lt;&#x2F;h2&gt;
&lt;p&gt;Metrics follow the same imperative pattern. You measure latency by hand and ensure you don&#x27;t forget to record failures.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;static void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWorkWithMetrics&lt;&#x2F;span&gt;&lt;span&gt;(LongCounter counter, DoubleHistogram latencyMs) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Attributes attributes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Attributes.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;put&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;example.attribute&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  long&lt;&#x2F;span&gt;&lt;span&gt; startNanos&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; System.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;nanoTime&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  try&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    doWork&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    double&lt;&#x2F;span&gt;&lt;span&gt; elapsedMs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (System.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;nanoTime&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; startNanos)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1_000_000.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    latencyMs.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;record&lt;&#x2F;span&gt;&lt;span&gt;(elapsedMs, attributes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    counter.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, attributes);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt; (Throwable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    double&lt;&#x2F;span&gt;&lt;span&gt; elapsedMs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (System.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;nanoTime&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; startNanos)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1_000_000.0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    latencyMs.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;record&lt;&#x2F;span&gt;&lt;span&gt;(elapsedMs, attributes.toBuilder.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;put&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;error.type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e.getClass.getName).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;static void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWork&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Doing some work&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;7-otel4s-overview&quot;&gt;7. otel4s overview&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;otel4s&#x2F;&quot;&gt;otel4s&lt;&#x2F;a&gt; brings the OpenTelemetry specification to Scala in a purely functional form.
It provides effect-aware context propagation and composable, idiomatic APIs for tracing, metrics, and logging.
The API integrates seamlessly with Cats Effect applications, without resorting to thread-locals or unsafe side effects.&lt;&#x2F;p&gt;
&lt;p&gt;While otel4s works perfectly with the official OpenTelemetry Java SDK, it also offers an alternative SDK implementation written in
Scala. This allows you to use the same observability model across different platforms: JVM, Scala.js, and Scala Native.
In other words, you can instrument Scala applications on the JVM or Scala Native using the same
OpenTelemetry concepts, all within the Typelevel ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;The library utilizes metaprogramming techniques to reduce runtime costs and allocations.
Near-zero overhead when telemetry is disabled, ensuring production performance is unaffected when tracing or metrics collection is not required.&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid&quot; style=&quot;display: flex; justify-content: center;&quot;&gt;
---
config:
  look: handDrawn
  layout: elk
---
graph BT
otel-spec[&amp;quot;OpenTelemetry Specification&amp;quot;]

otel4s-core[&amp;quot;otel4s-core&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Defines interfaces, such as Tracer, Meter, and Logger&amp;quot;] --&amp;gt; otel-spec
otel4s-sdk[&amp;quot;otel4s-sdk&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;An independent implementation of the OpenTelemetry specification in Scala&amp;quot;] --&amp;gt;
otel4s-core
otel4s-oteljava[&amp;quot;otel4s-oteljava&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Uses &amp;lt;a href=&amp;quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;open-telemetry&amp;#x2F;opentelemetry-java&amp;quot;&amp;gt;OpenTelemetry Java SDK&amp;lt;&amp;#x2F;a&amp;gt; under the hood&amp;quot;] --&amp;gt;
otel4s-core
&lt;&#x2F;pre&gt;

&lt;p style=&quot;text-align: center&quot;&gt;An oversimplified otel4s architecture&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;otel4s&#x2F;modules-structure.html&quot;&gt;modular architecture&lt;&#x2F;a&gt; allows including only the required components
and makes it easier for library authors to implement instrumentation for their tools.&lt;&#x2F;p&gt;
&lt;p&gt;Now, let&#x27;s get back to the API examples.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;7-1-tracing-api&quot;&gt;7.1. Tracing API&lt;&#x2F;h2&gt;
&lt;p&gt;otel4s can automatically manage the lifecycle of spans. This means you don&#x27;t have to manually start and end them.
If the effect fails, the &lt;code&gt;error.type&lt;&#x2F;code&gt; attribute is automatically set to the full-qualified name of
the exception class, and the span is marked as errored.
Propagation relies on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;otel4s&#x2F;tracing-context-propagation.html&quot;&gt;cats.mtl.Local&lt;&#x2F;a&gt; instead of thread-locals,
which keeps the context in sync across fibers and async boundaries.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWorkWithSpan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;do-work&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;example.attribute&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)).use { span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    doWork()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; *&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWork&lt;&#x2F;span&gt;&lt;span&gt;()(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;using&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;].currentSpanOrThrow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    _    &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Doing some work:&lt;&#x2F;span&gt;&lt;span&gt; ${span.context}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nevertheless, you can still have full control over the span lifecycle by using a low-level API.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;7-2-metrics-api&quot;&gt;7.2. Metrics API&lt;&#x2F;h2&gt;
&lt;p&gt;Meters mirror that philosophy. Instruments such as &lt;code&gt;Histogram&lt;&#x2F;code&gt; expose helpers like &lt;code&gt;recordDuration&lt;&#x2F;code&gt; that wrap an effect
and capture timing without manually using timers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWorkWithMetrics&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;counter&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Counter&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Long&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;latencyMs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Histogram&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Double&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; attributes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Attributes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;example.attribute&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; histogramAttributes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ExitCase&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Attributes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ExitCase&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Succeeded&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; attributes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ExitCase&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Errored&lt;&#x2F;span&gt;&lt;span&gt;(e)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; attributes &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;error.type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e.getClass.getName)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ExitCase&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Canceled&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;   =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; attributes &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;error.type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;canceled&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  latencyMs.recordDuration(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TimeUnit&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;MILLISECONDS&lt;&#x2F;span&gt;&lt;span&gt;, histogramAttributes).surround {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    doWork()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; *&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; counter.add(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1L&lt;&#x2F;span&gt;&lt;span&gt;, attributes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doWork&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  IO&lt;&#x2F;span&gt;&lt;span&gt;.println(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Doing some work&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As with the tracing API, you can still use the low-level API if you need more control.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;8-conclusion&quot;&gt;8. Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;Observability gives us a way to understand systems through the signals they produce: traces, metrics, and logs.&lt;br &#x2F;&gt;
We&#x27;ve looked at how these signals complement each other, how context propagation keeps them connected, and how
OpenTelemetry provides a shared foundation for collecting and exchanging them.&lt;&#x2F;p&gt;
&lt;p&gt;For Scala developers, otel4s brings these ideas into the functional world,
allowing telemetry to flow naturally through effectful code while staying consistent
with OpenTelemetry standards.&lt;&#x2F;p&gt;
&lt;p&gt;This post focused on the concepts behind observability: what the signals mean, how they relate, and why they matter. In
the next part of the series, we&#x27;ll move from theory to practice and see how to use otel4s to instrument the application.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Publishing test traces to Grafana using otel4s and weaver</title>
        <published>2024-08-02T10:00:00+00:00</published>
        <updated>2024-08-02T10:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ochenashko.com/otel4s-test-traces-grafana/"/>
        <id>https://ochenashko.com/otel4s-test-traces-grafana/</id>
        
        <content type="html" xml:base="https://ochenashko.com/otel4s-test-traces-grafana/">&lt;p&gt;Let&#x27;s explore how we can publish test traces to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;products&#x2F;cloud&#x2F;&quot;&gt;Grafana Cloud&lt;&#x2F;a&gt;
using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;typelevel.org&#x2F;otel4s&#x2F;&quot;&gt;otel4s&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;disneystreaming&#x2F;weaver-test&quot;&gt;weaver&lt;&#x2F;a&gt; while running tests on GitHub Action.&lt;&#x2F;p&gt;
&lt;p&gt;Even though CI machines often differ from production environments, and recorded spans might be volatile, we can still collect enough evidence to analyze system components&#x27; performance (latency).&lt;&#x2F;p&gt;
&lt;p&gt;So why bother with test traces? There are a few benefits:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Identify potential bottlenecks&lt;&#x2F;li&gt;
&lt;li&gt;Track performance degradation&lt;&#x2F;li&gt;
&lt;li&gt;Check the structure of spans&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The complete example is available in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iRevive&#x2F;otel4s-weaver-example&quot;&gt;GitHub repository&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;While this example uses Grafana Cloud, it will work with any OTLP-compatible setup: Jaeger, Honeycomb, etc.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;1-why-use-weaver-and-otel4s&quot;&gt;1. Why use weaver and otel4s?&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;disneystreaming&#x2F;weaver-test&quot;&gt;Weaver&lt;&#x2F;a&gt; is an excellent choice for testing due to its seamless integration with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typelevel&#x2F;cats-effect&quot;&gt;Cats Effect&lt;&#x2F;a&gt;, parallelism out of the box, and flexible API.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typelevel&#x2F;otel4s&quot;&gt;otel4s&lt;&#x2F;a&gt; is an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;&quot;&gt;OpenTelemetry&lt;&#x2F;a&gt; implementation for Scala built on top of Cats Effect. The library is available for all platforms: JVM, Scala.js, Scala Native.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;2-otel4s-befriends-weaver&quot;&gt;2. otel4s befriends weaver&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;settings-up-the-project&quot;&gt;Settings up the project&lt;&#x2F;h2&gt;
&lt;p&gt;To set up your project include the following dependencies in your &lt;code&gt;build.sbt&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;libraryDependencies &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;++=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Seq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.typelevel&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;       %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;otel4s-core-trace&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;         %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;0.8.1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;org.typelevel&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;       %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;otel4s-sdk-exporter-trace&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;0.8.1&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;com.disneystreaming&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;weaver-cats&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;               %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;0.8.4&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;com.disneystreaming&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;weaver-scalacheck&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;         %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;0.8.4&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;how-weaver-handles-test-results&quot;&gt;How weaver handles test results&lt;&#x2F;h2&gt;
&lt;p&gt;Weaver handles test results slightly differently from traditional testing frameworks by leveraging the &lt;code&gt;Expectations&lt;&#x2F;code&gt; as the outcome of a test.
Instead of failing tests with exceptions, tests return a value of type &lt;code&gt;Expectations&lt;&#x2F;code&gt;, where &lt;code&gt;Expectations&lt;&#x2F;code&gt; is defined as &lt;code&gt;ValidatedNel[AssertionException, Unit]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;extending-weaver&quot;&gt;Extending weaver&lt;&#x2F;h2&gt;
&lt;p&gt;First of all, we need to instrument the tests with the traces. Let&#x27;s start with the utility object:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TraceUtils&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; trace&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[_]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MonadCancelThrow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;      suiteName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;      name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TestName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;fa&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; testName&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; name.name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; attributes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Attributes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;test.name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, testName),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;test.suite&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, suiteName),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;test.source&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name.location.fileRelativePath &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;:&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; name.location.line),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;test.tags&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name.tags.toSeq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;$suiteName&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; $testName&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .addAttributes(attributes)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .withFinalizationStrategy(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanFinalizer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Strategy&lt;&#x2F;span&gt;&lt;span&gt;.empty)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;2&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .use(span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; fa.guaranteeCase(recordOutcome(span)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; recordOutcome&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[_]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Monad&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Span&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Outcome&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Throwable&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    ???&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;Configure span attributes: the test name, suite name, source location, and any tags associated with the test.&lt;&#x2F;li&gt;
&lt;li&gt;Disable default finalization strategy: we&#x27;ll handle the statuses manually by recording the outcome of the test execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;To ensure proper span finalization based on test results, we need to implement the &lt;code&gt;recordOutcome&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;private val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; AnsiColorRegex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\u001b\\&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;[([;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;d]*)m&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; recordOutcome&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[_]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Monad&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;span&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Span&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Outcome&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Throwable&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Outcome&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Succeeded&lt;&#x2F;span&gt;&lt;span&gt;(fa)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    fa.flatMap { expectations &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      expectations.run.fold(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        e &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; span.recordException(removeAnsiColors(e.head)),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Outcome&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Canceled&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;canceled&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;2&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Outcome&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Errored&lt;&#x2F;span&gt;&lt;span&gt;(error)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    span.setStatus(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;StatusCode&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; span.recordException(removeAnsiColors(error))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; removeAnsiColors&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;throwable&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Throwable&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Throwable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  throwable &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; AssertionException&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      a.copy(message &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; AnsiColorRegex&lt;&#x2F;span&gt;&lt;span&gt;.replaceAllIn(a.message, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    case&lt;&#x2F;span&gt;&lt;span&gt; other &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      other&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;If there&#x27;s an error, we set the span status to &lt;code&gt;Error&lt;&#x2F;code&gt; and record the exception. If the expectations are met, we set the span status to &lt;code&gt;Ok&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Set the span status to &lt;code&gt;Error&lt;&#x2F;code&gt; with the description &#x27;canceled&#x27;, indicating that the test was aborted.&lt;&#x2F;li&gt;
&lt;li&gt;Set the span status to &lt;code&gt;Error&lt;&#x2F;code&gt; and record the exception.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Additionally, the &lt;code&gt;removeAnsiColors&lt;&#x2F;code&gt; function cleans up ANSI escape codes from the exception messages to ensure they appear clearly in Grafana or Jaeger.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;extending-the-simpleiosuite-and-iosuite&quot;&gt;Extending the &lt;code&gt;SimpleIOSuite&lt;&#x2F;code&gt; and &lt;code&gt;IOSuite&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Weaver provides two types of test suites:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SimpleIOSuite&lt;&#x2F;code&gt; for tests without shared resources&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;IOSuite&lt;&#x2F;code&gt; for tests with shared resources&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We can add a &lt;code&gt;tracedTest&lt;&#x2F;code&gt; utility method to the &lt;code&gt;TracedSimpleIOSuite&lt;&#x2F;code&gt; trait:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedSimpleIOSuite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SimpleIOSuite&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; tracedTest&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TestName&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Unit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    registerTest(name)(_ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test&lt;&#x2F;span&gt;&lt;span&gt;(name.name, traced(name)(run)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; traced&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;testName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TestName&lt;&#x2F;span&gt;&lt;span&gt;)(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    SdkTraces&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .autoConfigured[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;](_.addExporterConfigurer(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;OtlpSpanExporterAutoConfigure&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .evalMap(_.tracerProvider.get(getClass.getName.stripSuffix(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;$&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .use(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;implicit&lt;&#x2F;span&gt;&lt;span&gt; tracer &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TraceUtils&lt;&#x2F;span&gt;&lt;span&gt;.trace(name, testName)(body(tracer)))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;2&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;Create an auto-configured &lt;code&gt;Tracer[IO]&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;code&gt;TraceUtils.trace&lt;&#x2F;code&gt; to wrap the test execution in a tracing span and record the outcome.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;For tests that use shared resources, such as a &lt;code&gt;Tracer[IO]&lt;&#x2F;code&gt;, the &lt;code&gt;TracedIOSuite&lt;&#x2F;code&gt; provides a way to integrate tracing into &lt;code&gt;IOSuite&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedIOSuite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IOSuite&lt;&#x2F;span&gt;&lt;span&gt; { self &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; sharedResource&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Resource&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    SdkTraces&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .autoConfigured[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;](_.addExporterConfigurer(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;OtlpSpanExporterAutoConfigure&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      .evalMap(_.tracerProvider.get(getClass.getName.stripSuffix(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;$&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  override def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TestName&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; PartiallyAppliedTest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;2&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedPartiallyAppliedTest&lt;&#x2F;span&gt;&lt;span&gt;(name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private final class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedPartiallyAppliedTest&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;      testName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TestName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; PartiallyAppliedTest&lt;&#x2F;span&gt;&lt;span&gt;(testName) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    override def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Unit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      registerTest(testName) { tracer &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;        Test&lt;&#x2F;span&gt;&lt;span&gt;(testName.name, (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Log&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; traced(log, tracer)((res, _)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; run(res)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    override def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Res&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Log&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Unit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      registerTest(testName) { tracer &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;        Test&lt;&#x2F;span&gt;&lt;span&gt;(testName.name, (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Log&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; traced(log, tracer)(run))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    private def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; traced&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;        log&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Log&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;        tracer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Log&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;      TraceUtils&lt;&#x2F;span&gt;&lt;span&gt;.trace(name, testName)(run(tracer, log))(implicitly, tracer)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;sharedResource&lt;&#x2F;code&gt; method sets up a shared &lt;code&gt;Tracer[IO]&lt;&#x2F;code&gt; instance that is created once per suite, so all tests within the suite use the same &lt;code&gt;Tracer&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;test&lt;&#x2F;code&gt; method is overridden to incorporate tracing into the test execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;bonus-point-instrumenting-scalacheck&quot;&gt;Bonus point. Instrumenting ScalaCheck&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typelevel&#x2F;scalacheck&quot;&gt;ScalaCheck&lt;&#x2F;a&gt; is a powerful property-based testing framework that allows you to test your code against pseudo-randomly generated properties.&lt;&#x2F;p&gt;
&lt;p&gt;We can wrap each property check invocation into its own span to make traces more meaningful and granular:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedIOCheckers&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Checkers&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MutableIOSuite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; must be &amp;#39;def&amp;#39;, so for every instantiation there will be a fresh counter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  implicit protected def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; unwrapWithTrace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;implicit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; PropF&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Checkers&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Prop&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]] {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      private val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Ref&lt;&#x2F;span&gt;&lt;span&gt;.unsafe[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Int&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; lift&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Expectations&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          count &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; counter.getAndUpdate(_ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          result &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .spanBuilder(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;forall#&lt;&#x2F;span&gt;&lt;span&gt;$count&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .withFinalizationStrategy(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SpanFinalizer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Strategy&lt;&#x2F;span&gt;&lt;span&gt;.empty)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .use(span &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; a.guaranteeCase(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;TraceUtils&lt;&#x2F;span&gt;&lt;span&gt;.recordOutcome(span)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;unwrapWithTrace&lt;&#x2F;code&gt; method creates a new tracing span for each property check invocation. The span name includes a counter to differentiate between multiple property checks within the same test.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;3-write-tests&quot;&gt;3. Write tests&lt;&#x2F;h1&gt;
&lt;p&gt;With the tracing utilities in place, we can finally write tests for the &lt;code&gt;Service&lt;&#x2F;code&gt; class that calculates the sum of two numbers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Service&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[_]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Temporal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Random&lt;&#x2F;span&gt;&lt;span&gt;] {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Long&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Long&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Long&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Tracer&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;].span(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;sum&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;x&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, x), &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Attribute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;y&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, y)).surround {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        delay &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Random&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;].nextIntBounded(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _     &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Temporal&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;].sleep(delay.millis)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; simulates computation time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Service&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;[_]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Async&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Tracer&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; F&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Random&lt;&#x2F;span&gt;&lt;span&gt;.scalaUtilRandom[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;].map(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;implicit&lt;&#x2F;span&gt;&lt;span&gt; random &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Service&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;F&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;tests-with-tracedsimpleiosuite&quot;&gt;Tests with &lt;code&gt;TracedSimpleIOSuite&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ServiceSuite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedSimpleIOSuite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedIOCheckers&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  tracedTest(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;calculate a sum of numbers (fixed)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implicit&lt;&#x2F;span&gt;&lt;span&gt; tracer &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      service &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Service&lt;&#x2F;span&gt;&lt;span&gt;.create[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      result  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; service.sum(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1L&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;2L&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; expect(result &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 3L&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  tracedTest(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;calculate a sum of numbers&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implicit&lt;&#x2F;span&gt;&lt;span&gt; tracer &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    forall { (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Long&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Long&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        service &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Service&lt;&#x2F;span&gt;&lt;span&gt;.create[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        result  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; service.sum(a, b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; expect(result &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; (a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; b))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;tests-with-tracediosuite&quot;&gt;Tests with &lt;code&gt;TracedIOSuite&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ServiceSharedTracerSuite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedIOSuite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TracedIOCheckers&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  test(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;calculate a sum of numbers (fixed)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implicit&lt;&#x2F;span&gt;&lt;span&gt; tracer &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      service &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Service&lt;&#x2F;span&gt;&lt;span&gt;.create[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      result  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; service.sum(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1L&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;2L&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; expect(result &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 3L&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  test(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;calculate a sum of numbers&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implicit&lt;&#x2F;span&gt;&lt;span&gt; tracer &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    forall { (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Long&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Long&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        service &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Service&lt;&#x2F;span&gt;&lt;span&gt;.create[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;IO&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        result  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; service.sum(a, b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; yield&lt;&#x2F;span&gt;&lt;span&gt; expect(result &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; (a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; b))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;4-collect-traces&quot;&gt;4. Collect traces&lt;&#x2F;h1&gt;
&lt;p&gt;Now, our tests are instrumented and can export proper traces. It&#x27;s time to collect them while running tests on GitHub Actions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prepare-build-sbt&quot;&gt;Prepare &lt;code&gt;build.sbt&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I suggest using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sbt&#x2F;sbt-github-actions&quot;&gt;sbt-github-actions&lt;&#x2F;a&gt; plugin to generate the GitHub Actions workflow.
First of all, we need to bind OpenTelemetry variables to configure the exporter:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ThisBuild&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; githubWorkflowEnv &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;++=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;OTEL_EXPORTER_OTLP_PROTOCOL&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;${{ secrets.OTEL_EXPORTER_OTLP_PROTOCOL }}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; &amp;lt;1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;OTEL_EXPORTER_OTLP_ENDPOINT&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; &amp;lt;2&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;OTEL_EXPORTER_OTLP_HEADERS&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;${{ secrets.OTEL_EXPORTER_OTLP_HEADERS }}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; &amp;lt;3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;OTEL_SERVICE_NAME&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;           -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;${{ github.ref }}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,                          &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; &amp;lt;4&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;OTEL_RESOURCE_ATTRIBUTES&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;revision=${{ github.sha }}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,                 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; &amp;lt;5&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;OTEL_SDK_DISABLED&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;           -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;${{ !startsWith(github.ref, &amp;#39;refs&#x2F;pull&amp;#39;) }}&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;6&amp;gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;Define the protocol for exporting traces (e.g., grpc, http&#x2F;protobuf)&lt;&#x2F;li&gt;
&lt;li&gt;The OTLP collector endpoint where spans should be sent&lt;&#x2F;li&gt;
&lt;li&gt;Security headers for authentication with the collector&lt;&#x2F;li&gt;
&lt;li&gt;Dynamically name the service based on the GitHub reference&lt;&#x2F;li&gt;
&lt;li&gt;Include additional attributes (like commit SHA) for filtering traces in Grafana&lt;&#x2F;li&gt;
&lt;li&gt;Disable tracing for non-PR branches, ensuring traces are only published for pull requests&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;configure-cloud-grafana&quot;&gt;Configure Cloud Grafana&lt;&#x2F;h2&gt;
&lt;p&gt;There are a few mandatory steps before we can start sending traces to the Grafana:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sign-in-into-grafana-cloud-and-navigate-to-your-org&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;auth&#x2F;sign-in&quot;&gt;Sign-in&lt;&#x2F;a&gt; into Grafana Cloud and navigate to your org:&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;grafana-cloud-portal.png&quot; alt=&quot;Grafana Cloud Portal&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enable-opentelemetry-otlp-collector&quot;&gt;Enable OpenTelemetry OTLP collector&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;grafana-cloud-otlp-configure.png&quot; alt=&quot;Grafana Cloud OTLP Configure&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;create-a-new-security-token&quot;&gt;Create a new security token&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;grafana-cloud-otlp-create-token.png&quot; alt=&quot;Grafana Cloud OTLP Create Token&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;save-the-secrets&quot;&gt;Save the secrets&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;grafana-cloud-otlp-secrets.png&quot; alt=&quot;Grafana Cloud OTLP Secrets&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configure-github-secrets-and-variables&quot;&gt;Configure GitHub secrets and variables&lt;&#x2F;h2&gt;
&lt;p&gt;Navigate to your GitHub repository, go to &lt;code&gt;Settings &amp;gt; Secrets and variables &amp;gt; Actions&lt;&#x2F;code&gt;, and add the secrets obtained in the previous step.
The secrets will be picked up by sbt while running tests.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configure-github-secrets&quot;&gt;Configure GitHub secrets&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;github-secrets.png&quot; alt=&quot;GitHub Secrets&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configure-github-variables&quot;&gt;Configure GitHub variables&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;github-variables.png&quot; alt=&quot;GitHub Variables&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus-point-create-a-comment-on-a-pr-with-a-link-to-traces&quot;&gt;Bonus point. Create a comment on a PR with a link to traces&lt;&#x2F;h2&gt;
&lt;p&gt;Update the &lt;code&gt;build.sbt&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ThisBuild&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; githubWorkflowBuildPreamble &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;1&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  WorkflowStep&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ComputeVar&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;tests_start_time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;date -d &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;$(date +&amp;#39;%Y-%m-%d&amp;#39;) 00:00:00&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; +%s%3N&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ThisBuild&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; githubWorkflowBuildPostamble &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;2&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  WorkflowStep&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ComputeVar&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;tests_end_time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;date -d &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;$(date +&amp;#39;%Y-%m-%d&amp;#39;) 23:59:59&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; +%s%3N&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ThisBuild&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; githubWorkflowBuildPostamble &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; &amp;lt;3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; panes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;      &amp;quot;&amp;quot;&amp;quot;{&amp;quot;7uq&amp;quot;: {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |  &amp;quot;datasource&amp;quot;:&amp;quot;grafanacloud-traces&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |  &amp;quot;queries&amp;quot;:[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |      &amp;quot;refId&amp;quot;:&amp;quot;A&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |      &amp;quot;datasource&amp;quot;:{&amp;quot;type&amp;quot;:&amp;quot;tempo&amp;quot;,&amp;quot;uid&amp;quot;:&amp;quot;grafanacloud-traces&amp;quot;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |      &amp;quot;queryType&amp;quot;:&amp;quot;traceql&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |      &amp;quot;limit&amp;quot;:100,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |      &amp;quot;query&amp;quot;:&amp;quot;{resource.revision=\&amp;quot;${{ github.sha }}\&amp;quot;}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |  ],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |  &amp;quot;range&amp;quot;:{&amp;quot;from&amp;quot;:&amp;quot;${{ env.tests_start_time }}&amp;quot;,&amp;quot;to&amp;quot;:&amp;quot;${{ env.tests_end_time }}&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;        |}}&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.stripMargin.replace(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).replace(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; link&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;{{ vars.GRAFANA_HOST }}&#x2F;explore?panes=&lt;&#x2F;span&gt;&lt;span&gt;$panes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;amp;schemaVersion=1&amp;amp;orgId=1&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;The traces can be reviewed here -&lt;&#x2F;span&gt;&lt;span&gt; $link&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;.&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  WorkflowStep&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Use&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    UseRef&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Public&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;peter-evans&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;create-or-update-comment&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;v4&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Publish &amp;#39;Grafana traces&amp;#39; comment&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cond &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;startsWith(github.ref, &amp;#39;refs&#x2F;pull&amp;#39;)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    params &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;      &amp;quot;issue-number&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;${{ github.event.pull_request.number }}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;      &amp;quot;body&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;         -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;Register &lt;code&gt;tests_start_time&lt;&#x2F;code&gt; before tests start - start of the day&lt;&#x2F;li&gt;
&lt;li&gt;Register &lt;code&gt;tests_end_time&lt;&#x2F;code&gt; once tests are executed - end of the day&lt;&#x2F;li&gt;
&lt;li&gt;Add a comment to the pull request&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It creates a comment on your pull request with a link to Grafana, where you can view traces for the specific commit and time range. Note that Grafana currently does not support timezone parameters in the URL, so the time range is set to a whole day of the test execution time.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;To make comments work, you must enable token&#x27;s write permissions in the &lt;code&gt;Settings &amp;gt; Actions &amp;gt; General &amp;gt; Read and write permissions&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;github-workflow-permissions.png&quot; alt=&quot;GitHub Workflow Permissions&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;5-check-the-result&quot;&gt;5. Check the result&lt;&#x2F;h1&gt;
&lt;p&gt;Push your changes, create a PR, check the result. The generated link automatically shows all spans associated with the current pipeline run.&lt;&#x2F;p&gt;
&lt;p&gt;Successful traces:
&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;.&#x2F;grafana-tempo-traces.png&quot; alt=&quot;Grafana Tempo Traces&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;An errored trace:
&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;otel4s-test-traces-grafana&#x2F;jaeger-errored-trace-example.png&quot; alt=&quot;Jaeger Errored Trace Example&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Scala 2: boilerplate-free type class definition</title>
        <published>2020-01-09T00:00:00+00:00</published>
        <updated>2020-01-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://ochenashko.com/boilerplate-free-type-class-definition/"/>
        <id>https://ochenashko.com/boilerplate-free-type-class-definition/</id>
        
        <content type="html" xml:base="https://ochenashko.com/boilerplate-free-type-class-definition/">&lt;p&gt;The development of an application requires design decisions. Fairly often a functional application is being designed around ad-hoc polymorphism.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ad-hoc polymorphism refers to when a value is able to adopt any one of several types because it, or a value it uses, has been given a separate definition for each of those types.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.haskell.org&#x2F;Polymorphism#Ad-hoc_polymorphism&quot;&gt;Haskell wiki&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Type class is an approach to ad-hoc polymorphism in Scala. Functional libraries widely use this concept:  &lt;code&gt;EntityEncoder&lt;&#x2F;code&gt;  in  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;http4s&#x2F;http4s&quot;&gt;http4s&lt;&#x2F;a&gt;,  &lt;code&gt;Functor&lt;&#x2F;code&gt;  in  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typelevel&#x2F;cats&quot;&gt;cats&lt;&#x2F;a&gt;,  &lt;code&gt;Encoder&lt;&#x2F;code&gt;  in  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;circe&#x2F;circe&quot;&gt;circe&lt;&#x2F;a&gt;, and so on. Since you need an instance of a type class for a specific type it can be either created manually or derived by a library (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;milessabin&#x2F;shapeless&quot;&gt;shapeless&lt;&#x2F;a&gt;,  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;propensive&#x2F;magnolia&quot;&gt;magnolia&lt;&#x2F;a&gt;).&lt;br &#x2F;&gt;
In common, an instance can be defined in a companion object or being derived at a call site. This is the point where the problem starts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;ochenashko.com&#x2F;boilerplate-free-type-class-definition&#x2F;.&#x2F;typeclasses.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scalaz&#x2F;scalaz-deriving&quot;&gt;scalaz-deriving&lt;&#x2F;a&gt; is a zero dependency library that provides a boilerplate-free way of defining a type class instance:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;scalaz.annotation.deriving(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Hash&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Codec&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;firstName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;lastName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The detailed configuration described at the end of the article.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-s-wrong-with-automated-derivation&quot;&gt;What&#x27;s wrong with automated derivation&lt;&#x2F;h1&gt;
&lt;p&gt;I guess everyone is familiar with wildcard imports that provide a generic derivation of a type class, e.g.  &lt;code&gt;import io.circe.generic.auto._&lt;&#x2F;code&gt;  ,  &lt;code&gt;import ShowMagnolia._&lt;&#x2F;code&gt;  , and so on.&lt;&#x2F;p&gt;
&lt;p&gt;This approach has several disadvantages:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;1. A type class is being generated at every call site&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It’s not a problem until your application is small or you don’t care about the compilation speed. Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; io&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;circe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;generic&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;firstName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;lastName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; stringifyNoSpaces&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  io.circe.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Encoder&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;].apply(value).noSpaces &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; Encoder instance #1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; stringify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  io.circe.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Encoder&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;].apply(value).toString &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; Encoder instance #2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; decode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;input&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Either&lt;&#x2F;span&gt;&lt;span&gt;[io.circe.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  io.circe.parser.decode[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;](input)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;          &#x2F;&#x2F; Decoder instance #1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;2. The output can be different&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The problem arises from the previous point. Magnolia can choose a different instance for the underlying type based on the imports. Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ShowMagnolia&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;firstName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;lastName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; stringify1&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Domain&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;toUpperCaseStringShow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;].show(value)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; Instance #1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; stringify2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;].show(value)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; Instance #2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; user&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;John&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Smith&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stringify1(user)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; output: User(firstName = JOHN, lastName = SMITH)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stringify2(user)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; output: User(firstName = John, lastName = Smith)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The example above is slightly unreal in the real world. But you can get a different behavior due to an accidental wildcard import  &lt;code&gt;import Domain._&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;cached-instances&quot;&gt;Cached instances&lt;&#x2F;h1&gt;
&lt;p&gt;An instance can be defined in a companion object and the compiler will reuse it in all necessary places:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; io&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;circe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Codec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; io&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;circe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;generic&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;semiauto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;firstName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;lastName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  implicit val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; userCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Codec&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; semiauto.deriveCodec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looks good, isn’t it? The compiler will automatically pick up an instance of the type class from the companion object. The most important thing, that the instance is being created only once, which is good for the compilation speed.&lt;&#x2F;p&gt;
&lt;p&gt;But the further you dive into the development process, the more type classes your model requires:  &lt;code&gt;cats.Hash&lt;&#x2F;code&gt;,  &lt;code&gt;cats.Eq&lt;&#x2F;code&gt;,  &lt;code&gt;cats.Show&lt;&#x2F;code&gt;, and so on.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; io&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;circe&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;generic&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;semiauto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;firstName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;lastName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  implicit val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; userCodec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Codec&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; semiauto.deriveCodec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  implicit val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; userEq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Eq&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;       =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Eq&lt;&#x2F;span&gt;&lt;span&gt;.fromUniversalEquals&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  implicit val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; userHash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Hash&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Hash&lt;&#x2F;span&gt;&lt;span&gt;.fromUniversalHashCode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  implicit val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; userShow&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ShowMagnolia&lt;&#x2F;span&gt;&lt;span&gt;.derive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well, this one looks much more polluted. And now imagine that you have dozens of different models. And it quickly turns into a mess.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the example above we can trace the pattern: the creation of an instance does not require any custom logic. An instance is being created by a utility method and since the implementation depends only on the type, the boilerplate part can be generated by a compiler plugin.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;scalaz-deriving-plugin&quot;&gt;scalaz-deriving plugin&lt;&#x2F;h1&gt;
&lt;p&gt;Apart from the name, the compiler plugin does not have any dependency on scalaz. The plugin creates corresponding instances using derivation methods described at  &lt;code&gt;deriving.conf&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The plugin logic is pretty straightforward:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Collect instances that should be derived;&lt;&#x2F;li&gt;
&lt;li&gt;Find a derivation method in the  &lt;code&gt;resources&#x2F;deriving.conf&lt;&#x2F;code&gt;  file;&lt;&#x2F;li&gt;
&lt;li&gt;Generate (if it does not exist) a companion object and append necessary instances.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Add the compiler plugin and macro library to the  &lt;code&gt;build.sbt&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;libraryDependencies &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;org.scalaz&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;deriving-macro&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;2.0.0-M7&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;addCompilerPlugin(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;org.scalaz&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %%&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;deriving-plugin&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;2.0.0-M7&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; cross &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;CrossVersion&lt;&#x2F;span&gt;&lt;span&gt;.full)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you want to use methods for derivation defined in the same compilation unit (e.g. Magnolia), add to the  &lt;code&gt;build.sbt&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Compile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; managedClasspath &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; res&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Compile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; resourceDirectory).value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; old&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Compile&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; managedClasspath).value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  Attributed&lt;&#x2F;span&gt;&lt;span&gt;.blank(res)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +:&lt;&#x2F;span&gt;&lt;span&gt; old&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Describe derivation rules in the  &lt;code&gt;resources&#x2F;deriving.conf&lt;&#x2F;code&gt;  file&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The compiler plugin takes the rules from the  &lt;code&gt;deriving.conf&lt;&#x2F;code&gt;  file, which must be in the  &lt;code&gt;resources&lt;&#x2F;code&gt;  folder. Rules example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cats.kernel.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; cats.kernel.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;.fromUniversalEquals  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cats.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; example.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ShowMagnolia&lt;&#x2F;span&gt;&lt;span&gt;.derive  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cats.kernel.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; cats.kernel.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Hash&lt;&#x2F;span&gt;&lt;span&gt;.fromUniversalHashCode  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;io.circe.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Codec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; io.circe.generic.semiauto.deriveCodec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Annotate your domain models&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;scalaz.annotation.deriving(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Hash&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Codec&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; User&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;firstName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;lastName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The difference is significant, isn’t it? The model looks much cleaner now.&lt;br &#x2F;&gt;
The first thing you can pay attention to is the lack of a companion object. It’s being generated along with the type classes.&lt;&#x2F;p&gt;
&lt;p&gt;Moreover, the plugin supports generic classes as well:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;scalaz.annotation.deriving(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GenericClass&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The generated code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;final case class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GenericClass&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GenericClass&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  implicit def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; _deriving_show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;implicit&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;    evidence$$A&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;    evidence$$B&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;    evidence$$C&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Show&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;GenericClass&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; example.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ShowMagnolia&lt;&#x2F;span&gt;&lt;span&gt;.derive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see,  &lt;code&gt;scalaz-deriving&lt;&#x2F;code&gt;  provides a simple way of keeping the models clean.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;instead-of-a-conclusion&quot;&gt;Instead of a conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;Not only  &lt;code&gt;scalaz-deriving&lt;&#x2F;code&gt;  can help us with a boilerplate. The library  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;manatki&#x2F;derevo&quot;&gt;derevo&lt;&#x2F;a&gt;  provides a similar syntax, but it does not support custom types yet. Also, Scala 3 received a fancy derivation mechanism. But in Scala 2 world, we can rely either on  &lt;code&gt;scalaz-deriving&lt;&#x2F;code&gt;  or  &lt;code&gt;derevo&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;further-reading&quot;&gt;&lt;strong&gt;Further reading&lt;&#x2F;strong&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;propensive&#x2F;magnolia&quot;&gt;Magnolia&lt;&#x2F;a&gt;  — shapeless-free type class derivation.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dotty.epfl.ch&#x2F;docs&#x2F;reference&#x2F;contextual&#x2F;derivation.html&quot;&gt;Scala 3 Derivation&lt;&#x2F;a&gt;  — Scala 3 finally received a fancy derivation mechanism.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubuszok.com&#x2F;compiled&#x2F;implicits-type-classes-and-extension-methods&quot;&gt;Implicits, type classes, and extension methods&lt;&#x2F;a&gt;  — explained Scala 2 implicits.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
