<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Manage Tempo on Grafana Labs</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/</link><description>Recent content in Manage Tempo on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/tempo/v2.2.x/operations/index.xml" rel="self" type="application/rss+xml"/><item><title>Tempo architecture</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/architecture/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/architecture/</guid><content><![CDATA[&lt;h1 id=&#34;tempo-architecture&#34;&gt;Tempo architecture&lt;/h1&gt;
&lt;p&gt;This topic provides an overview of the major components of Tempo. Refer to the &lt;a href=&#34;../../getting-started/example-demo-app/&#34;&gt;example setups&lt;/a&gt;
or &lt;a href=&#34;../../setup/deployment/&#34;&gt;deployment options&lt;/a&gt; for help deploying.&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;&lt;img src=&#34;../tempo_arch.png&#34; alt=&#34;Tempo Architecture&#34;&gt;&lt;/p&gt;
&lt;p&gt;Tempo comprises of the following top-level components.&lt;/p&gt;
&lt;h2 id=&#34;distributor&#34;&gt;Distributor&lt;/h2&gt;
&lt;p&gt;The distributor accepts spans in multiple formats including Jaeger, OpenTelemetry, Zipkin. It routes spans to ingesters by hashing the &lt;code&gt;traceID&lt;/code&gt; and using a &lt;a href=&#34;../consistent_hash_ring/&#34;&gt;distributed consistent hash ring&lt;/a&gt;.
The distributor uses the receiver layer from the &lt;a href=&#34;https://github.com/open-telemetry/opentelemetry-collector&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenTelemetry Collector&lt;/a&gt;.
For best performance it is recommended to ingest &lt;a href=&#34;https://github.com/open-telemetry/opentelemetry-proto&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OTel Proto&lt;/a&gt;. For this reason
the &lt;a href=&#34;https://github.com/grafana/agent&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Grafana Agent&lt;/a&gt; uses the otlp exporter/receiver to send spans to Tempo.&lt;/p&gt;
&lt;h2 id=&#34;ingester&#34;&gt;Ingester&lt;/h2&gt;
&lt;p&gt;The Ingester batches trace into blocks, creates bloom filters and indexes, and then flushes it all to the backend.
Blocks in the backend are generated in the following layout.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;&amp;lt;bucketname&amp;gt; / &amp;lt;tenantID&amp;gt; / &amp;lt;blockID&amp;gt; / &amp;lt;meta.json&amp;gt;
                                      / &amp;lt;index&amp;gt;
                                      / &amp;lt;data&amp;gt;
                                      / &amp;lt;bloom_0&amp;gt;
                                      / &amp;lt;bloom_1&amp;gt;
                                        ...
                                      / &amp;lt;bloom_n&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;query-frontend&#34;&gt;Query Frontend&lt;/h2&gt;
&lt;p&gt;The Query Frontend is responsible for sharding the search space for an incoming query.&lt;/p&gt;
&lt;p&gt;Traces are exposed via a simple HTTP endpoint:
&lt;code&gt;GET /api/traces/&amp;lt;traceID&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Internally, the Query Frontend splits the blockID space into a configurable number of shards and queues these requests.
Queriers connect to the Query Frontend via a streaming gRPC connection to process these sharded queries.&lt;/p&gt;
&lt;h2 id=&#34;querier&#34;&gt;Querier&lt;/h2&gt;
&lt;p&gt;The querier is responsible for finding the requested trace id in either the ingesters or the backend storage. Depending on
parameters it will query both the ingesters and pull bloom/indexes from the backend to search blocks in object
storage.&lt;/p&gt;
&lt;p&gt;The querier exposes an HTTP endpoint at:
&lt;code&gt;GET /querier/api/traces/&amp;lt;traceID&amp;gt;&lt;/code&gt;, but its not expected to be used directly.&lt;/p&gt;
&lt;p&gt;Queries should be sent to the Query Frontend.&lt;/p&gt;
&lt;h2 id=&#34;compactor&#34;&gt;Compactor&lt;/h2&gt;
&lt;p&gt;The Compactors stream blocks to and from the backend storage to reduce the total number of blocks.&lt;/p&gt;
&lt;h2 id=&#34;metrics-generator&#34;&gt;Metrics generator&lt;/h2&gt;
&lt;p&gt;This is an &lt;strong&gt;optional&lt;/strong&gt; component that derives metrics from ingested traces and writes them to a metrics storage. Refer to the &lt;a href=&#34;../../metrics-generator/&#34;&gt;metrics-generator documentation&lt;/a&gt; to learn more.&lt;/p&gt;
]]></content><description>&lt;h1 id="tempo-architecture">Tempo architecture&lt;/h1>
&lt;p>This topic provides an overview of the major components of Tempo. Refer to the &lt;a href="../../getting-started/example-demo-app/">example setups&lt;/a>
or &lt;a href="../../setup/deployment/">deployment options&lt;/a> for help deploying.&lt;/p>
&lt;p align="center">&lt;img src="../tempo_arch.png" alt="Tempo Architecture">&lt;/p>
&lt;p>Tempo comprises of the following top-level components.&lt;/p></description></item><item><title>Server-side metrics architecture</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/server_side_metrics/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/server_side_metrics/</guid><content><![CDATA[&lt;h1 id=&#34;server-side-metrics-architecture&#34;&gt;Server-side metrics architecture&lt;/h1&gt;
&lt;p&gt;Server-side metrics is a feature that derive metrics from ingested traces.&lt;/p&gt;
&lt;p&gt;To generate metrics, it uses an additional component: the &lt;a href=&#34;../../metrics-generator/&#34;&gt;metrics-generator&lt;/a&gt;.
If present, the distributor will write received spans to both the ingester and the metrics-generator.
The metrics-generator processes spans and writes metrics to a Prometheus datasource using the Prometheus remote write protocol.&lt;/p&gt;
&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;
&lt;p&gt;Generating and writing metrics introduces a whole new domain to Tempo unlike any other functionality thus far.
For this reason, a component, the metrics-generator, is dedicated to working with metrics.
This results in a clean division of responsibility and limits the blast radius from a metrics processors or the Prometheus remote write exporter blowing up.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;                                                                      │
                                                                      │
                                                                   Ingress
                                                                      │
                                                                      ▼
                                                          ┌──────────────────────┐
                                                          │                      │
                                                          │     Distributor      │
                                                          │                      │
                                                          └──────────────────────┘
                                                                    2│ │1
                                                                     │ │
                                                  ┌──────────────────┘ └────────┐
                                                  │                             │
                                                  ▼                             ▼
┌ ─ ─ ─ ─ ─ ─ ─ ─                     ┏━━━━━━━━━━━━━━━━━━━━━━┓      ┌──────────────────────┐
                 │                    ┃                      ┃      │                      │
│   Prometheus    ◀────Prometheus ────┃  Metrics-generator   ┃      │       Ingester       │◀───Queries────
                 │    Remote Write    ┃                      ┃      │                      │
└ ─ ─ ─ ─ ─ ─ ─ ─                     ┗━━━━━━━━━━━━━━━━━━━━━━┛      └──────────────────────┘
                                                                                │
                                                                                │
                                                                                │
                                                                                ▼
                                                                       ┌─────────────────┐
                                                                       │                 │
                                                                       │     Backend     │
                                                                       │                 │
                                                                       └─────────────────┘&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;For a detailed view of all the config options for the metrics generator, visit &lt;a href=&#34;../../configuration/#metrics-generator&#34;&gt;its config page&lt;/a&gt;.&lt;/p&gt;
]]></content><description>&lt;h1 id="server-side-metrics-architecture">Server-side metrics architecture&lt;/h1>
&lt;p>Server-side metrics is a feature that derive metrics from ingested traces.&lt;/p>
&lt;p>To generate metrics, it uses an additional component: the &lt;a href="../../metrics-generator/">metrics-generator&lt;/a>.
If present, the distributor will write received spans to both the ingester and the metrics-generator.
The metrics-generator processes spans and writes metrics to a Prometheus datasource using the Prometheus remote write protocol.&lt;/p></description></item><item><title>Best practices for traces</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/best-practices/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/best-practices/</guid><content><![CDATA[&lt;h1 id=&#34;best-practices-for-traces&#34;&gt;Best practices for traces&lt;/h1&gt;
&lt;p&gt;This page provides some general best practices for tracing.&lt;/p&gt;
&lt;h2 id=&#34;span-and-resource-attributes&#34;&gt;Span and resource attributes&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;../../traces/&#34;&gt;Traces&lt;/a&gt; are built from spans, which denote units of work such as a call to, or from, an upstream service. Spans are constructed primarily of span and resource attributes.
Spans also have a hierarchy, where parent spans can have children or siblings.&lt;/p&gt;
&lt;p&gt;In the screenshot below, the left side of the screen (1) shows the list of results for the query. The right side (2) lists each span that makes up the selected trace.&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/static/img/docs/tempo/trace-explore-spans.png&#34;
  alt=&#34;Traces example with query results and spans&#34; width=&#34;1225&#34;
     height=&#34;783&#34;/&gt;&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;span attribute&lt;/strong&gt; is a key/value pair that provides context for its span. For example, if the span deals with calling another service via HTTP, an attribute could include the HTTP URL (maybe as the span attribute key &lt;code&gt;http.url&lt;/code&gt;) and the HTTP status code returned (as the span attribute &lt;code&gt;http.status_code&lt;/code&gt;). Span attributes can consist of varying, non-null types.&lt;/p&gt;
&lt;p&gt;Unlike a span attribute, a &lt;strong&gt;resource attribute&lt;/strong&gt; is a key/value pair that describes the context of how the span was collected. Generally, these attributes describe the process that created the span.
For example, this could be a set of resource attributes concerning a Kubernetes cluster, in which case you may see resource attributes, for example: &lt;code&gt;k8s.namespace&lt;/code&gt;, &lt;code&gt;k8s.container_name&lt;/code&gt;, and &lt;code&gt;k8s.cluster&lt;/code&gt;.
These can also include information on the libraries that were used to instrument the spans for a trace, or any other infrastructure information.&lt;/p&gt;
&lt;p&gt;For more information, read the &lt;a href=&#34;https://opentelemetry.io/docs/specs/otel/overview/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Attribute and Resource&lt;/a&gt; sections in the OpenTelemetry specification.&lt;/p&gt;
&lt;h3 id=&#34;naming-conventions-for-span-and-resource-attributes&#34;&gt;Naming conventions for span and resource attributes&lt;/h3&gt;
&lt;p&gt;When naming attributes, use consistent, nested namespaces to ensures that attribute keys are obvious to anyone observing the spans of a trace and that common attributes can be shared by spans.
Using our example from above, the &lt;code&gt;http&lt;/code&gt; prefix of the attribute is the namespace, and &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;status_code&lt;/code&gt; are keys within that namespace.
Attributes can also be nested, for example &lt;code&gt;http.url.protocol&lt;/code&gt; might be &lt;code&gt;HTTP&lt;/code&gt; or &lt;code&gt;HTTPS&lt;/code&gt;, whereas &lt;code&gt;http.url.path&lt;/code&gt; might be &lt;code&gt;/api/v1/query&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more details around semantic naming conventions, refer to the &lt;a href=&#34;https://opentelemetry.io/docs/specs/otel/common/attribute-naming/#recommendations-for-opentelemetry-authors&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Recommendations for OpenTelemetry Authors&lt;/a&gt; documentation.&lt;/p&gt;
&lt;p&gt;Some third-party libraries provide auto-instrumentation that generate span and span attributes when included in a source base.&lt;/p&gt;
&lt;p&gt;For more information about instrumenting your app for tracing, refer to the &lt;a href=&#34;/docs/tempo/latest/getting-started/instrumentation/&#34;&gt;Instrument for distributed tracing&lt;/a&gt; documentation.&lt;/p&gt;
&lt;h2 id=&#34;determining-where-to-add-spans&#34;&gt;Determining where to add spans&lt;/h2&gt;
&lt;p&gt;When instrumenting, determine the smallest piece of work that you need to observe in a trace to be of value to ensure that you don’t over (or under) instrument.&lt;/p&gt;
&lt;p&gt;Creating a new span for any work that has a relatively significant duration allows the observation of a trace to immediately show where significant amounts of time are spent during the processing of a request into your application or system.&lt;/p&gt;
&lt;p&gt;For example, adding a span for a call to another services (either instrumented or not) may take an unknown amount of time to complete, and therefore being able to separate this work shows when services are taking longer than expected.&lt;/p&gt;
&lt;p&gt;Adding a span for a piece of work that might call many other functions in a loop is a good signal of how long that loop is taking (you might add a span attribute that counts how many time the loop runs to determine if the duration is acceptable).
However, adding a span for each method or function call in that loop might not, as it might produce hundreds or thousands of worthless spans.&lt;/p&gt;
]]></content><description>&lt;h1 id="best-practices-for-traces">Best practices for traces&lt;/h1>
&lt;p>This page provides some general best practices for tracing.&lt;/p>
&lt;h2 id="span-and-resource-attributes">Span and resource attributes&lt;/h2>
&lt;p>&lt;a href="../../traces/">Traces&lt;/a> are built from spans, which denote units of work such as a call to, or from, an upstream service. Spans are constructed primarily of span and resource attributes.
Spans also have a hierarchy, where parent spans can have children or siblings.&lt;/p></description></item><item><title>Monitor Tempo</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/monitoring/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/monitoring/</guid><content><![CDATA[&lt;h1 id=&#34;monitor-tempo&#34;&gt;Monitor Tempo&lt;/h1&gt;
&lt;p&gt;Tempo is instrumented to expose metrics, logs, and traces.
Furthermore, the Tempo repository has a &lt;a href=&#34;https://github.com/grafana/tempo/tree/main/operations/tempo-mixin&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;mixin&lt;/a&gt; that includes a
set of dashboards, rules, and alerts.
Together, these can be used to monitor Tempo in production.&lt;/p&gt;
&lt;h2 id=&#34;instrumentation&#34;&gt;Instrumentation&lt;/h2&gt;
&lt;p&gt;Tempo is already instrumented with metrics, logs, and traces.
These can be collected to observe Tempo.&lt;/p&gt;
&lt;h3 id=&#34;metrics&#34;&gt;Metrics&lt;/h3&gt;
&lt;p&gt;Tempo is instrumented with &lt;a href=&#34;https://prometheus.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus metrics&lt;/a&gt;.
It emits RED metrics for most services and backends. (RED metrics are a standardized format for monitoring microservices, where R stands for requests, E stands for errors, and D stands for duration)&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;#dashboards&#34;&gt;Tempo mixin&lt;/a&gt; provides several dashboards using these metrics.&lt;/p&gt;
&lt;h3 id=&#34;logs&#34;&gt;Logs&lt;/h3&gt;
&lt;p&gt;Tempo emits logs in the &lt;code&gt;key=value&lt;/code&gt; (&lt;a href=&#34;https://brandur.org/logfmt&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;logfmt&lt;/a&gt;) format.&lt;/p&gt;
&lt;h3 id=&#34;traces&#34;&gt;Traces&lt;/h3&gt;
&lt;p&gt;Tempo uses the &lt;a href=&#34;https://github.com/jaegertracing/jaeger-client-go&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Jaeger Golang SDK&lt;/a&gt; for tracing instrumentation.
As of this writing, the complete read path and some parts of the write of Tempo are instrumented for tracing.&lt;/p&gt;
&lt;p&gt;The tracer can be configured &lt;a href=&#34;https://github.com/jaegertracing/jaeger-client-go#environment-variables&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;using environment variables&lt;/a&gt;.
To enable tracing, set one of the following: &lt;code&gt;JAEGER_AGENT_HOST&lt;/code&gt; and &lt;code&gt;JAEGER_AGENT_PORT&lt;/code&gt;, or &lt;code&gt;JAEGER_ENDPOINT&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The Jaeger client uses remote sampling by default, if the management server is not available no traces will be sent.
To always send traces (no sampling), set the following environment variables:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;JAEGER_SAMPLER_TYPE=const
JAEGER_SAMPLER_PARAM=1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;dashboards&#34;&gt;Dashboards&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/grafana/tempo/tree/main/operations/tempo-mixin&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Tempo mixin&lt;/a&gt; has four Grafana dashboards in the &lt;code&gt;yamls&lt;/code&gt; folder that you can download and import into your Grafana UI.
Currently, these work well when Tempo is run in a Kubernetes (k8s) environment and metrics scraped have the
&lt;code&gt;cluster&lt;/code&gt; and &lt;code&gt;namespace&lt;/code&gt; labels.&lt;/p&gt;
&lt;h3 id=&#34;tempo-reads-dashboard&#34;&gt;Tempo Reads dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-reads.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Reads dashboard gives information information on Requests, Errors and Duration (R.E.D) on the Query Path of Tempo.
Each query touches the Gateway, Tempo-Query, Query-Frontend, Queriers, Ingesters, Cache (if present) and the backend.&lt;/p&gt;
&lt;p&gt;Use this dashboard to monitor the performance of each of the above mentioned components and to decide the number of
replicas in each deployment.&lt;/p&gt;
&lt;h3 id=&#34;tempo-writes-dashboard&#34;&gt;Tempo Writes dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-writes.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Writes dashboard gives information information on Requests, Errors and Duration (R.E.D) on the write/ingest Path of Tempo.
A write query touches the Gateway, Distributors, Ingesters and eventually the backend. This dashboard also gives information
on the number of operations performed by the Compactor to the backend.&lt;/p&gt;
&lt;p&gt;Use this dashboard to monitor the performance of each of the above mentioned components and to decide the number of
replicas in each deployment.&lt;/p&gt;
&lt;h3 id=&#34;tempo-resources-dashboard&#34;&gt;Tempo Resources dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-resources.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Resources dashboard provides information on &lt;code&gt;CPU&lt;/code&gt;, &lt;code&gt;Container Memory&lt;/code&gt; and &lt;code&gt;Go Heap Inuse&lt;/code&gt;, and is useful for resource
provisioning for the different Tempo components.&lt;/p&gt;
&lt;p&gt;Use this dashboard to see if any components are running close to their assigned limits!&lt;/p&gt;
&lt;h3 id=&#34;tempo-operational-dashboard&#34;&gt;Tempo Operational dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-operational.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Tempo Operational dashboard deserves special mention b/c it probably a stack of dashboard anti-patterns.
It&amp;rsquo;s big and complex, doesn&amp;rsquo;t use jsonnet and displays far too many metrics in one place.  And I love it.
For just getting started the Reads, Write and Resources dashboards are great places to learn how to monitor Tempo in an opaque way.&lt;/p&gt;
&lt;p&gt;This dashboard is included in this repo for two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It provides a stack of metrics for other operators to consider monitoring while running Tempo.&lt;/li&gt;
&lt;li&gt;We want it in our internal infrastructure and we vendor the tempo-mixin to do this.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;rules-and-alerts&#34;&gt;Rules and alerts&lt;/h2&gt;
&lt;p&gt;The Rules and Alerts are available as &lt;a href=&#34;https://github.com/grafana/tempo/tree/main/operations/tempo-mixin-compiled&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;yaml files in the compiled mixin&lt;/a&gt; on the repository.&lt;/p&gt;
&lt;p&gt;To set up alerting, download the provided json files and configure them for use on your Prometheus monitoring server.&lt;/p&gt;
&lt;p&gt;Check the &lt;a href=&#34;https://github.com/grafana/tempo/blob/main/operations/tempo-mixin/runbook.md&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;runbook&lt;/a&gt; to understand the
various steps that can be taken to fix firing alerts!&lt;/p&gt;
]]></content><description>&lt;h1 id="monitor-tempo">Monitor Tempo&lt;/h1>
&lt;p>Tempo is instrumented to expose metrics, logs, and traces.
Furthermore, the Tempo repository has a &lt;a href="https://github.com/grafana/tempo/tree/main/operations/tempo-mixin" target="_blank" rel="noopener noreferrer">mixin&lt;/a> that includes a
set of dashboards, rules, and alerts.
Together, these can be used to monitor Tempo in production.&lt;/p></description></item><item><title>Use polling to monitor Tempo's backend status</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/polling/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/polling/</guid><content><![CDATA[&lt;h1 id=&#34;use-polling-to-monitor-tempos-backend-status&#34;&gt;Use polling to monitor Tempo&amp;rsquo;s backend status&lt;/h1&gt;
&lt;p&gt;Tempo maintains knowledge of the state of the backend by polling it on regular intervals. There are currently
only two components that need this knowledge and, consequently, only two that poll the backend: compactors
and queriers.&lt;/p&gt;
&lt;p&gt;To reduce calls to the backend, only a small subset of compactors actually list all blocks and build
what&amp;rsquo;s called a tenant index.
The tenant index is a gzip&amp;rsquo;ed JSON file located at &lt;code&gt;/&amp;lt;tenant&amp;gt;/index.json.gz&lt;/code&gt; containing
an entry for every block and compacted block for that tenant.
This is done once every &lt;code&gt;blocklist_poll&lt;/code&gt; duration.&lt;/p&gt;
&lt;p&gt;All other compactors and all queriers then rely on downloading this file, unzipping it and using the contained list.
Again, this is done once every &lt;code&gt;blocklist_poll&lt;/code&gt; duration.&lt;/p&gt;
&lt;p&gt;Due to this behavior, a given compactor or querier will often have an out-of-date blocklist.
During normal operation, it will stale by at most twice the configured &lt;code&gt;blocklist_poll&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For details about configuring polling, see &lt;a href=&#34;../../configuration/polling/&#34;&gt;polling configuration&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id=&#34;monitor-polling-with-dashboards-and-alerts&#34;&gt;Monitor polling with dashboards and alerts&lt;/h2&gt;
&lt;p&gt;See our Jsonnet for example &lt;a href=&#34;https://github.com/grafana/tempo/blob/main/operations/tempo-mixin/alerts.libsonnet&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;alerts&lt;/a&gt; and &lt;a href=&#34;https://github.com/grafana/tempo/blob/main/operations/tempo-mixin/runbook.md&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;runbook entries&lt;/a&gt;
related to polling.&lt;/p&gt;
&lt;p&gt;If you are building your own dashboards or alerts, here are a few relevant metrics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tempodb_blocklist_poll_errors_total&lt;/code&gt;
A holistic metric that increments for any error with polling the blocklist. Any increase in this metric should be reviewed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tempodb_blocklist_poll_duration_seconds&lt;/code&gt;
Histogram recording the length of time in seconds to poll the entire blocklist.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tempodb_blocklist_length&lt;/code&gt;
Total blocks as seen by this component.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tempodb_blocklist_tenant_index_errors_total&lt;/code&gt;
A holistic metrics that indcrements for any error building the tenant index. Any increase in this metric should be reviewed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tempodb_blocklist_tenant_index_builder&lt;/code&gt;
A gauge that has the value 1 if this compactor is attempting to build the tenant index and 0 if it is not. At least one compactor
must have this value set to 1 for the system to be working.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tempodb_blocklist_tenant_index_age_seconds&lt;/code&gt;
The age of the last loaded tenant index. now() minus this value indicates how stale this components view of the blocklist is.&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="use-polling-to-monitor-tempos-backend-status">Use polling to monitor Tempo&amp;rsquo;s backend status&lt;/h1>
&lt;p>Tempo maintains knowledge of the state of the backend by polling it on regular intervals. There are currently
only two components that need this knowledge and, consequently, only two that poll the backend: compactors
and queriers.&lt;/p></description></item><item><title>Tune the consistent hash rings</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/consistent_hash_ring/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/consistent_hash_ring/</guid><content><![CDATA[&lt;h1 id=&#34;tune-the-consistent-hash-rings&#34;&gt;Tune the consistent hash rings&lt;/h1&gt;
&lt;p&gt;Tempo uses the &lt;a href=&#34;https://cortexmetrics.io/docs/architecture/#the-hash-ring&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Consistent Hash Ring&lt;/a&gt; implementation from Cortex.
By default, the ring is gossiped between all Tempo components.
However, it can be configured to use &lt;a href=&#34;https://www.consul.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Consul&lt;/a&gt; or &lt;a href=&#34;https://etcd.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Etcd&lt;/a&gt;, if desired.&lt;/p&gt;
&lt;p&gt;There are four consistent hash rings: distributor, ingester, metrics-generator, and compactor.
Each hash ring exists for a distinct reason.&lt;/p&gt;
&lt;h2 id=&#34;distributor&#34;&gt;Distributor&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;Unless you are running with limits, this ring does not impact Tempo operation.&lt;/p&gt;
&lt;p&gt;This ring is only used when &lt;code&gt;global&lt;/code&gt; rate limits are used. The distributors use it to count the other active distributors. Incoming traffic is assumed to be evenly spread across all distributors and (global_rate_limit / # of distributors) is used to rate limit locally.&lt;/p&gt;
&lt;h2 id=&#34;ingester&#34;&gt;Ingester&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Ingesters&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Distributors, Queriers&lt;/p&gt;
&lt;p&gt;This ring is used by the distributors to load balance traffic into the ingesters. When spans are received the trace id is hashed and they are sent to the appropriate ingesters based on token ownership in the ring. Queriers also use this ring to find the ingesters for querying recent traces.&lt;/p&gt;
&lt;h2 id=&#34;metrics-generator&#34;&gt;Metrics-generator&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Metrics-generators&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;This ring is used by distributors to load balance traffic to the metrics-generators. When spans are received, the trace ID is hashed, and the traces are sent to the appropriate metrics-generators based on token ownership in the ring.&lt;/p&gt;
&lt;h2 id=&#34;compactor&#34;&gt;Compactor&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Participants:&lt;/strong&gt; Compactors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Used by:&lt;/strong&gt; Compactors&lt;/p&gt;
&lt;p&gt;This ring is used by the compactors to shard compaction jobs. Jobs are hashed into the ring and the owning compactor is the only one allowed to compact a specific set of blocks to prevent race conditions on compaction.&lt;/p&gt;
&lt;h2 id=&#34;interacting-with-the-rings&#34;&gt;Interacting with the rings&lt;/h2&gt;
&lt;p&gt;Web pages are available at the following endpoints. They show every ring member, their tokens and includes the ability to &amp;ldquo;Forget&amp;rdquo; a ring member. &amp;ldquo;Forgetting&amp;rdquo; is useful when a
ring member leaves the ring without properly shutting down (and therefore leaves its tokens in the ring).&lt;/p&gt;
&lt;h3 id=&#34;distributor-1&#34;&gt;Distributor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/distributor/ring&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Unhealthy distributors have little impact but should be forgotten to reduce cost of maintaining the ring .&lt;/p&gt;
&lt;h3 id=&#34;ingester-1&#34;&gt;Ingester&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/ingester/ring&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Unhealthy ingesters will cause writes to fail. If the ingester is really gone, forget it immediately.&lt;/p&gt;
&lt;h3 id=&#34;metrics-generators&#34;&gt;Metrics-generators&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Distributors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/metrics-generator/ring&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Unhealthy metrics-generators will cause writes to fail. If the metrics-generator is really gone, forget it immediately.&lt;/p&gt;
&lt;h3 id=&#34;compactor-1&#34;&gt;Compactor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Available on:&lt;/strong&gt; Compactors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Path:&lt;/strong&gt; &lt;code&gt;/compactor/ring&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Unhealthy compactors will allow the blocklist to grow significantly. If the compactor is really gone, forget it immediately.&lt;/p&gt;
&lt;h2 id=&#34;configuring-the-rings&#34;&gt;Configuring the rings&lt;/h2&gt;
&lt;p&gt;Ring/Lifecycler configuration control how a component interacts with the ring. Refer to the &lt;a href=&#34;../../configuration/&#34;&gt;configuration&lt;/a&gt; topic for more details.&lt;/p&gt;
]]></content><description>&lt;h1 id="tune-the-consistent-hash-rings">Tune the consistent hash rings&lt;/h1>
&lt;p>Tempo uses the &lt;a href="https://cortexmetrics.io/docs/architecture/#the-hash-ring" target="_blank" rel="noopener noreferrer">Consistent Hash Ring&lt;/a> implementation from Cortex.
By default, the ring is gossiped between all Tempo components.
However, it can be configured to use &lt;a href="https://www.consul.io/" target="_blank" rel="noopener noreferrer">Consul&lt;/a> or &lt;a href="https://etcd.io/" target="_blank" rel="noopener noreferrer">Etcd&lt;/a>, if desired.&lt;/p></description></item><item><title>Resize ingester persistent volume operations</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/ingester_pvcs/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/ingester_pvcs/</guid><content><![CDATA[&lt;h1 id=&#34;resize-ingester-persistent-volume-operations&#34;&gt;Resize ingester persistent volume operations&lt;/h1&gt;
&lt;p&gt;Tempo ingesters make heavy use of local disks to store write-ahead logs and blocks before being flushed to the backend (GCS, S3, etc.).
It is important to monitor the free volume space as full disks can lead to data loss and other errors.
The amount of disk space available affects how much volume a Tempo ingester can process and the length of time an outage to the backend can be tolerated.&lt;/p&gt;
&lt;p&gt;Therefore it may be necessary to increase the disk space for ingesters as usage increases.&lt;/p&gt;
&lt;p&gt;We recommend using SSDs for local storage.&lt;/p&gt;
&lt;h2 id=&#34;increase-vcc-size&#34;&gt;Increase VCC size&lt;/h2&gt;
&lt;p&gt;When deployed as a StatefulSet with Persistent Volume Claims (PVC), some manual steps are required.
The following configuration has worked successfully on GKE with GCS:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Edit the persistent volume claim (pvc) for each ingester to the new size.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;kubectl patch pvc -n &amp;lt;namespace&amp;gt; -p &amp;#39;{&amp;#34;spec&amp;#34;: {&amp;#34;resources&amp;#34;: {&amp;#34;requests&amp;#34;: {&amp;#34;storage&amp;#34;: &amp;#34;&amp;#39;15Gi&amp;#39;&amp;#34;}}}}&amp;#39; &amp;lt;pod-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Check all disks have been upgraded by running:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kubectl get pvc -n &amp;lt;namespace&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;A restart is not necessary as the pods will automatically detect the increased disk space.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Delete the StatefulSet but leave the pods running:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kubectl delete sts --cascade=false -n &amp;lt;namespace&amp;gt; ingester&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edit and recreate the Statefulset with the new size. This covers new pods.  There are many ways to deploy Tempo to Kubernetes, these are examples for the popular ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Raw YAML: &lt;code&gt;kubectl apply -f &amp;lt;something&amp;gt;.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Helm: &lt;code&gt;helm upgrade ... tempo ...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tanka: &lt;code&gt;tk apply ...&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="resize-ingester-persistent-volume-operations">Resize ingester persistent volume operations&lt;/h1>
&lt;p>Tempo ingesters make heavy use of local disks to store write-ahead logs and blocks before being flushed to the backend (GCS, S3, etc.).
It is important to monitor the free volume space as full disks can lead to data loss and other errors.
The amount of disk space available affects how much volume a Tempo ingester can process and the length of time an outage to the backend can be tolerated.&lt;/p></description></item><item><title>Enable multi-tenancy</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/multitenancy/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/multitenancy/</guid><content><![CDATA[&lt;h1 id=&#34;enable-multi-tenancy&#34;&gt;Enable multi-tenancy&lt;/h1&gt;
&lt;p&gt;Tempo is a multi-tenant distributed tracing backend. It supports multi-tenancy through the use
of a header: &lt;code&gt;X-Scope-OrgID&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in setting up multi-tenancy, consult the &lt;a href=&#34;https://github.com/grafana/tempo/tree/main/example/docker-compose/otel-collector-multitenant&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;multi-tenant example&lt;/a&gt;
in the repo. This example uses the following settings to achieve multi-tenancy in Tempo.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Multi-tenancy on ingestion is currently &lt;a href=&#34;https://github.com/grafana/tempo/issues/495&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;only working&lt;/a&gt; with GPRC and this may never change. It is strongly recommended to use the OpenTelemetry Collector to support multi-tenancy.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id=&#34;configure-multi-tenancy&#34;&gt;Configure multi-tenancy&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Configure the OTEL Collector to attach the X-Scope-OrgID header on push:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;exporters:
  otlp:
    headers:
      x-scope-orgid: foo-bar-baz&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the Tempo data source in Grafana to pass the tenant with the same header:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;- name: Tempo-Multitenant
  jsonData:
    httpHeaderName1: &amp;#39;X-Scope-OrgID&amp;#39;
  secureJsonData:
    httpHeaderValue1: &amp;#39;foo-bar-baz&amp;#39;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enable multi-tenancy on Tempo backend, set the following configuration value on all Tempo components:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;multitenancy_enabled: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;or from the command line:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;--multitenancy.enabled=true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This option will force all Tempo components to require the &lt;code&gt;X-Scope-OrgID&lt;/code&gt; header.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- Commented out since 7.4 is no longer supported.
### Grafana 7.4.x

Grafana 7.4.x has the following configuration requirements:

- Configure the Tempo data source in Grafana to pass the tenant as a bearer token. This is necessary because it is the only header that Jaeger can be configured to pass to its GRPC plugin.

```
- name: Tempo-Multitenant
  jsonData:
    httpHeaderName1: &#39;Authorization&#39;
  secureJsonData:
    httpHeaderValue1: &#39;Bearer foo-bar-baz&#39;
```

- Configure Jaeger Query to pass the bearer token to its backend.

```
--query.bearer-token-propagation=true
```
--&gt;
]]></content><description>&lt;h1 id="enable-multi-tenancy">Enable multi-tenancy&lt;/h1>
&lt;p>Tempo is a multi-tenant distributed tracing backend. It supports multi-tenancy through the use
of a header: &lt;code>X-Scope-OrgID&lt;/code>.&lt;/p>
&lt;p>If you&amp;rsquo;re interested in setting up multi-tenancy, consult the &lt;a href="https://github.com/grafana/tempo/tree/main/example/docker-compose/otel-collector-multitenant" target="_blank" rel="noopener noreferrer">multi-tenant example&lt;/a>
in the repo. This example uses the following settings to achieve multi-tenancy in Tempo.&lt;/p></description></item><item><title>Improve performance with caching</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/caching/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/caching/</guid><content><![CDATA[&lt;h1 id=&#34;improve-performance-with-caching&#34;&gt;Improve performance with caching&lt;/h1&gt;
&lt;p&gt;Caching is mainly used to improve query performance by storing bloom filters of all backend blocks which are accessed on every query.&lt;/p&gt;
&lt;p&gt;Tempo uses an external cache to improve query performance.
The supported implementations are &lt;a href=&#34;https://memcached.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Memcached&lt;/a&gt; and &lt;a href=&#34;https://redis.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Redis&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;memcached&#34;&gt;Memcached&lt;/h2&gt;
&lt;p&gt;Memcached is one of the cache implementations supported by Tempo.
It is used by default in the Tanka and Helm examples, see &lt;a href=&#34;../../setup/deployment/&#34;&gt;Deploying Tempo&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;connection-limit&#34;&gt;Connection limit&lt;/h3&gt;
&lt;p&gt;As a cluster grows in size, the number of instances of Tempo connecting to the cache servers also increases.
By default, Memcached has a connection limit of 1024. If this limit is surpassed new connections are refused.
This is resolved by increasing the connection limit of Memcached.&lt;/p&gt;
&lt;p&gt;These errors can be observed using the &lt;code&gt;tempo_memcache_request_duration_seconds_count&lt;/code&gt; metric.
For example, by using the following query:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;promql&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-promql&#34;&gt;sum by (status_code) (
  rate(tempo_memcache_request_duration_seconds_count{}[$__rate_interval])
)&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This metric is also shown in &lt;a href=&#34;../monitoring/&#34;&gt;the monitoring dashboards&lt;/a&gt; (the left panel):&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;&lt;img src=&#34;../caching_memcached_connection_limit.png&#34; alt=&#34;QPS and latency of requests to memcached&#34;&gt;&lt;/p&gt;
&lt;p&gt;Note that the already open connections continue to function, just new connections are refused.&lt;/p&gt;
&lt;p&gt;Additionally, Memcached will log the following errors when it can&amp;rsquo;t accept any new requests:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;accept4(): No file descriptors available
Too many open connections
accept4(): No file descriptors available
Too many open connections&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When using the &lt;a href=&#34;https://github.com/prometheus/memcached_exporter&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;memcached_exporter&lt;/a&gt;, the number of open connections can be observed at &lt;code&gt;memcached_current_connections&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;cache-size-control&#34;&gt;Cache size control&lt;/h2&gt;
&lt;p&gt;Tempo querier accesses bloom filters of all blocks while searching for a trace. This essentially mandates the size
of cache to be at-least the total size of the bloom filters (the working set) . However, in larger deployments, the
working set might be larger than the desired size of cache. When that happens, eviction rates on the cache grow high,
and hit rate drop. Not nice!&lt;/p&gt;
&lt;p&gt;Tempo provides two config parameters in order to filter down on the items stored in cache.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;        # Min compaction level of block to qualify for caching bloom filter
        # Example: &amp;#34;cache_min_compaction_level: 2&amp;#34;
        [cache_min_compaction_level: &amp;lt;int&amp;gt;]

        # Max block age to qualify for caching bloom filter
        # Example: &amp;#34;cache_max_block_age: 48h&amp;#34;
        [cache_max_block_age: &amp;lt;duration&amp;gt;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Using a combination of these config options, we can narrow down on which bloom filters are cached, thereby reducing our
cache eviction rate, and increasing our cache hit rate. Nice!&lt;/p&gt;
&lt;p&gt;In order to decide the values of these config parameters, you can use a cache summary command in the &lt;a href=&#34;../tempo_cli/&#34;&gt;tempo-cli&lt;/a&gt; that
prints a summary of bloom filter shards per day and per compaction level. The result looks something like this:&lt;/p&gt;
&lt;p align=&#34;center&#34;&gt;&lt;img src=&#34;../cache-summary.png&#34; alt=&#34;Cache summary&#34;&gt;&lt;/p&gt;
&lt;p&gt;The above image shows the bloom filter shards over 14 days and 6 compaction levels. This can be used to decide the
above configuration parameters.&lt;/p&gt;
]]></content><description>&lt;h1 id="improve-performance-with-caching">Improve performance with caching&lt;/h1>
&lt;p>Caching is mainly used to improve query performance by storing bloom filters of all backend blocks which are accessed on every query.&lt;/p></description></item><item><title>Tempo CLI</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/tempo_cli/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/tempo_cli/</guid><content><![CDATA[&lt;h1 id=&#34;tempo-cli&#34;&gt;Tempo CLI&lt;/h1&gt;
&lt;p&gt;Tempo CLI is a separate executable that contains utility functions related to the Tempo software.
Although it is not required for a working installation, Tempo CLI can be helpful for deeper analysis or for troubleshooting.&lt;/p&gt;
&lt;h2 id=&#34;tempo-cli-command-syntax&#34;&gt;Tempo CLI command syntax&lt;/h2&gt;
&lt;p&gt;The general syntax for commands in Tempo CLI is:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli command [subcommand] [options] [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;--help&lt;/code&gt; or &lt;code&gt;-h&lt;/code&gt; displays the help for a command or subcommand.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli -h
tempo-cli command [subcommand] -h&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;run-tempo-cli&#34;&gt;Run Tempo CLI&lt;/h2&gt;
&lt;p&gt;Tempo CLI is currently available as source code. A working Go installation is required to build it. It can be compiled to a native binary and executed normally, or it can be executed using the &lt;code&gt;go run&lt;/code&gt; command.
It can be packaged as a Docker container using &lt;code&gt;make docker-tempo-cli&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;./tempo-cli [arguments...]
go run ./cmd/tempo-cli [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;make docker-tempo-cli
docker run docker.io/grafana/tempo-cli [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;backend-options&#34;&gt;Backend options&lt;/h2&gt;
&lt;p&gt;Tempo CLI connects directly to the storage backend for some commands, meaning that it requires the ability to read from S3, GCS, Azure or file-system storage.
The backend can be configured in a few ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Load an existing tempo configuration file using the &lt;code&gt;--config-file&lt;/code&gt; (&lt;code&gt;-c&lt;/code&gt;) option. This is the recommended option
for frequent usage. Refer to &lt;a href=&#34;../../configuration/&#34;&gt;Configuration&lt;/a&gt; documentation for more information.&lt;/li&gt;
&lt;li&gt;Specify individual settings:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--backend &amp;lt;value&amp;gt;&lt;/code&gt; The storage backend type, one of &lt;code&gt;s3&lt;/code&gt;, &lt;code&gt;gcs&lt;/code&gt;, &lt;code&gt;azure&lt;/code&gt;, and &lt;code&gt;local&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--bucket &amp;lt;value&amp;gt;&lt;/code&gt; The bucket name. The meaning of this value is backend-specific. Refer to &lt;a href=&#34;../../configuration/&#34;&gt;Configuration&lt;/a&gt; documentation for more information.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--s3-endpoint &amp;lt;value&amp;gt;&lt;/code&gt; The S3 API endpoint (i.e. s3.dualstack.us-east-2.amazonaws.com).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--s3-user &amp;lt;value&amp;gt;&lt;/code&gt;, &lt;code&gt;--s3-password &amp;lt;value&amp;gt;&lt;/code&gt; The S3 user name and password (or access key and secret key).
Optional, as Tempo CLI supports the same authentication mechanisms as Tempo. See &lt;a href=&#34;../../configuration/s3/&#34;&gt;S3 permissions documentation&lt;/a&gt; for more information.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each option applies only to the command in which it is used. For example, &lt;code&gt;--backend &amp;lt;value&amp;gt;&lt;/code&gt; does not permanently change where Tempo stores data. It only changes it for command in which you apply the option.&lt;/p&gt;
&lt;h2 id=&#34;query-api-command&#34;&gt;Query API command&lt;/h2&gt;
&lt;p&gt;Call the tempo API and retrieve a trace by ID.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli query api &amp;lt;api-endpoint&amp;gt; &amp;lt;trace-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;api-endpoint&lt;/code&gt; URL for tempo API.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trace-id&lt;/code&gt; Trace ID as a hexadecimal string.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--org-id &amp;lt;value&amp;gt;&lt;/code&gt; Organization ID (for use in multi-tenant setup).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli query api http://tempo:3200 f1cfe82a8eef933b&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;query-blocks-command&#34;&gt;Query blocks command&lt;/h2&gt;
&lt;p&gt;Iterate over all backend blocks and dump all data found for a given trace id.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli query blocks &amp;lt;trace-id&amp;gt; &amp;lt;tenant-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; can be intense as it downloads every bloom filter and some percentage of indexes/trace data.&lt;/p&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;trace-id&lt;/code&gt; Trace ID as a hexadecimal string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; Tenant to search.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:
See backend options above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli query blocks f1cfe82a8eef933b single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;list-blocks&#34;&gt;List blocks&lt;/h2&gt;
&lt;p&gt;Lists information about all blocks for the given tenant, and optionally perform integrity checks on indexes for duplicate records.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list blocks &amp;lt;tenant-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--include-compacted&lt;/code&gt; Include blocks that have been compacted. Default behavior is to display only active blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;
Explanation of output:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ID&lt;/code&gt; Block ID.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Lvl&lt;/code&gt; Compaction level of the block.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Objects&lt;/code&gt; Number of objects stored in the block.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Size&lt;/code&gt; Data size of the block after any compression.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Encoding&lt;/code&gt; Block encoding (compression algorithm).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Vers&lt;/code&gt; Block version.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Window&lt;/code&gt; The window of time that was considered for compaction purposes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Start&lt;/code&gt; The earliest timestamp stored in the block.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;End&lt;/code&gt; The latest timestamp stored in the block.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Duration&lt;/code&gt;Duration between the start and end time.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Age&lt;/code&gt; The age of the block.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Cmp&lt;/code&gt; Whether the block has been compacted (present when &amp;ndash;include-compacted is specified).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list blocks -c ./tempo.yaml single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;list-block&#34;&gt;List block&lt;/h2&gt;
&lt;p&gt;Lists information about a single block, and optionally, scan its contents.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list block &amp;lt;tenant-id&amp;gt; &amp;lt;block-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;block-id&lt;/code&gt; The block ID as UUID string.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--scan&lt;/code&gt; Also load the block data, perform integrity check for duplicates, and collect statistics. &lt;strong&gt;Note:&lt;/strong&gt; can be intense.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list block -c ./tempo.yaml single-tenant ca314fba-efec-4852-ba3f-8d2b0bbf69f1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;list-compaction-summary&#34;&gt;List compaction summary&lt;/h2&gt;
&lt;p&gt;Summarizes information about all blocks for the given tenant based on compaction level. This command is useful to analyze or troubleshoot compactor behavior.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list compaction-summary &amp;lt;tenant-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list compaction-summary -c ./tempo.yaml single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;list-cache-summary&#34;&gt;List cache summary&lt;/h2&gt;
&lt;p&gt;Prints information about the number of bloom filter shards per day per compaction level. This command is useful to
estimate and fine-tune cache storage. Read the &lt;a href=&#34;../caching/&#34;&gt;caching topic&lt;/a&gt; for more information.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list cache-summary &amp;lt;tenant-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list cache-summary -c ./tempo.yaml single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;list-index&#34;&gt;List index&lt;/h2&gt;
&lt;p&gt;Lists basic index info for the given block.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list index &amp;lt;tenant-id&amp;gt; &amp;lt;block-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;block-id&lt;/code&gt; The block ID as UUID string.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli list index -c ./tempo.yaml single-tenant ca314fba-efec-4852-ba3f-8d2b0bbf69f1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;view-index&#34;&gt;View index&lt;/h2&gt;
&lt;p&gt;View the index contents for the given block.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli view index &amp;lt;tenant-id&amp;gt; &amp;lt;block-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;block-id&lt;/code&gt; The block ID as UUID string.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli view index -c ./tempo.yaml single-tenant ca314fba-efec-4852-ba3f-8d2b0bbf69f1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;generate-bloom-filter&#34;&gt;Generate bloom filter&lt;/h2&gt;
&lt;p&gt;To generate the bloom filter for a block if the files were deleted/corrupted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; ensure that the block is in a local backend in the expected directory hierarchy, i.e. &lt;code&gt;path / tenant / blocks&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;block-id&lt;/code&gt; The block ID as UUID string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bloom-fp&lt;/code&gt; The false positive to be used for the bloom filter.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bloom-shard-size&lt;/code&gt; The shard size to be used for the bloom filter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli gen bloom --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant b18beca6-4d7f-4464-9f72-f343e688a4a0 0.05 100000&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The bloom filter will be generated at the required location under the block folder.&lt;/p&gt;
&lt;h2 id=&#34;generate-index&#34;&gt;Generate index&lt;/h2&gt;
&lt;p&gt;To generate the index/bloom for a block if the files were deleted/corrupted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; ensure that the block is in a local backend in the expected directory hierarchy, i.e. &lt;code&gt;path / tenant / blocks&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; The tenant ID.  Use &lt;code&gt;single-tenant&lt;/code&gt; for single tenant setups.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;block-id&lt;/code&gt; The block ID as UUID string.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli gen index --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant b18beca6-4d7f-4464-9f72-f343e688a4a0&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The index will be generated at the required location under the block folder.&lt;/p&gt;
&lt;h2 id=&#34;search-blocks-command&#34;&gt;Search blocks command&lt;/h2&gt;
&lt;p&gt;Search blocks in a given time range for a specific key/value pair.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli search blocks &amp;lt;name&amp;gt; &amp;lt;value&amp;gt; &amp;lt;start&amp;gt; &amp;lt;end&amp;gt; &amp;lt;tenant-id&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; can be intense as it downloads all relevant blocks and iterates through them.&lt;/p&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt; Name of the attribute to search for e.g. &lt;code&gt;http.post&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt; Value of the attribute to search for e.g. &lt;code&gt;GET&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start&lt;/code&gt; Start of the time range to search: (YYYY-MM-DDThh:mm:ss)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt; End of the time range to search: (YYYY-MM-DDThh:mm:ss)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tenant-id&lt;/code&gt; Tenant to search.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:
See backend options above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli search blocks http.post GET 2021-09-21T00:00:00 2021-09-21T00:05:00 single-tenant --backend=gcs --bucket=tempo-trace-data&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;parquet-convert-command&#34;&gt;Parquet convert command&lt;/h2&gt;
&lt;p&gt;Converts a parquet file from its existing schema to the one currently in the repository. This utility command is useful when
attempting to determine the impact of changing compression or encoding of columns.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli parquet convert &amp;lt;in file&amp;gt; &amp;lt;out file&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;in file&lt;/code&gt; Filename of an existing parquet file containing Tempo trace data&lt;/li&gt;
&lt;li&gt;&lt;code&gt;out file&lt;/code&gt; File to write to. (Existing file is overwritten.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli parquet convert data.parquet out.parquet&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;migrate-tenant-command&#34;&gt;Migrate tenant command&lt;/h2&gt;
&lt;p&gt;Copy blocks from one backend and tenant to another. Blocks can be copied within the same backend or between two
different backends. Data format will not be converted but tenant ID in &lt;code&gt;meta.json&lt;/code&gt; will be rewritten.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli migrate tenant &amp;lt;source tenant&amp;gt; &amp;lt;dest tenant&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;source tenant&lt;/code&gt; Tenant to copy blocks from&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dest tenant&lt;/code&gt; Tenant to copy blocks into&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--source-config-file &amp;lt;value&amp;gt;&lt;/code&gt; Configuration file for the source backend&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--config-file &amp;lt;value&amp;gt;&lt;/code&gt; Configuration file for the destination backend&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;tempo-cli migrate tenant --source-config source.yaml --config-file dest.yaml my-tenant my-other-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="tempo-cli">Tempo CLI&lt;/h1>
&lt;p>Tempo CLI is a separate executable that contains utility functions related to the Tempo software.
Although it is not required for a working installation, Tempo CLI can be helpful for deeper analysis or for troubleshooting.&lt;/p></description></item><item><title>Apache Parquet schema</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/schema/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/schema/</guid><content><![CDATA[&lt;h1 id=&#34;apache-parquet-schema&#34;&gt;Apache Parquet schema&lt;/h1&gt;
&lt;p&gt;Starting with Tempo 2.0, Apache Parquet is used as the default column-formatted block format.
Refer to the &lt;a href=&#34;../../configuration/parquet/&#34;&gt;Parquet configuration options&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;This document describes the schema used with the Parquet block format.&lt;/p&gt;
&lt;h2 id=&#34;fully-nested-versus-span-oriented-schema&#34;&gt;Fully nested versus span-oriented schema&lt;/h2&gt;
&lt;p&gt;There are two overall approaches to a columnar schema: fully nested or span-oriented.
Span-oriented means a flattened schema where traces are destructured into rows of spans.
A fully nested schema means the current trace structures such as Resource/Scope/Spans/Events are preserved (nested data is natively supported in Parquet).
In both cases, individual leaf values such as span name and duration are individual columns.&lt;/p&gt;
&lt;p&gt;We chose the nested schema for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The block size is much smaller for the nested schema. This is due to the high data duplication incurred when flattening resource-level attributes such as &lt;code&gt;service.name&lt;/code&gt; to each individual span.&lt;/li&gt;
&lt;li&gt;A flat schema is not truly &amp;ldquo;flat&amp;rdquo; because each span still contains nested data such as attributes and events.&lt;/li&gt;
&lt;li&gt;Nested schema is much faster to search for resource-level attributes because the resource-level columns are very small (1 row for each batch).&lt;/li&gt;
&lt;li&gt;Translation to and from the OpenTelemetry Protocol Specification (OTLP) is straightforward.&lt;/li&gt;
&lt;li&gt;Easily add computed columns (for example, trace duration) at multiple levels such as per-trace, per-batch, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;static-vs-dynamic-columns&#34;&gt;Static vs dynamic columns&lt;/h2&gt;
&lt;p&gt;Dynamic vs static columns add another layer to the schema.
A dynamic schema stores each attribute such as &lt;code&gt;service.name&lt;/code&gt; and &lt;code&gt;http.status_code&lt;/code&gt; as its own column and the columns in each parquet file can be different.
A static schema is unresponsive to the shape of the data, and all attributes are stored in generic key/value containers.&lt;/p&gt;
&lt;p&gt;The dynamic schema is the ultimate dream for a columnar format but it is too complex for a first release.
However, the benefits of that approach are also too good to pass up, so we propose a hybrid approach.
It is primarily a static schema but with some dynamic columns extracted from trace data based on some heuristics of frequently queried attributes.
We plan to continue investing in this direction to implement a fully dynamic schema where trace attributes are blown out into independent Parquet columns at runtime.&lt;/p&gt;
&lt;p&gt;For more information, refer to the &lt;a href=&#34;https://github.com/grafana/tempo/blob/main/docs/design-proposals/2022-04%20Parquet.md&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Parquet design document&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;schema-details&#34;&gt;Schema details&lt;/h2&gt;
&lt;p&gt;The adopted Parquet schema is mostly a direct translation of OTLP but with some key differences.&lt;/p&gt;
&lt;p&gt;The table below uses these abbreviations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rs&lt;/code&gt; - resource spans&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ss&lt;/code&gt; - scope spans&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;&lt;/th&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;&lt;/th&gt;
              &lt;th style=&#34;text-align: left&#34;&gt;&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Name&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Type&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Description&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;TraceID&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The trace ID in 16-byte binary form.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;TraceIDText&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The trace ID in hexadecimal text form.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;StartTimeUnixNano&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int64&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Start time of the first span in the trace, in nanoseconds since unix epoch.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;EndTimeUnixNano&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int64&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;End time of the last span in the trace, in nanoseconds since unix epoch.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;DurationNano&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int64&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Total trace duration in nanoseconds, computed as difference between EndTimeUnixNano and StartTimeUnixNano.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;RootServiceName&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The resource-level &lt;code&gt;service.name&lt;/code&gt; attribute (rs.Resource.ServiceName) from the root span of the trace if one exists, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;RootSpanName&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The name (rs.ss.Spans.Name) of the root span if one exists, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Short-hand for ResourceSpans&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.ServiceName&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;service.name&lt;/code&gt; attribute if present. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/#service&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/#service&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Cluster&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;cluster&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Namespace&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;namespace&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Pod&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;pod&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Container&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;container&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.K8sClusterName&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;k8s.cluster.name&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#cluster&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#cluster&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.K8sNamespaceName&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;k8s.namespace.name&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#namespace&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#namespace&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.K8sPodName&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;k8s.pod.name&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#pod&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#pod&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.K8sContainerName&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the resource-level &lt;code&gt;k8s.container.name&lt;/code&gt; attribute if present and of string type. Values of other types will be stored in the generic attribute columns. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#container&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/k8s/#container&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.Key&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;All resource attributes that do not have a dedicated column are stored as a key value pair in these columns. The Key column stores the name, and then one of the Value columns is populated according to the attribute&amp;rsquo;s data type. The other value columns will contain null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.Value&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if string type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.ValueInt&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if integer type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.ValueDouble&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;float&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if float type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.ValueBool&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;bool&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if boolean type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.ValueArray&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if nested array type, else null. Protocol buffer encoded binary data.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.ValueKVList&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if nested key/value map type, else null. Protocol buffer encoded binary data.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Shorthand for ResourceSpans.ScopeSpans&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Scope&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Shorthand for ResourceSpans.ScopeSpans.Scope&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Scope.Name&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Scope name if present, else empty string. &lt;a href=&#34;https://opentelemetry.io/docs/specs/otel/glossary/#instrumentation-scope&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/specs/otel/glossary/#instrumentation-scope&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Scope.Version&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The Scope version if present, else empty string. &lt;a href=&#34;https://opentelemetry.io/docs/specs/otel/glossary/#instrumentation-scope&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/specs/otel/glossary/#instrumentation-scope&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.SpanID&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Span unique ID.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.ParentSpanID&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The unique ID of the span&amp;rsquo;s parent. For root spans without a parent this is null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.ParentID&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int32&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Trace local numeric parent ID.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.NestedSetLeft&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int32&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Left bound of the nested set model. Also used as a trace local numeric span ID.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.NestedSetRight&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int32&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Right bound of the nested set model.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Name&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Span name.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.StartTimeUnixNano&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int64&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Start time the span in nanoseconds since unix epoch.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.DurationNano&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int64&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Span duration in nanoseconds.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Kind&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The span&amp;rsquo;s kind. Defined values: 0. Unset; 1. Internal; 2. Server; 3. Client; 4. Producer; 5. Consumer; &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/trace/api/#spankind&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/trace/api/#spankind&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.StatusCode&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The span status. Defined values: 0: Unset; 1: OK; 2: Error. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/trace/api/#set-status&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/trace/api/#set-status&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.StatusMessage&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Optional message to accompany Error status.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.HttpMethod&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the span-level &lt;code&gt;http.method&lt;/code&gt; attribute if present and of string type, else null. Values of other types will be stored in the generic attribute columns. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#common-attributes&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#common-attributes&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.HttpStatusCode&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the span-level &lt;code&gt;http.status_code&lt;/code&gt; attribute if present and of integer type, else null. Values of other types will be stored in the generic attribute columns. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#common-attributes&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#common-attributes&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.HttpUrl&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;A dedicated column for the span-level &lt;code&gt;http.url&lt;/code&gt; attribute if present and of string type, else null. Values of other types will be stored in the generic attribute columns. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#http-client&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#http-client&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.DroppedAttributesCount&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Number of attributes that were dropped&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Attrs.Key&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;All span attributes that do not have a dedicated column are stored as a key value pair in these columns. The Key column stores the name, and then one of the Value columns is populated according to the attribute&amp;rsquo;s data type. The other value columns will contain null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Attrs.Value&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if string type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Attrs.ValueInt&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if integer type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Attrs.ValueDouble&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;float&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if float type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Attrs.ValueBool&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;bool&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if boolean type, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Attrs.ValueArray&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if nested array type, else null. Protocol buffer encoded binary data.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Attrs.ValueKVList&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value if nested key/value map type, else null. Protocol buffer encoded binary data.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.DroppedEventsCount&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The number of events that were dropped&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Events.TimeUnixNano&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int64&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The timestamp of the event, as nanoseconds since unix epoch.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Events.Name&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The event name or message.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Events.DroppedAttributesCount&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The number of event attributes that were dropped.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Events.Attrs.Key&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;All event attributes are stored as a key value pair in these columns. The Key column stores the name.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Events.Attrs.Value&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The attribute value, Protocol buffer encoded binary data.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.DroppedLinksCount&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;int&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The number of links that were dropped.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.Links&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;byte array&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Protocol-buffer encoded span links if present, else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.TraceState&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;string&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;The span&amp;rsquo;s TraceState value if present, else empty string.https://opentelemetry.io/docs/reference/specification/trace/api/#tracestate&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;To increase the readability table omits the groups &lt;code&gt;list.element&lt;/code&gt; that are added for nested list types in Parquet.&lt;/p&gt;
&lt;h3 id=&#34;block-schema-display-in-parquet-message-format&#34;&gt;Block Schema display in Parquet Message format&lt;/h3&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;message Trace {
  required binary TraceID;
  required group rs (LIST) {
    repeated group list {
      required group element {
        required group Resource {
          required group Attrs (LIST) {
            repeated group list {
              required group element {
                required binary Key (STRING);
                optional binary Value (STRING);
                optional int64 ValueInt (INTEGER(64,true));
                optional double ValueDouble;
                optional boolean ValueBool;
                optional binary ValueKVList (STRING);
                optional binary ValueArray (STRING);
              }
            }
          }
          required binary ServiceName (STRING);
          optional binary Cluster (STRING);
          optional binary Namespace (STRING);
          optional binary Pod (STRING);
          optional binary Container (STRING);
          optional binary K8sClusterName (STRING);
          optional binary K8sNamespaceName (STRING);
          optional binary K8sPodName (STRING);
          optional binary K8sContainerName (STRING);
          optional binary Test (STRING);
        }
        required group ss (LIST) {
          repeated group list {
            required group element {
              required group Scope {
                required binary Name (STRING);
                required binary Version (STRING);
              }
              required group Spans (LIST) {
                repeated group list {
                  required group element {
                    required binary SpanID;
                    required binary ParentSpanID;
                    required int32 ParentID (INTEGER(32,true));
                    required int32 NestedSetLeft (INTEGER(32,true));
                    required int32 NestedSetRight (INTEGER(32,true));
                    required binary Name (STRING);
                    required int64 Kind (INTEGER(64,true));
                    required binary TraceState (STRING);
                    required int64 StartTimeUnixNano (INTEGER(64,false));
                    required int64 DurationNano (INTEGER(64,false));
                    required int64 StatusCode (INTEGER(64,true));
                    required binary StatusMessage (STRING);
                    required group Attrs (LIST) {
                      repeated group list {
                        required group element {
                          required binary Key (STRING);
                          optional binary Value (STRING);
                          optional int64 ValueInt (INTEGER(64,true));
                          optional double ValueDouble;
                          optional boolean ValueBool;
                          optional binary ValueKVList (STRING);
                          optional binary ValueArray (STRING);
                        }
                      }
                    }
                    required int32 DroppedAttributesCount (INTEGER(32,true));
                    required group Events (LIST) {
                      repeated group list {
                        required group element {
                          required int64 TimeUnixNano (INTEGER(64,false));
                          required binary Name (STRING);
                          required group Attrs (LIST) {
                            repeated group list {
                              required group element {
                                required binary Key (STRING);
                                required binary Value;
                              }
                            }
                          }
                          required int32 DroppedAttributesCount (INTEGER(32,true));
                          optional binary Test (STRING);
                        }
                      }
                    }
                    required int32 DroppedEventsCount (INTEGER(32,true));
                    required binary Links;
                    required int32 DroppedLinksCount (INTEGER(32,true));
                    optional binary HttpMethod (STRING);
                    optional binary HttpUrl (STRING);
                    optional int64 HttpStatusCode (INTEGER(64,true));
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  required binary TraceIDText (STRING);
  required int64 StartTimeUnixNano (INTEGER(64,false));
  required int64 EndTimeUnixNano (INTEGER(64,false));
  required int64 DurationNano (INTEGER(64,false));
  required binary RootServiceName (STRING);
  required binary RootSpanName (STRING);
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;trace-level-attributes&#34;&gt;Trace-level attributes&lt;/h2&gt;
&lt;p&gt;For speed and ease-of-use, we are projecting several values to columns at the trace-level:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Trace ID - Don&amp;rsquo;t store on each span.&lt;/li&gt;
&lt;li&gt;Root service/span names/StartTimeUnixNano - These are selected properties of the root span in each trace (if there is one). These are used for displaying results in the Grafana UI. These properties are computed at ingest time and stored once for efficiency, so we don&amp;rsquo;t have to find the root span.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DurationNanos&lt;/code&gt; - The total trace duration, computed at ingest time. This powers the min/max duration filtering in the current Tempo search and is more efficient than scanning the spans duration column. However, it may go away with TraceQL or we could decide to change it to span-level duration filtering too.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;dedicated-columns&#34;&gt;Dedicated columns&lt;/h2&gt;
&lt;p&gt;Projecting attributes to their own columns has benefits for speed and size.
Therefore we are taking an opinionated approach and projecting some common attributes to their own columns.
All other attributes are stored in the generic key/value maps and are still searchable, but not as quickly.
We chose these attributes based on what we commonly use ourselves (scratching our own itch), but we think they will be useful to most workloads.&lt;/p&gt;
&lt;p&gt;Resource-level attributes include the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;service.name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cluster&lt;/code&gt; and &lt;code&gt;k8s.cluster.name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;namespace&lt;/code&gt; and &lt;code&gt;k8s.namespace.name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pod&lt;/code&gt; and &lt;code&gt;k8s.pod.name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;container&lt;/code&gt; and &lt;code&gt;k8s.container.name&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Span-level attributes include the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http.method&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http.url&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http.status_code&lt;/code&gt; (int)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;any-type-attributes&#34;&gt;&amp;ldquo;Any&amp;rdquo;-type Attributes&lt;/h2&gt;
&lt;p&gt;OTLP attributes have variable data types, which is easy to accomplish in formats like protocol-buffers, but does not translate directly to Parquet.
Each column must have a concrete type.
There are several possibilities here but we chose to have optional values for each concrete type.
&lt;code&gt;Array&lt;/code&gt; and &lt;code&gt;KeyValueList&lt;/code&gt; types are stored as protocol-buffer-encoded byte arrays.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;repeated group Attrs {
    required binary  Key (STRING);

    # Only one of these will be set
    optional binary  Value (STRING);
    optional boolean ValueBool;
    optional double  ValueDouble;
    optional int64   ValueInt (INT(64,true));
    optional binary  ValueArray (STRING);
    optional binary  ValueKVList (STRING);
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;event-attributes&#34;&gt;Event attributes&lt;/h2&gt;
&lt;p&gt;Event attributes are stored as protocol-buffer encoded.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;YAML&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-yaml&#34;&gt;repeated group Attrs {
    required binary Key (STRING);
    required binary Value (STRING);
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;compression-and-encoding&#34;&gt;Compression and encoding&lt;/h2&gt;
&lt;p&gt;Parquet has robust support for many compression algorithms and data encodings. We have found excellent combinations of storage size and performance with the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Snappy Compression - Enable on all columns&lt;/li&gt;
&lt;li&gt;Dictionary encoding - Enable on all string columns (including byte array ParentSpanID). Most strings are very repetitive so this works well to optimize storage size. However we can greatly speed up search by inspecting the dictionary first and eliminating pages with no matches.&lt;/li&gt;
&lt;li&gt;Time and duration unix nanos - Delta encoding&lt;/li&gt;
&lt;li&gt;Rarely used columns such as &lt;code&gt;DroppedAttributesCount&lt;/code&gt; - These columns are usually all zeroes, RLE works well.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;bloom-filters&#34;&gt;Bloom filters&lt;/h3&gt;
&lt;p&gt;Parquet has native support for bloom filters. However, Tempo does not use them at this time. Tempo already has sophisticated support for sharding and caching bloom filters.&lt;/p&gt;
]]></content><description>&lt;h1 id="apache-parquet-schema">Apache Parquet schema&lt;/h1>
&lt;p>Starting with Tempo 2.0, Apache Parquet is used as the default column-formatted block format.
Refer to the &lt;a href="../../configuration/parquet/">Parquet configuration options&lt;/a> for more information.&lt;/p></description></item><item><title>Tune search performance</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/backend_search/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/backend_search/</guid><content><![CDATA[&lt;h1 id=&#34;tune-search-performance&#34;&gt;Tune search performance&lt;/h1&gt;
&lt;p&gt;Regardless of whether or not you are using TraceQL or the original search API, Tempo will search all of the blocks
in the specified time range.
Depending on your volume, this may result in slow queries.
This document contains suggestions for tuning your backend to improve performance.&lt;/p&gt;
&lt;p&gt;General advice is to scale your compactors and queriers. Additional queriers can more effectively run jobs in parallel
while additional compactors will more aggressively reduce the length of your blocklist and copies of data (if using RF=3).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; All forms of search (TraceQL and tags based) are only supported on the &lt;code&gt;vParquet&lt;/code&gt; and forward blocks. &lt;a href=&#34;../../configuration/parquet/#choose-a-different-block-format&#34;&gt;v2 blocks&lt;/a&gt;
can only be used for trace by id lookup.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id=&#34;general-guidelines&#34;&gt;General guidelines&lt;/h2&gt;
&lt;p&gt;Tuning the search pipeline can be difficult as it requires balancing a number of different configuration parameters. The below tips
can you get your head around the general problem, but the specifics require experimentation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Review the query-frontend logs for lines like the following to get a feeling for how many jobs your queries are creating:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;level=info ts=2023-07-19T19:38:01.354220385Z caller=searchsharding.go:236 msg=&amp;#34;sharded search query request stats and SearchMetrics&amp;#34; ...&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For a single TraceQL query the maximum number of parallel jobs is constrained by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;query_frontend.search.concurrent_jobs&lt;/code&gt;: This is the maximum number of jobs the frontend will dispatch for one TraceQL query.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# queriers * querier.max_concurrent_queries * query_frontend.max_batch_size&lt;/code&gt;: This is the maximum job capacity of your Tempo cluster.
If a given TraceQL query produces less jobs then these two values it should be executed entirely in parallel on the queriers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Increasing &lt;code&gt;querier.max_concurrent_queries&lt;/code&gt; is a great way to get more out of your queriers. However, if queriers are OOMing or saturating other
resources then this should be lowered. Lowering &lt;code&gt;query_frontend.max_batch_size&lt;/code&gt; will also reduce the total work attempted by one querier.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;Queriers and query frontends have additional configuration related
to search of the backend datastore.&lt;/p&gt;
&lt;h3 id=&#34;querier&#34;&gt;Querier&lt;/h3&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;querier:
  # Control the amount of work each querier will attempt. The total number of
  # jobs a querier will attempt this is this value * query_frontend.max_batch_size
  max_concurrent_queries: 20&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With serverless technologies:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Serverless can be a nice way to reduce cost by using it as spare query capacity. However, serverless tends to have higher variance then simply allowing the queriers to perform the searches themselves.&lt;/p&gt;&lt;/blockquote&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;querier:

  search:
    # A list of endpoints to query. Load will be spread evenly across
    # these multiple serverless functions.
    external_endpoints:
    - https://&amp;lt;serverless endpoint&amp;gt;

    # If set to a non-zero value a second request will be issued at the provided duration. Recommended to
    # be set to p99 of search requests to reduce long tail latency.
    external_hedge_requests_at: 8s

    # The maximum number of requests to execute when hedging. Requires hedge_requests_at to be set.
    external_hedge_requests_up_to: 2&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;query-frontend&#34;&gt;Query frontend&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;../../configuration/#query-frontend&#34;&gt;Query frontend&lt;/a&gt; lists all configuration
options.&lt;/p&gt;
&lt;p&gt;These suggestions will help deal with scaling issues.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;server:
  # At larger scales, searching starts to feel more like a batch job.
  # Increase the server timeout intervals.
  http_server_read_timeout: 2m
  http_server_write_timeout: 2m

query_frontend:
  # When increasing concurrent_jobs, also increase the queue size per tenant,
  # or search requests will be cause 429 errors. This is the total number of jobs
  # per tenant allowed in the queue.
  max_outstanding_per_tenant: 2000

  # The number of jobs the query-frontend will batch together when passing jobs to the queriers. This value
  # This value * querier.max_concurrent_queries is your the max number of jobs a given querier will try at once.
  max_batch_size: 3

  search:
    # At larger scales, increase the number of jobs attempted simultaneously,
    # per search query.
    concurrent_jobs: 2000

    # The query frontend will attempt to divide jobs up by an estimate of job size. The smallest possible
    # job size is a single parquet row group. Increasing this value will create fewer, larger jobs. Decreasing
    # it will create more, smaller jobs.
    target_bytes_per_job: 50_000_000&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;serverless-environment&#34;&gt;Serverless environment&lt;/h2&gt;
&lt;p&gt;Serverless is not required, but with larger loads, serverless can be used to reduce costs.
Tempo has support for Google Cloud Run and AWS Lambda. In both cases, you will use the following
settings to configure Tempo to use a serverless environment:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;querier:
  search:
    # A list of external endpoints that the querier will use to offload backend search requests. They must
    # take and return the same value as /api/search endpoint on the querier. This is intended to be
    # used with serverless technologies for massive parallelization of the search path.
    # The default value of &amp;#34;&amp;#34; disables this feature.
    [external_endpoints: &amp;lt;list of strings&amp;gt; | default = &amp;lt;empty list&amp;gt;]

    # If external_endpoints is set then the querier will primarily act as a proxy for whatever serverless backend
    # you have configured. This setting allows the operator to have the querier prefer itself for a configurable
    # number of subqueries. In the default case of 2 the querier will process up to 2 search requests subqueries before starting
    # to reach out to external_endpoints.
    # Setting this to 0 will disable this feature and the querier will proxy all search subqueries to external_endpoints.
    [prefer_self: &amp;lt;int&amp;gt; | default = 2 ]

    # If set to a non-zero value a second request will be issued at the provided duration. Recommended to
    # be set to p99 of external search requests to reduce long tail latency.
    # (default: 4s)
    [external_hedge_requests_at: &amp;lt;duration&amp;gt;]

    # The maximum number of requests to execute when hedging. Requires hedge_requests_at to be set.
    # (default: 3)
    [external_hedge_requests_up_to: &amp;lt;int&amp;gt;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;See here for cloud-specific details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../serverless_aws/&#34;&gt;AWS Lambda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../serverless_gcp/&#34;&gt;Google Cloud Run&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;caching&#34;&gt;Caching&lt;/h2&gt;
&lt;p&gt;If you have set up an external cache (redis or memcached) in in your storage block you can also use it to cache
parquet footers using the following configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;storage:
  trace:
    search:
      cache_control:
        footer: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="tune-search-performance">Tune search performance&lt;/h1>
&lt;p>Regardless of whether or not you are using TraceQL or the original search API, Tempo will search all of the blocks
in the specified time range.
Depending on your volume, this may result in slow queries.
This document contains suggestions for tuning your backend to improve performance.&lt;/p></description></item><item><title>Search with Google Cloud Run</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/serverless_gcp/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/serverless_gcp/</guid><content><![CDATA[&lt;h1 id=&#34;search-with-google-cloud-run&#34;&gt;Search with Google Cloud Run&lt;/h1&gt;
&lt;p&gt;This document walks you through setting up a Google Cloud Run for serverless backend search.
For more guidance on configuration options for full backend search &lt;a href=&#34;../backend_search/&#34;&gt;check here&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Build the docker image:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;cd ./cmd/tempo-serverless &amp;amp;&amp;amp; make build-docker-gcr&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will create the Docker container image to be deployed to Google Cloud Run.
The docker image will be named: &lt;code&gt;tempo-serverless:latest&lt;/code&gt; and &lt;code&gt;tempo-serverless:&amp;lt;branch&amp;gt;-&amp;lt;commit hash&amp;gt;&lt;/code&gt;.
Here is an example of that name:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;$ docker images | grep tempo-serverless
tempo-serverless                                                           cloud-run-3be4efa               146c9d9fa63c   58 seconds ago   47.9MB
tempo-serverless                                                           latest                          146c9d9fa63c   58 seconds ago   47.9MB&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Push the image to a Google Container Registry repo.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provision the Google Cloud Run service. This example uses Terraform. Configuration values
should be adjusted to meet the needs of your installation.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;locals {
  // this can be increased if you would like to use multiple functions
  count = 1
}

resource &amp;#34;google_cloud_run_service&amp;#34; &amp;#34;run&amp;#34; {
  count = local.count

  name     = &amp;#34;&amp;lt;service name&amp;gt;&amp;#34;
  location = &amp;#34;&amp;lt;appropriate region&amp;gt;&amp;#34;

  metadata {
    annotations = {
        &amp;#34;run.googleapis.com/ingress&amp;#34;      = &amp;#34;internal&amp;#34;,     # this annotation can be used to limit connectivity to the service
    }
  }

  template {
    metadata {
      annotations = {
          &amp;#34;autoscaling.knative.dev/minScale&amp;#34;                   = &amp;#34;1&amp;#34;,
          &amp;#34;autoscaling.knative.dev/maxScale&amp;#34;                   = &amp;#34;1000&amp;#34;,
          &amp;#34;autoscaling.knative.dev/panic-threshold-percentage&amp;#34; = &amp;#34;110.0&amp;#34;,  # default 200.0. how aggressively to go into panic mode and start scaling heavily
          &amp;#34;autoscaling.knative.dev/window&amp;#34;                     = &amp;#34;10s&amp;#34;,    # default 60s. window over which to average metrics to make scaling decisions
      }
    }
    spec {
      container_concurrency = 4
      containers {
        image = &amp;#34;&amp;lt;container image created above&amp;gt;&amp;#34;
        resources {
          limits = {
              cpu = &amp;#34;2&amp;#34;
              memory = &amp;#34;1Gi&amp;#34;
          }
        }
        env {
          name = &amp;#34;TEMPO_GCS_BUCKET_NAME&amp;#34;
          value = &amp;#34;&amp;lt;gcs bucket where tempo data is stored&amp;gt;&amp;#34;
        }
        env {
          name = &amp;#34;TEMPO_BACKEND&amp;#34;
          value = &amp;#34;gcs&amp;#34;
        }
        env {
          name = &amp;#34;TEMPO_GCS_HEDGE_REQUESTS_AT&amp;#34;
          value = &amp;#34;400ms&amp;#34;
        }
        env {
          name = &amp;#34;TEMPO_GCS_HEDGE_REQUESTS_UP_TO&amp;#34;
          value = &amp;#34;2&amp;#34;
        }
        env {
          name = &amp;#34;GOGC&amp;#34;
          value = &amp;#34;400&amp;#34;
        }
      }
    }
  }

  traffic {
    percent         = 100
    latest_revision = true
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the newly-created cloud run service as external endpoints in your querier
configuration. The endpoint can be retrieved from the &lt;strong&gt;Details&lt;/strong&gt; tab in Google Cloud Run:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;querier:
  search:
    external_endpoints:
    - &amp;lt;trigger url from console&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="search-with-google-cloud-run">Search with Google Cloud Run&lt;/h1>
&lt;p>This document walks you through setting up a Google Cloud Run for serverless backend search.
For more guidance on configuration options for full backend search &lt;a href="../backend_search/">check here&lt;/a>.&lt;/p></description></item><item><title>Search with AWS Lambda</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/serverless_aws/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/serverless_aws/</guid><content><![CDATA[&lt;h1 id=&#34;search-with-aws-lambda&#34;&gt;Search with AWS Lambda&lt;/h1&gt;
&lt;p&gt;This document explains how to set up AWS Lambda for serverless backend search.
Read &lt;a href=&#34;../backend_search/&#34;&gt;improve search performance&lt;/a&gt; for more guidance on configuration options for backend search.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Build the code package:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;cd ./cmd/tempo-serverless &amp;amp;&amp;amp; make build-lambda-zip&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will create a ZIP file containing the binary required for
the function. The file name will be of the form: &lt;code&gt;./lambda/tempo-&amp;lt;branch name&amp;gt;-&amp;lt;commit hash&amp;gt;.zip&lt;/code&gt;.
Here is an example of that name:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;ls lambda/*.zip
lambda/tempo-serverless-backend-search-297172a.zip&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provision an S3 bucket.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the ZIP file into your bucket.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;aws s3 cp lambda/tempo-serverless-backend-search-297172a.zip gs://&amp;lt;newly provisioned gcs bucket&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Provision the Lambda. For a Lambda function to be invoked via HTTP, we also need to create an
ALB and some other resources. This example uses Terraform and only includes the function definition.
Additionally, you will need a VPC, security groups, IAM roles, an ALB, target groups, etc., but that is
beyond the scope of this guide.&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;locals {
  // this can be increased if you would like to use multiple functions
  count = 1
}

resource &amp;#34;aws_lambda_function&amp;#34; &amp;#34;lambda&amp;#34; {
    count = local.count

    function_name    = &amp;#34;${local.name}-${count.index}&amp;#34;
    description      = &amp;#34;${local.name}-${count.index}&amp;#34;
    role             = &amp;lt;arn of appropriate role&amp;gt;
    handler          = &amp;#34;main&amp;#34;
    runtime          = &amp;#34;go1.x&amp;#34;
    timeout          = &amp;#34;60&amp;#34;
    s3_key           = &amp;#34;tempo-serverless-backend-search-297172a.zip&amp;#34;
    s3_bucket        = &amp;lt;S3 bucket created above&amp;gt;
    memory_size      = 1769 # 1 vcpu

    vpc_config {
        subnet_ids         = &amp;lt;appropriate subnets&amp;gt;
        security_group_ids = [&amp;lt;appropriate security groups&amp;gt;]
    }

    environment {
        variables = {
        &amp;#34;TEMPO_S3_BUCKET&amp;#34;               = &amp;#34;&amp;lt;S3 bucket name backing your Tempo instance&amp;gt;&amp;#34;
        &amp;#34;TEMPO_BACKEND&amp;#34;                 = &amp;#34;s3&amp;#34;
        &amp;#34;TEMPO_S3_HEDGE_REQUESTS_AT&amp;#34;    = &amp;#34;400ms&amp;#34;
        &amp;#34;TEMPO_S3_HEDGE_REQUESTS_UP_TO&amp;#34; = &amp;#34;2&amp;#34;
        &amp;#34;TEMPO_S3_ENDPOINT&amp;#34;             = &amp;#34;s3.dualstack.us-east-2.amazonaws.com&amp;#34;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the hostname of the newly-created ALB to the querier config:&lt;/p&gt;

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;querier:
  search:
    external_endpoints:
    - http://&amp;lt;alb dns hostname&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="search-with-aws-lambda">Search with AWS Lambda&lt;/h1>
&lt;p>This document explains how to set up AWS Lambda for serverless backend search.
Read &lt;a href="../backend_search/">improve search performance&lt;/a> for more guidance on configuration options for backend search.&lt;/p></description></item><item><title>Generic forwarding</title><link>https://grafana.com/docs/tempo/v2.2.x/operations/generic_forwarding/</link><pubDate>Fri, 03 Apr 2026 12:35:46 -0500</pubDate><guid>https://grafana.com/docs/tempo/v2.2.x/operations/generic_forwarding/</guid><content><![CDATA[&lt;h1 id=&#34;generic-forwarding&#34;&gt;Generic forwarding&lt;/h1&gt;
&lt;p&gt;Generic forwarding allows asynchronous replication of ingested traces.
The distributor writes received spans to both the ingester and defined endpoints, if enabled.
This feature works in a &amp;ldquo;best-effort&amp;rdquo; manner, meaning that no retries happen if an error occurs during replication.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Generic forwarding does not work retroactively. Once enabled, the distributor only replicates freshly ingested spans.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id=&#34;configure-generic-forwarding&#34;&gt;Configure generic forwarding&lt;/h2&gt;
&lt;p&gt;Enabling generic forwarding requires the configuration of the &lt;code&gt;distributor&lt;/code&gt; and &lt;code&gt;overrides&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, define a list of forwarders in the &lt;code&gt;distributor&lt;/code&gt; section. Each forwarder must specify a unique &lt;code&gt;name&lt;/code&gt;, supported &lt;code&gt;backend&lt;/code&gt;, and backend-specific configuration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Second, reference these forwarders in the &lt;code&gt;overrides&lt;/code&gt; section. This allows for fine-grained control over forwarding and makes it possible to enable this feature globally or on a per-tenant basis.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For a detailed view of all the config options for the generic forwarding feature, please refer to &lt;a href=&#34;../../configuration/#distributor&#34;&gt;distributor&lt;/a&gt; and &lt;a href=&#34;../../configuration/#overrides&#34;&gt;overrides&lt;/a&gt; configuration pages.&lt;/p&gt;
]]></content><description>&lt;h1 id="generic-forwarding">Generic forwarding&lt;/h1>
&lt;p>Generic forwarding allows asynchronous replication of ingested traces.
The distributor writes received spans to both the ingester and defined endpoints, if enabled.
This feature works in a &amp;ldquo;best-effort&amp;rdquo; manner, meaning that no retries happen if an error occurs during replication.&lt;/p></description></item></channel></rss>