<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Send native histograms to Mimir on Grafana Labs</title><link>https://grafana.com/docs/mimir/v3.1.x/send/native-histograms/</link><description>Recent content in Send native histograms to Mimir on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/mimir/v3.1.x/send/native-histograms/index.xml" rel="self" type="application/rss+xml"/><item><title>Send native histograms with exponential buckets to Grafana Mimir</title><link>https://grafana.com/docs/mimir/v3.1.x/send/native-histograms/_exponential_buckets/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/send/native-histograms/_exponential_buckets/</guid><content><![CDATA[&lt;h1 id=&#34;send-native-histograms-with-exponential-buckets-to-grafana-mimir&#34;&gt;Send native histograms with exponential buckets to Grafana Mimir&lt;/h1&gt;
&lt;p&gt;Prometheus &lt;a href=&#34;https://prometheus.io/docs/specs/native_histograms/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;native histograms&lt;/a&gt; with exponential buckets, also known officially as native histograms with standard schemas, is a sample type in the Prometheus ecosystem that makes it possible to produce, store, and query a high-resolution &lt;a href=&#34;https://prometheus.io/docs/concepts/metric_types/#histogram&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;histogram&lt;/a&gt; of observations.&lt;/p&gt;
&lt;p&gt;Native histograms with exponential buckets are different from classic Prometheus histograms in a number of ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exponential bucket boundaries are calculated by a formula that depends on the scale, or resolution, of the native histogram and are not user-defined. The calculation produces exponentially increasing bucket boundaries. For details, refer to &lt;a href=&#34;#exponential-bucket-boundary-calculation&#34;&gt;Exponential bucket boundary calculation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Exponential bucket boundaries might change dynamically if the observations result in too many buckets. For details, refer to &lt;a href=&#34;#limit-the-number-of-buckets&#34;&gt;Limit the number of buckets&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Exponential bucket counters only count observations inside the bucket boundaries, whereas the classic histogram buckets only have an upper bound called &lt;code&gt;le&lt;/code&gt; and count all observations in the bucket and all lower buckets cumulatively.&lt;/li&gt;
&lt;li&gt;An instance of a native histogram metric only requires a single time series, because the buckets, sum of observations, and the count of observations are stored in a single sample type called &lt;code&gt;native histogram&lt;/code&gt; rather than in separate time series using the &lt;code&gt;float&lt;/code&gt; sample type. Thus, there are no &lt;code&gt;&amp;lt;metric&amp;gt;_bucket&lt;/code&gt;, &lt;code&gt;&amp;lt;metric&amp;gt;_sum&lt;/code&gt;, and &lt;code&gt;&amp;lt;metric&amp;gt;_count&lt;/code&gt; series. There is only a &lt;code&gt;&amp;lt;metric&amp;gt;&lt;/code&gt; time series.&lt;/li&gt;
&lt;li&gt;Querying native histograms via the Prometheus query language (PromQL) uses a different syntax. For details, refer to 
    &lt;a href=&#34;/docs/mimir/v3.1.x/visualize/native-histograms/&#34;&gt;Visualize native histograms&lt;/a&gt; and &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/functions/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;functions&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For an introduction to native histograms, watch the &lt;a href=&#34;https://www.youtube.com/watch?v=AcmABV6NCYk&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Native Histograms in Prometheus&lt;/a&gt; presentation.&lt;/p&gt;
&lt;p&gt;This document provides a practical implementation guide for using native histograms with exponential schemas in Grafana Mimir. For comprehensive guidance, refer to the official &lt;a href=&#34;https://prometheus.io/docs/specs/native_histograms/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;specification&lt;/a&gt; in the Prometheus documentation.&lt;/p&gt;
&lt;h2 id=&#34;advantages-and-disadvantages&#34;&gt;Advantages and disadvantages&lt;/h2&gt;
&lt;p&gt;There are advantages and disadvantages of using native histograms with exponential buckets compared to the classic Prometheus histograms. For more information, refer to the &lt;a href=&#34;https://www.youtube.com/watch?v=TgINvIK9SYc&amp;amp;t=127s&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus Native Histograms in Production&lt;/a&gt; video.&lt;/p&gt;
&lt;h3 id=&#34;advantages&#34;&gt;Advantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Simpler instrumentation: You don&amp;rsquo;t need to think about bucket boundaries because they are created automatically.&lt;/li&gt;
&lt;li&gt;Better resolution in practice: Custom bucket layouts are usually not high resolution.&lt;/li&gt;
&lt;li&gt;Increased compatibility: Native histograms with exponential buckets are compatible with each other. They have an automatic layout, which makes them easy to combine.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;disadvantages&#34;&gt;Disadvantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Observations might be distributed in a way that is not a good fit for the exponential bucket schema, such as sound pressure measured in decibels, which are already logarithmic.&lt;/li&gt;
&lt;li&gt;If converting from an externally represented histogram with specific bucket boundaries, there is generally no precise match with the exponential bucket boundaries of the native histogram, in which case you need to use interpolation.&lt;/li&gt;
&lt;li&gt;There is no way to set an arbitrary bucket boundary, such as one that is particularly interesting for an SLO definition. Generally, ratios of observations above or below a given threshold have to be estimated by interpolation, rather than being precise in the case for a classic histogram with a configured bucket boundary at a given threshold.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The preceding problems are mitigated by high resolution, which native histograms with exponential buckets can provide at a much lower resource cost compared to classic histograms.&lt;/p&gt;
&lt;h2 id=&#34;instrument-application-with-prometheus-client-libraries&#34;&gt;Instrument application with Prometheus client libraries&lt;/h2&gt;
&lt;p&gt;The following examples have some reasonable defaults to define a new native histogram with exponential buckets metric. The examples use the &lt;a href=&#34;https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#Histogram&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Go client library&lt;/a&gt; version 1.16 and the &lt;a href=&#34;https://prometheus.github.io/client_java/api/io/prometheus/metrics/core/metrics/Histogram.Builder.html&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Java client library&lt;/a&gt; 1.0.&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;You can add native histogram options to existing classic histograms to get both the classic and native histogram at the same time. Refer to &lt;a href=&#34;#migrate-from-classic-histograms&#34;&gt;Migrate from classic histograms&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&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;Native histograms with exponential schema take precedence over 
    &lt;a href=&#34;/docs/mimir/v3.1.x/send/native-histograms/_custom_buckets/&#34;&gt;native histograms with custom buckets&lt;/a&gt;, which means that if a histogram is scraped as a native histogram with exponential buckets, then no native histograms with custom buckets can be generated for the same histogram.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;




  

  


&lt;div data-element=&#34;tabs&#34;&gt;
  &lt;div data-element=&#34;tabs-bar&#34;&gt;
    
      &lt;div data-element=&#34;tab&#34; data-key=&#34;0&#34; data-label=&#34;Go&#34;&gt;Go&lt;/div&gt;
    
      &lt;div data-element=&#34;tab&#34; data-key=&#34;1&#34; data-label=&#34;java&#34;&gt;java&lt;/div&gt;
    
  &lt;/div&gt;
  &lt;div data-element=&#34;tab-content&#34;&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;Go&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-go&#34;&gt;histogram := prometheus.NewHistogram(
   prometheus.HistogramOpts{
      Name: &amp;#34;request_latency_seconds&amp;#34;,
      Help: &amp;#34;Histogram of request latency in seconds&amp;#34;,
      NativeHistogramBucketFactor: 1.1,
      NativeHistogramMaxBucketNumber: 100,
      NativeHistogramMinResetDuration: 1*time.Hour,
})&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;java&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-java&#34;&gt;static final Histogram requestLatency = Histogram.build()
     .name(&amp;#34;requests_latency_seconds&amp;#34;)
     .help(&amp;#34;Histogram of request latency in seconds&amp;#34;)
     .nativeOnly()
     .nativeInitialSchema(3)
     .nativeMaxNumberOfBuckets(100)
     .nativeResetDuration(1, TimeUnit.HOURS)
     .register();&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In Go, the &lt;code&gt;NativeHistogramBucketFactor&lt;/code&gt; option sets an upper limit of the relative growth from one exponential bucket to the next. The value 1.1 means that an exponential bucket is at most 10% wider than the next smaller exponential bucket. The currently supported values range from &lt;code&gt;1.0027&lt;/code&gt; or 0.27% up to 65536 or 655%. For a more detailed explanation, refer to &lt;a href=&#34;#exponential-bucket-boundary-calculation&#34;&gt;Exponential bucket boundary calculation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some of the resulting exponential buckets for factor &lt;code&gt;1.1&lt;/code&gt; rounded to two decimal places are:&lt;/p&gt;
&lt;p&gt;&amp;hellip;, (0.84, 0.92], (0.92, 1], (1, 1.09], (1.09, 1.19], (1.19, 1.30], &amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;hellip;, (76.1, 83], (83, 91], (91, 99], &amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;hellip;, (512, 558], (558, 608], (608, 663], &amp;hellip;&lt;/p&gt;
&lt;p&gt;In Java, &lt;code&gt;.nativeInitialSchema&lt;/code&gt; using a schema value of &lt;code&gt;3&lt;/code&gt; results in the same exponential bucket boundaries. For more information about the schema supported in Java, consult the documentation for &lt;a href=&#34;https://prometheus.github.io/client_java/api/io/prometheus/metrics/core/metrics/Histogram.Builder.html#nativeInitialSchema%28int%29&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;nativeInitialSchema&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The value of &lt;code&gt;NativeHistogramMaxBucketNumber&lt;/code&gt;/&lt;code&gt;nativeMaxNumberOfBuckets&lt;/code&gt; limits the number of exponential buckets produced by the observations. This can be especially useful if the receiver side is limiting the number of buckets that can be sent. For more information about the bucket limit, refer to &lt;a href=&#34;#limit-the-number-of-buckets&#34;&gt;Limit the number of buckets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The duration in &lt;code&gt;NativeHistogramMinResetDuration&lt;/code&gt;/&lt;code&gt;nativeResetDuration&lt;/code&gt; prohibits automatic counter resets inside that period. Counter resets are related to the bucket limit. For more information, refer to &lt;a href=&#34;#limit-the-number-of-buckets&#34;&gt;Limit the number of buckets&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;scrape-and-send-native-histograms-with-prometheus&#34;&gt;Scrape and send native histograms with Prometheus&lt;/h2&gt;
&lt;p&gt;Use Prometheus version 3.00 or later.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;To enable scraping native histograms from the application, set &lt;code&gt;scrape_native_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in your scrape jobs. For 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;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;scrape_configs:
  - job_name: myapp
    scrape_native_histograms: true&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;In Prometheus versions 3.8 and earlier, you need to enable the native histograms feature via the command-line flag &lt;code&gt;--enable-feature=native-histograms&lt;/code&gt;. Starting with Prometheus 3.9, this feature flag is a no-op and the &lt;code&gt;scrape_native_histograms&lt;/code&gt; config option must be used instead.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;This setting makes Prometheus detect and scrape 
    &lt;a href=&#34;/docs/mimir/v3.1.x/send/native-histograms/_exponential_buckets/&#34;&gt;native histograms with exponential buckets&lt;/a&gt; over the &lt;code&gt;PrometheusProto&lt;/code&gt; scrape protocol and ignore the classic histogram version of metrics that have native histograms defined as well. Classic histograms without native histogram definitions are not affected.&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;!-- Issue: https://github.com/prometheus/prometheus/issues/11265 --&gt;
&lt;p&gt;Native histograms don&amp;rsquo;t have a textual presentation on the application&amp;rsquo;s &lt;code&gt;/metrics&lt;/code&gt; endpoint. Therefore, Prometheus negotiates a Protobuf protocol transfer in these cases.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To keep scraping the classic histogram version of native histogram metrics, you need to set &lt;code&gt;always_scrape_classic_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in your scrape jobs.&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;In Prometheus versions 3.0 and earlier, the &lt;code&gt;always_scrape_classic_histograms&lt;/code&gt; setting is called &lt;code&gt;scrape_classic_histograms&lt;/code&gt;. Use the setting name that corresponds to the version of Prometheus you&amp;rsquo;re using.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;For example, to get both classic and native histograms, use the following 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;scrape_configs:
  - job_name: myapp
    always_scrape_classic_histograms: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To send native histograms to a Prometheus remote-write compatible receiver, for example Grafana Cloud Metrics or Grafana Mimir, set &lt;code&gt;send_native_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in the remote-write configuration. For 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;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;remote_write:
  - url: http://.../api/prom/push
    send_native_histograms: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;scrape-and-send-native-histograms-with-grafana-alloy&#34;&gt;Scrape and send native histograms with Grafana Alloy&lt;/h2&gt;
&lt;p&gt;Use 
    &lt;a href=&#34;/docs/alloy/latest/&#34;&gt;Grafana Alloy&lt;/a&gt; version 1.11 or later.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;To scrape native histograms, set the &lt;code&gt;scrape_native_histograms&lt;/code&gt; argument in the &lt;code&gt;prometheus.scrape&lt;/code&gt; component to &lt;code&gt;true&lt;/code&gt;.&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;scrape_native_histograms = true&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;p&gt;In Grafana Alloy versions 1.10 and earlier, setting &lt;code&gt;scrape_native_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; isn&amp;rsquo;t required.
For more information, refer to &lt;a href=&#34;/docs/alloy/latest/release-notes/&#34;&gt;Release notes for Grafana Alloy&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&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;For now, native histograms are only available through the Prometheus Protobuf exposition format.
Make sure to either not override the argument &lt;code&gt;scrape_protocols&lt;/code&gt; or that the first item is
&lt;code&gt;PrometheusProto&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To scrape classic histograms in addition to native histograms, set &lt;code&gt;scrape_classic_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&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;scrape_native_histograms = true
scrape_classic_histograms = true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For more information, refer to 
    &lt;a href=&#34;/docs/alloy/latest/reference/components/prometheus/prometheus.scrape/&#34;&gt;prometheus.scrape&lt;/a&gt; in the Grafana Alloy documentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To send native histograms to a Prometheus remote-write compatible receiver, such as Grafana Cloud Metrics or Grafana Mimir, set the &lt;code&gt;send_native_histograms&lt;/code&gt; argument to &lt;code&gt;true&lt;/code&gt; in the &lt;code&gt;prometheus.remote_write&lt;/code&gt; component. For example:&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;prometheus.remote_write &amp;#34;mimir&amp;#34; {
  endpoint {
    url = &amp;#34;http://.../api/prom/push&amp;#34;
    send_native_histograms = true
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;migrate-from-classic-histograms&#34;&gt;Migrate from classic histograms&lt;/h2&gt;
&lt;p&gt;To ease the migration process, you can keep the custom bucket definition of a classic histogram and add native histogram exponential buckets at the same time.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add the native histogram exponential buckets definition to an existing histogram in the instrumentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the existing histogram doesn&amp;rsquo;t have buckets defined, add the default buckets to keep the classic histogram.&lt;/p&gt;
&lt;p&gt;The following code examples have both classic and native histograms defined for the same metric:&lt;/p&gt;



  

  


&lt;div data-element=&#34;tabs&#34;&gt;
  &lt;div data-element=&#34;tabs-bar&#34;&gt;
    
      &lt;div data-element=&#34;tab&#34; data-key=&#34;0&#34; data-label=&#34;Go&#34;&gt;Go&lt;/div&gt;
    
      &lt;div data-element=&#34;tab&#34; data-key=&#34;1&#34; data-label=&#34;java&#34;&gt;java&lt;/div&gt;
    
  &lt;/div&gt;
  &lt;div data-element=&#34;tab-content&#34;&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;Go&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-go&#34;&gt;histogram := prometheus.NewHistogram(
   prometheus.HistogramOpts{
       Name: &amp;#34;request_latency_seconds&amp;#34;,
       Help: &amp;#34;Histogram of request latency in seconds&amp;#34;,
       Buckets: prometheus.DefBuckets,  // If buckets weren&amp;#39;t already defined.
       NativeHistogramBucketFactor: 1.1,
       NativeHistogramMaxBucketNumber: 100,
       NativeHistogramMinResetDuration: 1*time.Hour,
})&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;java&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-java&#34;&gt;static final Histogram requestLatency = Histogram.build()
   .name(&amp;#34;requests_latency_seconds&amp;#34;)
   .help(&amp;#34;Histogram of request latency in seconds&amp;#34;)
   .classicUpperBounds(Histogram.Builder.DEFAULT_CLASSIC_UPPER_BOUNDS)  // If upper bounds weren&amp;#39;t already defined.
   .nativeInitialSchema(3)
   .nativeMaxNumberOfBuckets(100)
   .nativeResetDuration(1, TimeUnit.HOURS)
   .register();&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let Prometheus or Grafana Alloy scrape both classic and native histograms with exponential buckets for metrics that have both defined.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Send native histograms to remote write along with the existing classic histograms.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Modify dashboards to use the native histograms metrics. Refer to 
    &lt;a href=&#34;/docs/mimir/v3.1.x/visualize/native-histograms/&#34;&gt;Visualize native histograms&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;Use one of the following strategies to update dashboards.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Recommended) Add new dashboards with the new native histograms queries. This solution requires looking at different dashboards for data before and after the migration, until data before the migration is removed due to passing its retention time. You can publish the new dashboard when sufficient time has passed to serve users with the new data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a dashboard variable to your dashboard to enable switching between classic histograms and native histograms. There isn&amp;rsquo;t support for selectively enabling and disabling queries in Grafana (&lt;a href=&#34;https://github.com/grafana/grafana/issues/79848&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;issue 79848&lt;/a&gt;). As a workaround, add the dashboard variable &lt;code&gt;latency_metrics&lt;/code&gt;, for example, and assign it a value of either &lt;code&gt;-1&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;. Then, add the following two queries to the panel:&lt;/p&gt;

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

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;(&amp;lt;native_query&amp;gt;) and on() (vector($latency_metrics) == -1)&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where &lt;code&gt;classic_query&lt;/code&gt; is the original query and &lt;code&gt;native_query&lt;/code&gt; is the same query using native histograms query syntax placed inside parentheses. Grafana Mimir dashboards use this technique. For an example, refer to the &lt;a href=&#34;https://github.com/grafana/mimir/blob/main/operations/mimir-mixin-compiled/dashboards/mimir-overview.json&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Overview dashboard&lt;/a&gt; in the Grafana Mimir repository.&lt;/p&gt;
&lt;p&gt;This solution allows users to switch between classic histograms and native histograms without going to a different dashboard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the existing classic histograms queries with modified queries. For example, replace:&lt;/p&gt;

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

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;&amp;lt;native_query&amp;gt; or &amp;lt;classic_query&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where &lt;code&gt;classic_query&lt;/code&gt; is the original query and &lt;code&gt;native_query&lt;/code&gt; is the same query using native histograms query syntax.&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;Using the PromQL operator &lt;code&gt;or&lt;/code&gt; can lead to unexpected results. For example, if a query uses a range of seven days, such as &lt;code&gt;sum(rate(http_request_duration_seconds[7d]))&lt;/code&gt;, then this query returns a value as soon as there are two native histograms samples present before the end time specified in the query. In this case, the seven day rate is calculated from a couple of minutes, rather than seven days, worth of data. This results in an inaccuracy in the graph around the time you started scraping native histograms.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start adding new recording rules and alerts to use native histograms. Do not remove the existing recording rules and alerts at this time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It is important to keep scraping both classic and native histograms for at least the period of the longest range in your recording rules and alerts, plus one day. This is the minimum amount of time, but it&amp;rsquo;s recommended to keep scraping both sample types until the new rules and alerts can be verified.&lt;/p&gt;
&lt;p&gt;For example, if you have an alert that calculates the rate of requests, such as &lt;code&gt;sum(rate(http_request_duration_seconds[7d]))&lt;/code&gt;, this query looks at the data from the last seven days plus the Prometheus &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/basics/#staleness&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;lookback period&lt;/a&gt;. When you start sending native histograms, the data isn&amp;rsquo;t there for the entire seven days, and therefore, the results might be unreliable for alerting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After configuring native histogram collection, choose one of the following ways to stop collecting classic histograms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove the custom bucket definition, &lt;code&gt;Buckets&lt;/code&gt;/&lt;code&gt;classicUpperBounds&lt;/code&gt;, from the instrumentation. In Java, also use the &lt;code&gt;nativeOnly()&lt;/code&gt; option. Refer to the examples in &lt;a href=&#34;#instrument-application-with-prometheus-client-libraries&#34;&gt;Instrument application with Prometheus client libraries&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Drop the classic histogram series with &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus relabeling&lt;/a&gt; or 
    &lt;a href=&#34;/docs/alloy/latest/reference/components/prometheus/prometheus.relabel&#34;&gt;Grafana Alloy prometheus.relabel&lt;/a&gt; at the time of scraping.&lt;/li&gt;
&lt;li&gt;Stop scraping the classic histogram version of metrics. This option applies to all metrics of a scrape target.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clean up recording rules and alerts by deleting the classic histogram version of the rule or alert.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;exponential-bucket-boundary-calculation&#34;&gt;Exponential bucket boundary calculation&lt;/h2&gt;
&lt;p&gt;This section assumes that you are familiar with basic algebra. Native histogram exponential bucket boundaries are calculated from an exponential formula with a base of 2.&lt;/p&gt;
&lt;p&gt;Native histogram with exponential buckets samples have three different kind of buckets, for any observed value the value is counted towards one kind of bucket.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A zero bucket, which contains the count of observations whose absolute value is smaller or equal to the zero threshold.&lt;/li&gt;
&lt;/ul&gt;
&lt;!--- LaTeX equation source: -threshold \leq v \leq threshold --&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;../zero-threshold-def.svg&#34;
  alt=&#34;Zero threshold definition&#34;/&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Positive buckets, which contain the count of observations with a positive value that is greater than the lower bound and less or equal to the upper bound of a bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;!--- LaTeX equation source: {\left( 2^{2^{-schema}} \right)}^{index-1} &lt; v \leq {\left( 2^{2^{-schema}}\right)}^{index} --&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;../pos-bucket-def.svg&#34;
  alt=&#34;Positive bucket definition&#34;/&gt;&lt;/p&gt;
&lt;p&gt;where the &lt;em&gt;index&lt;/em&gt; can be a positive or negative integer resulting in boundaries above 1 and fractions below 1. The &lt;em&gt;schema&lt;/em&gt; either directly specified out of &lt;code&gt;[-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8]&lt;/code&gt; at instrumentation time or it is the largest number chosen from the list in such way that&lt;/p&gt;
&lt;!--- LaTeX equation source: 2^{2^{-schema}} &lt;= factor --&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;../factor-equation.svg&#34;
  alt=&#34;Factor equation&#34;/&gt;&lt;/p&gt;
&lt;p&gt;for example for factor &lt;code&gt;1.1&lt;/code&gt;:&lt;/p&gt;
&lt;!--- Latex equation source: 2^{2^{-3}}\simeq1.09&lt;=1.1 --&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;../factor-1.1-equation.svg&#34;
  alt=&#34;Factor 1.1 equation&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Table of schema to factor:&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;&lt;em&gt;schema&lt;/em&gt;&lt;/th&gt;
              &lt;th&gt;&lt;em&gt;factor&lt;/em&gt;&lt;/th&gt;
              &lt;th&gt;&lt;/th&gt;
              &lt;th&gt;&lt;em&gt;schema&lt;/em&gt;&lt;/th&gt;
              &lt;th&gt;&lt;em&gt;factor&lt;/em&gt;&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;-4&lt;/td&gt;
              &lt;td&gt;65536&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;3&lt;/td&gt;
              &lt;td&gt;1.0905&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;-3&lt;/td&gt;
              &lt;td&gt;256&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;4&lt;/td&gt;
              &lt;td&gt;1.0443&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;-2&lt;/td&gt;
              &lt;td&gt;16&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;5&lt;/td&gt;
              &lt;td&gt;1.0219&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;-1&lt;/td&gt;
              &lt;td&gt;4&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;6&lt;/td&gt;
              &lt;td&gt;1.0109&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;0&lt;/td&gt;
              &lt;td&gt;2&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;7&lt;/td&gt;
              &lt;td&gt;1.0054&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;1&lt;/td&gt;
              &lt;td&gt;1.4142&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;8&lt;/td&gt;
              &lt;td&gt;1.0027&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;2&lt;/td&gt;
              &lt;td&gt;1.1892&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;ul&gt;
&lt;li&gt;Negative buckets, which contain the count of observations with a negative value that is smaller than the upper bound and greater than or equal to the lower bound of a bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;!--- LaTeX equation source: -{\left( 2^{2^{-schema}} \right)}^{index} \leq v &lt; -{\left( 2^{2^{-schema}}\right)}^{index-1} --&gt;
&lt;p&gt;&lt;img
  class=&#34;lazyload d-inline-block&#34;
  data-src=&#34;../neg-bucket-def.svg&#34;
  alt=&#34;Negative bucket definition&#34;/&gt;&lt;/p&gt;
&lt;p&gt;where the &lt;code&gt;schema&lt;/code&gt; is chosen as above.&lt;/p&gt;
&lt;h2 id=&#34;limit-the-number-of-buckets&#34;&gt;Limit the number of buckets&lt;/h2&gt;
&lt;p&gt;Emitting and storing a potentially unlimited number of buckets isn&amp;rsquo;t practical, as higher resolution increases the storage costs with diminishing returns.&lt;/p&gt;
&lt;p&gt;You can limit the number of buckets in Grafana Mimir or Grafana Cloud, Prometheus, or in application instrumentation.&lt;/p&gt;
&lt;h3 id=&#34;limit-the-number-of-buckets-in-grafana-mimir-or-grafana-cloud&#34;&gt;Limit the number of buckets in Grafana Mimir or Grafana Cloud&lt;/h3&gt;
&lt;p&gt;To limit the number of buckets in all native histograms ingested by Grafana Mimir or Grafana Cloud, set the tenant limit 
    &lt;a href=&#34;/docs/mimir/v3.1.x/configure/configure-native-histograms-ingestion/#configure-native-histograms-per-tenant&#34;&gt;&lt;code&gt;max_native_histogram_buckets&lt;/code&gt;&lt;/a&gt; in Grafana Mimir or submit a support request for Grafana Cloud.&lt;/p&gt;
&lt;p&gt;Native histograms that have a higher bucket count than the limit are converted to a native histogram with a lower resolution by merging buckets to reduce the number of buckets. In some rare cases, if the buckets are too widely spread out, merging them isn&amp;rsquo;t possible and the native histogram is rejected.&lt;/p&gt;
&lt;h3 id=&#34;limit-the-number-of-buckets-in-prometheus&#34;&gt;Limit the number of buckets in Prometheus&lt;/h3&gt;
&lt;p&gt;To limit the number of buckets in native histograms scraped by a &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;scrape configuration&lt;/a&gt;, set the parameter &lt;code&gt;native_histogram_bucket_limit&lt;/code&gt; in the scrape configuration.&lt;/p&gt;
&lt;p&gt;Native histograms that have a higher bucket count than the limit are converted to a native histogram with a lower resolution by merging buckets to reduce the number of buckets. In some rare cases, if the buckets are too widely spread out, merging them isn&amp;rsquo;t possible and the native histogram is rejected.&lt;/p&gt;
&lt;h3 id=&#34;limit-the-number-of-buckets-in-application-instrumentation&#34;&gt;Limit the number of buckets in application instrumentation&lt;/h3&gt;
&lt;p&gt;The instrumentation libraries of Prometheus have automation to keep the number of exponential buckets down, provided that the maximum bucket number option is used, such as &lt;code&gt;NativeHistogramMaxBucketNumber&lt;/code&gt; in Go.&lt;/p&gt;
&lt;p&gt;After the set maximum is exceeded, the following strategy is enacted:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First, if the last reset, or the creation, of the histogram is at least the minimum reset duration, then the whole histogram is reset to its initial state, including classic buckets. This only works if the minimum reset duration was set (&lt;code&gt;NativeHistogramMinResetDuration&lt;/code&gt; in Go).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If less time has passed, or if the minimum reset duration is zero, no reset is performed. Instead, the zero threshold is increased sufficiently to reduce the number of exponential buckets to or below the maximum bucket number, but not to more than the maximum zero threshold (&lt;code&gt;NativeHistogramMaxZeroThreshold&lt;/code&gt; in Go). Thus, if the threshold is at or above the maximum threshold already, nothing happens at this step.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After that, if the number of exponential buckets still exceeds the maximum bucket number, the resolution of the histogram is reduced by doubling the width of all the exponential buckets up to a growth factor between one bucket to the next of 2^(2^4) = 65536. Refer to &lt;a href=&#34;#exponential-bucket-boundary-calculation&#34;&gt;Exponential bucket boundary calculation&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any increased zero threshold or reduced resolution is reset back to their original values once the minimum reset duration has passed since the last reset or the creation of the histogram.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="send-native-histograms-with-exponential-buckets-to-grafana-mimir">Send native histograms with exponential buckets to Grafana Mimir&lt;/h1>
&lt;p>Prometheus &lt;a href="https://prometheus.io/docs/specs/native_histograms/" target="_blank" rel="noopener noreferrer">native histograms&lt;/a> with exponential buckets, also known officially as native histograms with standard schemas, is a sample type in the Prometheus ecosystem that makes it possible to produce, store, and query a high-resolution &lt;a href="https://prometheus.io/docs/concepts/metric_types/#histogram" target="_blank" rel="noopener noreferrer">histogram&lt;/a> of observations.&lt;/p></description></item><item><title>Send native histograms with custom buckets to Grafana Mimir</title><link>https://grafana.com/docs/mimir/v3.1.x/send/native-histograms/_custom_buckets/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/send/native-histograms/_custom_buckets/</guid><content><![CDATA[&lt;h1 id=&#34;send-native-histograms-with-custom-buckets-to-grafana-mimir&#34;&gt;Send native histograms with custom buckets to Grafana Mimir&lt;/h1&gt;
&lt;p&gt;Prometheus &lt;a href=&#34;https://prometheus.io/docs/specs/native_histograms/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;native histograms&lt;/a&gt; with custom buckets, also known as NHCBs, are a sample type in the Prometheus ecosystem that makes it possible to store classic Prometheus &lt;a href=&#34;https://prometheus.io/docs/concepts/metric_types/#histogram&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;histograms&lt;/a&gt; as NHCBs.&lt;/p&gt;
&lt;p&gt;NHCBs are different from classic Prometheus histograms in a number of ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An instance of a native histogram metric only requires a single time series. This is because the buckets, sum of observations, and the count of observations are stored in a single sample type called &lt;code&gt;native histogram&lt;/code&gt; rather than in separate time series using the &lt;code&gt;float&lt;/code&gt; sample type. Thus, there are no &lt;code&gt;&amp;lt;metric&amp;gt;_bucket&lt;/code&gt;, &lt;code&gt;&amp;lt;metric&amp;gt;_sum&lt;/code&gt;, or &lt;code&gt;&amp;lt;metric&amp;gt;_count&lt;/code&gt; series. There is only a &lt;code&gt;&amp;lt;metric&amp;gt;&lt;/code&gt; time series.&lt;/li&gt;
&lt;li&gt;Querying native histograms via the Prometheus query language (PromQL) uses a different syntax. For details, refer to 
    &lt;a href=&#34;/docs/mimir/v3.1.x/visualize/native-histograms/&#34;&gt;Visualize native histograms&lt;/a&gt; and &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/functions/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;functions&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For an introduction to native histograms in general, watch the &lt;a href=&#34;https://www.youtube.com/watch?v=AcmABV6NCYk&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Native Histograms in Prometheus&lt;/a&gt; presentation. For a short introduction to NHCBs, watch &lt;a href=&#34;https://www.youtube.com/watch?v=2v9DOGq2Mos&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Native Histograms With Custom Buckets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This document provides a practical implementation guide for using NHCBs in Grafana Mimir. For comprehensive guidance, refer to the official &lt;a href=&#34;https://prometheus.io/docs/specs/native_histograms/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;specification&lt;/a&gt; in the Prometheus documentation.&lt;/p&gt;
&lt;h2 id=&#34;advantages-and-disadvantages&#34;&gt;Advantages and disadvantages&lt;/h2&gt;
&lt;p&gt;There are advantages and disadvantages of using NHCBs compared to classic Prometheus histograms.&lt;/p&gt;
&lt;h3 id=&#34;advantages&#34;&gt;Advantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Lower storage costs. NHCBs use a single series and applies a sparse representation that avoids storing empty buckets.&lt;/li&gt;
&lt;li&gt;Storage and query of NHCBs are atomic, meaning that either all or none of a NHCB sample is stored or retrieved. This is different from classic histograms, which are split into multiple independent time series that might be individually lost or delayed, resulting in corrupted or inconsistent data.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s possible to migrate to NHCBs without modifying the instrumentation.&lt;/li&gt;
&lt;li&gt;A migration to 
    &lt;a href=&#34;/docs/mimir/v3.1.x/send/native-histograms/_exponential_buckets/&#34;&gt;native histograms with exponential buckets&lt;/a&gt; takes fewer steps once NHCBs are in use, as queries and visualizations are already migrated.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;disadvantages&#34;&gt;Disadvantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You need to adopt certain queries and visualizations to enable the advantages.&lt;/li&gt;
&lt;li&gt;NHCBs depends on experimental Prometheus Remote-Write 2.0.&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s some overhead to the scrape process. This depends on the scrape protocol and the ratio of classic histograms to other kind of metrics.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;query-result-equivalence&#34;&gt;Query result equivalence&lt;/h2&gt;
&lt;p&gt;NHCBs contain the same information as classic histograms. However, this doesn&amp;rsquo;t mean that all queries return exactly the same result. Here are some edge cases when query results may be different:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Classic histograms are stored in independent series which might be lost or delayed independently from each other, whereas NHCBs are stored in a single series. This means that a classic histogram might be inconsistent compared to an NHCB and query results might differ.&lt;/li&gt;
&lt;li&gt;In a normal case when classic histograms series are not lost or delayed, the bucket counts, overall count, and sum of observations are equal between the classic histograms and NHCBs.&lt;/li&gt;
&lt;li&gt;Rate, increase, and delta calculation results might differ, even when both the classic histograms and NHCBs are in sync. This occurs when the rate interval overlaps with one or more buckets transitioning from being empty to being in use. This can happen if the series just came into existence or when buckets transition from a value of &lt;code&gt;0&lt;/code&gt; to a positive value. The reason is that the PromQL function &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/functions/#rate&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;&lt;code&gt;rate&lt;/code&gt;&lt;/a&gt; and related functions use extrapolation that is applied to classic histograms series independently resulting in potentially different calculations for &lt;code&gt;0&lt;/code&gt; points and slopes. For NHCBs, the extrapolation is consistent across all buckets.&lt;/li&gt;
&lt;li&gt;In general, the PromQL warning &amp;ldquo;input to histogram_quantile needed to be fixed for monotonicity&amp;rdquo; that sometimes happens for classic histograms should not happen for NHCBs, as NHCBs are atomic, self-consistent, and extrapolated consistently.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;instrumentation&#34;&gt;Instrumentation&lt;/h2&gt;
&lt;p&gt;No change is required in instrumentation.&lt;/p&gt;
&lt;p&gt;Currently scrape processes like Prometheus or Grafana Alloy convert classic histograms during scrape to NHCBs, as there is no support for NHCBs in exposition formats.&lt;/p&gt;
&lt;h2 id=&#34;scrape-and-send-native-histograms-with-prometheus&#34;&gt;Scrape and send native histograms with Prometheus&lt;/h2&gt;
&lt;p&gt;Use the latest Prometheus version.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;To enable scraping native histograms from the application, set &lt;code&gt;scrape_native_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in your scrape jobs. For 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;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;scrape_configs:
  - job_name: myapp
    scrape_native_histograms: true&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;In Prometheus versions 3.8 and earlier, you need to enable the native histograms feature via the command-line flag &lt;code&gt;--enable-feature=native-histograms&lt;/code&gt;. Starting with Prometheus 3.9, this feature flag is a no-op and the &lt;code&gt;scrape_native_histograms&lt;/code&gt; config option must be used instead.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;This setting makes Prometheus detect and scrape 
    &lt;a href=&#34;/docs/mimir/v3.1.x/send/native-histograms/_exponential_buckets/&#34;&gt;native histogram with exponential buckets&lt;/a&gt; over the &lt;code&gt;PrometheusProto&lt;/code&gt; scrape protocol and ignore the classic histogram version of metrics that have native histograms defined as well.&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;!-- Issue: https://github.com/prometheus/prometheus/issues/11265 --&gt;
&lt;p&gt;Native histograms don&amp;rsquo;t have a textual presentation on the application&amp;rsquo;s &lt;code&gt;/metrics&lt;/code&gt; endpoint. Therefore, Prometheus negotiates a Protobuf protocol transfer in these cases.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optionally, to disable native histograms with exponential buckets and only use NHCBs, you need to set scrape protocols that don&amp;rsquo;t carry native histograms with exponential buckets. This is not a best practice, as it does not save on migration time or effort, yet loses the advantages of exponential buckets and has higher overhead than using &lt;code&gt;PrometheusProto&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, use this scrape protocol setting to avoid scraping native histograms with the exponential schema:&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;scrape_configs:
  - job_name: myapp
    scrape_protocols:
      [OpenMetricsText1.0.0, OpenMetricsText0.0.1, PrometheusText0.0.4]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To enable converting classic histograms into NHCBs, you need to set &lt;code&gt;convert_classic_histograms_to_nhcb&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in your scrape jobs. This setting has no effect for histograms that already have a native histogram defined, such as with 
    &lt;a href=&#34;/docs/mimir/v3.1.x/send/native-histograms/_exponential_buckets/&#34;&gt;native histogram with exponential buckets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example, to convert classic histograms to NHCBs, use the following 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;scrape_configs:
  - job_name: myapp
    convert_classic_histograms_to_nhcb: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To keep scraping the classic histogram version of native histogram metrics, you need to set &lt;code&gt;always_scrape_classic_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in your scrape jobs.&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;In Prometheus versions 3.0 and earlier, the &lt;code&gt;always_scrape_classic_histograms&lt;/code&gt; setting is called &lt;code&gt;scrape_classic_histograms&lt;/code&gt;. Use the setting name that corresponds to the version of Prometheus you&amp;rsquo;re using.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;For example, to get both classic and native histograms, use the following 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;scrape_configs:
  - job_name: myapp
    convert_classic_histograms_to_nhcb: true
    always_scrape_classic_histograms: true&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To be able to send native histograms to a Prometheus remote-write 2.0 compatible receiver, for example, Grafana Cloud Metrics or Mimir, set &lt;code&gt;send_native_histograms&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;protobuf_message&lt;/code&gt; to &lt;code&gt;io.prometheus.write.v2.Request&lt;/code&gt; in the remote-write configuration. For 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;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;remote_write:
  - url: http://.../api/prom/push
    send_native_histograms: true
    protobuf_message: &amp;#34;io.prometheus.write.v2.Request&amp;#34;&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;Prometheus remote-write 2.0 is experimental. For more information, refer to the &lt;a href=&#34;https://prometheus.io/docs/specs/prw/remote_write_spec_2_0/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus Remote-Write 2.0 specification&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&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;Prometheus remote-write 2.0 doesn&amp;rsquo;t fully support &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/api/#querying-metadata&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;metadata&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;migrate-from-classic-histograms&#34;&gt;Migrate from classic histograms&lt;/h2&gt;
&lt;p&gt;To ease the migration process, you can keep scraping classic histograms and NHCBs at the same time.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Let Prometheus scrape both classic histograms and NHCBs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Send native histograms to remote write, along with the existing classic histograms.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Modify dashboards to use the native histograms metrics. Refer to 
    &lt;a href=&#34;/docs/mimir/v3.1.x/visualize/native-histograms/&#34;&gt;Visualize native histograms&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;Use one of the following strategies to update dashboards.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Recommended) Add new dashboards with the new native histograms queries. This solution requires looking at different dashboards for data before and after the migration until data before the migration is removed due to passing its retention time. You can publish the new dashboard when sufficient time has passed to serve users with the new data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a dashboard variable to your dashboard to enable switching between classic histograms and native histograms. There isn&amp;rsquo;t support for selectively enabling and disabling queries in Grafana (&lt;a href=&#34;https://github.com/grafana/grafana/issues/79848&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;issue 79848&lt;/a&gt;). As a workaround, add the dashboard variable &lt;code&gt;latency_metrics&lt;/code&gt;, for example, and assign it a value of either &lt;code&gt;-1&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;. Then, add the following two queries to the panel:&lt;/p&gt;

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

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;(&amp;lt;native_query&amp;gt;) and on() (vector($latency_metrics) == -1)&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where &lt;code&gt;classic_query&lt;/code&gt; is the original query and &lt;code&gt;native_query&lt;/code&gt; is the same query using native histograms query syntax placed inside parentheses. Mimir dashboards use this technique. For an example, refer to the &lt;a href=&#34;https://github.com/grafana/mimir/blob/main/operations/mimir-mixin-compiled/dashboards/mimir-overview.json&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Overview dashboard&lt;/a&gt; in the Mimir repository.&lt;/p&gt;
&lt;p&gt;This solution allows users to switch between classic histograms and native histograms without going to a different dashboard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace the existing classic histograms queries with modified queries. For example, replace:&lt;/p&gt;

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

&lt;div class=&#34;code-snippet code-snippet__mini&#34;&gt;&lt;div class=&#34;lang-toolbar__mini&#34;&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet code-snippet__border&#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-none&#34;&gt;&amp;lt;native_query&amp;gt; or &amp;lt;classic_query&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where &lt;code&gt;classic_query&lt;/code&gt; is the original query and &lt;code&gt;native_query&lt;/code&gt; is the same query using native histograms query syntax.&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;Using the PromQL operator &lt;code&gt;or&lt;/code&gt; can lead to unexpected results. For example, if a query uses a range of seven days, such as &lt;code&gt;sum(rate(http_request_duration_seconds[7d]))&lt;/code&gt;, then this query returns a value as soon as there are two native histograms samples present before the end time specified in the query. In this case, the seven day rate is calculated from a couple of minutes, rather than seven days, worth of data. This results in an inaccuracy in the graph around the time you started scraping native histograms.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start adding new recording rules and alerts to use native histograms. Do not remove the existing recording rules and alerts at this time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It is important to keep scraping both classic and native histograms for at least the period of the longest range in your recording rules and alerts plus one day. This is the minimum amount of time, but it&amp;rsquo;s recommended to keep scraping both sample types until the new rules and alerts can be verified.&lt;/p&gt;
&lt;p&gt;For example, if you have an alert that calculates the rate of requests, such as &lt;code&gt;sum(rate(http_request_duration_seconds[7d]))&lt;/code&gt;, this query looks at the data from the last seven days plus the Prometheus &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/basics/#staleness&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;lookback period&lt;/a&gt;. When you start sending native histograms, the data isn&amp;rsquo;t there for the entire seven days, and therefore, the results might be unreliable for alerting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After configuring the collection of native histograms, choose one of the following ways to stop collecting classic histograms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Drop the classic histogram series with &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Prometheus relabeling&lt;/a&gt; or 
    &lt;a href=&#34;/docs/alloy/latest/reference/components/prometheus/prometheus.relabel&#34;&gt;Grafana Alloy prometheus.relabel&lt;/a&gt; at the time of scraping.&lt;/li&gt;
&lt;li&gt;Stop scraping the classic histogram version of metrics. This option applies to all metrics of a scrape target.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clean up recording rules and alerts by deleting the classic histogram version of the rule or alert.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;limit-the-number-of-buckets&#34;&gt;Limit the number of buckets&lt;/h2&gt;
&lt;p&gt;There is no way to automatically reduce the resolution or merge custom buckets like there is with 
    &lt;a href=&#34;/docs/mimir/v3.1.x/send/native-histograms/_exponential_buckets/#limit-the-number-buckets&#34;&gt;native histogram with exponential buckets&lt;/a&gt;. Set bucket limits greater than the largest expected bucket count to avoid having NHCBs rejected.&lt;/p&gt;
]]></content><description>&lt;h1 id="send-native-histograms-with-custom-buckets-to-grafana-mimir">Send native histograms with custom buckets to Grafana Mimir&lt;/h1>
&lt;p>Prometheus &lt;a href="https://prometheus.io/docs/specs/native_histograms/" target="_blank" rel="noopener noreferrer">native histograms&lt;/a> with custom buckets, also known as NHCBs, are a sample type in the Prometheus ecosystem that makes it possible to store classic Prometheus &lt;a href="https://prometheus.io/docs/concepts/metric_types/#histogram" target="_blank" rel="noopener noreferrer">histograms&lt;/a> as NHCBs.&lt;/p></description></item></channel></rss>