# Бібліотеки клієнтів Prometheus чи OpenTelemetry

LLMS index: [llms.txt](/llms.txt)

---

<?code-excerpt path-base="examples/java/prometheus-compatibility"?>

> [!NOTE]
>
> Ця сторінка охоплює Java та Go. Приклади для інших мов плануються.

Цей посібник призначений для розробників, знайомих з [бібліотеками клієнтів Prometheus](https://prometheus.io/docs/instrumenting/clientlibs/), які хочуть зрозуміти еквівалентні шаблони в API та SDK метрик OpenTelemetry. Він охоплює найпоширеніші шаблони, але не є вичерпним.

## Концептуальні відмінності {#conceptual-differences}

Перед тим як розглядати код, корисно зрозуміти кілька структурних відмінностей між двома системами. Специфікація [Сумісність Prometheus та OpenMetrics](/docs/specs/otel/compatibility/prometheus_and_openmetrics/) документує повні правила трансляції між двома системами. Цей розділ охоплює відмінності, які найбільш актуальні для написання нового коду інструментування.

### Реєстр (MeterProvider) {#registry-meterprovider}

В Prometheus, метрики реєструються в реєстрі — зазвичай глобально. Ви можете оголосити метрику будь-де у вашому коді, і вона стане доступною для збору після реєстрації. Експортер (HTTP сервер або OTLP push) підключається до реєстру як окремий, незалежний крок.

В OpenTelemetry, `MeterProvider` та `Meter` є частиною API метрик. Ви отримуєте `Meter`, обмежений вашою бібліотекою або компонентом, від `MeterProvider` і створюєте інструменти з цього `Meter`. Як ці вимірювання обробляються, які експортери їх отримують, як вони агрегуються, за яким графіком, визначається SDK, привʼязаний до `MeterProvider` та його конфігурацією, яка відокремлена від коду інструментування (див. [API та SDK](#otel-api-and-sdk)).

Як і Prometheus, OpenTelemetry підтримує як глобальний `MeterProvider` (не вимагаючи явного підключення з коду інструментування), так і явні екземпляри `MeterProvider`, які можна передавати бібліотекам, що їх підтримують.

### Назви міток (атрибути) {#label-names-attributes}

Prometheus вимагає, щоб назви міток були оголошені під час створення метрики. Значення міток привʼязуються під час запису за допомогою `labelValues(...)`.

OpenTelemetry не вимагає попереднього оголошення міток. Ключі та значення атрибутів надаються разом під час вимірювання за допомогою `Attributes`.

### Домовленості щодо найменування {#naming-conventions}

Prometheus використовує імена метрик у форматі `snake_case`. Імена лічильників закінчуються на `_total`. За домовленістю, імена метрик Prometheus мають префікс з назви застосунку або бібліотеки, щоб уникнути конфліктів (наприклад, `smart_home_hvac_on_seconds_total`), оскільки всі метрики використовують плаский глобальний простір імен.

OpenTelemetry зазвичай використовує [імена з крапками](/docs/specs/semconv/general/naming/). Власність та простір імен фіксуються в області інструментування (імʼя `Meter`, наприклад `smart.home`), тому самі імена метрик не потребують префікса (наприклад, `hvac.on`). При експорті в Prometheus експортер перетворює імена: крапки стають підкресленнями, скорочення одиниць розширюються до повних слів (наприклад, `s` → `seconds`), а лічильники отримують суфікс `_total`. Лічильник OpenTelemetry з іменем `hvac.on` та одиницею `s` експортується як `hvac_on_seconds_total`. Див. [специфікацію сумісності](/docs/specs/otel/compatibility/prometheus_and_openmetrics/) для повного набору правил перетворення імен. Стратегію перетворення можна налаштувати — наприклад, для збереження символів UTF-8 або придушення суфіксів одиниць та типів. Див. [експортер Prometheus](/docs/specs/otel/metrics/sdk_exporters/prometheus/) для деталей конфігурації.

### Інструменти з станом та зворотним викликом {#stateful-and-callback-instruments}

Обидві системи підтримують два режими запису:

- **Prometheus** розрізняє інструменти зі збереженням _стану_ (`Counter`, `Gauge`), які підтримують власне накопичене значення, та інструменти на основі функцій, які виконують зворотний виклик під час збору, щоб повернути поточне значення. Найменування варіюється залежно від бібліотеки клієнта (`GaugeFunc`/`CounterFunc` у Go; `GaugeWithCallback`/`CounterWithCallback` у Java).
- **OpenTelemetry** називає їх _синхронними_ (лічильник, гістограма тощо) та _асинхронними_ (спостережувані через зареєстрований зворотний виклик). Семантика та сама.

Зауважте, що Prometheus `Gauge` охоплює два різні типи інструментів OTel: `Gauge` для неадитивних значень (наприклад, температура) та `UpDownCounter` для адитивних значень, які можуть збільшуватися або зменшуватися (наприклад, активні зʼєднання). Див. [Gauge](#gauge) для деталей.

### OTel: API та SDK {#otel-api-and-sdk}

OpenTelemetry відділяє інструментування від конфігурації за допомогою двошарового дизайну: пакунок **API** та пакунок **SDK**. API визначає інтерфейси, які використовуються для запису метрик. SDK забезпечує реалізацію — конкретного провайдера, експортери та обробку конвеєра.

Код інструментування повинен залежати лише від API. SDK налаштовується один раз під час запуску застосунку і підключається до посилання на API, яке передається решті коду. Це дозволяє коду бібліотеки інструментування бути відокремленим від будь-якої конкретної версії SDK і спрощує заміну на реалізацію без операцій для тестування.

### OTel: Сфера застосування інструментування {#otel-instrumentation-scope}

Метрики Prometheus мають глобальний характер: усі метрики в одному процесі використовують єдиний плоский простір імен, який ідентифікується лише за назвою та мітками.

OpenTelemetry обмежує кожну групу інструментів до `Meter`, який ідентифікується за назвою та необовʼязковою версією (наприклад, `smart.home`). Під час експорту до Prometheus, назва та версія області додаються як мітки `otel_scope_name` та `otel_scope_version` до кожної точки метрики. Будь-які додаткові атрибути області також додаються як мітки, названі `otel_scope_[attr name]`. Ці мітки зʼявляються автоматично і можуть бути незнайомими користувачам, які переходять з Prometheus. Їх можна вимкнути за допомогою опції `without_scope_info` експортера, див. [Prometheus exporter](/docs/specs/otel/metrics/sdk_exporters/prometheus/) для деталей конфігурації. Зверніть увагу, що вимкнення інформації про область безпечне лише тоді, коли кожна назва метрики створюється однією областю. Якщо дві області генерують метрику з однаковою назвою, мітки області є єдиним способом їх розрізнити; без цих міток ви отримаєте дублікати часових рядів без можливості визначити їхнє походження, що призводить до некоректного виводу в Prometheus.

### OTel: Часові характеристики агрегації {#otel-aggregation-temporality}

Метрики Prometheus завжди є накопичувальними. OpenTelemetry підтримує як накопичувальний, так і дельта-тип обчислення, але експортер Prometheus застосовує накопичувальний тип для всіх інструментів. Для розробників, які переходять з Prometheus, цей процес є прозорим — звична для вас поведінка залишається незмінною.

### OTel: Атрибути ресурсу {#otel-resource-attributes}

Prometheus визначає обʼєкти збору даних за допомогою міток `job` та `instance`, які додаються сервером Prometheus під час збору даних.

OpenTelemetry має `Resource` — структуровані метадані, прикріплені до всієї телеметрії з процесу, з атрибутами, такими як `service.name` та `service.instance.id`. Під час експорту до Prometheus експортер переносить атрибути ресурсу на мітки `job` та `instance`, а будь-які залишкові атрибути присутні в метриці `target_info` (`target_info` є конвенцією OpenMetrics 1.0, якщо ви наразі вручну емулюєте її з Prometheus, еквівалент OTel — встановити атрибути ресурсу). Див. [специфікацію сумісності](/docs/specs/otel/compatibility/prometheus_and_openmetrics/) для точних правил зіставлення. Метрику `target_info` можна вимкнути за допомогою `without_target_info`, а конкретні атрибути ресурсу можна підняти до міток на рівні метрики за допомогою `with_resource_constant_labels`. Див. [експортер Prometheus](/docs/specs/otel/metrics/sdk_exporters/prometheus/) для деталей конфігурації.

## Ініціалізація {#initialization}

Приклади нижче охоплюють два основні сценарії розгортання: експонування точки доступу збору Prometheus та надсилання до точки доступу OTLP.

### Експонування точки доступу збору Prometheus {#expose-a-prometheus-scrape-endpoint}

   <ul class="nav nav-tabs" id="tabs-0" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-00-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-00-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-00-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-00-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-00-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-0-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-00-00" role="tabpanel" aria-labelled-by="tabs-00-00-tab" tabindex="0">
        <p>Prometheus</p>
<?code-excerpt "src/main/java/otel/PrometheusScrapeInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Counter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.exporter.httpserver.HTTPServer</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.io.IOException</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusScrapeInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">IOException</span><span class="p">,</span><span class="w"> </span><span class="n">InterruptedException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Створіть лічильник і зареєструйте його в стандартному PrometheusRegistry.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Counter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Counter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;door_opens_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Запустіть HTTP-сервер; Prometheus збирає дані з http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">HTTPServer</span><span class="w"> </span><span class="n">server</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HTTPServer</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">port</span><span class="p">(</span><span class="n">9464</span><span class="p">).</span><span class="na">buildAndStart</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">server</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;front&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// очікувати нескінченно</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelScrapeInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.LongCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.exporter.prometheus.PrometheusHttpServer</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.OpenTelemetrySdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.SdkMeterProvider</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelScrapeInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Попередньо виділіть ключі атрибутів і, коли значення статичні, цілі об&#39;єкти Attributes.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DOOR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">FRONT_DOOR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DOOR</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;front&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">InterruptedException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Налаштуйте SDK: зареєструйте Prometheus reader, який обслуговує /metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetrySdk</span><span class="w"> </span><span class="n">sdk</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">OpenTelemetrySdk</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setMeterProvider</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">SdkMeterProvider</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">registerMetricReader</span><span class="p">(</span><span class="n">PrometheusHttpServer</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">setPort</span><span class="p">(</span><span class="n">9464</span><span class="p">).</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">sdk</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Код інструментування використовує тип API OpenTelemetry, а не тип SDK безпосередньо.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Метрики обслуговуються за адресою http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">LongCounter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">FRONT_DOOR</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// очікувати нескінченно</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-00-01" role="tabpanel" aria-labelled-by="tabs-00-01-tab" tabindex="0">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_scrape_init.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;net/http&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;github.com/prometheus/client_golang/prometheus/promhttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Створіть лічильник і зареєструйте його у власному реєстрі.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewRegistry</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewCounterVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;door_opens_total&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;door&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">doorOpens</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Prometheus зчитує дані з http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">http</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span><span class="s">&#34;/metrics&#34;</span><span class="p">,</span><span class="w"> </span><span class="nx">promhttp</span><span class="p">.</span><span class="nf">HandlerFor</span><span class="p">(</span><span class="nx">reg</span><span class="p">,</span><span class="w"> </span><span class="nx">promhttp</span><span class="p">.</span><span class="nx">HandlerOpts</span><span class="p">{}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">go</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">(</span><span class="s">&#34;:9464&#34;</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;front&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">select</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="c1">// очікувати нескінченно</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_scrape_init.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;net/http&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;github.com/prometheus/client_golang/prometheus/promhttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/exporters/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">sdkmetric</span><span class="w"> </span><span class="s">&#34;go.opentelemetry.io/otel/sdk/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ctx</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Налаштуйте SDK: зареєструйте Prometheus reader, який обслуговує /metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">exporter</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">New</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">provider</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewMeterProvider</span><span class="p">(</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">WithReader</span><span class="p">(</span><span class="nx">exporter</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">defer</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Shutdown</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Метрики обслуговуються за адресою http://localhost:9464/metrics.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">http</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span><span class="s">&#34;/metrics&#34;</span><span class="p">,</span><span class="w"> </span><span class="nx">promhttp</span><span class="p">.</span><span class="nf">Handler</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">go</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">(</span><span class="s">&#34;:9464&#34;</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Код інструментування використовує тип API OpenTelemetry, а не тип SDK безпосередньо.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">meter</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Meter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64Counter</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;front&#34;</span><span class="p">)))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">select</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="c1">// очікувати нескінченно</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


### надсилання метрик до точки доступу OTLP {#push-metrics-to-an-otlp-endpoint}

   <ul class="nav nav-tabs" id="tabs-1" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-01-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-01-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-01-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-01-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-01-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-1-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-01-00" role="tabpanel" aria-labelled-by="tabs-01-00-tab" tabindex="1">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusOtlpInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Counter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.exporter.opentelemetry.OpenTelemetryExporter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusOtlpInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Створіть лічильник і зареєструйте його у стандартному реєстрі Prometheus.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Counter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Counter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;door_opens_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Запустіть експортер OTLP. Він читає дані з стандартного реєстру Prometheus і</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// надсилає метрики на налаштовану точку доступу з фіксованим інтервалом.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetryExporter</span><span class="w"> </span><span class="n">exporter</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">OpenTelemetryExporter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">protocol</span><span class="p">(</span><span class="s">&#34;http/protobuf&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">endpoint</span><span class="p">(</span><span class="s">&#34;http://localhost:4318&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">intervalSeconds</span><span class="p">(</span><span class="n">60</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">buildAndStart</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">exporter</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;front&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// очікувати нескінченно</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelOtlpInit.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.LongCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.OpenTelemetrySdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.SdkMeterProvider</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.export.PeriodicMetricReader</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.time.Duration</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelOtlpInit</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">InterruptedException</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Налаштуйте SDK: експортуйте метрики через OTLP/HTTP з фіксованим інтервалом.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetrySdk</span><span class="w"> </span><span class="n">sdk</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">OpenTelemetrySdk</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setMeterProvider</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">SdkMeterProvider</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">registerMetricReader</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                        </span><span class="n">PeriodicMetricReader</span><span class="p">.</span><span class="na">builder</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                                </span><span class="n">OtlpHttpMetricExporter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                                    </span><span class="p">.</span><span class="na">setEndpoint</span><span class="p">(</span><span class="s">&#34;http://localhost:4318&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                                    </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                            </span><span class="p">.</span><span class="na">setInterval</span><span class="p">(</span><span class="n">Duration</span><span class="p">.</span><span class="na">ofSeconds</span><span class="p">(</span><span class="n">60</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                            </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">.</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Thread</span><span class="p">(</span><span class="n">sdk</span><span class="p">::</span><span class="n">close</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Код інструментування використовує тип API OpenTelemetry, а не тип SDK безпосередньо.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sdk</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">LongCounter</span><span class="w"> </span><span class="n">doorOpens</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">doorOpens</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Thread</span><span class="p">.</span><span class="na">currentThread</span><span class="p">().</span><span class="na">join</span><span class="p">();</span><span class="w"> </span><span class="c1">// очікувати нескінченно</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-01-01" role="tabpanel" aria-labelled-by="tabs-01-01-tab" tabindex="1">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<p>Клієнтська бібліотека Prometheus для Go не включає експортер OTLP push.</p>
<p>OpenTelemetry</p>
<?code-excerpt "otel_otlp_init.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">sdkmetric</span><span class="w"> </span><span class="s">&#34;go.opentelemetry.io/otel/sdk/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ctx</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Налаштуйте SDK: експортуйте метрики через OTLP/HTTP з фіксованим інтервалом.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Точка доступу зазвичай localhost:4318 і може бути налаштована через</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// змінну середовища OTEL_EXPORTER_OTLP_ENDPOINT.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">exporter</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">provider</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewMeterProvider</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">WithReader</span><span class="p">(</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewPeriodicReader</span><span class="p">(</span><span class="nx">exporter</span><span class="p">)),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">defer</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Shutdown</span><span class="p">(</span><span class="nx">ctx</span><span class="p">)</span><span class="w"> </span><span class="cp">//nolint:errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">meter</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">provider</span><span class="p">.</span><span class="nf">Meter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64Counter</span><span class="p">(</span><span class="s">&#34;door.opens&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total number of times a door has been opened&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">doorOpens</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;door&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;front&#34;</span><span class="p">)))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">select</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="c1">// очікувати нескінченно</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


## Лічильник {#counter}

Лічильник записує монотонно збільшувані значення. Prometheus `Counter` відповідає інструменту OpenTelemetry `Counter`.

- **Кодування одиниць**: Prometheus кодує одиницю в назві метрики (`hvac_on_seconds_total`). OpenTelemetry розділяє назву (`hvac.on`) та одиницю (`s`), а експортер Prometheus автоматично додає суфікс одиниці.

### Лічильник {#counter-1}

Prometheus `Counter` включає дві функції управління серіями, які не мають еквівалента в OpenTelemetry:

- **Попередня ініціалізація серій**: клієнти Prometheus можуть попередньо ініціалізувати комбінації значень міток, щоб вони зʼявлялися у виводі scrape зі значенням 0 до того, як відбудеться будь-який запис. OpenTelemetry не має еквівалента; точки даних зʼявляються вперше при першому виклику `add()`.
- **Попередньо привʼязані серії**: клієнти Prometheus дозволяють кешувати результат `labelValues()`, щоб попередньо привʼязати до конкретної комбінації значень міток. Наступні виклики йдуть безпосередньо до точки даних, пропускаючи внутрішній пошук серії. OpenTelemetry не має еквівалента, хоча це [обговорюється](https://github.com/open-telemetry/opentelemetry-specification/issues/4126).

   <ul class="nav nav-tabs" id="tabs-2" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-02-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-02-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-02-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-02-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-02-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-2-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-02-00" role="tabpanel" aria-labelled-by="tabs-02-00-tab" tabindex="2">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Counter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Counter</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Counter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;hvac_on_seconds_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total time the HVAC system has been running, in seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Попередньо привʼязати до наборів значень міток: наступні виклики йдуть безпосередньо до точки даних,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// пропускаючи внутрішній пошук серії.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">var</span><span class="w"> </span><span class="n">upstairs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">var</span><span class="w"> </span><span class="n">downstairs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">upstairs</span><span class="p">.</span><span class="na">inc</span><span class="p">(</span><span class="n">127</span><span class="p">.</span><span class="na">5</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">downstairs</span><span class="p">.</span><span class="na">inc</span><span class="p">(</span><span class="n">3600</span><span class="p">.</span><span class="na">0</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Попередньо ініціалізувати зони, щоб вони зʼявлялися у /metrics зі значенням 0 при запуску.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">initLabelValues</span><span class="p">(</span><span class="s">&#34;basement&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Попередньо виділити ключі атрибутів і, коли значення статичні, цілі обʼєкти Attributes.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ZONE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Час роботи системи опалення, вентиляції та кондиціонування (HVAC) виражається у дробовій формі — використовується функція `useOfDoubles()` для отримання лічильника типу `DoubleCounter`.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Відсутність попереднього оголошення міток: атрибути задаються під час запису.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleCounter</span><span class="w"> </span><span class="n">hvacOnTime</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;hvac.on&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total time the HVAC system has been running&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">ofDoubles</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">127</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">hvacOnTime</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">3600</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>inc(value)</code> → <code>add(value)</code>. На відміну від Prometheus, OpenTelemetry вимагає явного значення — немає скорочення <code>inc()</code>.</li>
<li>OpenTelemetry розрізняє <code>LongCounter</code> (цілі числа, зазвичай) і <code>DoubleCounter</code> (через <code>.ofDoubles()</code>, для дробових значень). Prometheus використовує один тип <code>Counter</code>.</li>
<li>Попередньо виділяйте екземпляри <code>AttributeKey</code> (завжди) і обʼєкти <code>Attributes</code> (коли значення статичні), щоб уникнути виділення пам&rsquo;яті при кожному виклику на гарячому шляху.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-02-01" role="tabpanel" aria-labelled-by="tabs-02-01-tab" tabindex="2">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">hvacOnTime</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewCounterVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;hvac_on_seconds_total&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Total time the HVAC system has been running, in seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;zone&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusCounterUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">hvacOnTime</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Попередньо привʼязати до наборів значень міток: наступні виклики йдуть безпосередньо до точки даних,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// пропускаючи внутрішній пошук серії.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">upstairs</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">downstairs</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">upstairs</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="mf">127.5</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">downstairs</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="mf">3600.0</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Попередньо ініціалізувати серію, щоб вона зʼявлялася у /metrics зі значенням 0.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;basement&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Попередньо виділяйте опції атрибутів, коли значення статичні, щоб уникнути виділення пам&#39;яті при кожному виклику.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneUpstairsOpts</span><span class="w">   </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneDownstairsOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelCounterUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Відсутність попереднього оголошення міток: атрибути задаються під час запису.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Counter</span><span class="p">(</span><span class="s">&#34;hvac.on&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total time the HVAC system has been running&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">127.5</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneUpstairsOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hvacOnTime</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">3600.0</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneDownstairsOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>Add(value)</code> → <code>Add(ctx, value, metric.WithAttributes(...))</code>. Усі виклики інструментів вимагають <code>context.Context</code> як першого аргументу.</li>
<li>У Go <code>meter.Float64Counter</code> і <code>meter.Int64Counter</code> є окремими методами. Prometheus використовує один тип <code>Counter</code>.</li>
<li>Створення інструменту повертає <code>(Instrument, error)</code> і помилку потрібно обробляти.</li>
</ul>

    </div>
</div>


### Лічильник із зворотним викликом (асинхронний) {#callback-async-counter}

Використовуйте лічильник із зворотним викликом (асинхронний лічильник у OpenTelemetry), коли загальне значення підтримується зовнішнім джерелом, наприклад, пристроєм або середовищем виконання, і ви хочете відстежувати його під час збору даних, а не збільшувати самостійно.

   <ul class="nav nav-tabs" id="tabs-3" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-03-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-03-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-03-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-03-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-03-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-3-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-03-00" role="tabpanel" aria-labelled-by="tabs-03-00-tab" tabindex="3">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.CounterWithCallback</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterCallbackUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Кожна зона має власний розумний лічильник енергії, який відстежує накопичені джоулі.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Використовуйте лічильник із зворотним викликом, щоб повідомляти ці значення під час збору даних,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// не підтримуючи окремі лічильники в коді програми.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">CounterWithCallback</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;energy_consumed_joules_total&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Total energy consumed in joules&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">callback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">callback</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ZONE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">counterCallbackUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Кожна зона має власний розумний лічильник енергії, який відстежує накопичені джоулі.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Використовуйте асинхронний лічильник, щоб повідомляти ці значення під час збору даних,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// не підтримуючи окремі лічильники в коді програми.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">counterBuilder</span><span class="p">(</span><span class="s">&#34;energy.consumed&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Total energy consumed&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;J&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">ofDoubles</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">buildWithCallback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">measurement</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li>OpenTelemetry розрізняє цілочисельні та числові лічильники з рухомою комою; <code>.ofDoubles()</code> вибирає числовий варіант з рухомою комою. Prometheus <code>CounterWithCallback</code> завжди використовує значення з рухомою комою.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-03-01" role="tabpanel" aria-labelled-by="tabs-03-01-tab" tabindex="3">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">energyCollector</span><span class="w"> </span><span class="kd">struct</span><span class="p">{</span><span class="w"> </span><span class="nx">desc</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">newEnergyCollector</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="nx">energyCollector</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">energyCollector</span><span class="p">{</span><span class="nx">desc</span><span class="p">:</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewDesc</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;energy_consumed_joules_total&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;Total energy consumed in joules&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;zone&#34;</span><span class="p">},</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">energyCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Describe</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">energyCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Collect</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Metric</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterValue</span><span class="p">,</span><span class="w"> </span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">CounterValue</span><span class="p">,</span><span class="w"> </span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusCounterCallbackUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Кожна зона має власний розумний лічильник енергії, який відстежує накопичені джоулі.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Реалізуйте prometheus.Collector, щоб повідомляти ці значення під час збору даних.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nf">newEnergyCollector</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneUpstairs</span><span class="w">   </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneDownstairs</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelCounterCallbackUsage</span><span class="p">(</span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Кожна зона має власний розумний лічильник енергії, який відстежує накопичені джоулі.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Використовуйте спостережуваний лічильник, щоб повідомляти ці значення під час збору даних.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64ObservableCounter</span><span class="p">(</span><span class="s">&#34;energy.consumed&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Total energy consumed&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;J&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithFloat64Callback</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">_</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Float64Observer</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">zoneUpstairs</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">totalEnergyJoules</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">zoneDownstairs</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li>Приклад Prometheus реалізує <code>prometheus.Collector</code> з методами <code>Describe</code> та <code>Collect</code> для повідомлення значень лічильників з мітками.</li>
<li>OpenTelemetry розрізняє <code>Float64ObservableCounter</code> та <code>Int64ObservableCounter</code>.</li>
</ul>

    </div>
</div>


## Gauge {#gauge}

Записи Gauge фіксують миттєве значення, яке може збільшуватися або зменшуватися. Prometheus використовує один тип `Gauge` для всіх таких значень, але OpenTelemetry розрізняє **адитивні** та **неадитивні** значення при виборі відповідного інструменту:

- **Неадитивні** значення не можна змістовно сумувати між екземплярами — наприклад, температура: додавання показників трьох датчиків кімнати не дає корисного числа. Вони відповідають OTel `Gauge` та `ObservableGauge`.
- **Адитивні** значення можна змістовно сумувати між екземплярами — наприклад, кількість підключених пристроїв, сумована між екземплярами сервісу, дає корисну загальну кількість. Вони відповідають OTel `UpDownCounter` та `ObservableUpDownCounter`.

Ця відмінність застосовується до всіх шаблонів gauge: abs, inc і dec, а також варіантів зворотного виклику. Див. [керівництво з вибору інструментів](/docs/specs/otel/metrics/supplementary-guidelines/#instrument-selection) для детальнішого пояснення.

### Gauge — abs

Використовуйте цей шаблон для значень, що записуються як абсолютне значення — наприклад, конфігураційне значення або встановлена точка пристрою. Prometheus `Gauge` відповідає інструменту OpenTelemetry `Gauge`.

   <ul class="nav nav-tabs" id="tabs-4" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-04-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-04-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-04-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-04-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-04-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-04-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-4-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-04-00" role="tabpanel" aria-labelled-by="tabs-04-00-tab" tabindex="4">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusGauge.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Gauge</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusGauge</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Gauge</span><span class="w"> </span><span class="n">thermostatSetpoint</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Gauge</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;thermostat_setpoint_celsius&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">).</span><span class="na">set</span><span class="p">(</span><span class="n">22</span><span class="p">.</span><span class="na">5</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">).</span><span class="na">set</span><span class="p">(</span><span class="n">20</span><span class="p">.</span><span class="na">0</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelGauge.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleGauge</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelGauge</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Попередньо виділіть ключі атрибутів і, коли значення статичні, цілі об&#39;єкти Attributes.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ZONE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ZONE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleGauge</span><span class="w"> </span><span class="n">thermostatSetpoint</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">gaugeBuilder</span><span class="p">(</span><span class="s">&#34;thermostat.setpoint&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">set</span><span class="p">(</span><span class="n">22</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">UPSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">thermostatSetpoint</span><span class="p">.</span><span class="na">set</span><span class="p">(</span><span class="n">20</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">DOWNSTAIRS</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>set(value)</code> → <code>set(value, attributes)</code>. Назва методу залишається тією ж.</li>
<li>OpenTelemetry розрізняє <code>LongGauge</code> (цілі числа, через <code>.ofLongs()</code>) та <code>DoubleGauge</code> (зазвичай). Prometheus використовує один тип <code>Gauge</code>.</li>
<li>Попередньо виділіть екземпляри <code>AttributeKey</code> (завжди) та обʼєкти <code>Attributes</code> (коли значення статичні), щоб уникнути виділення памʼяті при кожному виклику на гарячому шляху.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-04-01" role="tabpanel" aria-labelled-by="tabs-04-01-tab" tabindex="4">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_gauge.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">thermostatSetpoint</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewGaugeVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;thermostat_setpoint_celsius&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;zone&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusGaugeUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">thermostatSetpoint</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;upstairs&#34;</span><span class="p">).</span><span class="nf">Set</span><span class="p">(</span><span class="mf">22.5</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;downstairs&#34;</span><span class="p">).</span><span class="nf">Set</span><span class="p">(</span><span class="mf">20.0</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_gauge.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Попередньо виділіть параметри атрибутів, коли значення статичні, щоб уникнути виділення пам&#39;яті при кожному виклику.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneUpstairsGaugeOpts</span><span class="w">   </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;upstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">zoneDownstairsGaugeOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;zone&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;downstairs&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelGaugeUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Gauge</span><span class="p">(</span><span class="s">&#34;thermostat.setpoint&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Target temperature set on the thermostat&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">22.5</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneUpstairsGaugeOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">thermostatSetpoint</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">20.0</span><span class="p">,</span><span class="w"> </span><span class="nx">zoneDownstairsGaugeOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>Set(value)</code> → <code>Record(ctx, value, metric.WithAttributes(...))</code>.</li>
<li>В Go, <code>meter.Float64Gauge</code> та <code>meter.Int64Gauge</code> є окремими методами. Prometheus використовує один тип <code>Gauge</code>.</li>
</ul>

    </div>
</div>


### Gauge зі зворотним викликом — abs {#callback-gauge--abs}

Використовуйте gauge зі зворотним викликом (асинхронний gauge в OpenTelemetry), коли значення не є адитивним і підтримується зовнішньо, наприклад, показання датчика, і ви хочете спостерігати його під час збору, а не відстежувати самостійно.

   <ul class="nav nav-tabs" id="tabs-5" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-05-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-05-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-05-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-05-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-05-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-5-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-05-00" role="tabpanel" aria-labelled-by="tabs-05-00-tab" tabindex="5">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusGaugeCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.GaugeWithCallback</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusGaugeCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeCallbackUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Датчики температури підтримують власні показання у прошивці.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Використовуйте gauge зі зворотним викликом, щоб повідомляти ці значення під час збору, не підтримуючи окремий gauge у коді програми.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">GaugeWithCallback</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;room_temperature_celsius&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">callback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">callback</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelGaugeCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelGaugeCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ROOM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LIVING_ROOM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ROOM</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">BEDROOM</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">ROOM</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">gaugeCallbackUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Датчики температури підтримують власні показання у прошивці.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Використовуйте асинхронний gauge, щоб повідомляти ці значення під час збору метрик,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// не підтримуючи окремі gauge у коді програми.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">gaugeBuilder</span><span class="p">(</span><span class="s">&#34;room.temperature&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">buildWithCallback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">measurement</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="n">LIVING_ROOM</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="n">BEDROOM</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-05-01" role="tabpanel" aria-labelled-by="tabs-05-01-tab" tabindex="5">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_gauge_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">temperatureCollector</span><span class="w"> </span><span class="kd">struct</span><span class="p">{</span><span class="w"> </span><span class="nx">desc</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">newTemperatureCollector</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="nx">temperatureCollector</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">temperatureCollector</span><span class="p">{</span><span class="nx">desc</span><span class="p">:</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewDesc</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;room_temperature_celsius&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;room&#34;</span><span class="p">},</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">temperatureCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Describe</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">temperatureCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Collect</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Metric</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nf">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nf">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusGaugeCallbackUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Датчики температури підтримують власні показання у прошивці.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Реалізуйте prometheus.Collector, щоб повідомляти ці значення під час збору.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nf">newTemperatureCollector</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_gauge_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">roomLivingRoom</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;living_room&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">roomBedroom</span><span class="w">    </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;room&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;bedroom&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelGaugeCallbackUsage</span><span class="p">(</span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Датчики температури підтримують власні показання у прошивці.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Використовуйте асинхронний gauge, щоб повідомляти ці значення під час збору метрик,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// не підтримуючи окремі gauge у коді програми.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64ObservableGauge</span><span class="p">(</span><span class="s">&#34;room.temperature&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Current temperature in the room&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;Cel&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithFloat64Callback</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">_</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Float64Observer</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">livingRoomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">roomLivingRoom</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nf">bedroomTemperatureCelsius</span><span class="p">(),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">roomBedroom</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li>Приклад Prometheus реалізує <code>prometheus.Collector</code> з методами <code>Describe</code> та <code>Collect</code> для повідомлення значень gauge з мітками.</li>
</ul>

    </div>
</div>


### Gauge — inc та dec {#gauge--inc-and-dec}

Prometheus `Gauge` підтримує інкрементування та декрементування для значень, які змінюються поступово — таких як кількість підключених пристроїв або активних сесій. OpenTelemetry `Gauge` записує лише абсолютні значення; цей шаблон відповідає інструменту OpenTelemetry `UpDownCounter`.

   <ul class="nav nav-tabs" id="tabs-6" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-06-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-06-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-06-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-06-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-06-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-06-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-6-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-06-00" role="tabpanel" aria-labelled-by="tabs-06-00-tab" tabindex="6">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusUpDownCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Gauge</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusUpDownCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Prometheus використовує Gauge для значень, які можуть збільшуватися або зменшуватися.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Gauge</span><span class="w"> </span><span class="n">devicesConnected</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Gauge</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;devices_connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Інкрементуйте, коли пристрій підключається, декрементуйте, коли він відключається.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">inc</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">dec</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelUpDownCounter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.LongUpDownCounter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelUpDownCounter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Попередньо виділіть ключі атрибутів і, коли значення статичні, цілі об&#39;єкти Attributes.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">LongUpDownCounter</span><span class="w"> </span><span class="n">devicesConnected</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">upDownCounterBuilder</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// add() приймає як додатні, так і від&#39;ємні значення.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">devicesConnected</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="o">-</span><span class="n">1</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>inc()</code> / <code>dec()</code> → <code>add(1)</code> / <code>add(-1)</code>. <code>add()</code> приймає як додатні, так і від&rsquo;ємні значення.</li>
<li>Тип Prometheus — <code>Gauge</code>; тип OpenTelemetry — <code>LongUpDownCounter</code> (або <code>DoubleUpDownCounter</code> через <code>.ofDoubles()</code>).</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-06-01" role="tabpanel" aria-labelled-by="tabs-06-01-tab" tabindex="6">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_up_down_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Prometheus використовує Gauge для значень, які можуть збільшуватися або зменшуватися.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">devicesConnected</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewGaugeVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;devices_connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusUpDownCounterUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">devicesConnected</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Інкрементуйте, коли пристрій підключається, декрементуйте, коли він відключається.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Inc</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Dec</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_up_down_counter.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Попередньо виділіть ключі атрибутів і, коли значення статичні, цілі об&#39;єкти Attributes.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceThermostatAddOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceLockAddOpts</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">AddOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelUpDownCounterUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64UpDownCounter</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Add() приймає як додатні, так і від&#39;ємні значення.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceThermostatAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceThermostatAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceLockAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">devicesConnected</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceLockAddOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>Inc()</code> / <code>Dec()</code> → <code>Add(ctx, 1, ...)</code> / <code>Add(ctx, -1, ...)</code>. <code>Add()</code> приймає як додатні, так і від&rsquo;ємні значення.</li>
<li>Тип Prometheus — <code>Gauge</code>; тип OpenTelemetry — <code>Int64UpDownCounter</code> (або <code>Float64UpDownCounter</code> через <code>meter.Float64UpDownCounter</code>).</li>
</ul>

    </div>
</div>


### Gauge зі зворотним викликом — inc та dec {#callback-gauge--inc-and-dec}

Використовуйте gauge зі зворотним викликом (асинхронний лічильник з можливістю збільшення та зменшення в OpenTelemetry), коли додатний лічильник, який зазвичай відстежується за допомогою `inc()`/`dec()`, підтримується зовнішньо, наприклад, менеджером пристроїв або пулом зʼєднань, і ви хочете спостерігати його під час збору метрик.

   <ul class="nav nav-tabs" id="tabs-7" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-07-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-07-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-07-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-07-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-07-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-07-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-7-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-07-00" role="tabpanel" aria-labelled-by="tabs-07-00-tab" tabindex="7">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusUpDownCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.GaugeWithCallback</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusUpDownCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterCallbackUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Менеджер пристроїв підтримує кількість підключених пристроїв.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Використовуйте gauge зі зворотним викликом, щоб повідомляти це значення під час збору метрик.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">GaugeWithCallback</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;devices_connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">callback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">callback</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">callback</span><span class="p">.</span><span class="na">call</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">),</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelUpDownCounterCallback.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelUpDownCounterCallback</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">upDownCounterCallbackUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Менеджер пристроїв підтримує кількість підключених пристроїв.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Використовуйте асинхронний лічильник з можливістю збільшення та зменшення, щоб повідомляти це значення під час збору метрик.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">upDownCounterBuilder</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">buildWithCallback</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">measurement</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="n">measurement</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">SmartHomeDevices</span><span class="p">.</span><span class="na">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">),</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-07-01" role="tabpanel" aria-labelled-by="tabs-07-01-tab" tabindex="7">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_up_down_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">deviceCountCollector</span><span class="w"> </span><span class="kd">struct</span><span class="p">{</span><span class="w"> </span><span class="nx">desc</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">newDeviceCountCollector</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="nx">deviceCountCollector</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">deviceCountCollector</span><span class="p">{</span><span class="nx">desc</span><span class="p">:</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewDesc</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;devices_connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">},</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">deviceCountCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Describe</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Desc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="w"> </span><span class="o">*</span><span class="nx">deviceCountCollector</span><span class="p">)</span><span class="w"> </span><span class="nf">Collect</span><span class="p">(</span><span class="nx">ch</span><span class="w"> </span><span class="kd">chan</span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Metric</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nb">float64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">)),</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">ch</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">MustNewConstMetric</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">desc</span><span class="p">,</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">GaugeValue</span><span class="p">,</span><span class="w"> </span><span class="nb">float64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">)),</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusUpDownCounterCallbackUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Менеджер пристроїв підтримує кількість підключених пристроїв.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Реалізуйте prometheus.Collector, щоб повідомляти ці значення під час збору метрик.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nf">newDeviceCountCollector</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_up_down_counter_callback.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceThermostat</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceLock</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelUpDownCounterCallbackUsage</span><span class="p">(</span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Менеджер пристроїв підтримує кількість підключених пристроїв.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Використовуйте асинхронний лічильник з можливістю збільшення та зменшення, щоб повідомляти це значення під час збору метрик.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Int64ObservableUpDownCounter</span><span class="p">(</span><span class="s">&#34;devices.connected&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Number of smart home devices currently connected&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithInt64Callback</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">_</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Int64Observer</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nb">int64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">)),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">deviceThermostat</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="nx">o</span><span class="p">.</span><span class="nf">Observe</span><span class="p">(</span><span class="nb">int64</span><span class="p">(</span><span class="nf">connectedDeviceCount</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">)),</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">deviceLock</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li>Приклад Prometheus реалізує <code>prometheus.Collector</code> з методами <code>Describe</code> та <code>Collect</code> для повідомлення значень gauge з мітками.</li>
<li><code>Int64ObservableUpDownCounter</code> використовує <code>metric.WithInt64Callback</code>.</li>
</ul>

    </div>
</div>


## Гістограма {#histogram}

Гістограма записує розподіл набору вимірювань, відстежуючи кількість спостережень, їх суму та кількість, що потрапляє в налаштовувані межі кошиків.

Як Prometheus так й OpenTelemetry підтримують класичні (explicit-bucket) гістограми та нативні (base2 exponential) гістограми. Prometheus також має тип `Summary`, який не має прямого еквівалента в OTel — див. [Summary](#summary) нижче.

Prometheus `Histogram` відповідає інструменту OpenTelemetry `Histogram`.

### Класична (explicit) гістограма {#classic-explicit-histogram}

Обидві системи підтримують класичні гістограми, де фіксовані межі кошиків розділяють спостереження на дискретні діапазони.

- **Налаштування кошиків**: Prometheus оголошує межі кошиків на самому інструменті під час створення. В OpenTelemetry межі кошиків встановлюються на інструменті як підказка, яку можна перевизначити або замінити видами, налаштованими на рівні SDK. Це розділення дозволяє коду інструментування залишатися незалежним від конфігурації збору. Якщо межі не вказані і вид не налаштований, SDK використовує стандартний набір, призначений для затримки в мілісекундах (`[0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000]`), що, ймовірно, невірно для вимірювань у секундах. Завжди надавайте межі або налаштовуйте вид при міграції наявних гістограм.

   <ul class="nav nav-tabs" id="tabs-8" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-08-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-08-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-08-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-08-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-08-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-08-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-8-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-08-00" role="tabpanel" aria-labelled-by="tabs-08-00-tab" tabindex="8">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusHistogram.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Histogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusHistogram</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">histogramUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Histogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Histogram</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">classicUpperBounds</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">1</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">25</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">1</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">2</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">5</span><span class="p">.</span><span class="na">0</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelHistogram.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleHistogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.List</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogram</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c1">// Попередньо виділяйте ключі атрибутів і, коли значення статичні, цілі об&#39;єкти Attributes.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">histogramUsage</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// setExplicitBucketBoundariesAdvice() встановлює стандартні межі як підказку для SDK.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Види, налаштовані на рівні SDK, мають пріоритет над цією підказкою.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleHistogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">histogramBuilder</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setExplicitBucketBoundariesAdvice</span><span class="p">(</span><span class="n">List</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">1</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">25</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">1</span><span class="p">.</span><span class="na">0</span><span class="p">,</span><span class="w"> </span><span class="n">2</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">5</span><span class="p">.</span><span class="na">0</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>observe(value)</code> → <code>record(value, attributes)</code>.</li>
<li>OpenTelemetry розрізняє <code>LongHistogram</code> (цілі числа, через <code>.ofLongs()</code>) та <code>DoubleHistogram</code> (за замовчуванням). Prometheus використовує один тип <code>Histogram</code>.</li>
<li>Попередньо виділяйте екземпляри <code>AttributeKey</code> (завжди) та обʼєкти <code>Attributes</code> (коли значення статичні), щоб уникнути виділення памʼяті при кожному виклику на гарячому шляху.</li>
<li>Види SDK можуть перевизначати межі, встановлені за допомогою <code>setExplicitBucketBoundariesAdvice()</code>, а також можуть налаштовувати інші аспекти збору гістограм, такі як фільтрація атрибутів, мінімальне/максимальне записування та перейменування інструментів.</li>
</ul>

    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-08-01" role="tabpanel" aria-labelled-by="tabs-08-01-tab" tabindex="8">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_histogram.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">deviceCommandDuration</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewHistogramVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">HistogramOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w">    </span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w">    </span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Buckets</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span><span class="kt">float64</span><span class="p">{</span><span class="mf">0.1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.25</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">,</span><span class="w"> </span><span class="mf">1.0</span><span class="p">,</span><span class="w"> </span><span class="mf">2.5</span><span class="p">,</span><span class="w"> </span><span class="mf">5.0</span><span class="p">},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">prometheusHistogramUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">deviceCommandDuration</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.35</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.85</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_histogram.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Попередньо виділяйте опції атрибутів, коли значення статичні, щоб уникнути виділення пам&#39;яті при кожному виклику.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceThermostatOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceLockOpts</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">otelHistogramUsage</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// WithExplicitBucketBoundaries встановлює стандартні межі як підказку для SDK.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Види, налаштовані на рівні SDK, мають пріоритет над цією підказкою.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Histogram</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithExplicitBucketBoundaries</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span><span class="w"> </span><span class="mf">0.25</span><span class="p">,</span><span class="w"> </span><span class="mf">0.5</span><span class="p">,</span><span class="w"> </span><span class="mf">1.0</span><span class="p">,</span><span class="w"> </span><span class="mf">2.5</span><span class="p">,</span><span class="w"> </span><span class="mf">5.0</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.35</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceThermostatOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.85</span><span class="p">,</span><span class="w"> </span><span class="nx">deviceLockOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>Observe(value)</code> → <code>Record(ctx, value, metric.WithAttributes(...))</code>.</li>
<li>У Go функція metric.WithExplicitBucketBoundaries(&hellip;) є варіантною (а не зрізом). Prometheus використовує поле Buckets у класі HistogramOpts.</li>
<li>Види SDK можуть перевизначати межі, встановлені за допомогою <code>WithExplicitBucketBoundaries()</code>, а також можуть налаштовувати інші аспекти збору гістограм, такі як фільтрація атрибутів, мінімальне/максимальне записування та перейменування інструментів.</li>
</ul>

    </div>
</div>


### Нативна (base2 exponential) гістограма {#native-base2-exponential-histogram}

Обидві системи підтримують нативні (base2 exponential) гістограми, які автоматично налаштовують межі кошиків, щоб охопити спостережуваний діапазон без необхідності ручного налаштування.

- **Вибір формату**: Інструменти Prometheus можуть видавати лише класичний формат, лише нативний формат або обидва одночасно, що дозволяє поступову міграцію без змін у інструментуванні. У OpenTelemetry вибір формату налаштовується поза кодом інструментування, на експортері або через вид, тому код інструментування не потребує змін у будь-якому випадку.
- **Код інструментування**: Код інструментування OpenTelemetry ідентичний для класичних та нативних гістограм. Ті самі виклики `record()` генерують будь-який формат залежно від того, як налаштовано SDK.

   <ul class="nav nav-tabs" id="tabs-9" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-09-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-09-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-09-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-09-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-09-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-09-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-9-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-09-00" role="tabpanel" aria-labelled-by="tabs-09-00-tab" tabindex="9">
        <p>Prometheus</p>
<p>В Prometheus, формат гістограми контролюється під час створення інструменту. Приклад нижче використовує <code>.nativeOnly()</code>, щоб обмежити формат лише нативним; якщо його опустити, будуть одночасно генеруватись як класичний, так і нативний формати:</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusHistogramNative.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Histogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusHistogramNative</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">nativeHistogramUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Histogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Histogram</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">nativeOnly</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-09-01" role="tabpanel" aria-labelled-by="tabs-09-01-tab" tabindex="9">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<p>В Prometheus, встановлення <code>NativeHistogramBucketFactor</code> дозволяє використовувати нативні гістограми разом із класичною конфігурацією кошиків — обидва формати звітуються одночасно:</p>
<?code-excerpt "prometheus_histogram_native.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">nativeDeviceCommandDuration</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewHistogramVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">HistogramOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w">                        </span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w">                        </span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">NativeHistogramBucketFactor</span><span class="p">:</span><span class="w"> </span><span class="mf">1.1</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">nativeHistogramUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">nativeDeviceCommandDuration</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">nativeDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.35</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">nativeDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.85</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>Ключові відмінності:</p>
<ul>
<li><code>NativeHistogramBucketFactor</code> має бути встановлено на значення більше 1.0, щоб увімкнути нативні гістограми в Go — це не є опціональним. Встановлення його на 0 (нульове значення) повністю вимикає нативні гістограми. Значення контролює максимальне співвідношення між послідовними межами кошиків; менші значення дають більш точне розділення за рахунок більшої кількості кошиків. Щоб наблизити ту ж щільність кошиків, що й зазвичай використовуване значення <code>1.1</code>, встановіть <code>MaxScale: 3</code> на <code>AggregationBase2ExponentialHistogram</code>.</li>
</ul>

    </div>
</div>


В OpenTelemetry, код інструментування ідентичний до випадку з класичною гістограмою. Формат base2 exponential налаштовується окремо, поза шаром інструментування.

Бажаний підхід — налаштувати його на експортері метрик. Це застосовується до всіх гістограм, експортованих через цей експортер, без зміни коду інструментування:

   <ul class="nav nav-tabs" id="tabs-10" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-10-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-10-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-10-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-10-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-10-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-10-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-10-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-10-00" role="tabpanel" aria-labelled-by="tabs-10-00-tab" tabindex="10">
        <?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/OtelHistogramExponentialExporter.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.Aggregation</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.InstrumentType</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogramExponentialExporter</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">static</span><span class="w"> </span><span class="n">OtlpHttpMetricExporter</span><span class="w"> </span><span class="nf">createExporter</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Налаштуйте експортер для використання експоненціальних гістограм для всіх інструментів гістограм.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Це бажаний підхід — він застосовується глобально без зміни коду інструментування.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">OtlpHttpMetricExporter</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setEndpoint</span><span class="p">(</span><span class="s">&#34;http://localhost:4318&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">setDefaultAggregationSelector</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">DefaultAggregationSelector</span><span class="p">.</span><span class="na">getDefault</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">.</span><span class="na">with</span><span class="p">(</span><span class="n">InstrumentType</span><span class="p">.</span><span class="na">HISTOGRAM</span><span class="p">,</span><span class="w"> </span><span class="n">Aggregation</span><span class="p">.</span><span class="na">base2ExponentialBucketHistogram</span><span class="p">()))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-10-01" role="tabpanel" aria-labelled-by="tabs-10-01-tab" tabindex="10">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<?code-excerpt "otel_histogram_exponential_exporter.go" region="createExponentialExporter"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">sdkmetric</span><span class="w"> </span><span class="s">&#34;go.opentelemetry.io/otel/sdk/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">createExponentialExporter</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nx">Exporter</span><span class="p">,</span><span class="w"> </span><span class="kt">error</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Налаштуйте експортер для використання експоненціальних гістограм для всіх інструментів гістограм.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Це бажаний підхід — він застосовується глобально без зміни коду інструментування.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">otlpmetrichttp</span><span class="p">.</span><span class="nf">WithAggregationSelector</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">ik</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">InstrumentKind</span><span class="p">)</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">Aggregation</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">if</span><span class="w"> </span><span class="nx">ik</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">InstrumentKindHistogram</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">				</span><span class="k">return</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">AggregationBase2ExponentialHistogram</span><span class="p">{}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">DefaultAggregationSelector</span><span class="p">(</span><span class="nx">ik</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


Для більш детального керування — наприклад, щоб використовувати експоненціальні гістограми base2 для конкретних інструментів, залишаючи явні кошики для інших — налаштуйте view:

   <ul class="nav nav-tabs" id="tabs-11" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-11-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-11-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-11-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-11-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-11-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-11-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-11-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-11-00" role="tabpanel" aria-labelled-by="tabs-11-00-tab" tabindex="11">
        <?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/OtelHistogramExponentialView.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.Aggregation</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.InstrumentSelector</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.SdkMeterProvider</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.sdk.metrics.View</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogramExponentialView</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">static</span><span class="w"> </span><span class="n">SdkMeterProvider</span><span class="w"> </span><span class="nf">createMeterProvider</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Використовуйте view для керування на рівні інструменту — виберіть конкретний інструмент за назвою</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// щоб використовувати експоненціальні гістограми, залишаючи явні кошики для інших.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">SdkMeterProvider</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">registerView</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">InstrumentSelector</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">setName</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">).</span><span class="na">build</span><span class="p">(),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">View</span><span class="p">.</span><span class="na">builder</span><span class="p">().</span><span class="na">setAggregation</span><span class="p">(</span><span class="n">Aggregation</span><span class="p">.</span><span class="na">base2ExponentialBucketHistogram</span><span class="p">()).</span><span class="na">build</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-11-01" role="tabpanel" aria-labelled-by="tabs-11-01-tab" tabindex="11">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<?code-excerpt "otel_histogram_exponential.go" region="createExponentialView"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">createExponentialView</span><span class="p">()</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">View</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Використовуйте view для керування на рівні інструменту — виберіть конкретний інструмент за назвою</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// щоб використовувати експоненціальні гістограми, залишаючи явні кошики для інших.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nf">NewView</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">Instrument</span><span class="p">{</span><span class="nx">Name</span><span class="p">:</span><span class="w"> </span><span class="s">&#34;device.command.duration&#34;</span><span class="p">},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">Stream</span><span class="p">{</span><span class="nx">Aggregation</span><span class="p">:</span><span class="w"> </span><span class="nx">sdkmetric</span><span class="p">.</span><span class="nx">AggregationBase2ExponentialHistogram</span><span class="p">{}!},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>


### Summary {#summary}

Prometheus `Summary` рахує квантилі на стороні клієнта під час збору даних і експортує їх як часові серії з мітками (наприклад, `{quantile="0.95"}`). OpenTelemetry не має прямого еквівалента.

Для оцінки квантилів рекомендується використовувати **гістограму з експоненціальними кошиками base2**: вона автоматично налаштовує межі кошиків для покриття спостережуваного діапазону, а `histogram_quantile()` у PromQL може обчислювати квантилі з обмеженою похибкою під час запиту. На відміну від `Summary`, результати можна агрегувати між екземплярами. Див. [Native (base2 exponential) histogram](#native-base2-exponential-histogram).

Якщо вам потрібні лише кількість і сума, а не квантилі, гістограма без явних меж кошиків фіксує ці статистики з мінімальними витратами. Нижче наведено приклади цього простішого підходу.

   <ul class="nav nav-tabs" id="tabs-12" role="tablist">
  <li class="nav-item">
      <button class="nav-link active"
          id="tabs-12-00-tab" data-bs-toggle="tab" data-bs-target="#tabs-12-00" role="tab"
          data-td-tp-persist="java" aria-controls="tabs-12-00" aria-selected="true">
        Java
      </button>
    </li><li class="nav-item">
      <button class="nav-link"
          id="tabs-12-01-tab" data-bs-toggle="tab" data-bs-target="#tabs-12-01" role="tab"
          data-td-tp-persist="go" aria-controls="tabs-12-01" aria-selected="false">
        Go
      </button>
    </li>
</ul>

<div class="tab-content" id="tabs-12-content">
    <div class="tab-body tab-pane fade show active"
        id="tabs-12-00" role="tabpanel" aria-labelled-by="tabs-12-00-tab" tabindex="12">
        <p>Prometheus</p>
<?code-excerpt path-base="examples/java/prometheus-compatibility"?>
<?code-excerpt "src/main/java/otel/PrometheusSummary.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.prometheus.metrics.core.metrics.Summary</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">PrometheusSummary</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">summaryUsage</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Summary</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Summary</span><span class="p">.</span><span class="na">builder</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">name</span><span class="p">(</span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">help</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">labelNames</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">quantile</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">5</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">05</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">quantile</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">95</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">01</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">quantile</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">99</span><span class="p">,</span><span class="w"> </span><span class="n">0</span><span class="p">.</span><span class="na">001</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">register</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">labelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="na">observe</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "src/main/java/otel/OtelHistogramAsSummary.java"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nn">otel</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.OpenTelemetry</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.AttributeKey</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.common.Attributes</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.DoubleHistogram</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">io.opentelemetry.api.metrics.Meter</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.List</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">OtelHistogramAsSummary</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">AttributeKey</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DEVICE_TYPE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AttributeKey</span><span class="p">.</span><span class="na">stringKey</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Attributes</span><span class="w"> </span><span class="n">LOCK</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Attributes</span><span class="p">.</span><span class="na">of</span><span class="p">(</span><span class="n">DEVICE_TYPE</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">summaryReplacement</span><span class="p">(</span><span class="n">OpenTelemetry</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">Meter</span><span class="w"> </span><span class="n">meter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">openTelemetry</span><span class="p">.</span><span class="na">getMeter</span><span class="p">(</span><span class="s">&#34;smart.home&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// Немає явних меж кошиків: фіксує лише кількість і суму, хороший замінник для більшості</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c1">// випадків використання Summary. Для оцінки квантилів додайте межі, що охоплюють ваші пороги.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">DoubleHistogram</span><span class="w"> </span><span class="n">deviceCommandDuration</span><span class="w"> </span><span class="o">=</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">meter</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">histogramBuilder</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">setExplicitBucketBoundariesAdvice</span><span class="p">(</span><span class="n">List</span><span class="p">.</span><span class="na">of</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="na">build</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">35</span><span class="p">,</span><span class="w"> </span><span class="n">THERMOSTAT</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">deviceCommandDuration</span><span class="p">.</span><span class="na">record</span><span class="p">(</span><span class="n">0</span><span class="p">.</span><span class="na">85</span><span class="p">,</span><span class="w"> </span><span class="n">LOCK</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-12-01" role="tabpanel" aria-labelled-by="tabs-12-01-tab" tabindex="12">
        <?code-excerpt path-base="examples/go/prometheus-compatibility"?>
<p>Prometheus</p>
<?code-excerpt "prometheus_summary.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;github.com/prometheus/client_golang/prometheus&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">summaryDeviceCommandDuration</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">prometheus</span><span class="p">.</span><span class="nf">NewSummaryVec</span><span class="p">(</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">SummaryOpts</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Name</span><span class="p">:</span><span class="w">       </span><span class="s">&#34;device_command_duration_seconds&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Help</span><span class="p">:</span><span class="w">       </span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">Objectives</span><span class="p">:</span><span class="w"> </span><span class="kd">map</span><span class="p">[</span><span class="kt">float64</span><span class="p">]</span><span class="kt">float64</span><span class="p">{</span><span class="mf">0.5</span><span class="p">:</span><span class="w"> </span><span class="mf">0.05</span><span class="p">,</span><span class="w"> </span><span class="mf">0.95</span><span class="p">:</span><span class="w"> </span><span class="mf">0.01</span><span class="p">,</span><span class="w"> </span><span class="mf">0.99</span><span class="p">:</span><span class="w"> </span><span class="mf">0.001</span><span class="p">},</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">},</span><span class="w"> </span><span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;device_type&#34;</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">summaryUsage</span><span class="p">(</span><span class="nx">reg</span><span class="w"> </span><span class="o">*</span><span class="nx">prometheus</span><span class="p">.</span><span class="nx">Registry</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">reg</span><span class="p">.</span><span class="nf">MustRegister</span><span class="p">(</span><span class="nx">summaryDeviceCommandDuration</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;thermostat&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.35</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryDeviceCommandDuration</span><span class="p">.</span><span class="nf">WithLabelValues</span><span class="p">(</span><span class="s">&#34;lock&#34;</span><span class="p">).</span><span class="nf">Observe</span><span class="p">(</span><span class="mf">0.85</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>OpenTelemetry</p>
<?code-excerpt "otel_histogram_as_summary.go"?>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;context&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/attribute&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;go.opentelemetry.io/otel/metric&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c1">// Попередньо виділіть параметри атрибутів, коли значення статичні, щоб уникнути виділення пам&#39;яті при кожному виклику.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryThermostatOpts</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;thermostat&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">summaryLockOpts</span><span class="w">       </span><span class="p">=</span><span class="w"> </span><span class="p">[]</span><span class="nx">metric</span><span class="p">.</span><span class="nx">RecordOption</span><span class="p">{</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithAttributes</span><span class="p">(</span><span class="nx">attribute</span><span class="p">.</span><span class="nf">String</span><span class="p">(</span><span class="s">&#34;device_type&#34;</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;lock&#34;</span><span class="p">))}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">summaryReplacement</span><span class="p">(</span><span class="nx">ctx</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span><span class="w"> </span><span class="nx">meter</span><span class="w"> </span><span class="nx">metric</span><span class="p">.</span><span class="nx">Meter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// Немає явних меж кошиків: фіксує лише кількість і суму, хороший замінник для більшості</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// випадків використання Summary. Для оцінки квантилів додайте межі, що охоплюють ваші пороги.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">meter</span><span class="p">.</span><span class="nf">Float64Histogram</span><span class="p">(</span><span class="s">&#34;device.command.duration&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithDescription</span><span class="p">(</span><span class="s">&#34;Time to receive acknowledgment from a smart home device&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithUnit</span><span class="p">(</span><span class="s">&#34;s&#34;</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">metric</span><span class="p">.</span><span class="nf">WithExplicitBucketBoundaries</span><span class="p">())</span><span class="w"> </span><span class="c1">// немає меж кошиків</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.35</span><span class="p">,</span><span class="w"> </span><span class="nx">summaryThermostatOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">deviceCommandDuration</span><span class="p">.</span><span class="nf">Record</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span><span class="w"> </span><span class="mf">0.85</span><span class="p">,</span><span class="w"> </span><span class="nx">summaryLockOpts</span><span class="o">...</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div>
    </div>
</div>
