<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/v3.0.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/v3.0.x/operations/index.xml" rel="self" type="application/rss+xml"/><item><title>Compaction</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/compaction/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/compaction/</guid><content><![CDATA[&lt;h1 id=&#34;compaction&#34;&gt;Compaction&lt;/h1&gt;
&lt;p&gt;Tempo stores trace data as immutable blocks in object storage.
Over time, many small blocks accumulate from frequent flushes.
Compaction merges groups of small blocks into fewer, larger blocks, reducing storage costs and improving query performance by limiting the number of blocks a querier must scan.&lt;/p&gt;
&lt;h2 id=&#34;block-states&#34;&gt;Block states&lt;/h2&gt;
&lt;p&gt;Every block has one of two states, signaled by which metadata file is present in the backend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Live&lt;/strong&gt; (&lt;code&gt;meta.json&lt;/code&gt;): the block is queryable and included in query plans.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compacted&lt;/strong&gt; (&lt;code&gt;meta.compacted.json&lt;/code&gt;): the block&amp;rsquo;s data has been merged into a new block. The file is renamed from &lt;code&gt;meta.json&lt;/code&gt; to &lt;code&gt;meta.compacted.json&lt;/code&gt; at the time of compaction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Blocks are never deleted immediately after compaction.
Because the blocklist is polled periodically, queriers may not yet know about the new merged block when the old blocks are first marked compacted.
The &lt;code&gt;compacted_block_retention&lt;/code&gt; window keeps the old blocks readable until all pollers have caught up.&lt;/p&gt;
&lt;h2 id=&#34;blocklist-and-poller&#34;&gt;Blocklist and poller&lt;/h2&gt;
&lt;p&gt;Tempo components rely on an in-memory blocklist to know which blocks exist in object storage.
They do not scan object storage directly on each request.
The blocklist is maintained by the poller, a background process that reads the backend on a fixed interval controlled by &lt;code&gt;blocklist_poll&lt;/code&gt; (default 5 minutes).
The poller is how compaction results become visible to queriers and other components: newly merged blocks appear in the blocklist and compacted blocks are removed.
A component can only serve data from blocks the poller has discovered. If the poller falls behind or fails, the component&amp;rsquo;s view of the backend becomes incomplete.&lt;/p&gt;
&lt;p&gt;The poller reads a pre-built tenant index from the backend rather than scanning all objects on each cycle.
If the tenant index is missing or older than &lt;code&gt;blocklist_poll_stale_tenant_index&lt;/code&gt;, the component falls back to scanning the backend directly.
Setting &lt;code&gt;blocklist_poll_fallback: true&lt;/code&gt; (the default) enables this fallback; disabling it means a stale or missing index causes the poll to fail rather than recover.&lt;/p&gt;
&lt;p&gt;Because the poller runs on an interval, the blocklist is always slightly out of date.
In a healthy system, the blocklist will be stale by at most twice the configured &lt;code&gt;blocklist_poll&lt;/code&gt; duration.
This is because a writer may update the backend at any point within a polling cycle, and the reader may have just started its own cycle at that same moment.&lt;/p&gt;
&lt;h2 id=&#34;timing-requirements&#34;&gt;Timing requirements&lt;/h2&gt;
&lt;p&gt;The 2x staleness bound drives two concrete configuration requirements.&lt;/p&gt;
&lt;h3 id=&#34;query_backend_after-must-be-at-least-2x-blocklist_poll&#34;&gt;query_backend_after must be at least 2x blocklist_poll&lt;/h3&gt;
&lt;p&gt;The query-frontend uses &lt;code&gt;query_backend_after&lt;/code&gt; to decide where to search:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Traces more recent than &lt;code&gt;query_backend_after&lt;/code&gt; are served from live-stores only.&lt;/li&gt;
&lt;li&gt;Traces older than &lt;code&gt;query_backend_after&lt;/code&gt; are served from the backend.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A newly flushed block will not appear in the querier&amp;rsquo;s blocklist until up to &lt;code&gt;2 * blocklist_poll&lt;/code&gt; after it was written.
During that window, the block would be missed if the query-frontend routed the request to the backend.
Setting &lt;code&gt;query_backend_after&lt;/code&gt; to at least &lt;code&gt;2 * blocklist_poll&lt;/code&gt; ensures that such blocks are still covered by live-stores and are not yet expected to appear in the backend.&lt;/p&gt;
&lt;p&gt;With the default &lt;code&gt;blocklist_poll&lt;/code&gt; of 5 minutes, &lt;code&gt;query_backend_after&lt;/code&gt; should be at least 10 minutes.
The default of 15 minutes for search provides a comfortable margin.&lt;/p&gt;
&lt;h3 id=&#34;compacted_block_retention-must-be-at-least-2x-blocklist_poll&#34;&gt;compacted_block_retention must be at least 2x blocklist_poll&lt;/h3&gt;
&lt;p&gt;When a block is compacted, its data is merged into a new block and the old block is marked compacted.
A querier with a stale blocklist may still reference the old block until it completes its next poll cycle.
Setting &lt;code&gt;compacted_block_retention&lt;/code&gt; to at least &lt;code&gt;2 * blocklist_poll&lt;/code&gt; ensures those queriers can still read the old block before it is deleted.
The default of 1 hour is well above the minimum for typical configurations.&lt;/p&gt;
&lt;h2 id=&#34;block-selection&#34;&gt;Block selection&lt;/h2&gt;
&lt;p&gt;Before any compaction work begins, the block selector determines which blocks to compact together.&lt;/p&gt;
&lt;p&gt;The time window block selector groups blocks by their time range and compaction level.
Blocks are only compacted with other blocks that share the same compaction window, data encoding, format version, and dedicated column configuration.&lt;/p&gt;
&lt;p&gt;The selector divides the blocklist into two zones based on the &lt;strong&gt;active window&lt;/strong&gt; (the most recent 24 hours):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inside the active window&lt;/strong&gt;: blocks are grouped by compaction level, then by time window. Lower compaction levels are prioritized, and within each group the smallest blocks are selected first.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outside the active window&lt;/strong&gt;: blocks are grouped by time window only, ignoring compaction level. This allows older data to be consolidated regardless of how many times it has already been compacted.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The selector only returns a group for compaction if it contains at least the minimum number of input blocks (default 2).
Each input set is also bounded by &lt;code&gt;max_block_bytes&lt;/code&gt; (default 100 GB).
If a full group would exceed this limit, the selector picks the largest contiguous subset of blocks that fits; any remaining blocks in the group are eligible in subsequent compaction runs.&lt;/p&gt;
&lt;p&gt;The number of input blocks per compaction job is configurable via &lt;code&gt;min_input_blocks&lt;/code&gt; and &lt;code&gt;max_input_blocks&lt;/code&gt;, defaulting to a minimum of 2 and a maximum of 4.&lt;/p&gt;
&lt;h2 id=&#34;how-compaction-works&#34;&gt;How compaction works&lt;/h2&gt;
&lt;p&gt;Compaction is handled by the backend scheduler and backend workers.
The scheduler is a singleton that assigns compaction jobs to a pool of workers.
Workers request jobs from the scheduler and report back when complete; the scheduler tracks active jobs and avoids handing out overlapping work.&lt;/p&gt;
&lt;p&gt;The scheduler uses a priority queue to choose which tenant to work on next.
Outstanding blocks are those the block selector has identified as eligible for compaction &amp;ndash; blocks that meet the window, encoding, and minimum-group-size requirements.
Tenants are ranked by the sum of their total blocklist length and their outstanding block count, so tenants with more overall backend work receive jobs first.
A tenant with no outstanding blocks receives a priority of zero and is not scheduled.&lt;/p&gt;
&lt;p&gt;The scheduler processes one tenant at a time, issuing jobs until the tenant&amp;rsquo;s eligible blocks are exhausted or the per-tenant job limit (&lt;code&gt;max_jobs_per_tenant&lt;/code&gt;, default 1000) is reached, then moves to the next tenant.
This cap is the mechanism that prevents a single busy tenant from monopolizing the workers.&lt;/p&gt;
&lt;p&gt;Within a tenant, the block selector prioritizes lower compaction levels first.
Higher-level blocks are still compacted, but after lower-level work is cleared.&lt;/p&gt;
&lt;p&gt;The compaction provider waits for a poll notification before selecting new work, preventing idle spin when no blocks are eligible.
A minimum cycle interval (&lt;code&gt;min_cycle_interval&lt;/code&gt;, default 30 seconds) rate-limits tenant prioritization when the queue is empty.&lt;/p&gt;
&lt;h3 id=&#34;autoscaling&#34;&gt;Autoscaling&lt;/h3&gt;
&lt;p&gt;Outstanding block counts are measured for all tenants on a periodic ticker (&lt;code&gt;measure_interval&lt;/code&gt;, default 1 minute), giving an aggregate view of total backend work.
Autoscaling thresholds should be set against this aggregate total rather than per-instance averages.
For a reference KEDA autoscaling configuration driven by outstanding block metrics, see &lt;code&gt;operations/jsonnet/microservices/autoscaling.libsonnet&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;configuration-reference&#34;&gt;Configuration reference&lt;/h2&gt;
&lt;p&gt;For a full configuration reference, refer to the &lt;a href=&#34;../configuration/&#34;&gt;configuration documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following fields are most relevant to compaction behavior.&lt;/p&gt;
&lt;h3 id=&#34;polling-interval-storagetrace&#34;&gt;Polling interval (&lt;code&gt;storage.trace&lt;/code&gt;)&lt;/h3&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;storage:
  trace:
    # How often to poll the backend for new blocks. Default: 5m.
    blocklist_poll: 5m&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;compaction-settings-backend_workercompaction&#34;&gt;Compaction settings (&lt;code&gt;backend_worker.compaction&lt;/code&gt;)&lt;/h3&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;backend_worker:
  compaction:
    # Size of the time window used to group blocks. Default: 1h.
    compaction_window: 1h

    # Maximum size of a compacted output block in bytes. Default: 100GB.
    max_block_bytes: 107374182400

    # How long to keep a block after compaction. Must be &amp;gt;= 2x blocklist_poll. Default: 1h.
    compacted_block_retention: 1h&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;query-cutoff-must-be--2x-blocklist_poll&#34;&gt;Query cutoff (must be &amp;gt;= 2x blocklist_poll)&lt;/h3&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;query_frontend:
  search:
    # Default: 15m.
    query_backend_after: 15m&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;scheduler-compaction-backend_schedulerprovidercompaction&#34;&gt;Scheduler compaction (&lt;code&gt;backend_scheduler.provider.compaction&lt;/code&gt;)&lt;/h3&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;backend_scheduler:
  provider:
    compaction:
      # Maximum jobs to issue per tenant before switching. Default: 1000.
      max_jobs_per_tenant: 1000

      # Minimum number of input blocks per job. Default: 2.
      min_input_blocks: 2

      # Maximum number of input blocks per job. Default: 4.
      max_input_blocks: 4

      # Minimum time between tenant selection cycles. Default: 30s.
      min_cycle_interval: 30s&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The &lt;code&gt;backend_worker.compaction&lt;/code&gt; configuration block contains two fields that are not used by the current scheduled compaction path: &lt;code&gt;max_time_per_tenant&lt;/code&gt; and &lt;code&gt;compaction_cycle&lt;/code&gt;.
These fields were used by the ring-based compaction loop, which has been removed.
They are accepted by the configuration parser but have no effect.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;see-also&#34;&gt;See also&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../configuration/polling/&#34;&gt;Polling configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;./monitor/polling/&#34;&gt;Monitor backend polling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="compaction">Compaction&lt;/h1>
&lt;p>Tempo stores trace data as immutable blocks in object storage.
Over time, many small blocks accumulate from frequent flushes.
Compaction merges groups of small blocks into fewer, larger blocks, reducing storage costs and improving query performance by limiting the number of blocks a querier must scan.&lt;/p></description></item><item><title>Monitor Tempo</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/monitor/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/monitor/</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;Metrics, logs, and traces from Tempo can be collected to observe its services and functions.&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; and 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;h4 id=&#34;query-frontend-inspected-bytes&#34;&gt;Query frontend inspected bytes&lt;/h4&gt;
&lt;p&gt;Use &lt;code&gt;tempo_query_frontend_bytes_inspected_total&lt;/code&gt; to monitor how many bytes the query frontend reads from disk and object storage.
This counter is emitted per &lt;code&gt;tenant&lt;/code&gt; and &lt;code&gt;op&lt;/code&gt; (&lt;code&gt;traces&lt;/code&gt;, &lt;code&gt;search&lt;/code&gt;, &lt;code&gt;metadata&lt;/code&gt;, &lt;code&gt;metrics&lt;/code&gt;).
Because cached responses from queriers are excluded, it reflects actual storage and network I/O.&lt;/p&gt;
&lt;p&gt;For PromQL examples and alerting guidance, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/monitor/query-io-and-timestamp-distance/&#34;&gt;Query query IO and time stamp distance&lt;/a&gt;.&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/open-telemetry/opentelemetry-go&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenTelemetry SDK&lt;/a&gt; for tracing instrumentation.
The complete read path and some parts of the write path of Tempo are instrumented for tracing.&lt;/p&gt;
&lt;p&gt;You can configure the tracer &lt;a href=&#34;https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/&#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;OTEL_EXPORTER_OTLP_ENDPOINT&lt;/code&gt; or &lt;code&gt;OTEL_EXPORTER_OTLP_TRACES_ENDPOINT&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The OpenTelemetry SDK uses OTLP/HTTP by default, which can be configured with &lt;code&gt;OTEL_EXPORTER_OTLP_PROTOCOL&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;polling&#34;&gt;Polling&lt;/h2&gt;
&lt;p&gt;Tempo maintains knowledge of the state of the backend by polling it on regular intervals.
Several components need this knowledge, including schedulers, workers, queriers, and query-frontends.&lt;/p&gt;
&lt;p&gt;Refer to &lt;a href=&#34;polling/&#34;&gt;Use polling to monitor the backend status&lt;/a&gt; for Tempo.&lt;/p&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 eight Grafana dashboards in the &lt;code&gt;dashboards&lt;/code&gt; folder that you can download and import into your Grafana UI.
These dashboards work well when you run Tempo 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 on Requests, Errors, and Duration (RED) on the query path of Tempo.
Each query touches the Gateway, Query-Frontend, Queriers, Live-stores, Memcached, and the backend.&lt;/p&gt;
&lt;p&gt;Use this dashboard to monitor the performance of each of the 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 on RED on the write/ingest path of Tempo.
A write query touches the Gateway, Distributors, and Kafka.
The dashboard also shows compaction activity against Memcached and the backend.&lt;/p&gt;
&lt;p&gt;Use this dashboard to monitor the performance of each of the 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;.
This dashboard 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 because it is probably a stack of dashboard anti-patterns.
It&amp;rsquo;s big and complex, doesn&amp;rsquo;t use &lt;code&gt;jsonnet&lt;/code&gt;, and displays far too many metrics in one place.
For just getting started, the RED 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 the Tempo repository for two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The dashboard provides a stack of metrics for other operators to consider monitoring while running Tempo.&lt;/li&gt;
&lt;li&gt;We want the dashboard in our internal infrastructure and we vendor the &lt;code&gt;tempo-mixin&lt;/code&gt; to do this.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;tempo-backend-work-dashboard&#34;&gt;Tempo Backend Work dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-backendwork.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Backend Work dashboard monitors blocklist maintenance, compaction jobs, and backend component resources.
It tracks blocklist length and poll duration, active and completed compaction jobs, failure and retry rates, and objects written and combined during compaction.
The dashboard also shows CPU and memory usage for the backend-scheduler and backend-worker components.&lt;/p&gt;
&lt;p&gt;Use this dashboard to monitor compaction health, detect stalled or failing jobs, and right-size backend-scheduler and backend-worker resources.&lt;/p&gt;
&lt;h3 id=&#34;tempo-block-builder-dashboard&#34;&gt;Tempo Block Builder dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-block-builder.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Block Builder dashboard monitors the Kafka-based ingest path introduced.
It tracks Kafka fetch rates and read throughput, flushed blocks per second, and per-partition lag in both records and seconds.
Heatmaps show partition section and cycle durations, and resource panels track CPU and memory usage.&lt;/p&gt;
&lt;p&gt;Use this dashboard to monitor block-builder throughput, detect partition lag, and ensure the ingest pipeline keeps up with incoming trace data.&lt;/p&gt;
&lt;h3 id=&#34;tempo-rollout-progress-dashboard&#34;&gt;Tempo Rollout Progress dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-rollout-progress.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Rollout Progress dashboard tracks the health of a Tempo deployment during upgrades and rollouts.
It breaks down write and read requests by status code (2xx, 4xx, 5xx), shows 99th percentile latency, and counts unhealthy Pods.
A version panel shows the number of pods running each version, and a latency comparison panel shows current latency against the previous 24-hour baseline.&lt;/p&gt;
&lt;p&gt;Use this dashboard during upgrades to confirm that new versions aren&amp;rsquo;t introducing errors or latency regressions.&lt;/p&gt;
&lt;h3 id=&#34;tempo-tenants-dashboard&#34;&gt;Tempo Tenants dashboard&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This is available as &lt;code&gt;tempo-tenants.json&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The Tenants dashboard provides per-tenant visibility into ingestion, reads, storage, and metrics generation.
It shows a limits table alongside distributor bytes and spans per second, live trace counts, query rates for ID lookups and searches, blocklist length, outstanding compactions, and metrics-generator bytes and active series.&lt;/p&gt;
&lt;p&gt;Use this dashboard in multitenant deployments to identify tenants with high ingestion rates, query volumes, or storage growth.&lt;/p&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>Manage trace ingestion</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-trace-ingestion/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-trace-ingestion/</guid><content><![CDATA[&lt;h1 id=&#34;manage-trace-ingestion&#34;&gt;Manage trace ingestion&lt;/h1&gt;
&lt;p&gt;If you are seeing &lt;code&gt;RATE_LIMITED&lt;/code&gt;, &lt;code&gt;LIVE_TRACES_EXCEEDED&lt;/code&gt;, or &lt;code&gt;TRACE_TOO_LARGE&lt;/code&gt; errors, or if your trace storage costs are rising unexpectedly, this page can help.&lt;/p&gt;
&lt;p&gt;Grafana Tempo enforces ingestion limits at multiple points in the write path.
The distributor checks rate limits before writing spans to Kafka.
Downstream, live-stores enforce per-trace size and live trace count limits asynchronously, and block-builders enforce per-trace size limits.
If limits are too low for your workload, spans are discarded and data is lost.
If limits are unchecked, ingestion volume can grow beyond what you intended.&lt;/p&gt;
&lt;p&gt;This page covers three tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#size-ingestion-limits-for-your-workload&#34;&gt;Size ingestion limits&lt;/a&gt; when deploying or reviewing your configuration.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#find-and-fix-discarded-spans&#34;&gt;Find and fix discarded spans&lt;/a&gt; when you are actively losing data.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#identify-what-is-driving-ingestion-volume&#34;&gt;Identify what is driving ingestion volume&lt;/a&gt; when costs are growing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For an overview of how trace data flows through the write path, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/introduction/architecture/&#34;&gt;Tempo architecture&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;size-ingestion-limits-for-your-workload&#34;&gt;Size ingestion limits for your workload&lt;/h2&gt;
&lt;p&gt;Tempo enforces three ingestion limits. Understanding what the defaults mean for your traffic helps you set appropriate values at deploy time, rather than discovering them through production incidents.&lt;/p&gt;
&lt;h3 id=&#34;rate-limit&#34;&gt;Rate limit&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rate_limit_bytes&lt;/code&gt; (default: &lt;code&gt;15,000,000&lt;/code&gt;) sets the sustained byte rate each distributor allows per tenant, measured in bytes per second.
For a typical span size of around 500 bytes, the default accommodates roughly 30,000 spans per second per distributor.&lt;/p&gt;
&lt;p&gt;How this scales depends on your &lt;code&gt;rate_strategy&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;local&lt;/code&gt;&lt;/strong&gt; (default): each distributor enforces the limit independently. With three distributors, the effective cluster limit is approximately 90,000 spans per second.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;global&lt;/code&gt;&lt;/strong&gt;: the configured rate is shared across all distributors. The total cluster rate equals the configured value regardless of how many distributors you run.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;burst_size_bytes&lt;/code&gt; (default: &lt;code&gt;20,000,000&lt;/code&gt;) allows temporary spikes above the sustained rate, for example during application deployments. The burst allowance is always applied locally, regardless of rate strategy.&lt;/p&gt;
&lt;h3 id=&#34;live-trace-limit&#34;&gt;Live trace limit&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;max_traces_per_user&lt;/code&gt; (default: &lt;code&gt;10,000&lt;/code&gt;) caps the number of concurrently active traces per tenant on each live-store.
This limit is enforced asynchronously in the live-store, not at ingestion time in the distributor.
Block-builders do not enforce this limit.
If your services produce many short-lived traces in parallel, you may need to raise this.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The &lt;code&gt;max_global_traces_per_user&lt;/code&gt; setting, which provides a cluster-wide cap for the ingester write path, has been moved to &lt;code&gt;ingestion.max_global_traces_per_user&lt;/code&gt; in Tempo 3.0.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;per-trace-size-limit&#34;&gt;Per-trace size limit&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;max_bytes_per_trace&lt;/code&gt; (default: &lt;code&gt;5,000,000&lt;/code&gt;) caps the total size of a single trace.
This limit is enforced asynchronously in live-stores and block-builders.
Traces that exceed this limit are partially dropped.
Unusually large traces often indicate a retry loop or misconfigured instrumentation rather than normal application behavior.&lt;/p&gt;
&lt;h3 id=&#34;example-configuration&#34;&gt;Example configuration&lt;/h3&gt;
&lt;p&gt;To estimate the rate limit you need, multiply your average span size by your peak spans-per-second across all services for a given tenant.&lt;/p&gt;
&lt;p&gt;The following example raises the defaults for a high-throughput workload:&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;overrides:
  defaults:
    ingestion:
      rate_strategy: local
      rate_limit_bytes: 30000000
      burst_size_bytes: 40000000
      max_traces_per_user: 50000
    global:
      max_bytes_per_trace: 10000000&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you run a multi-tenant deployment, you can set different limits per tenant using runtime overrides instead of raising the global defaults.
Refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/multitenancy/&#34;&gt;Enable multi-tenancy&lt;/a&gt; for per-tenant override examples.&lt;/p&gt;
&lt;p&gt;For the full list of available settings, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#ingestion-limits&#34;&gt;Ingestion limits&lt;/a&gt; in the configuration reference.
You can also manage per-tenant limits through the API using 
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/user-configurable-overrides/&#34;&gt;user-configurable overrides&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;find-and-fix-discarded-spans&#34;&gt;Find and fix discarded spans&lt;/h2&gt;
&lt;p&gt;When a span exceeds an ingestion limit or fails validation, Tempo discards it and increments the &lt;code&gt;tempo_discarded_spans_total&lt;/code&gt; metric.
The distributor rejects entire push requests that exceed the rate limit or contain invalid trace or span IDs, before any spans reach Kafka.
Live-stores discard spans that exceed per-trace size or live trace count limits after consuming them from Kafka.
Block-builders discard spans that exceed per-trace size limits.&lt;/p&gt;
&lt;h3 id=&#34;error-reference&#34;&gt;Error reference&lt;/h3&gt;
&lt;p&gt;The following table lists the three error types, what each one means, and how to fix it.&lt;/p&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&gt;Error&lt;/th&gt;
              &lt;th&gt;Cause&lt;/th&gt;
              &lt;th&gt;Fix&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;RATE_LIMITED&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The tenant&amp;rsquo;s byte rate exceeded &lt;code&gt;rate_limit_bytes&lt;/code&gt;.&lt;/td&gt;
              &lt;td&gt;Raise &lt;code&gt;rate_limit_bytes&lt;/code&gt;, or add distributors if using &lt;code&gt;rate_strategy: local&lt;/code&gt;. If volume is genuinely higher than intended, reduce it upstream with 
    &lt;a href=&#34;/docs/tempo/v3.0.x/set-up-for-tracing/instrument-send/set-up-collector/tail-sampling/&#34;&gt;sampling&lt;/a&gt;.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;LIVE_TRACES_EXCEEDED&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The number of concurrent active traces on a live-store exceeded &lt;code&gt;max_traces_per_user&lt;/code&gt;.&lt;/td&gt;
              &lt;td&gt;Raise &lt;code&gt;max_traces_per_user&lt;/code&gt;, or add live-store instances to distribute the active trace count across more nodes.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;TRACE_TOO_LARGE&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;A single trace exceeded &lt;code&gt;max_bytes_per_trace&lt;/code&gt; (default 5 MB).&lt;/td&gt;
              &lt;td&gt;Raise &lt;code&gt;max_bytes_per_trace&lt;/code&gt; in the &lt;code&gt;global&lt;/code&gt; overrides. Also investigate why the trace is so large. Common causes include retry loops and misconfigured instrumentation.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;check-why-spans-are-being-discarded&#34;&gt;Check why spans are being discarded&lt;/h3&gt;
&lt;p&gt;Query the &lt;code&gt;tempo_discarded_spans_total&lt;/code&gt; metric.
The &lt;code&gt;reason&lt;/code&gt; label identifies why Tempo discarded each span:&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 (reason) (rate(tempo_discarded_spans_total[5m]))&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following table lists the possible &lt;code&gt;reason&lt;/code&gt; values:&lt;/p&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&gt;Reason&lt;/th&gt;
              &lt;th&gt;Meaning&lt;/th&gt;
              &lt;th&gt;Component&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;rate_limited&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Tenant byte rate exceeded &lt;code&gt;rate_limit_bytes&lt;/code&gt;.&lt;/td&gt;
              &lt;td&gt;Distributor&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;trace_too_large&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Single trace exceeded &lt;code&gt;max_bytes_per_trace&lt;/code&gt;.&lt;/td&gt;
              &lt;td&gt;Live-store, block-builder&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;live_traces_exceeded&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Active trace count exceeded &lt;code&gt;max_traces_per_user&lt;/code&gt;.&lt;/td&gt;
              &lt;td&gt;Live-store&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;invalid_trace_id&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Batch contained a trace ID that isn&amp;rsquo;t 128 bits.&lt;/td&gt;
              &lt;td&gt;Distributor&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;invalid_span_id&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Batch contained a span ID that isn&amp;rsquo;t 64 bits or was all zeros.&lt;/td&gt;
              &lt;td&gt;Distributor&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;trace_too_large_to_compact&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Trace too large for the backend-worker to compact.&lt;/td&gt;
              &lt;td&gt;Backend-worker&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;unknown_error&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Unexpected error during span processing.&lt;/td&gt;
              &lt;td&gt;Live-store&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;log-discarded-spans-for-debugging&#34;&gt;Log discarded spans for debugging&lt;/h3&gt;
&lt;p&gt;To log spans discarded by the distributor (rate-limited spans) with their trace IDs, enable &lt;code&gt;log_discarded_spans&lt;/code&gt; in the distributor configuration:&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;distributor:
  log_discarded_spans:
    enabled: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Set &lt;code&gt;include_all_attributes: true&lt;/code&gt; for more verbose output that includes span attributes.&lt;/p&gt;
&lt;p&gt;Spans discarded by live-stores for &lt;code&gt;LIVE_TRACES_EXCEEDED&lt;/code&gt; or &lt;code&gt;TRACE_TOO_LARGE&lt;/code&gt; are logged at debug level by the live-store.
To see these entries, set the live-store log level to &lt;code&gt;debug&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/troubleshooting/send-traces/max-trace-limit-reached/&#34;&gt;Distributor refusing spans&lt;/a&gt; for additional troubleshooting steps.&lt;/p&gt;
&lt;h3 id=&#34;traces-missing-from-queries-without-errors&#34;&gt;Traces missing from queries without errors&lt;/h3&gt;
&lt;p&gt;If the distributor is not refusing spans but traces are missing from query results, the issue may be downstream.
Live-stores consume trace data from Kafka and serve recent queries.
If a live-store falls behind its Kafka partition, query results may be incomplete.&lt;/p&gt;
&lt;p&gt;Monitor the &lt;code&gt;tempo_live_store_lagged_requests_total&lt;/code&gt; metric to detect when this happens.
This counter increments every time a search or metrics query hits a live-store whose Kafka lag overlaps the requested time range, meaning results may be incomplete.
The metric is labeled by &lt;code&gt;route&lt;/code&gt; (&lt;code&gt;/tempopb.Querier/SearchRecent&lt;/code&gt; or &lt;code&gt;/tempopb.Metrics/QueryRange&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;fail_on_high_lag&lt;/code&gt; setting (default &lt;code&gt;false&lt;/code&gt;) controls how the live-store responds when lag is detected:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When &lt;code&gt;false&lt;/code&gt;, the live-store returns whatever data it has, which may be incomplete. The metric still increments.&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;true&lt;/code&gt;, the live-store returns an error when it cannot guarantee completeness.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/troubleshooting/querying/unable-to-see-trace/&#34;&gt;Unable to find traces&lt;/a&gt; for query-side troubleshooting.&lt;/p&gt;
&lt;h2 id=&#34;identify-what-is-driving-ingestion-volume&#34;&gt;Identify what is driving ingestion volume&lt;/h2&gt;
&lt;p&gt;When your cluster is healthy but ingestion is growing, the first step is finding which services are responsible for the most volume.&lt;/p&gt;
&lt;h3 id=&#34;set-up-cost-attribution&#34;&gt;Set up cost attribution&lt;/h3&gt;
&lt;p&gt;The usage tracker breaks down ingested bytes by configurable attributes, giving you a per-service view of who is consuming capacity.&lt;/p&gt;
&lt;p&gt;Enable cost attribution in the distributor and configure which attributes to track in overrides:&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;distributor:
  usage:
    cost_attribution:
      enabled: true

overrides:
  defaults:
    cost_attribution:
      dimensions:
        resource.service.name: &amp;#34;service&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;find-the-top-contributors&#34;&gt;Find the top contributors&lt;/h3&gt;
&lt;p&gt;After enabling cost attribution, the distributor exposes the &lt;code&gt;tempo_usage_tracker_bytes_received_total&lt;/code&gt; metric on the &lt;code&gt;/usage_metrics&lt;/code&gt; endpoint, labeled by the dimensions you configured.&lt;/p&gt;
&lt;p&gt;You can query this endpoint directly:&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;curl http://&amp;lt;distributor-host&amp;gt;:3200/usage_metrics&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you scrape this endpoint with Prometheus, you can use the following query to find which services are sending the most data:&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;topk(10,
  sum by (service) (
    rate(tempo_usage_tracker_bytes_received_total[1h])
  )
)&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For the full set of configuration options, including scoping dimensions by resource or span and customizing label names, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/usage-tracker/&#34;&gt;Usage tracker&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;reduce-volume-from-noisy-services&#34;&gt;Reduce volume from noisy services&lt;/h3&gt;
&lt;p&gt;After you know which services are driving volume, the most effective way to reduce it is 
    &lt;a href=&#34;/docs/tempo/v3.0.x/set-up-for-tracing/instrument-send/set-up-collector/tail-sampling/&#34;&gt;sampling&lt;/a&gt; at the collector layer.
Tail sampling lets you keep traces with errors or high latency while dropping routine ones, reducing volume without losing visibility into the problems that matter.&lt;/p&gt;
]]></content><description>&lt;h1 id="manage-trace-ingestion">Manage trace ingestion&lt;/h1>
&lt;p>If you are seeing &lt;code>RATE_LIMITED&lt;/code>, &lt;code>LIVE_TRACES_EXCEEDED&lt;/code>, or &lt;code>TRACE_TOO_LARGE&lt;/code> errors, or if your trace storage costs are rising unexpectedly, this page can help.&lt;/p></description></item><item><title>Dedicated attribute columns</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/dedicated_columns/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/dedicated_columns/</guid><content><![CDATA[&lt;h1 id=&#34;dedicated-attribute-columns&#34;&gt;Dedicated attribute columns&lt;/h1&gt;
&lt;p&gt;Dedicated attribute columns improve query performance by storing the most frequently used attributes in their own columns,
rather than in the generic attribute key-value list.&lt;/p&gt;
&lt;p&gt;Dedicated attribute columns are available when using &lt;code&gt;vParquet4&lt;/code&gt; or later block formats.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vParquet5&lt;/code&gt; expands on the feature with doubled string column limits, integer dedicated columns, event-scoped attributes, array-valued attributes, and blob attributes using the &lt;code&gt;options&lt;/code&gt; field.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;You can configure dedicated attribute columns in the storage block or via overrides.&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;# Storage configuration for traces
storage:
  trace:
    block:
      # Default dedicated columns for all blocks
      parquet_dedicated_columns:
        - name: &amp;lt;string&amp;gt; # name of the attribute
          type: &amp;lt;string&amp;gt; # type of the attribute. options: string (vParquet3&amp;#43;), int (vParquet5 only)
          scope: &amp;lt;string&amp;gt; # scope of the attribute. options: resource, span (vParquet3&amp;#43;), event (vParquet5 only)
          options: [&amp;lt;string&amp;gt;] # optional, vParquet5 only. options: array, blob

overrides:
  # Global overrides for dedicated columns configuration
  parquet_dedicated_columns:
    - name: &amp;lt;string&amp;gt; # name of the attribute
      type: &amp;lt;string&amp;gt; # type of the attribute. options: string, int
      scope: &amp;lt;string&amp;gt; # scope of the attribute. options: resource, span, event
      options: [&amp;lt;string&amp;gt;] # optional, vParquet5 only. options: array, blob

  per_tenant_override_config: /conf/overrides.yaml
---
# /conf/overrides.yaml
# Tenant-specific overrides configuration
overrides:
  &amp;#34;&amp;lt;tenant id&amp;gt;&amp;#34;:
    parquet_dedicated_columns:
      - name: &amp;lt;string&amp;gt; # name of the attribute
        type: &amp;lt;string&amp;gt; # type of the attribute. options: string, int
        scope: &amp;lt;string&amp;gt; # scope of the attribute. options: resource, span, event
        options: [&amp;lt;string&amp;gt;] # optional, vParquet5 only. options: array, blob

  # A &amp;#34;wildcard&amp;#34; override can be used that will apply to all tenants if a match is not found.
  &amp;#34;*&amp;#34;:
    parquet_dedicated_columns:
      - name: &amp;lt;string&amp;gt; # name of the attribute
        type: &amp;lt;string&amp;gt; # type of the attribute. options: string, int
        scope: &amp;lt;string&amp;gt; # scope of the attribute. options: resource, span, event
        options: [&amp;lt;string&amp;gt;] # optional, vParquet5 only. options: array, blob&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Priority is given to the most specific configuration, so tenant-specific overrides will take precedence over global overrides.
Similarly, default overrides take precedence over storage block configuration.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;p&gt;The number of dedicated attribute columns depends on the block format version:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;vParquet4&lt;/strong&gt;: Up to 10 string attributes per scope (span and resource). Integer dedicated columns and event scope are not supported.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;vParquet5&lt;/strong&gt;: Up to 20 string attributes and 5 integer attributes per scope (span, resource, and event).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a rule of thumb, good candidates for dedicated attribute columns are attributes that contribute the most to the block size,
even if they aren&amp;rsquo;t frequently queried.
Reducing the generic attribute key-value list size significantly improves query performance.&lt;/p&gt;
&lt;h3 id=&#34;integer-attribute-selection&#34;&gt;Integer attribute selection&lt;/h3&gt;
&lt;p&gt;Integer dedicated columns are most effective when the attribute is present on at least 5% of rows in a scope.
The &lt;code&gt;tempo-cli analyse block&lt;/code&gt; command shows the percentage of rows for each integer attribute and marks candidates that meet this threshold with a recommendation.
Sparse integer attributes (below 5% prevalence) typically perform better in the generic attribute storage.&lt;/p&gt;
&lt;h3 id=&#34;array-valued-attributes&#34;&gt;Array-valued attributes&lt;/h3&gt;
&lt;p&gt;Dedicated attribute columns support array-valued attributes.
This is useful for attributes that can have multiple values, such as HTTP headers or custom tags.&lt;/p&gt;
&lt;p&gt;To enable array support, add &lt;code&gt;options: [&amp;quot;array&amp;quot;]&lt;/code&gt; to the dedicated attribute column configuration.
The &lt;code&gt;options&lt;/code&gt; field is only available in &lt;code&gt;vParquet5&lt;/code&gt; and later.
Earlier versions ignore this field and only support single-valued attributes.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;options: [&amp;quot;array&amp;quot;]&lt;/code&gt; is set, the dedicated column stores multiple values per attribute.
Without this option (default), only single values are supported.&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;storage:
  trace:
    block:
      version: vParquet5
      parquet_dedicated_columns:
        # Single-valued string attribute (default behavior)
        - name: http.method
          type: string
          scope: span

        # Array-valued string attribute
        - name: http.request.header.accept
          type: string
          scope: span
          options: [&amp;#34;array&amp;#34;]

        # Array-valued integer attribute
        - name: custom.retry.counts
          type: int
          scope: span
          options: [&amp;#34;array&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;blob-attributes&#34;&gt;Blob attributes&lt;/h3&gt;
&lt;p&gt;Blob attributes are designed for high-cardinality or high-length string values where dictionary encoding becomes inefficient.
Examples include UUIDs, stack traces, request bodies, or any attribute with many unique values.&lt;/p&gt;
&lt;p&gt;When an attribute&amp;rsquo;s dictionary size per row group exceeds a threshold (default 4MiB), the column should be marked as a blob.
The &lt;code&gt;tempo-cli analyse block&lt;/code&gt; command can help identify blob candidates by showing the estimated dictionary size per row group.&lt;/p&gt;
&lt;p&gt;To enable blob mode, add &lt;code&gt;options: [&amp;quot;blob&amp;quot;]&lt;/code&gt; to the dedicated attribute column configuration.
Blob columns use &lt;code&gt;zstd&lt;/code&gt; compression instead of dictionary encoding, which is more efficient for high-cardinality data.&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;storage:
  trace:
    block:
      version: vParquet5
      parquet_dedicated_columns:
        # Standard dedicated column (uses dictionary encoding)
        - name: http.method
          type: string
          scope: span

        # Blob column for high-cardinality data
        - name: db.statement
          type: string
          scope: span
          options: [&amp;#34;blob&amp;#34;]

        # Blob column for stack traces
        - name: exception.stacktrace
          type: string
          scope: event
          options: [&amp;#34;blob&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Use the &lt;code&gt;tempo-cli analyse block&lt;/code&gt; command with the &lt;code&gt;--blob-threshold&lt;/code&gt; option to identify attributes that should be configured as blobs.
Attributes exceeding the threshold are marked as &amp;ldquo;(blob)&amp;rdquo; in the output.&lt;/p&gt;
&lt;h3 id=&#34;event-scoped-attributes&#34;&gt;Event-scoped attributes&lt;/h3&gt;
&lt;p&gt;With &lt;code&gt;vParquet5&lt;/code&gt;, dedicated columns support event-scoped attributes in addition to span and resource scopes.
Event-scoped columns are useful for frequently queried event attributes such as exception details or custom event data.&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;storage:
  trace:
    block:
      version: vParquet5
      parquet_dedicated_columns:
        # Event-scoped string attribute
        - name: exception.message
          type: string
          scope: event

        # Event-scoped attribute with blob option
        - name: exception.stacktrace
          type: string
          scope: event
          options: [&amp;#34;blob&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;tempo-cli&#34;&gt;Tempo-cli&lt;/h3&gt;
&lt;p&gt;You can use the &lt;code&gt;tempo-cli&lt;/code&gt; tool to find good candidates for dedicated attribute columns.
The &lt;code&gt;tempo-cli&lt;/code&gt; provides the commands &lt;code&gt;analyse block &amp;lt;tenant-id&amp;gt; &amp;lt;block-id&amp;gt;&lt;/code&gt; and &lt;code&gt;analyse blocks &amp;lt;tenant-id&amp;gt;&lt;/code&gt; that will output the
top N attributes by size for a given block or all blocks in a tenant.&lt;/p&gt;
&lt;p&gt;Example:&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 analyse blocks --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Refer to the &lt;a href=&#34;../tempo_cli/&#34;&gt;tempo-cli documentation&lt;/a&gt; for more information.&lt;/p&gt;
]]></content><description>&lt;h1 id="dedicated-attribute-columns">Dedicated attribute columns&lt;/h1>
&lt;p>Dedicated attribute columns improve query performance by storing the most frequently used attributes in their own columns,
rather than in the generic attribute key-value list.&lt;/p></description></item><item><title>Tune search performance</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/backend_search/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.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 searches all of the blocks
in the specified time range.
Depending on your volume, this may result in slow queries.&lt;/p&gt;
&lt;p&gt;This document explains how read path in Tempo works, what controls you have to tune the read path, details of the core configuration options, and how to tune these configuration options to get the most out of your Tempo cluster.&lt;/p&gt;
&lt;p&gt;The general advice is to scale your workers and queriers. Additional queriers can more effectively run jobs in parallel
while additional workers more aggressively reduce the length of your blocklist and copies of data (if using &lt;code&gt;RF=3&lt;/code&gt;).&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;All forms of search (TraceQL and tags based) require &lt;code&gt;vParquet&lt;/code&gt; block formats. The v2 block format has been removed in Tempo 3.0.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;../dedicated_columns/&#34;&gt;Dedicated attribute columns&lt;/a&gt; are another effective method to improve search performance.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;before-you-begin&#34;&gt;Before you begin&lt;/h2&gt;
&lt;p&gt;You should understand the basic Tempo architecture.&lt;/p&gt;
&lt;p&gt;For more information, refer to the &lt;a href=&#34;/docs/tempo/latest/operations/architecture/#query-frontend&#34;&gt;Tempo architecture&lt;/a&gt; to learn about how Tempo works.&lt;/p&gt;
&lt;h3 id=&#34;glossary&#34;&gt;Glossary&lt;/h3&gt;
&lt;dl&gt;
&lt;dt&gt;query&lt;/dt&gt;
&lt;dd&gt;A search query, issued by end user. For example, &lt;code&gt;{ traceDuration &amp;gt; 1s }&lt;/code&gt; is a TraceQL query.&lt;/dd&gt;
&lt;dt&gt;job&lt;/dt&gt;
&lt;dd&gt;A shard of a search query, the lowest unit of work. A query is broken down into multiple jobs and processed.&lt;/dd&gt;
&lt;dt&gt;batch&lt;/dt&gt;
&lt;dd&gt;A group of jobs is called a batch.&lt;/dd&gt;
&lt;dt&gt;frontend&lt;/dt&gt;
&lt;dd&gt;Another name for query-frontend&lt;/dd&gt;
&lt;dt&gt;querier&lt;/dt&gt;
&lt;dd&gt;Responsible for executing (processing) the jobs, and sending the results back to query-frontend.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2 id=&#34;tempo-query-path&#34;&gt;Tempo query path&lt;/h2&gt;
&lt;p&gt;Tempo has a query path made up of a query-frontend, querier, live-store, and backend.&lt;/p&gt;
&lt;p&gt;You can think about each component in a query path as a generic producer and worker model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The query-frontend is a producer and it has multiple workers connected to it. The query-frontend takes a single query and shards it into multiple jobs (units of work).&lt;/li&gt;
&lt;li&gt;The queriers are workers. They enqueue work from a queue, process it, and send the results back to the producer (query-frontend).&lt;/li&gt;
&lt;li&gt;The querier either reads data from backend and processes the query, or it delegates the query to live-stores based on the type of job, time range, and query type.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/tempo/tempo-query-frontend.svg&#34;
  alt=&#34;Tempo query path architecture&#34;/&gt;&lt;/p&gt;
&lt;h3 id=&#34;lifecycle-of-a-query&#34;&gt;Lifecycle of a query&lt;/h3&gt;
&lt;p&gt;A search request comes from the user, and it is split into multiple jobs in the query-frontend.&lt;/p&gt;
&lt;p&gt;These jobs are then added to a queue and queriers pick up jobs in batches to process.&lt;/p&gt;
&lt;p&gt;A single search query can create hundreds of jobs based on the time range and other variables.
These jobs are batched and sent to queriers.&lt;/p&gt;
&lt;p&gt;The querier receives the batch and processes the jobs in the batch, builds results, and sends the results of the whole batch back to the query-frontend.&lt;/p&gt;
&lt;p&gt;The query-frontend merges and deduplicates the results, and sends them back to the client.&lt;/p&gt;
&lt;p&gt;When querier starts, it opens multiple connections to each query-frontend.&lt;/p&gt;
&lt;p&gt;Job batches are sent over these connections, and return the results.
This process is synchronized so a single job batch can block a connection.&lt;/p&gt;
&lt;p&gt;The number of connections control the number of batches a querier processes concurrently.
The number of connections is controlled by &lt;code&gt;querier.max_concurrent_queries&lt;/code&gt; OR &lt;code&gt;frontend_worker.parallelism&lt;/code&gt;.&lt;/p&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 dispatches 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;querier-and-query-frontend-configuration&#34;&gt;Querier and query-frontend 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 &#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;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;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 help deal with scaling issues.&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;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;settings-that-are-safe-to-increase-without-major-impact&#34;&gt;Settings that are safe to increase without major impact.&lt;/h2&gt;
&lt;p&gt;Scaling up queriers is a safe way to add more query capacity.
At Grafana Labs, we prefer to scale queries horizontally by adding more replicas.
If you see out of memory (OOM) errors, it might be worth scaling the queriers vertically.&lt;/p&gt;
&lt;p&gt;We recommend running at least two replicates of query-frontend. These replicas should be scaled vertically instead of horizontally.
If you need to scale, scale query-frontends vertically by adding more CPU and RAM.
Currently, query-frontends aren’t scaled horizontally, but this might change in the future.&lt;/p&gt;
&lt;p&gt;The reason we keep only two replicas is because each query-frontend has its own request queue and it also impacts the amount of jobs sent to each querier.
If you add more query-frontends, you need to tune other configuration parameters to account for the change.
We decided to keep query-frontend to two replicas for now.&lt;/p&gt;
&lt;p&gt;In a dedicated cluster, you can increase &lt;code&gt;query_frontend.max_outstanding_per_tenant&lt;/code&gt; because the cluster is dedicated to a single customer.
In a shared cluster, you need to use more caution when increasing &lt;code&gt;querier.max_outstanding_per_tenant&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;parameter-interactions&#34;&gt;Parameter interactions&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;query_frontend&lt;/code&gt; configuration options control how Tempo shards a query into multiple jobs.
These options also control the size of a single job, number of jobs, and the number of jobs added to the work queue at once (concurrently) for queriers to be picked up.
The &lt;code&gt;max_batch_size&lt;/code&gt; option controls how many jobs are sent to queriers at once in a single batch.&lt;/p&gt;
&lt;p&gt;Querier configuration options control processing of these jobs, queries operate at a job level.
They&amp;rsquo;re workers: they pick a job from the queue and execute the job, and return the results back to the query-frontend.
Querier options control how many jobs it processes at once by opening concurrent connections to query-frontends, and each connection processes a single.&lt;/p&gt;
&lt;h2 id=&#34;guidelines-on-key-configuration-parameters&#34;&gt;Guidelines on key configuration parameters&lt;/h2&gt;
&lt;p&gt;The following sections provide recommendations for key configuration parameters.&lt;/p&gt;
&lt;h3 id=&#34;query_frontendmax_outstanding_per_tenant-parameter&#34;&gt;&lt;code&gt;query_frontend.max_outstanding_per_tenant&lt;/code&gt; parameter&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;query_frontend.max_outstanding_per_tenant&lt;/code&gt; parameter decides the maximum number of outstanding requests per tenant per frontend; requests beyond this error with HTTP &lt;code&gt;429&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This configuration controls how much load a single tenant can put on a cluster. A return of &lt;code&gt;429&lt;/code&gt; indicates users to slow down.&lt;/p&gt;
&lt;p&gt;This configuration can be used to maintain quality of service (QoS) for tenants by asking tenants to slow down by sending &lt;code&gt;429&lt;/code&gt; to the tenant that&amp;rsquo;s overloading the system.&lt;/p&gt;
&lt;h4 id=&#34;guidelines&#34;&gt;Guidelines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;In a dedicated cluster with one big tenant, it’s okay to increase the number for &lt;code&gt;query_frontend.max_outstanding_per_tenant.&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In a shared cluster with a lot of small tenants, keep the number small.&lt;/li&gt;
&lt;li&gt;If a single tenant is overwhelming the whole cluster, you should decrease this parameter. It reduces the amount of work the tenant can enqueue at once. It starts returning &lt;code&gt;429&lt;/code&gt; to the tenant.&lt;/li&gt;
&lt;li&gt;If your tenants are complaining about getting &lt;code&gt;429&lt;/code&gt;, you might want to increase this parameter and scale out queries to handle the query load.&lt;/li&gt;
&lt;li&gt;If you increase other configurations that increase the query throughput or scale queriers, you might want to reduce this parameter to control the amount of work that can be enqueued.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;query_frontendmax_batch_size-parameter&#34;&gt;&lt;code&gt;query_frontend.max_batch_size&lt;/code&gt; parameter&lt;/h3&gt;
&lt;p&gt;The number of jobs to batch together in one HTTP request to the querier.
Large search queries over a longer time range produce thousands of jobs.
Instead of sending jobs one by one, batch the jobs and send them at once.
The querier picks up and process them.&lt;/p&gt;
&lt;p&gt;Batching pushes jobs faster to the queriers, and reduce the time spent waiting around for jobs to be picked up by the querier.&lt;/p&gt;
&lt;h4 id=&#34;guidelines-1&#34;&gt;Guidelines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Default value of &lt;code&gt;max_batch_size&lt;/code&gt; is set to &lt;code&gt;7&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We DO NOT recommend changing the batch size from the default value of &lt;code&gt;7&lt;/code&gt;. Based on testing at Grafana Labs, &lt;code&gt;7&lt;/code&gt; is a good default.&lt;/li&gt;
&lt;li&gt;If the batch size is big, you push more jobs at once but it takes longer for the querier to process the batch and return the results back.&lt;/li&gt;
&lt;li&gt;Big batch size will increase the latency of the querier requests, and they might start hitting timeouts of 5xx, which will increase the rate of retries.&lt;/li&gt;
&lt;li&gt;Bigger &lt;code&gt;max_batch_size&lt;/code&gt; results in pushing too many jobs to the queriers. The jobs then have to be canceled if a query is exited early.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;query_frontendsearchconcurrent_jobs-parameter&#34;&gt;&lt;code&gt;query_frontend.search.concurrent_jobs&lt;/code&gt; parameter&lt;/h3&gt;
&lt;p&gt;The number of concurrent jobs to execute when searching the backend. This controls how much work is produced concurrently.&lt;/p&gt;
&lt;p&gt;To put it another way, if a search job is sharded into 5000 jobs, and &lt;code&gt;concurrent_jobs&lt;/code&gt; is set to 1000, then Tempo only executes 1000 jobs concurrently.
The other 4000 jobs are processed one by one as the first 1000 jobs return the responses.&lt;/p&gt;
&lt;p&gt;If Tempo manages to answer the search query without executing all 5000 jobs, Tempo exits early and cancels the jobs that weren&amp;rsquo;t started.&lt;/p&gt;
&lt;h4 id=&#34;guidelines-2&#34;&gt;Guidelines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;This params controls the numbers of concurrent jobs to the number of jobs to put in the queue at once for processing a query.&lt;/li&gt;
&lt;li&gt;If this number is low, big queries that create lots of jobs processed slowly.&lt;/li&gt;
&lt;li&gt;If this number is high, the frontend pushes work faster to queries, and the frontend needs to cancel those jobs if the search exits early because the query is fulfilled.&lt;/li&gt;
&lt;li&gt;If you see high load, spikes, or OOMs in the queriers, you can lower this configuration for a fair QoS and stability.&lt;/li&gt;
&lt;li&gt;Having this number to a high value will allow a single tenant to push lots of work at once and overwhelm the querier. So keeping it to a lower number in a shared cluster allows for fair scheduling.&lt;/li&gt;
&lt;li&gt;This parameter controls how fast jobs are pushed into the queue for queries to be picked up by queries&lt;/li&gt;
&lt;li&gt;Adjusting this can impact your batch size so that metric should be watched while making changes to this configuration, and make sure that actual batch size is around the &lt;code&gt;max_batch_size&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We recommend keeping it high in dedicated clusters with a single big tenant.&lt;/li&gt;
&lt;li&gt;We recommend keeping it low in shared clusters because it ensures that a single tenant can&amp;rsquo;t overwhelm the read path.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;query_frontendmax_retries-parameter&#34;&gt;&lt;code&gt;query_frontend.max_retries&lt;/code&gt; parameter&lt;/h3&gt;
&lt;p&gt;This option controls the number of times to retry a request sent to a querier.
We only retry on 5xx from a queriers (&lt;em&gt;translated from the equivalent gRPC error&lt;/em&gt;).&lt;/p&gt;
&lt;h4 id=&#34;guidelines-3&#34;&gt;Guidelines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;This option controls the retries from query-frontend to queriers.&lt;/li&gt;
&lt;li&gt;High &lt;code&gt;max_retries&lt;/code&gt; amplifies the slow queriers and result in a lot more load then required.&lt;/li&gt;
&lt;li&gt;Low &lt;code&gt;max_retries&lt;/code&gt; can lead to users having bad experience due failed queriers, because  a job failed and wasn’t retried.&lt;/li&gt;
&lt;li&gt;If there are too many retries in a cluster, it can be a sign that queriers are struggling to finish work and needs to be scaled up.&lt;/li&gt;
&lt;li&gt;Big jobs (high &lt;code&gt;target_bytes_per_job&lt;/code&gt; or &lt;code&gt;max_batch_size&lt;/code&gt;) can result in increased retries. Make the jobs smaller by reducing the &lt;code&gt;target_bytes_per_job&lt;/code&gt; or &lt;code&gt;max_batch_size&lt;/code&gt; to reduce the retries. If not, scale up the queriers.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t set &lt;code&gt;query_frontend.max_retries&lt;/code&gt; to a high number. The default of &lt;code&gt;2&lt;/code&gt; is a good default.&lt;/li&gt;
&lt;li&gt;Higher retries impact the backend when you have a big query that’s generating lots of jobs.&lt;/li&gt;
&lt;li&gt;High &lt;code&gt;max_retries&lt;/code&gt; can overwhelm the queriers when they&amp;rsquo;re under heavy load and failing to process the jobs. Retries can snowball, and degrade the query performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;query_frontendsearchtarget_bytes_per_job-parameter&#34;&gt;&lt;code&gt;query_frontend.search.target_bytes_per_job&lt;/code&gt; parameter&lt;/h3&gt;
&lt;p&gt;The target number of bytes for each job to handle when performing a backend search.&lt;/p&gt;
&lt;p&gt;This parameter controls the size of a single job, and size of a job dictates how much data a single job reads.
You can tune this to make big or small jobs.&lt;/p&gt;
&lt;p&gt;This option controls the upper limit on the size of a job, and can be used as a proxy for  how much data a single search job scans or the amount of work a querier needs to do to process a job.&lt;/p&gt;
&lt;h4 id=&#34;guidelines-4&#34;&gt;Guidelines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Setting this to a small value produces too many jobs, and results in more overhead, setting it too high produces big jobs. Queriers might struggle to finish those jobs and it can lead to high latency.&lt;/li&gt;
&lt;li&gt;In testing at Grafana Labs, 100MB to 200MB is a good range for this configuration, and works across different sizes of clusters.&lt;/li&gt;
&lt;li&gt;We recommend keeping this fixed within the recommended range.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;querierfrontend_workerparallelism-parameter&#34;&gt;&lt;code&gt;querier.frontend_worker.parallelism&lt;/code&gt; parameter&lt;/h3&gt;
&lt;p&gt;Number of simultaneous queries to process per query-frontend or query-scheduler. This configuration controls the number of concurrent requests per query-frontend a querier process.&lt;/p&gt;
&lt;p&gt;If parallelism is set to 5 and there are two query-frontends running, then a querier process opens 5 connections to each query-frontend, and in total of 10 connections.&lt;/p&gt;
&lt;p&gt;One batch (or job, if batching is disabled) is processed per connection, so this controls the maximum number of concurrent jobs processed.&lt;/p&gt;
&lt;p&gt;A single batch is processed in sync and size of the batch is controlled by &lt;code&gt;max_batch_size&lt;/code&gt;, a connection is blocked until it&amp;rsquo;s process and returns the result of a batch.&lt;/p&gt;
&lt;p&gt;You can also disable it and use &lt;code&gt;max_concurrent_connections&lt;/code&gt; but we use this to make sure we queriers are picking up work from both query-frontends and jobs are being scheduled fairly.&lt;/p&gt;
&lt;p&gt;If you want to make sure you always have connections defined in this config, you should set  &lt;code&gt;match_max_concurrent: false&lt;/code&gt; in your configuration to ensure you are not limited by &lt;code&gt;max_concurrent_connections&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;guidelines-5&#34;&gt;Guidelines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Maximum number of jobs a querier processes when using parallelism is equal to &lt;code&gt;parallelism * query_frontend replicas * max_batch_size&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;As you add more queriers, connections to an individual frontend increase. Query-frontend has a shared lock on these connections so if you see issues when you scale out queriers, lower the parallelism to reduce contention.&lt;/li&gt;
&lt;li&gt;It’s recommended to set &lt;code&gt;match_max_concurrent: false&lt;/code&gt; and not set &lt;code&gt;max_concurrent_queries&lt;/code&gt; when using parallelism.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;queriermax_concurrent_queries-parameter&#34;&gt;&lt;code&gt;querier.max_concurrent_queries&lt;/code&gt; parameter&lt;/h3&gt;
&lt;p&gt;This controls the maximum number of jobs a querier processes concurrently. It doesn&amp;rsquo;t distinguish between the types of queries. These jobs can be from two different queries, or different tenants as well.&lt;/p&gt;
&lt;p&gt;Querier processes these in sync, blocks the connection, and once it returns the results, it picks up a new job from the query-frontend queue.&lt;/p&gt;
&lt;h4 id=&#34;guidelines-6&#34;&gt;Guidelines&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;max_concurrent_queries&lt;/code&gt; parameter controls the number of queries that are processed by querier at once (concurrently).&lt;/li&gt;
&lt;li&gt;if queriers are under-utilized, increase this value to process more jobs concurrently and process the queries faster.&lt;/li&gt;
&lt;li&gt;If queriers are over utilized, seeing spikes, or OOMs, you can reduce this config to do less work per queriers and scale out queriers to add more capacity to the cluster.&lt;/li&gt;
&lt;li&gt;This setting depends on the resources, in small queriers, it should be set to a lower number.&lt;/li&gt;
&lt;li&gt;If you have large queriers, this configuration should be set to a higher value to fully utilize the capacity of the querier.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;querier-memory-sizing&#34;&gt;Querier memory sizing&lt;/h2&gt;
&lt;p&gt;If you are seeing that your queries are using more memory then you prefer, reduce the amount of work a querier is doing concurrently. That reduces resource usage.&lt;/p&gt;
&lt;p&gt;If you want your queries to use more memory then they&amp;rsquo;re currently using, increase the amount of work a querier is doing concurrently and it increases the resource usage.&lt;/p&gt;
&lt;p&gt;You can tune &lt;code&gt;query_frontend.search.target_bytes_per_job&lt;/code&gt;, &lt;code&gt;querier.frontend_worker.parallelism&lt;/code&gt;, and &lt;code&gt;querier.max_concurrent_queries&lt;/code&gt; to tune the amount of work a querier is doing concurrently.&lt;/p&gt;
&lt;p&gt;Queriers memory request roughly translates to job size times the concurrent work and some buffer.&lt;/p&gt;
&lt;h2 id=&#34;scaling-cache&#34;&gt;Scaling cache&lt;/h2&gt;
&lt;p&gt;Tempo can be configured to use multiple caches for different types of data.
When configured, Tempo uses these caches to improve the performance of queries.&lt;/p&gt;
&lt;p&gt;Here are few general heuristics to know when to scale a cache:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Look at cache latency. If cache latency is hitting &lt;code&gt;cache_timeout&lt;/code&gt;, that means that cache is under scaled and it’s taking too long to read or write, scale the cache.&lt;/li&gt;
&lt;li&gt;Scale the cache if a cache has a high eviction rate. The cache might be under provisioned.&lt;/li&gt;
&lt;li&gt;Lower level cache like bloom cache, parquet-page cache, parquet-footer cache sees higher hit rates (usually around 90% of above). If you have a consistent query traffic and these lower level caches have low hit rate, they&amp;rsquo;re undervalued and needs to be scaled up.&lt;/li&gt;
&lt;li&gt;Higher level cache like frontend-search cache has a low hit rate and is only useful when the same query is being repeated. Size these according to the amount of data you want you want to cache&lt;/li&gt;
&lt;li&gt;Cache sizes are also dictated by how much data you want to cache at each tier, it’s better to cache more at lower level caches because they have higher hit rate and is useful across queries.&lt;/li&gt;
&lt;/ul&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 searches all of the blocks
in the specified time range.
Depending on your volume, this may result in slow queries.&lt;/p></description></item><item><title>Improve performance with caching</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/caching/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.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;Tempo uses an external cache to improve query performance.
Tempo supports &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; (experimental).&lt;/p&gt;
&lt;h2 id=&#34;cache-roles&#34;&gt;Cache roles&lt;/h2&gt;
&lt;p&gt;Tempo caches different types of data, each assigned a &lt;strong&gt;role&lt;/strong&gt;.
You configure one or more cache instances under the top-level &lt;code&gt;cache:&lt;/code&gt; block and assign roles to each instance.
This lets you size and tune each cache independently based on the workload it handles.&lt;/p&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&gt;Role&lt;/th&gt;
              &lt;th&gt;What it caches&lt;/th&gt;
              &lt;th&gt;Volume&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;bloom&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Bloom filters used for trace ID lookup.&lt;/td&gt;
              &lt;td&gt;Moderate&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;trace-id-index&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Trace ID index used to locate traces within blocks.&lt;/td&gt;
              &lt;td&gt;Moderate&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;parquet-footer&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Parquet file footer metadata. Useful for both search and trace-by-ID queries.&lt;/td&gt;
              &lt;td&gt;Low&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;parquet-column-idx&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Parquet column index sections.&lt;/td&gt;
              &lt;td&gt;Low&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;parquet-offset-idx&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Parquet offset index sections.&lt;/td&gt;
              &lt;td&gt;Low&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;parquet-page&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Parquet data pages. Caches most Parquet reads.&lt;/td&gt;
              &lt;td&gt;&lt;strong&gt;High&lt;/strong&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;frontend-search&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Query-frontend search job results.&lt;/td&gt;
              &lt;td&gt;Varies&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;You can assign multiple roles to a single cache instance, or split high-volume roles (like &lt;code&gt;parquet-page&lt;/code&gt;) onto a dedicated instance.
For example, you might use a large Memcached pool for &lt;code&gt;parquet-page&lt;/code&gt; and a smaller one for &lt;code&gt;bloom&lt;/code&gt; and &lt;code&gt;parquet-footer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For configuration parameters and an example, refer to the 
    &lt;a href=&#34;/docs/tempo/v3.0.x/configuration/#cache&#34;&gt;Cache&lt;/a&gt; section of the Tempo configuration reference.&lt;/p&gt;
&lt;p&gt;For information about search performance, refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/backend_search/&#34;&gt;Tune search performance&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;memcached&#34;&gt;Memcached&lt;/h2&gt;
&lt;p&gt;Memcached is used by default in the Tanka and Helm examples.
Refer to 
    &lt;a href=&#34;/docs/tempo/v3.0.x/set-up-for-tracing/setup-tempo/deploy/&#34;&gt;Deploy 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.
Memcached refuses connections when this limit is surpassed.
You can resolve this issue by increasing the connection limit of Memcached.&lt;/p&gt;
&lt;p&gt;You can use the &lt;code&gt;tempo_memcache_request_duration_seconds_count&lt;/code&gt; metric to observe these errors.
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;../monitor/&#34;&gt;the monitoring dashboards&lt;/a&gt; (the left panel):&lt;/p&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/tempo/caching_memcached_connection_limit.png&#34;
  alt=&#34;QPS and latency of requests to memcached&#34; width=&#34;1631&#34;
     height=&#34;274&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Note that the already open connections continue to function. New connections are refused.&lt;/p&gt;
&lt;p&gt;Additionally, Memcached logs 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;, you can observe the number of open connections 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.&lt;/p&gt;
&lt;p&gt;Tempo provides two configuration parameters 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 configuration options, you can narrow down on which bloom filters are cached, thereby reducing the
cache eviction rate, and increasing the cache hit rate.&lt;/p&gt;
&lt;p&gt;In order to decide the values of these configuration 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&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;/media/docs/tempo/cache-summary.png&#34;
  alt=&#34;Cache summary output&#34; width=&#34;2176&#34;
     height=&#34;418&#34;/&gt;&lt;/p&gt;
&lt;p&gt;This image shows the bloom filter shards over 14 days and 6 compaction levels. This can be used to decide the configuration parameters.&lt;/p&gt;
]]></content><description>&lt;h1 id="improve-performance-with-caching">Improve performance with caching&lt;/h1>
&lt;p>Tempo uses an external cache to improve query performance.
Tempo supports &lt;a href="https://memcached.org/" target="_blank" rel="noopener noreferrer">Memcached&lt;/a> and &lt;a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis&lt;/a> (experimental).&lt;/p>
&lt;h2 id="cache-roles">Cache roles&lt;/h2>
&lt;p>Tempo caches different types of data, each assigned a &lt;strong>role&lt;/strong>.
You configure one or more cache instances under the top-level &lt;code>cache:&lt;/code> block and assign roles to each instance.
This lets you size and tune each cache independently based on the workload it handles.&lt;/p></description></item><item><title>Manage advanced systems</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/manage-advanced-systems/</guid><content><![CDATA[&lt;h1 id=&#34;manage-advanced-systems&#34;&gt;Manage advanced systems&lt;/h1&gt;
&lt;p&gt;This section provides resources for managing and tuning advanced Tempo configurations.
For an overview of Tempo components and how they interact, refer to the 
    &lt;a href=&#34;/docs/tempo/v3.0.x/introduction/architecture/&#34;&gt;Architecture&lt;/a&gt; topic.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/multitenancy/&#34;&gt;Enable multi-tenancy&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/cross_tenant_query/&#34;&gt;Cross-tenant query federation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/user-configurable-overrides/&#34;&gt;User-configurable overrides&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/generic_forwarding/&#34;&gt;Generic forwarding&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/consistent_hash_ring/&#34;&gt;Tune the consistent hash rings&lt;/a&gt;&lt;/li&gt;&lt;li&gt;
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/zone-aware-live-stores/&#34;&gt;Zone-aware replication for live-stores&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
]]></content><description>&lt;h1 id="manage-advanced-systems">Manage advanced systems&lt;/h1>
&lt;p>This section provides resources for managing and tuning advanced Tempo configurations.
For an overview of Tempo components and how they interact, refer to the
&lt;a href="/docs/tempo/v3.0.x/introduction/architecture/">Architecture&lt;/a> topic.&lt;/p></description></item><item><title>Tempo CLI</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/tempo_cli/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.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&amp;rsquo;s 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;Example:&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 available as source code and as a Docker image.&lt;/p&gt;
&lt;h3 id=&#34;run-with-docker-published-image&#34;&gt;Run with Docker (published image)&lt;/h3&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 run --rm grafana/tempo-cli [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;run-directly-with-go-run&#34;&gt;Run directly with &lt;code&gt;go run&lt;/code&gt;&lt;/h3&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;go run ./cmd/tempo-cli [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;build-and-run-a-local-binary&#34;&gt;Build and run a local binary&lt;/h3&gt;
&lt;p&gt;To build a local binary, you need a working Go installation and build environment.&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;make tempo-cli
./bin/$(go env GOOS)/tempo-cli-$(go env GOARCH) [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;build-and-run-a-local-docker-image&#34;&gt;Build and run a local Docker image&lt;/h3&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 --rm 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.
You can configure the backend using the following options:&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-pass &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. Refer to &lt;a href=&#34;../../configuration/hosted-storage/s3/&#34;&gt;S3 permissions documentation&lt;/a&gt; for more information.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--insecure-skip-verify&lt;/code&gt; skip TLS verification, only applies to S3 and GCS.&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&amp;rsquo;s used. For example, &lt;code&gt;--backend &amp;lt;value&amp;gt;&lt;/code&gt; doesn&amp;rsquo;t 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;h3 id=&#34;trace-id&#34;&gt;Trace ID&lt;/h3&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 trace-id &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 the 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;li&gt;&lt;code&gt;--header &amp;lt;key=value&amp;gt;&lt;/code&gt; Extra HTTP header to send with the request. Can be specified multiple times.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--v1&lt;/code&gt; use v1 API (use /api/traces endpoint to fetch traces, default: /api/v2/traces).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 trace-id http://tempo:3200 f1cfe82a8eef933b&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example with a custom authentication header:&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 trace-id http://tempo:3200 f1cfe82a8eef933b --header &amp;#34;X-TOKEN=&amp;lt;API_TOKEN&amp;gt;&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Replace &lt;em&gt;&lt;code&gt;&amp;lt;API_TOKEN&amp;gt;&lt;/code&gt;&lt;/em&gt; with your authentication token.&lt;/p&gt;
&lt;h3 id=&#34;search&#34;&gt;Search&lt;/h3&gt;
&lt;p&gt;Call the Tempo API and search using TraceQL.&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 search &amp;lt;host-port&amp;gt; &amp;lt;trace-ql&amp;gt; [&amp;lt;start&amp;gt; &amp;lt;end&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;host-port&lt;/code&gt; A host/port combination for Tempo. The scheme is inferred from the options.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trace-ql&lt;/code&gt; TraceQL query.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start&lt;/code&gt; Start of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T00:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now-1h&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt; End of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T01:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now&lt;/code&gt;)&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;li&gt;&lt;code&gt;--header &amp;lt;key=value&amp;gt;&lt;/code&gt; Extra header to send with the request (as gRPC metadata when using &lt;code&gt;--use-grpc&lt;/code&gt;). Can be specified multiple times.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--use-grpc&lt;/code&gt; Use GRPC streaming&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--spss &amp;lt;value&amp;gt;&lt;/code&gt; Number of spans to return for each spanset&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--limit &amp;lt;value&amp;gt;&lt;/code&gt; Number of results to return&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--path-prefix &amp;lt;value&amp;gt;&lt;/code&gt; String to prefix search paths with&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--secure&lt;/code&gt; Use HTTPS or gRPC with TLS&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Set the &lt;code&gt;stream_over_http_enabled&lt;/code&gt; flag to true in the Tempo configuration to enable streaming over HTTP. For more information, refer to &lt;a href=&#34;../../api_docs/&#34;&gt;Tempo GRPC API documentation&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Example searching for error spans using relative time:&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 search localhost:3200 &amp;#39;{status = error}&amp;#39; now-1h now&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example searching for error spans using absolute time:&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 search localhost:3200 &amp;#39;{status = error}&amp;#39; 2024-01-01T00:00:00Z 2024-01-01T01:00:00Z&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example using GRPC streaming with organization 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 search --use-grpc --org-id my-org localhost:3200 &amp;#39;{span.http.status_code &amp;gt;= 400}&amp;#39; now-1h now&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example with a custom authentication header over GRPC:&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 search --use-grpc --header &amp;#34;X-TOKEN=&amp;lt;API_TOKEN&amp;gt;&amp;#34; localhost:9095 &amp;#39;{status = error}&amp;#39; now-1h now&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;search-tags&#34;&gt;Search tags&lt;/h3&gt;
&lt;p&gt;Call the Tempo API and search attribute names.&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 search-tags &amp;lt;host-port&amp;gt; [&amp;lt;start&amp;gt; &amp;lt;end&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;host-port&lt;/code&gt; A host/port combination for Tempo. The scheme will be inferred based on the options provided.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start&lt;/code&gt; Start of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T00:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now-1h&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt; End of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T01:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now&lt;/code&gt;)&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;li&gt;&lt;code&gt;--header &amp;lt;key=value&amp;gt;&lt;/code&gt; Extra header to send with the request (as gRPC metadata when using &lt;code&gt;--use-grpc&lt;/code&gt;). Can be specified multiple times.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--use-grpc&lt;/code&gt; Use GRPC streaming&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--path-prefix &amp;lt;value&amp;gt;&lt;/code&gt; String to prefix search paths with&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--secure&lt;/code&gt; Use HTTPS or gRPC with TLS&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Set the &lt;code&gt;stream_over_http_enabled&lt;/code&gt; flag to true in the Tempo configuration to enable streaming over HTTP. For more information, refer to &lt;a href=&#34;../../api_docs/&#34;&gt;Tempo GRPC API documentation&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Example:&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 search-tags localhost:3200&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example with relative time range:&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 search-tags localhost:3200 now-1h now&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example with absolute time range:&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 search-tags localhost:3200 2024-01-01T00:00:00Z 2024-01-02T00:00:00Z&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;search-tag-values&#34;&gt;Search tag values&lt;/h3&gt;
&lt;p&gt;Call the Tempo API and search attribute values.&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 search-tag-values &amp;lt;host-port&amp;gt; &amp;lt;tag&amp;gt; [&amp;lt;start&amp;gt; &amp;lt;end&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;host-port&lt;/code&gt; A host/port combination for Tempo. The scheme is inferred from the options.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tag&lt;/code&gt; The fully qualified TraceQL tag to search for. For example, &lt;code&gt;resource.service.name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start&lt;/code&gt; Start of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T00:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now-1h&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt; End of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T01:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now&lt;/code&gt;)&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;li&gt;&lt;code&gt;--header &amp;lt;key=value&amp;gt;&lt;/code&gt; Extra header to send with the request (as gRPC metadata when using &lt;code&gt;--use-grpc&lt;/code&gt;). Can be specified multiple times.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--query &amp;lt;value&amp;gt;&lt;/code&gt; TraceQL query to filter attribute results by.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--use-grpc&lt;/code&gt; Use GRPC streaming&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--path-prefix &amp;lt;value&amp;gt;&lt;/code&gt; String to prefix search paths with&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--secure&lt;/code&gt; Use HTTP or gRPC with TLS&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Set the &lt;code&gt;stream_over_http_enabled&lt;/code&gt; flag to true in the Tempo configuration to enable streaming over HTTP. For more information, refer to &lt;a href=&#34;../../api_docs/&#34;&gt;Tempo GRPC API documentation&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Example to find all service names:&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 search-tag-values localhost:3200 resource.service.name&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example with query filter to find service names that have errors:&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 search-tag-values --query &amp;#39;{status = error}&amp;#39; localhost:3200 resource.service.name&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;metrics&#34;&gt;Metrics&lt;/h3&gt;
&lt;p&gt;Call the Tempo API and generate metrics from traces using TraceQL.&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 metrics &amp;lt;host-port&amp;gt; &amp;lt;trace-ql metrics query&amp;gt; [&amp;lt;start&amp;gt; &amp;lt;end&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;host-port&lt;/code&gt; A host/port combination for Tempo. The scheme will be inferred based on the options provided.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trace-ql metrics query&lt;/code&gt; TraceQL metrics query.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start&lt;/code&gt; Start of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T00:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now-1h&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt; End of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T01:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now&lt;/code&gt;)&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;li&gt;&lt;code&gt;--header &amp;lt;key=value&amp;gt;&lt;/code&gt; Extra header to send with the request (as gRPC metadata when using &lt;code&gt;--use-grpc&lt;/code&gt;). Can be specified multiple times.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--use-grpc&lt;/code&gt; Use GRPC streaming&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--instant&lt;/code&gt; Perform an instant query instead of a range query.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--path-prefix &amp;lt;value&amp;gt;&lt;/code&gt; String to prefix search paths with&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--secure&lt;/code&gt; Use HTTPS or gRPC with TLS&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Set the &lt;code&gt;stream_over_http_enabled&lt;/code&gt; flag to true in the Tempo configuration to enable streaming over HTTP. For more information, refer to &lt;a href=&#34;../../api_docs/&#34;&gt;Tempo GRPC API documentation&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Example range query for request rates by service:&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 metrics localhost:3200 &amp;#39;{} | rate() by (resource.service.name)&amp;#39; now-1h now&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example instant query for current error rates:&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 metrics --instant localhost:3200 &amp;#39;{status = error} | rate()&amp;#39; now-1h now&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;query-trace-id-command&#34;&gt;Query trace-id 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 trace-id &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;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;This can be intense as it downloads every bloom filter and some percentage of indexes/trace data.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--percentage &amp;lt;value&amp;gt;&lt;/code&gt; Percentage of blocks to scan (for example, 0.1 for 10%). Useful for sampling large datasets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 trace-id f1cfe82a8eef933b single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example scanning only 10% of blocks:&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 trace-id --percentage 0.1 f1cfe82a8eef933b single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;query-trace-summary-command&#34;&gt;Query trace summary command&lt;/h2&gt;
&lt;p&gt;Iterate over all backend blocks and dump a summary for a given trace ID.&lt;/p&gt;
&lt;p&gt;The summary includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;number of blocks the trace is found in&lt;/li&gt;
&lt;li&gt;span count&lt;/li&gt;
&lt;li&gt;trace size&lt;/li&gt;
&lt;li&gt;trace duration&lt;/li&gt;
&lt;li&gt;root service name&lt;/li&gt;
&lt;li&gt;root span info&lt;/li&gt;
&lt;li&gt;top frequent service names&lt;/li&gt;
&lt;/ul&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 trace-summary &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;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;This can be intense as it downloads every bloom filter and some percentage of indexes/trace data.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--percentage &amp;lt;value&amp;gt;&lt;/code&gt; Percentage of blocks to scan (for example, 0.1 for 10%). Useful for sampling large datasets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 trace-summary 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;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;Example:&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-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 compaction 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;Example:&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;Example:&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-column&#34;&gt;List column&lt;/h2&gt;
&lt;p&gt;Lists values in a given column of a block. Useful for inspecting parquet block data directly.&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 column &amp;lt;tenant-id&amp;gt; &amp;lt;block-id&amp;gt; [column-name]&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;li&gt;&lt;code&gt;column-name&lt;/code&gt; Column name to list values of (default: &lt;code&gt;TraceID&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 column -c ./tempo.yaml single-tenant ca314fba-efec-4852-ba3f-8d2b0bbf69f1 TraceID&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;view-schema&#34;&gt;View schema&lt;/h2&gt;
&lt;p&gt;View block metadata, parquet schema structure, and column sizes for a 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 schema &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;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The output includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Block metadata&lt;/li&gt;
&lt;li&gt;Parquet schema structure&lt;/li&gt;
&lt;li&gt;Column sizes in KB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 schema -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;query-search-command&#34;&gt;Query search 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 query search &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;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;This can be intense as it downloads all relevant blocks and iterates through them.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&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, for example, &lt;code&gt;http.method&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt; Value of the attribute to search for, for example, &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 in RFC3339 format (e.g. &lt;code&gt;2024-01-01T00:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now-1h&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt; End of the time range to search in RFC3339 format (e.g. &lt;code&gt;2024-01-01T01:00:00Z&lt;/code&gt;) or relative (e.g. &lt;code&gt;now&lt;/code&gt;)&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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example using relative time:&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 search http.method GET now-1h now single-tenant --backend=gcs --bucket=tempo-trace-data&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example using absolute time:&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 search http.method GET 2024-01-01T00:00:00Z 2024-01-01T00:05:00Z 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-a-to-b-command&#34;&gt;Parquet convert A to B command&lt;/h2&gt;
&lt;p&gt;Converts a vParquet file (actual data.parquet) of format A to a block of newer format B with an optional list of dedicated attribute columns.
Actual supported versions for A and B vary by Tempo release. This utility command is useful when testing the impact of different combinations
of dedicated columns.&lt;/p&gt;
&lt;h3 id=&#34;convert-vparquet3-to-vparquet4&#34;&gt;Convert vParquet3 to vParquet4&lt;/h3&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;&lt;code&gt;vParquet3&lt;/code&gt; is deprecated. Convert any remaining vParquet3 blocks to vParquet4 or later before upgrading to Tempo 3.0.&lt;/p&gt;&lt;/blockquote&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;tempo-cli parquet convert-3to4 &amp;lt;in file&amp;gt; [&amp;lt;out path&amp;gt;] [&amp;lt;list of dedicated columns&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; Path to an existing vParquet3 block directory.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;out path&lt;/code&gt; Path to write the vParquet4 block to. The default is &lt;code&gt;./out&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;list of dedicated columns&lt;/code&gt; Optional list of columns to make dedicated. Columns use TraceQL syntax with scope. For example, &lt;code&gt;span.db.statement&lt;/code&gt;, &lt;code&gt;resource.namespace&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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-3to4 ./block-in ./out span.db.statement span.db.name&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;convert-vparquet4-to-vparquet5&#34;&gt;Convert vParquet4 to vParquet5&lt;/h3&gt;
&lt;p&gt;Converts a vParquet4 block to vParquet5 format with an optional list of dedicated attribute 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-4to5 &amp;lt;in file&amp;gt; [&amp;lt;out path&amp;gt;] [&amp;lt;list of dedicated columns&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; Path to an existing vParquet4 block directory.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;out path&lt;/code&gt; Path to write the vParquet5 block to. The default is &lt;code&gt;./out&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;list of dedicated columns&lt;/code&gt; Optional list of columns to make dedicated. Columns use TraceQL syntax with scope. For example, &lt;code&gt;span.http.method&lt;/code&gt;, &lt;code&gt;resource.namespace&lt;/code&gt;, &lt;code&gt;event.exception.message&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Column prefixes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;int/&lt;/code&gt; marks the column as an integer type. For example, &lt;code&gt;int/span.http.status_code&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;blob/&lt;/code&gt; marks the column for blob encoding. For example, &lt;code&gt;blob/span.db.statement&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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-4to5 ./block-in ./block-out &amp;#34;span.http.method&amp;#34; &amp;#34;int/span.http.status_code&amp;#34; &amp;#34;blob/span.db.statement&amp;#34;&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. The data format isn&amp;rsquo;t converted but the tenant ID in &lt;code&gt;meta.json&lt;/code&gt; is 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; (required) 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;Example:&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-file source.yaml --config-file dest.yaml my-tenant my-other-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;migrate-overrides-config-command&#34;&gt;Migrate overrides config command&lt;/h2&gt;
&lt;p&gt;Migrate the overrides section of a full Tempo config file from the legacy flat format to the new scoped format.
The command reads the full config, converts any legacy overrides, and outputs only user-set values.&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 overrides-config &amp;lt;config-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;config-file&lt;/code&gt; Path to the full Tempo config file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-d, --config-dest &amp;lt;path&amp;gt;&lt;/code&gt; Path to write the migrated overrides section. If not specified, output is printed to &lt;code&gt;stdout&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 overrides-config config.yaml -d migrated-overrides.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Fields set to Go zero values (&lt;code&gt;false&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;) may be silently dropped due to &lt;code&gt;omitempty&lt;/code&gt; tags. Compare against your original config to ensure nothing is lost.&lt;/li&gt;
&lt;li&gt;Secret values (for example, &lt;code&gt;remote_write_headers&lt;/code&gt;) are masked as &lt;code&gt;&amp;lt;secret&amp;gt;&lt;/code&gt; in the output. You must manually restore the original values.&lt;/li&gt;
&lt;li&gt;Some struct fields without &lt;code&gt;omitempty&lt;/code&gt; may appear with zero values (for example, &lt;code&gt;exclude: null&lt;/code&gt;) that were not in your original config.&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;migrate-overrides-per-tenant-command&#34;&gt;Migrate overrides per-tenant command&lt;/h2&gt;
&lt;p&gt;Migrate a per-tenant overrides file from the legacy flat format to the new scoped format.
The command handles both legacy and new format entries, and outputs only tenant-specific values.&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 overrides-per-tenant &amp;lt;overrides-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;overrides-file&lt;/code&gt; Path to the per-tenant overrides file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-d, --output-dest &amp;lt;path&amp;gt;&lt;/code&gt; Path to write the migrated per-tenant overrides. If not specified, output is printed to &lt;code&gt;stdout&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 overrides-per-tenant overrides.yaml -d migrated-overrides.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Fields set to Go zero values (&lt;code&gt;false&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;) may be silently dropped due to &lt;code&gt;omitempty&lt;/code&gt; tags. Compare against your original config to ensure nothing is lost.&lt;/li&gt;
&lt;li&gt;Secret values (for example, &lt;code&gt;remote_write_headers&lt;/code&gt;) are masked as &lt;code&gt;&amp;lt;secret&amp;gt;&lt;/code&gt; in the output. You must manually restore the original values.&lt;/li&gt;
&lt;li&gt;Some struct fields without &lt;code&gt;omitempty&lt;/code&gt; may appear with zero values (for example, &lt;code&gt;exclude: null&lt;/code&gt;) that were not in your original config.&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;migrate-config-command&#34;&gt;Migrate config command&lt;/h2&gt;
&lt;p&gt;Migrate a Tempo 2.x configuration file to a valid 3.0 configuration. The command removes obsolete configuration sections (such as &lt;code&gt;ingester&lt;/code&gt;, &lt;code&gt;ingester_client&lt;/code&gt;, and &lt;code&gt;compactor&lt;/code&gt;), adds Kafka ingest configuration for microservices mode, disables compaction in overrides for parallel operation during migration, and strips the removed &lt;code&gt;local-blocks&lt;/code&gt; metrics-generator processor.&lt;/p&gt;
&lt;p&gt;The tool works at the YAML map level rather than rewriting the file from fully decoded Tempo structs, so environment variable references like &lt;code&gt;${VAR}&lt;/code&gt; are preserved.
Top-level sections that are not recognized by the Tempo 3.0 configuration are dropped from the output.
Unknown nested keys normally cause validation to fail, but validation is best-effort when the configuration contains &lt;code&gt;${VAR}&lt;/code&gt; placeholders where non-string types are expected, which may let unknown nested keys through.&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 config [options] &amp;lt;config-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;config-file&lt;/code&gt; Path to the 2.x Tempo configuration file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--kafka-address &amp;lt;address&amp;gt;&lt;/code&gt; Kafka broker address. Required when running in microservices mode.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--kafka-topic &amp;lt;topic&amp;gt;&lt;/code&gt; Kafka topic name. Defaults to &lt;code&gt;tempo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--mode &amp;lt;monolithic|microservices&amp;gt;&lt;/code&gt; Override automatic deployment mode detection. By default, the mode is detected from the &lt;code&gt;target&lt;/code&gt; field (&lt;code&gt;all&lt;/code&gt; or absent means monolithic, any other value means microservices).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The migrated configuration is printed to &lt;code&gt;stdout&lt;/code&gt;. Warnings are printed to &lt;code&gt;stderr&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;examples&#34;&gt;Examples&lt;/h3&gt;
&lt;p&gt;Monolithic mode (no Kafka flags needed):&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 config old-config.yaml &amp;gt; new-config.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Microservices mode:&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 config --kafka-address=kafka:9092 --kafka-topic=tempo-traces old-config.yaml &amp;gt; new-config.yaml&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;The output is a starting point for your 3.0 configuration. Always review it before deploying.&lt;/li&gt;
&lt;li&gt;If your configuration uses legacy (flat) overrides, you must run &lt;code&gt;tempo-cli migrate overrides-config&lt;/code&gt; first.&lt;/li&gt;
&lt;li&gt;If your configuration references an external per-tenant overrides file (&lt;code&gt;per_tenant_override_config&lt;/code&gt;), you must manually add &lt;code&gt;compaction_disabled: true&lt;/code&gt; for each tenant in that file.&lt;/li&gt;
&lt;li&gt;YAML comments and key ordering from the original file are not preserved.&lt;/li&gt;
&lt;li&gt;Remove &lt;code&gt;compaction_disabled: true&lt;/code&gt; from overrides after fully decommissioning your 2.x deployment.&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;analyse-block&#34;&gt;Analyse block&lt;/h2&gt;
&lt;!-- Note that the command uses analyse and not analyze --&gt;
&lt;p&gt;Analyses a block and outputs a summary of the block&amp;rsquo;s generic attributes.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s of particular use when trying to determine candidates for dedicated attribute columns in vParquet3&#43;.
The output includes span, resource, and event attributes with cardinality and size information.&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;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--num-attr &amp;lt;value&amp;gt;&lt;/code&gt; Number of attributes to output (default: 20)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--num-int-attr &amp;lt;value&amp;gt;&lt;/code&gt; Number of integer attributes to display. If set to 0, uses the &lt;code&gt;--num-attr&lt;/code&gt; value (default: 5)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--blob-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Mark attributes as blob candidates when their dictionary size per row group exceeds this value. Set to 0 to disable. (default: 4MiB)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--include-well-known&lt;/code&gt; Include well-known attributes in the analysis. Enable when generating dedicated columns for vParquet5 or higher. (default: false)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--generate-jsonnet&lt;/code&gt; Generate Jsonnet overrides for dedicated columns&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--generate-cli-args&lt;/code&gt; Generate command-line arguments for the parquet conversion command&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--int-percent-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Threshold for integer attributes in dedicated columns (default: 0.05)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--str-percent-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Threshold for string attributes in dedicated columns (default: 0.03)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--simple-summary&lt;/code&gt; Print only a single line of top attributes (default: false)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--print-full-summary&lt;/code&gt; Print full summary of the analysed block (default: true)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 analyse block --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;Example with blob detection:&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 analyse block --blob-threshold=4MiB --generate-jsonnet --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;h2 id=&#34;analyse-blocks&#34;&gt;Analyse blocks&lt;/h2&gt;
&lt;p&gt;Analyses all blocks in a given time range and outputs a summary of the blocks&amp;rsquo; generic attributes.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s of particular use when trying to determine candidates for dedicated attribute columns in vParquet3&#43;.
The output includes span, resource, and event attributes with cardinality and size information.&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;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--num-attr &amp;lt;value&amp;gt;&lt;/code&gt; Number of attributes to output (default: 20)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--num-int-attr &amp;lt;value&amp;gt;&lt;/code&gt; Number of integer attributes to display. If set to 0, uses the &lt;code&gt;--num-attr&lt;/code&gt; value (default: 5)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--min-compaction-level &amp;lt;value&amp;gt;&lt;/code&gt; Minimum compaction level to include in the analysis (default: 3)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--max-blocks &amp;lt;value&amp;gt;&lt;/code&gt; Maximum number of blocks to analyze (default: 10)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--max-start-time &amp;lt;value&amp;gt;&lt;/code&gt; Oldest start time for a block to be processed. RFC3339 format (default: disabled)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--min-start-time &amp;lt;value&amp;gt;&lt;/code&gt; Newest start time for a block to be processed. RFC3339 format (default: disabled)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--blob-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Mark attributes as blob candidates when their dictionary size per row group exceeds this value. Set to 0 to disable. (default: 4MiB)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--include-well-known&lt;/code&gt; Include well-known attributes in the analysis. (default: false)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--jsonnet&lt;/code&gt; Generate Jsonnet overrides for dedicated columns&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--cli&lt;/code&gt; Generate command-line arguments for the parquet conversion command&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--int-percent-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Threshold for integer attributes in dedicated columns (default: 0.05)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--str-percent-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Threshold for string attributes in dedicated columns (default: 0.03)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--simple-summary&lt;/code&gt; Print only a single line of top attributes (default: false)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--print-full-summary&lt;/code&gt; Print full summary of the analysed block (default: true)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 analyse blocks --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example with blob detection and Jsonnet output:&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 analyse blocks --blob-threshold=4MiB --jsonnet --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;suggest-columns&#34;&gt;Suggest columns&lt;/h2&gt;
&lt;p&gt;Suggests dedicated columns for a tenant based on analysis of blocks. This command analyzes block data and outputs configuration recommendations in YAML or Jsonnet format that can be used to configure dedicated attribute 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 suggest columns &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;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--block-id &amp;lt;value&amp;gt;&lt;/code&gt; Specific block ID to analyse. If not provided, analyzes multiple blocks.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--min-compaction-level &amp;lt;value&amp;gt;&lt;/code&gt; Minimum compaction level to analyse (default: 3)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--max-blocks &amp;lt;value&amp;gt;&lt;/code&gt; Maximum number of blocks to analyse (default: 10)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--num-attr &amp;lt;value&amp;gt;&lt;/code&gt; Number of attributes to display (default: 20)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--num-int-attr &amp;lt;value&amp;gt;&lt;/code&gt; Number of integer attributes to display. If set to 0, uses the &lt;code&gt;--num-attr&lt;/code&gt; value (default: 5)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--int-percent-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Threshold for integer attributes put in dedicated columns (default: 0.05)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--str-percent-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Threshold for string attributes in dedicated columns (default: 0.03)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--include-well-known&lt;/code&gt; Include well-known attributes in the analysis (default: true)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--blob-threshold &amp;lt;value&amp;gt;&lt;/code&gt; Convert column to blob when dictionary size reaches this value (default: 4MiB)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--max-start-time &amp;lt;value&amp;gt;&lt;/code&gt; Oldest start time for a block to be processed. RFC3339 format.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--min-start-time &amp;lt;value&amp;gt;&lt;/code&gt; Newest start time for a block to be processed. RFC3339 format.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-o, --out &amp;lt;value&amp;gt;&lt;/code&gt; File to write output to. If not specified, output is printed to stdout.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-f, --format &amp;lt;jsonnet|yaml&amp;gt;&lt;/code&gt; Output format (default: yaml)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example outputting YAML to a file:&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 suggest columns -c ./tempo.yaml --format yaml --out suggestions.yaml single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example outputting Jsonnet for use in overrides:&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 suggest columns -c ./tempo.yaml --format jsonnet single-tenant&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;generate-attribute-index&#34;&gt;Generate attribute index&lt;/h2&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;This command is EXPERIMENTAL and meant to facilitate experimentation with different kinds of indexes.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Generate an attribute index for a parquet block. This creates an index file that can be used for faster attribute lookups.&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 attr-index &amp;lt;input-path&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;input-path&lt;/code&gt; Path to the input parquet block directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--add-intrinsics&lt;/code&gt; Add intrinsic attributes to the index such as name, kind, status, and others.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--index-types &amp;lt;rows|codes|rows,codes&amp;gt;&lt;/code&gt; Type of index to generate (default: rows,codes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&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 attr-index ./path/to/block&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Example with intrinsic attributes:&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 attr-index --add-intrinsics ./path/to/block&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;drop-traces-by-id&#34;&gt;Drop traces by ID&lt;/h2&gt;
&lt;p&gt;Rewrites all blocks for a tenant that contain specific trace IDs. The traces are dropped from
the new blocks and the rewritten blocks are marked compacted so they will be cleaned up.&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 rewrite-blocks drop-traces &amp;lt;tenant-id&amp;gt; &amp;lt;trace-ids&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;trace-ids&lt;/code&gt; The comma-separated trace IDs to drop (also supports single trace ID).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#backend-options&#34;&gt;Backend options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--drop-trace&lt;/code&gt; By default, this command runs in dry run mode. Supplying this argument causes it to actually rewrite blocks with the traces dropped.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--background&lt;/code&gt; Run in background mode (default: false). Suppresses progress dots for use in automated scripts.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;examples-1&#34;&gt;Examples&lt;/h3&gt;
&lt;p&gt;Dry run (default) to see which blocks would be affected:&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 rewrite-blocks drop-traces --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant 04d5f549746c96e4f3daed6202571db2&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Drop one trace (actually perform the operation):&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 rewrite-blocks drop-traces --drop-trace --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant 04d5f549746c96e4f3daed6202571db2&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Drop multiple traces:&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 rewrite-blocks drop-traces --drop-trace --backend=local --bucket=./cmd/tempo-cli/test-data/ single-tenant 04d5f549746c96e4f3daed6202571db2,111fa1850042aea83c17cd7e674210b8&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;redact-traces&#34;&gt;Redact traces&lt;/h2&gt;
&lt;p&gt;Remove traces containing personally identifiable information or other sensitive data from object storage without waiting for retention to expire.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;redact&lt;/code&gt; command submits a redaction request to the 
    &lt;a href=&#34;/docs/tempo/v3.0.x/reference-tempo-architecture/components/compaction/#backend-scheduler&#34;&gt;backend scheduler&lt;/a&gt;.
The scheduler creates jobs that rewrite affected blocks in object storage to remove the specified traces.
Unlike &lt;a href=&#34;#drop-traces-by-id&#34;&gt;&lt;code&gt;drop-traces&lt;/code&gt;&lt;/a&gt;, which operates directly on object storage from the CLI, &lt;code&gt;redact&lt;/code&gt; delegates the work to the backend scheduler over gRPC.&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 redact --tenant=&amp;lt;TENANT_ID&amp;gt; --trace-id=&amp;lt;TRACE_ID&amp;gt; [--trace-id=&amp;lt;TRACE_ID&amp;gt; ...] &amp;lt;scheduler-address&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;scheduler-address&lt;/code&gt; The backend scheduler gRPC address (&lt;code&gt;host:port&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--tenant &amp;lt;value&amp;gt;&lt;/code&gt; &lt;strong&gt;(required)&lt;/strong&gt; Tenant ID.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--trace-id &amp;lt;value&amp;gt;&lt;/code&gt; &lt;strong&gt;(required)&lt;/strong&gt; Trace ID to redact, in hex format. Specify multiple times to redact several traces in one request.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--tls&lt;/code&gt; Use TLS for the gRPC connection (default: &lt;code&gt;false&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--tls-server-name &amp;lt;value&amp;gt;&lt;/code&gt; Override the TLS server name (SNI).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--tls-ca &amp;lt;value&amp;gt;&lt;/code&gt; Path to a PEM-encoded CA certificate file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On success, the command prints the batch ID and the number of jobs created:&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;batch_id:     &amp;lt;BATCH_ID&amp;gt;
jobs_created: &amp;lt;COUNT&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Monitor job progress through the 
    &lt;a href=&#34;/docs/tempo/v3.0.x/api_docs/#backend-scheduler-job-status&#34;&gt;&lt;code&gt;/status/backendscheduler&lt;/code&gt;&lt;/a&gt; endpoint.&lt;/p&gt;
&lt;h3 id=&#34;examples-2&#34;&gt;Examples&lt;/h3&gt;
&lt;p&gt;Redact a single trace:&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 redact --tenant=my-tenant --trace-id=931281e2a09876de16e15f45ff86283d localhost:9095&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Redact multiple traces in one request:&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 redact --tenant=my-tenant --trace-id=931281e2a09876de16e15f45ff86283d --trace-id=00000000000000000000000000000001 localhost:9095&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With TLS and a custom CA:&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 redact --tenant=my-tenant --trace-id=931281e2a09876de16e15f45ff86283d --tls --tls-ca=/path/to/ca.pem scheduler.example.com:9095&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&amp;rsquo;s not required for a working installation, Tempo CLI can be helpful for deeper analysis or for troubleshooting.&lt;/p></description></item><item><title>Tempo Vulture</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/tempo-vulture/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/tempo-vulture/</guid><content><![CDATA[&lt;h1 id=&#34;tempo-vulture&#34;&gt;Tempo Vulture&lt;/h1&gt;
&lt;p&gt;Tempo Vulture is a testing tool that validates the end-to-end functionality of Tempo by continuously writing traces and verifying they can be read back correctly.
It is useful for monitoring data integrity in production environments and for post-deployment validation testing.&lt;/p&gt;
&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;Tempo Vulture performs the following operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write traces: Pushes test traces to Tempo using OTLP over gRPC&lt;/li&gt;
&lt;li&gt;Read traces by ID: Queries Tempo to retrieve traces by their trace ID&lt;/li&gt;
&lt;li&gt;Search traces: Uses TraceQL to search for traces by attributes&lt;/li&gt;
&lt;li&gt;Metrics queries: Validates TraceQL metrics queries (enabled by default)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tempo Vulture can run in two modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Continuous mode (default): Runs indefinitely, continuously writing and reading traces while exposing Prometheus metrics&lt;/li&gt;
&lt;li&gt;Validation mode: Executes a fixed number of write/read cycles and exits with a status code indicating success or failure&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;run-tempo-vulture&#34;&gt;Run Tempo Vulture&lt;/h2&gt;
&lt;p&gt;Tempo Vulture is available as a 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;docker run grafana/tempo-vulture:latest [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can also build it from source:&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;make tempo-vulture
./tempo-vulture [arguments...]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;configuration-flags&#34;&gt;Configuration flags&lt;/h2&gt;
&lt;p&gt;Configure Tempo Vulture using command-line flags.&lt;/p&gt;
&lt;h3 id=&#34;required-flags&#34;&gt;Required flags&lt;/h3&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&gt;Flag&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
              &lt;th&gt;Example&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-query-url&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The URL (scheme://hostname) at which to query Tempo&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;http://tempo:3200&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-push-url&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The URL (scheme://hostname:port) at which to push traces to Tempo&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;http://tempo:4317&lt;/code&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;optional-flags&#34;&gt;Optional flags&lt;/h3&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&gt;Flag&lt;/th&gt;
              &lt;th&gt;Default&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-org-id&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The org ID to use when querying Tempo (for multi-tenant deployments)&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-push-tls&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Whether to use TLS when pushing spans to Tempo&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-write-backoff-duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;15s&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Time to pause between write operations&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-long-write-backoff-duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;1m&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Time to pause between long write operations&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-read-backoff-duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;30s&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Time to pause between read operations&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-search-backoff-duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;1m&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Time to pause between search operations. Set to &lt;code&gt;0s&lt;/code&gt; to disable search validation&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-metrics-backoff-duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;10s&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Time to pause between TraceQL metrics operations. Set to &lt;code&gt;0s&lt;/code&gt; to disable&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-retention-duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;336h&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;The block retention that Tempo is using&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-recent-traces-backoff-duration&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;14m&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Cutoff between recent and old traces query checks&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--tempo-query-livestore&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Whether to query live stores&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--prometheus-listen-address&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;:80&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Address to listen on for Prometheus scrapes&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--prometheus-path&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;/metrics&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Path to publish Prometheus metrics&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;validation-mode-flags&#34;&gt;Validation mode flags&lt;/h3&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&gt;Flag&lt;/th&gt;
              &lt;th&gt;Default&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--validation-mode&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Run in validation mode: execute a fixed number of cycles and exit&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--validation-cycles&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Number of write/read cycles to perform in validation mode&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;--validation-timeout&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;&lt;code&gt;5m&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Maximum time to run validation mode before timing out&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h2 id=&#34;continuous-mode&#34;&gt;Continuous mode&lt;/h2&gt;
&lt;p&gt;In continuous mode, Tempo Vulture runs indefinitely and exposes Prometheus metrics that can be used for monitoring and alerting.&lt;/p&gt;
&lt;h3 id=&#34;example&#34;&gt;Example&lt;/h3&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 run grafana/tempo-vulture:latest \
  --tempo-query-url=http://tempo:3200 \
  --tempo-push-url=http://tempo:4317 \
  --tempo-org-id=my-tenant \
  --tempo-write-backoff-duration=15s \
  --tempo-read-backoff-duration=30s \
  --tempo-search-backoff-duration=60s&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;prometheus-metrics&#34;&gt;Prometheus metrics&lt;/h3&gt;
&lt;p&gt;Tempo Vulture exposes the following key metrics:&lt;/p&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&gt;Metric&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;tempo_vulture_trace_total&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Counter&lt;/td&gt;
              &lt;td&gt;Total number of trace operations performed&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;tempo_vulture_trace_error_total&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Counter&lt;/td&gt;
              &lt;td&gt;Total number of trace errors by error type&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;p&gt;Error types include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;incorrectresult&lt;/code&gt;: Retrieved trace doesn&amp;rsquo;t match the expected trace&lt;/li&gt;
&lt;li&gt;&lt;code&gt;incorrect_metrics_result&lt;/code&gt;: Metrics query returned unexpected results&lt;/li&gt;
&lt;li&gt;&lt;code&gt;missingspans&lt;/code&gt;: Trace has missing spans&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notfound_byid&lt;/code&gt;: Trace not found by ID&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notfound_search&lt;/code&gt;: Trace not found via search&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notfound_traceql&lt;/code&gt;: Trace not found via TraceQL&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notfound_metrics&lt;/code&gt;: Trace not found via metrics query&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notfound_search_attribute&lt;/code&gt;: No searchable attribute found in trace&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inaccurate_metrics&lt;/code&gt;: Metrics count doesn&amp;rsquo;t match actual span count&lt;/li&gt;
&lt;li&gt;&lt;code&gt;requestfailed&lt;/code&gt;: Request to Tempo failed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;alerting&#34;&gt;Alerting&lt;/h3&gt;
&lt;p&gt;You can configure alerts based on Tempo Vulture metrics.
For example, the Tempo mixin includes a &lt;a href=&#34;https://github.com/grafana/tempo/blob/08325a7d5da6a330ac5564265eee52e13544abc9/operations/tempo-mixin/alerts.libsonnet#L426&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;TempoVultureHighErrorRate&lt;/code&gt; alert&lt;/a&gt; that fires when the error rate exceeds a configurable threshold.&lt;/p&gt;
&lt;h2 id=&#34;validation-mode&#34;&gt;Validation mode&lt;/h2&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Validation mode was added in Tempo 2.10.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;Validation mode runs Tempo Vulture as a one-shot test that can be integrated into CI/CD pipelines for post-deployment validation.
Instead of running continuously, it executes a fixed number of write/read cycles and exits with a status code indicating success or failure.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;Running Vulture as a Deployment while in validation mode causes problems in Kubernetes. Because Deployments expect long-running processes, a container that finishes its task and exits triggers a &lt;code&gt;CrashLoopBackOff&lt;/code&gt; (even with exit code &lt;code&gt;0&lt;/code&gt;). Run validation mode as a Job instead.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;exit-codes&#34;&gt;Exit codes&lt;/h3&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&gt;Exit code&lt;/th&gt;
              &lt;th&gt;Meaning&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;All validations passed&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;One or more validations failed, or configuration error&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;environment-variables&#34;&gt;Environment variables&lt;/h3&gt;
&lt;p&gt;Validation mode requires authentication:&lt;/p&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&gt;Variable&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;TEMPO_ACCESS_POLICY_TOKEN&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;Access policy token for authenticating with Tempo (required in validation mode)&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;example-1&#34;&gt;Example&lt;/h3&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 run \
  -e TEMPO_ACCESS_POLICY_TOKEN=your-token \
  grafana/tempo-vulture:latest \
  --tempo-query-url=https://tempo.example.com \
  --tempo-push-url=https://tempo.example.com:4317 \
  --tempo-org-id=my-tenant \
  --validation-mode \
  --validation-cycles=5 \
  --validation-timeout=10m&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;cicd-pipeline-integration&#34;&gt;CI/CD pipeline integration&lt;/h3&gt;
&lt;p&gt;Validation mode is useful for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Post-deployment testing&lt;/strong&gt;: Verify Tempo is functioning correctly after a deployment&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smoke testing&lt;/strong&gt;: Quick validation that write and read paths are working&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration testing&lt;/strong&gt;: Ensure end-to-end trace pipeline is operational&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example CI/CD usage in a GitHub Actions workflow:&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;- name: Validate Tempo deployment
  run: |
    docker run \
      -e TEMPO_ACCESS_POLICY_TOKEN=${{ secrets.TEMPO_TOKEN }} \
      grafana/tempo-vulture:latest \
      --tempo-query-url=${{ vars.TEMPO_URL }} \
      --tempo-push-url=${{ vars.TEMPO_PUSH_URL }} \
      --tempo-org-id=${{ vars.TEMPO_ORG_ID }} \
      --validation-mode \
      --validation-cycles=3 \
      --validation-timeout=5m&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;validation-process&#34;&gt;Validation process&lt;/h3&gt;
&lt;p&gt;In validation mode, Tempo Vulture performs these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;For each cycle (default: 3):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write a test trace to Tempo&lt;/li&gt;
&lt;li&gt;Wait briefly for ingestion&lt;/li&gt;
&lt;li&gt;Read the trace back by ID and verify it matches&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After all cycles complete:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wait for traces to be searchable (if search is enabled)&lt;/li&gt;
&lt;li&gt;Search for each trace using a random attribute&lt;/li&gt;
&lt;li&gt;Verify all traces are found&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exit with code &lt;code&gt;0&lt;/code&gt; if all validations pass, or &lt;code&gt;1&lt;/code&gt; if any fail&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;docker-compose-example&#34;&gt;Docker Compose example&lt;/h2&gt;
&lt;p&gt;The Tempo repository includes Docker Compose examples that demonstrate how to run Tempo Vulture.
Refer to the &lt;a href=&#34;https://github.com/grafana/tempo/tree/main/example/docker-compose&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;example configurations&lt;/a&gt; for complete setups.&lt;/p&gt;
&lt;p&gt;Example from a Docker Compose file:&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;vulture:
  image: grafana/tempo-vulture:latest
  command:
    - &amp;#34;-tempo-push-url=http://distributor:4317&amp;#34;
    - &amp;#34;-tempo-query-url=http://query-frontend:3200&amp;#34;
    - &amp;#34;-tempo-org-id=&amp;#34;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="tempo-vulture">Tempo Vulture&lt;/h1>
&lt;p>Tempo Vulture is a testing tool that validates the end-to-end functionality of Tempo by continuously writing traces and verifying they can be read back correctly.
It is useful for monitoring data integrity in production environments and for post-deployment validation testing.&lt;/p></description></item><item><title>Apache Parquet schema</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/schema/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/schema/</guid><content><![CDATA[&lt;h1 id=&#34;apache-parquet-schema&#34;&gt;Apache Parquet schema&lt;/h1&gt;
&lt;!-- vale Grafana.GoogleSpacing = NO --&gt;
&lt;!-- vale Grafana.We = NO --&gt;
&lt;!-- vale Grafana.GooglePassive = NO --&gt;
&lt;!-- vale Grafana.GoogleWill = NO --&gt;
&lt;p&gt;Apache Parquet is the only supported block format in Tempo 3.0.
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;version-applicability&#34;&gt;Version applicability&lt;/h2&gt;
&lt;p&gt;Tempo defaults to the vParquet4 schema. vParquet5 is production-ready and differs in some schema details.
Unless otherwise noted, the sections below describe vParquet4.&lt;/p&gt;
&lt;p&gt;The following sections apply to both vParquet4 and vParquet5:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fully nested versus span-oriented schema&lt;/li&gt;
&lt;li&gt;Static vs dynamic columns (see vParquet5 differences for changes to dedicated columns)&lt;/li&gt;
&lt;li&gt;Compression and encoding&lt;/li&gt;
&lt;li&gt;Bloom filters&lt;/li&gt;
&lt;/ul&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;!-- vale Grafana.GoogleSpacing = NO --&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 empty string.&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 empty string.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;ServiceStats&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;map&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Per-service counts keyed by service name. Values include span count and error count.&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;string&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.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 resource attributes that were dropped.&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.IsArray&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;Indicates if the attribute is stored as an array.&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 (or array of strings), 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 (or array of integers), 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 (or array of floats), 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 (or array of booleans), else null.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.Attrs.ValueUnsupported&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;JSON-encoded AnyValue for unsupported or mixed-type values.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.DedicatedAttributes&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Group containing spares for dedicated attribute columns with resource scope.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.Resource.DedicatedAttributes.String01 &amp;hellip; String10&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;10 spare string columns for dedicated attributes (vParquet4). vParquet5 expands to String01 &amp;hellip; String20 and adds Int01 &amp;hellip; Int05.&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.Scope.Attrs&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Scope attributes, using the same columns as rs.Resource.Attrs.*&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Scope.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 scope 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.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&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Span attributes, using the same columns as rs.Resource.Attrs.*&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.DedicatedAttributes&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Group containing spares for dedicated attribute columns with span scope&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;rs.ss.Spans.DedicatedAttributes.String01 &amp;hellip; String10&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;10 spare string columns for dedicated attributes (vParquet4). vParquet5 expands to String01 &amp;hellip; String20 and adds Int01 &amp;hellip; Int05.&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.TimeSinceStartNano&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 event timestamp in nanoseconds, relative to the span start time.&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&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Event attributes, using the same columns as rs.Resource.Attrs.*&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;&lt;/td&gt;
              &lt;td style=&#34;text-align: left&#34;&gt;Repeated link records with TraceID, SpanID, TraceState, Attrs, and DroppedAttributesCount.&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. &lt;a href=&#34;https://opentelemetry.io/docs/reference/specification/trace/api/#tracestate&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://opentelemetry.io/docs/reference/specification/trace/api/#tracestate&lt;/a&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;!-- vale Grafana.GoogleSpacing = YES --&gt;
&lt;p&gt;To increase the readability the table omits the groups &lt;code&gt;list.element&lt;/code&gt; that are added for nested list types in Parquet.
For maps (for example, ServiceStats), Parquet also inserts map-specific group levels that are omitted here.&lt;/p&gt;
&lt;div class=&#34;collapse&#34; x-data=&#34;app_collapse()&#34;&gt;
  &lt;button class=&#34;collapse-trigger&#34; @click=&#34;toggle()&#34;&gt;
    &lt;span class=&#34;body-large&#34;&gt;vParquet4 block schema example&lt;/span&gt;
    &lt;span class=&#34;collapse-trigger__icon&#34; :class=&#34;{ &#39;collapse-trigger__icon-open&#39; : open }&#34;&gt;
      
  &lt;svg width=&#34;27&#34; height=&#34;26&#34; viewBox=&#34;0 0 27 26&#34; fill=&#34;none&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;
&lt;path opacity=&#34;0.2&#34; d=&#34;M1.73047 12.8359C1.73047 19.4634 7.10305 24.8359 13.7305 24.8359C20.3579 24.8359 25.7305 19.4634 25.7305 12.8359C25.7305 6.20852 20.3579 0.835937 13.7305 0.835937C7.10305 0.835937 1.73047 6.20852 1.73047 12.8359Z&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M18.2344 12.8359L9.23438 12.8359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;path d=&#34;M13.7344 8.33594L13.7344 17.3359&#34; stroke=&#34;black&#34; stroke-width=&#34;1.5&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;/&gt;
&lt;/svg&gt;


    &lt;/span&gt;
  &lt;/button&gt;
  &lt;div class=&#34;collapse-content&#34; x-ref=&#34;content&#34; hidden=&#34;until-found&#34;&gt;
    &lt;div class=&#34;collapse-content__inner&#34; x-ref=&#34;content-inner&#34;&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 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);
  optional group ServiceStats (MAP) {
    repeated group key_value {
      required binary key (STRING);
      required group value {
        required int32 SpanCount (INTEGER(32,false));
        required int32 ErrorCount (INTEGER(32,false));
      }
    }
  }
  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);
                required boolean IsArray;
                required group Value (LIST) {
                  repeated group list {
                    required binary element (STRING);
                  }
                }
                required group ValueInt (LIST) {
                  repeated group list {
                    required int64 element (INTEGER(64,true));
                  }
                }
                required group ValueDouble (LIST) {
                  repeated group list {
                    required double element;
                  }
                }
                required group ValueBool (LIST) {
                  repeated group list {
                    required boolean element;
                  }
                }
                optional binary ValueUnsupported (STRING);
              }
            }
          }
          required int32 DroppedAttributesCount (INTEGER(32,true));
          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);
          required group DedicatedAttributes {
            optional binary String01 (STRING);
            optional binary String02 (STRING);
            optional binary String03 (STRING);
            optional binary String04 (STRING);
            optional binary String05 (STRING);
            optional binary String06 (STRING);
            optional binary String07 (STRING);
            optional binary String08 (STRING);
            optional binary String09 (STRING);
            optional binary String10 (STRING);
          }
        }
        required group ss (LIST) {
          repeated group list {
            required group element {
              required group Scope {
                required binary Name (STRING);
                required binary Version (STRING);
                required group Attrs (LIST) {
                  repeated group list {
                    required group element {
                      required binary Key (STRING);
                      required boolean IsArray;
                      required group Value (LIST) {
                        repeated group list {
                          required binary element (STRING);
                        }
                      }
                      required group ValueInt (LIST) {
                        repeated group list {
                          required int64 element (INTEGER(64,true));
                        }
                      }
                      required group ValueDouble (LIST) {
                        repeated group list {
                          required double element;
                        }
                      }
                      required group ValueBool (LIST) {
                        repeated group list {
                          required boolean element;
                        }
                      }
                      optional binary ValueUnsupported (STRING);
                    }
                  }
                }
                required int32 DroppedAttributesCount (INTEGER(32,true));
              }
              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);
                          required boolean IsArray;
                          required group Value (LIST) {
                            repeated group list {
                              required binary element (STRING);
                            }
                          }
                          required group ValueInt (LIST) {
                            repeated group list {
                              required int64 element (INTEGER(64,true));
                            }
                          }
                          required group ValueDouble (LIST) {
                            repeated group list {
                              required double element;
                            }
                          }
                          required group ValueBool (LIST) {
                            repeated group list {
                              required boolean element;
                            }
                          }
                          optional binary ValueUnsupported (STRING);
                        }
                      }
                    }
                    required int32 DroppedAttributesCount (INTEGER(32,true));
                    required group Events (LIST) {
                      repeated group list {
                        required group element {
                          required int64 TimeSinceStartNano (INTEGER(64,false));
                          required binary Name (STRING);
                          required group Attrs (LIST) {
                            repeated group list {
                              required group element {
                                required binary Key (STRING);
                                required boolean IsArray;
                                required group Value (LIST) {
                                  repeated group list {
                                    required binary element (STRING);
                                  }
                                }
                                required group ValueInt (LIST) {
                                  repeated group list {
                                    required int64 element (INTEGER(64,true));
                                  }
                                }
                                required group ValueDouble (LIST) {
                                  repeated group list {
                                    required double element;
                                  }
                                }
                                required group ValueBool (LIST) {
                                  repeated group list {
                                    required boolean element;
                                  }
                                }
                                optional binary ValueUnsupported (STRING);
                              }
                            }
                          }
                          required int32 DroppedAttributesCount (INTEGER(32,true));
                        }
                      }
                    }
                    required int32 DroppedEventsCount (INTEGER(32,true));
                    required group Links (LIST) {
                      repeated group list {
                        required group element {
                          required binary TraceID;
                          required binary SpanID;
                          required binary TraceState (STRING);
                          required group Attrs (LIST) {
                            repeated group list {
                              required group element {
                                required binary Key (STRING);
                                required boolean IsArray;
                                required group Value (LIST) {
                                  repeated group list {
                                    required binary element (STRING);
                                  }
                                }
                                required group ValueInt (LIST) {
                                  repeated group list {
                                    required int64 element (INTEGER(64,true));
                                  }
                                }
                                required group ValueDouble (LIST) {
                                  repeated group list {
                                    required double element;
                                  }
                                }
                                required group ValueBool (LIST) {
                                  repeated group list {
                                    required boolean element;
                                  }
                                }
                                optional binary ValueUnsupported (STRING);
                              }
                            }
                          }
                          required int32 DroppedAttributesCount (INTEGER(32,true));
                        }
                      }
                    }
                    required int32 DroppedLinksCount (INTEGER(32,true));
                    optional binary HttpMethod (STRING);
                    optional binary HttpUrl (STRING);
                    optional int64 HttpStatusCode (INTEGER(64,true));
                    required group DedicatedAttributes {
                      optional binary String01 (STRING);
                      optional binary String02 (STRING);
                      optional binary String03 (STRING);
                      optional binary String04 (STRING);
                      optional binary String05 (STRING);
                      optional binary String06 (STRING);
                      optional binary String07 (STRING);
                      optional binary String08 (STRING);
                      optional binary String09 (STRING);
                      optional binary String10 (STRING);
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;For the authoritative schema, refer to &lt;code&gt;tempodb/encoding/vparquet4/schema.go&lt;/code&gt; and &lt;code&gt;tempodb/encoding/vparquet5/schema.go&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;summary-of-vparquet5-differences&#34;&gt;Summary of vParquet5 differences&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Resource-level dedicated columns (Cluster/Namespace/Pod/Container/K8s*) and span HTTP columns are removed; vParquet5 relies on dynamically assigned dedicated columns only.&lt;/li&gt;
&lt;li&gt;Dedicated attribute columns are doubled from 10 to 20 string spares per scope and add 5 integer spares per scope. Event scope is also supported. Array attributes and optional blob configuration are available for selected columns.&lt;/li&gt;
&lt;li&gt;Additional fields exist for optimization, including span &lt;code&gt;ChildCount&lt;/code&gt;, rounded start time buckets, and trace-level &lt;code&gt;ServiceStats&lt;/code&gt; as a list with explicit service names.&lt;/li&gt;
&lt;/ul&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;DurationNano&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;li&gt;&lt;code&gt;ServiceStats&lt;/code&gt; - Per-service span and error counts for each trace.&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 simpler in formats like protocol-buffers, but doesn&amp;rsquo;t 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.
Unsupported or mixed-type values are stored as JSON-encoded AnyValue in &lt;code&gt;ValueUnsupported&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Only scalar values are stored in the dedicated attribute columns. Arrays and unsupported types remain in the generic attribute 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;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 boolean IsArray;
  repeated binary Value (STRING);
  repeated int64 ValueInt (INTEGER(64,true));
  repeated double ValueDouble;
  repeated boolean ValueBool;
  optional binary ValueUnsupported (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&amp;rsquo;ve 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. Most strings are very repetitive so this works well to optimize storage size. However, you 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 doesn&amp;rsquo;t use them at this time. Tempo already has sophisticated support for sharding and caching bloom filters.&lt;/p&gt;
&lt;!-- vale Grafana.GoogleSpacing = YES --&gt;
&lt;!-- vale Grafana.We = YES --&gt;
&lt;!-- vale Grafana.GooglePassive = YES --&gt;
&lt;!-- vale Grafana.GoogleWill = YES --&gt;
]]></content><description>&lt;h1 id="apache-parquet-schema">Apache Parquet schema&lt;/h1>
&lt;!-- vale Grafana.GoogleSpacing = NO -->
&lt;!-- vale Grafana.We = NO -->
&lt;!-- vale Grafana.GooglePassive = NO -->
&lt;!-- vale Grafana.GoogleWill = NO -->
&lt;p>Apache Parquet is the only supported block format in Tempo 3.0.
Refer to the &lt;a href="../../configuration/parquet/">Parquet configuration options&lt;/a> for more information.&lt;/p></description></item><item><title>Manage authentication</title><link>https://grafana.com/docs/tempo/v3.0.x/operations/authentication/</link><pubDate>Thu, 28 May 2026 17:50:33 +0100</pubDate><guid>https://grafana.com/docs/tempo/v3.0.x/operations/authentication/</guid><content><![CDATA[&lt;h1 id=&#34;manage-authentication&#34;&gt;Manage authentication&lt;/h1&gt;
&lt;p&gt;Grafana Tempo does not come with any included authentication layer. You must run an authenticating reverse proxy in front of your services.&lt;/p&gt;
&lt;p&gt;We recommend that in all 
    &lt;a href=&#34;/docs/tempo/v3.0.x/setup/deployment/&#34;&gt;deployment modes&lt;/a&gt; you add a reverse proxy in front of Tempo to direct client API requests to the various components.&lt;/p&gt;
&lt;p&gt;A list of open-source reverse proxies you can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.haproxy.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;HAProxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.nginx.com/nginx/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;NGINX&lt;/a&gt; using their &lt;a href=&#34;https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;guide on restricting access with HTTP basic authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oauth2-proxy.github.io/oauth2-proxy/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OAuth2 proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.pomerium.com/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Pomerium&lt;/a&gt;, which has a &lt;a href=&#34;https://www.pomerium.com/docs/guides/grafana&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;guide for securing Grafana&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;When using Tempo in multi-tenant mode, Tempo requires the HTTP header
&lt;code&gt;X-Scope-OrgID&lt;/code&gt; to be set to a string identifying the tenant.
It&amp;rsquo;s assumed that clients setting &lt;code&gt;X-Scope-OrgID&lt;/code&gt; are trusted clients, and the responsibility of populating this value should be handled by the authenticating reverse proxy.
For more information, read the 
    &lt;a href=&#34;/docs/tempo/v3.0.x/operations/manage-advanced-systems/multitenancy/&#34;&gt;multi-tenancy&lt;/a&gt; documentation.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

]]></content><description>&lt;h1 id="manage-authentication">Manage authentication&lt;/h1>
&lt;p>Grafana Tempo does not come with any included authentication layer. You must run an authenticating reverse proxy in front of your services.&lt;/p>
&lt;p>We recommend that in all
&lt;a href="/docs/tempo/v3.0.x/setup/deployment/">deployment modes&lt;/a> you add a reverse proxy in front of Tempo to direct client API requests to the various components.&lt;/p></description></item></channel></rss>