# Поширення

> Поширення контексту для JS SDK

---

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

---


Завдяки поширенню контексту [сигнали](/docs/concepts/signals/) можуть бути повʼязані між собою, незалежно від того, де вони генеруються. Хоча поширення контексту не обмежується трейсами, воно дозволяє [трейсам](/docs/concepts/signals/traces/) створювати причинно-наслідкову інформацію про систему між сервісами, які довільно розподілені між процесами та межами мереж.

У переважній більшості випадків використання бібліотеки, що нативно підтримують OpenTelemetry або [бібліотеки інструментування](../libraries/), автоматично поширюватимуть контекст трасування між сервісами. Лише в рідкісних випадках вам доведеться поширювати контекст вручну.



Щоб дізнатися більше, дивіться [Поширення контексту](/docs/concepts/context-propagation).




{{__hugo_ctx/}}




> [!NOTE]
>
> У документації OpenTelemetry передбачається, що скомпільований застосунок працює у форматі [CommonJS](https://nodejs.org/api/modules.html#modules-commonjs-modules). Якщо застосунок працює як ESM, додайте хук завантажувача, як зазначено в [документації щодо підтримки ESM](https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/esm-support.md).
{{__hugo_ctx/}}


## Автоматичне поширення контексту {#automatic-context-propagation}

[Бібліотеки інструментування](../libraries/) такі як [`@opentelemetry/instrumentation-http`](https://www.npmjs.com/package/@opentelemetry/instrumentation-http) або [`@opentelemetry/instrumentation-express`](https://www.npmjs.com/package/@opentelemetry/instrumentation-express) поширюють контекст між сервісами за вас.

Якщо ви слідували [Посібнику з початку роботи](../getting-started/nodejs), ви можете створити клієнтський застосунок, який запитує точку доступу `/rolldice`.

> [!NOTE]
>
> Ви можете поєднати цей приклад із демонстраційним застосунком з Посібника з початку роботи будь-якою іншою мовою. Кореляція працює між застосунками, написаними різними мовами, без будь-яких відмінностей.

Почніть зі створення нової теки з назвою `dice-client` та встановлення необхідних залежностей:

   <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="typescript" aria-controls="tabs-02-00" aria-selected="true">
        TypeScript
      </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="javascript" aria-controls="tabs-02-01" aria-selected="false">
        JavaScript
      </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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">npm init -y
</span></span><span class="line"><span class="cl">npm install undici <span class="se">\
</span></span></span><span class="line"><span class="cl">  @opentelemetry/instrumentation-undici <span class="se">\
</span></span></span><span class="line"><span class="cl">  @opentelemetry/sdk-node
</span></span><span class="line"><span class="cl">npm install -D tsx  <span class="c1"># інструмент для безпосереднього запуску файлів TypeScript (.ts) за допомогою node</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-02-01" role="tabpanel" aria-labelled-by="tabs-02-01-tab" tabindex="2">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">npm init -y
</span></span><span class="line"><span class="cl">npm install undici <span class="se">\
</span></span></span><span class="line"><span class="cl">  @opentelemetry/instrumentation-undici <span class="se">\
</span></span></span><span class="line"><span class="cl">  @opentelemetry/sdk-node
</span></span></code></pre></div>
    </div>
</div>


Далі створіть новий файл з назвою `client.ts` (або `client.js`) з наступним вмістом:

   <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="typescript" aria-controls="tabs-03-00" aria-selected="true">
        TypeScript
      </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="javascript" aria-controls="tabs-03-01" aria-selected="false">
        JavaScript
      </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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="cl"><span class="cm">/* client.ts */</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">NodeSDK</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">SimpleSpanProcessor</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">ConsoleSpanExporter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/sdk-trace-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">UndiciInstrumentation</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/instrumentation-undici&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">spanProcessors</span><span class="o">:</span> <span class="p">[</span><span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="k">new</span> <span class="nx">ConsoleSpanExporter</span><span class="p">())],</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="k">new</span> <span class="nx">UndiciInstrumentation</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">request</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;undici&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">request</span><span class="p">(</span><span class="s1">&#39;http://localhost:8080/rolldice&#39;</span><span class="p">).</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">response</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">json</span><span class="p">().</span><span class="nx">then</span><span class="p">((</span><span class="nx">json</span>: <span class="kt">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">json</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-03-01" role="tabpanel" aria-labelled-by="tabs-03-01-tab" tabindex="3">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="cm">/* instrumentation.mjs */</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">NodeSDK</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@opentelemetry/sdk-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">SimpleSpanProcessor</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">ConsoleSpanExporter</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@opentelemetry/sdk-trace-node&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">UndiciInstrumentation</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@opentelemetry/instrumentation-undici&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">sdk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">NodeSDK</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">spanProcessors</span><span class="o">:</span> <span class="p">[</span><span class="k">new</span> <span class="nx">SimpleSpanProcessor</span><span class="p">(</span><span class="k">new</span> <span class="nx">ConsoleSpanExporter</span><span class="p">())],</span>
</span></span><span class="line"><span class="cl">  <span class="nx">instrumentations</span><span class="o">:</span> <span class="p">[</span><span class="k">new</span> <span class="nx">UndiciInstrumentation</span><span class="p">()],</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="nx">sdk</span><span class="p">.</span><span class="nx">start</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">request</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;undici&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">request</span><span class="p">(</span><span class="s1">&#39;http://localhost:8080/rolldice&#39;</span><span class="p">).</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">response</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">json</span><span class="p">().</span><span class="nx">then</span><span class="p">((</span><span class="nx">json</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">json</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div>
    </div>
</div>


Переконайтеся, що у вас запущена інструментована версія `app.ts` (або `app.js`) з [Посібника з початку роботи](../getting-started/nodejs) в одному терміналі:

   <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="typescript" aria-controls="tabs-04-00" aria-selected="true">
        TypeScript
      </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="javascript" aria-controls="tabs-04-01" aria-selected="false">
        JavaScript
      </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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> npx tsx --import ./instrumentation.ts app.ts
</span></span><span class="line"><span class="cl"><span class="go">Listening for requests on http://localhost:8080
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-04-01" role="tabpanel" aria-labelled-by="tabs-04-01-tab" tabindex="4">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> node --import ./instrumentation.mjs app.js
</span></span><span class="line"><span class="cl"><span class="go">Listening for requests on http://localhost:8080
</span></span></span></code></pre></div>
    </div>
</div>


Запустіть другий термінал і виконайте `client.ts` (або `client.js`):

   <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="typescript" aria-controls="tabs-05-00" aria-selected="true">
        TypeScript
      </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="javascript" aria-controls="tabs-05-01" aria-selected="false">
        JavaScript
      </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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">npx tsx client.ts
</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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">node client.js
</span></span></code></pre></div>
    </div>
</div>


Обидва термінали повинні виводити деталі відрізків в консоль. Вивід клієнта виглядає подібно до наступного:

```javascript {hl_lines=[7,11]}
{
  resource: {
    attributes: {
      // ...
    }
  },
  traceId: 'cccd19c3a2d10e589f01bfe2dc896dc2',
  parentSpanContext: undefined,
  traceState: undefined,
  name: 'GET',
  id: '6f64ce484217a7bf',
  kind: 2,
  timestamp: 1718875320295000,
  duration: 19836.833,
  attributes: {
    'url.full': 'http://localhost:8080/rolldice',
    // ...
  },
  status: { code: 0 },
  events: [],
  links: []
}
```

Зверніть увагу на traceId (`cccd19c3a2d10e589f01bfe2dc896dc2`) та ID (`6f64ce484217a7bf`). Обидва можна знайти у виводі клієнта також:

```javascript {hl_lines=["6,9"]}
{
  resource: {
    attributes: {
      // ...
  },
  traceId: 'cccd19c3a2d10e589f01bfe2dc896dc2',
  parentSpanContext: {
    traceId: 'cccd19c3a2d10e589f01bfe2dc896dc2',
    spanId: '6f64ce484217a7bf',
    traceFlags: 1,
    isRemote: true
  },
  traceState: undefined,
  name: 'GET /rolldice',
  id: '027c5c8b916d29da',
  kind: 1,
  timestamp: 1718875320310000,
  duration: 3894.792,
  attributes: {
    'http.url': 'http://localhost:8080/rolldice',
    // ...
  },
  status: { code: 0 },
  events: [],
  links: []
}
```

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

## Ручне поширення контексту {#manual-context-propagation}

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

Коли вам потрібно вручну поширювати контекст, ви можете використовувати [API контексту](/docs/languages/js/context).

### Загальний приклад {#generic-example}

Наступний загальний приклад демонструє, як ви можете вручну поширювати контекст трасування.

Спочатку, на сервісі, що відправляє, вам потрібно буде зробити інʼєкцію поточного `context`:

   <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="typescript" aria-controls="tabs-06-00" aria-selected="true">
        TypeScript
      </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="javascript" aria-controls="tabs-06-01" aria-selected="false">
        JavaScript
      </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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="c1">// Сервіс, що відправляє
</span></span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">propagation</span><span class="p">,</span> <span class="nx">trace</span> <span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/api&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Визначте інтерфейс для вихідного обʼєкта, який буде містити інформацію про трасування.
</span></span></span><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Carrier</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">traceparent?</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">tracestate?</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Створіть вихідний обʼєкт, який відповідає цьому інтерфейсу.
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">output</span>: <span class="kt">Carrier</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Сереалізуйте traceparent та tracestate з контексту у
</span></span></span><span class="line"><span class="cl"><span class="c1">// вихідний обʼєкт.
</span></span></span><span class="line"><span class="cl"><span class="c1">//
</span></span></span><span class="line"><span class="cl"><span class="c1">// Цей приклад використовує активний контекст трасування, але ви можете
</span></span></span><span class="line"><span class="cl"><span class="c1">// використовувати будь-який контекст, який підходить для вашого сценарію.
</span></span></span><span class="line"><span class="cl"><span class="nx">propagation</span><span class="p">.</span><span class="nx">inject</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">active</span><span class="p">(),</span> <span class="nx">output</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Витягніть значення traceparent та tracestate з вихідного обʼєкта.
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">traceparent</span><span class="p">,</span> <span class="nx">tracestate</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">output</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Ви можете передати дані traceparent та tracestate
</span></span></span><span class="line"><span class="cl"><span class="c1">// через будь-який механізм, який ви використовуєте для пропагації
</span></span></span><span class="line"><span class="cl"><span class="c1">// між сервісами.
</span></span></span></code></pre></div>
    </div>
    <div class="tab-body tab-pane fade"
        id="tabs-06-01" role="tabpanel" aria-labelled-by="tabs-06-01-tab" tabindex="6">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="c1">// Сервіс, що надсилає
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">propagation</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;@opentelemetry/api&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">output</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Сереалізуйте traceparent та tracestate з контексту у
</span></span></span><span class="line"><span class="cl"><span class="c1">// вихідний обʼєкт.
</span></span></span><span class="line"><span class="cl"><span class="c1">//
</span></span></span><span class="line"><span class="cl"><span class="c1">// Цей приклад використовує активний контекст трасування, але ви можете
</span></span></span><span class="line"><span class="cl"><span class="c1">// використовувати будь-який контекст, який підходить для вашого сценарію.
</span></span></span><span class="line"><span class="cl"><span class="nx">propagation</span><span class="p">.</span><span class="nx">inject</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">active</span><span class="p">(),</span> <span class="nx">output</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">traceparent</span><span class="p">,</span> <span class="nx">tracestate</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">output</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="c1">// Ви можете передати дані traceparent та tracestate
</span></span></span><span class="line"><span class="cl"><span class="c1">// через будь-який механізм, який ви використовуєте для пропагації
</span></span></span><span class="line"><span class="cl"><span class="c1">// між сервісами.
</span></span></span></code></pre></div>
    </div>
</div>


На сервісі, що приймає, вам потрібно буде витягти `context` (наприклад, з розібраних HTTP заголовків) і потім встановити їх як поточний контекст трасування.

   <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="typescript" aria-controls="tabs-07-00" aria-selected="true">
        TypeScript
      </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="javascript" aria-controls="tabs-07-01" aria-selected="false">
        JavaScript
      </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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="cl"><span class="c1">// Сервіс, що приймає
</span></span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">type</span> <span class="nx">Context</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">propagation</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">trace</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">Span</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">context</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="kr">from</span> <span class="s1">&#39;@opentelemetry/api&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Визначте інтерфейс для вхідного обʼєкта, який включає &#39;traceparent&#39; та &#39;tracestate&#39;.
</span></span></span><span class="line"><span class="cl"><span class="kr">interface</span> <span class="nx">Carrier</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">traceparent?</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">tracestate?</span>: <span class="kt">string</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Припустимо, що &#34;input&#34; є обʼєктом з ключами &#39;traceparent&#39; та &#39;tracestate&#39;.
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">input</span>: <span class="kt">Carrier</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Витягує дані &#39;traceparent&#39; та &#39;tracestate&#39; у контекстний обʼєкт.
</span></span></span><span class="line"><span class="cl"><span class="c1">//
</span></span></span><span class="line"><span class="cl"><span class="c1">// Ви можете потім вважати цей контекст активним для ваших
</span></span></span><span class="line"><span class="cl"><span class="c1">// трасувань.
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">activeContext</span>: <span class="kt">Context</span> <span class="o">=</span> <span class="nx">propagation</span><span class="p">.</span><span class="nx">extract</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">active</span><span class="p">(),</span> <span class="nx">input</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">tracer</span> <span class="o">=</span> <span class="nx">trace</span><span class="p">.</span><span class="nx">getTracer</span><span class="p">(</span><span class="s1">&#39;app-name&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">span</span>: <span class="kt">Span</span> <span class="o">=</span> <span class="nx">tracer</span><span class="p">.</span><span class="nx">startSpan</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">spanName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">attributes</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">activeContext</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Встановіть створений спан як активний у десереалізованому контексті.
</span></span></span><span class="line"><span class="cl"><span class="nx">trace</span><span class="p">.</span><span class="nx">setSpan</span><span class="p">(</span><span class="nx">activeContext</span><span class="p">,</span> <span class="nx">span</span><span class="p">);</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">
        <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="c1">// Сервіс, що приймає
</span></span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">propagation</span><span class="p">,</span> <span class="nx">trace</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;@opentelemetry/api&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Припустимо, що &#34;input&#34; є обʼєктом з ключами &#39;traceparent&#39; та &#39;tracestate&#39;
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">input</span> <span class="o">=</span> <span class="p">{};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Витягує дані &#39;traceparent&#39; та &#39;tracestate&#39; у контекстний обʼєкт.
</span></span></span><span class="line"><span class="cl"><span class="c1">//
</span></span></span><span class="line"><span class="cl"><span class="c1">// Ви можете потім вважати цей контекст активним для ваших
</span></span></span><span class="line"><span class="cl"><span class="c1">// трасувань.
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">activeContext</span> <span class="o">=</span> <span class="nx">propagation</span><span class="p">.</span><span class="nx">extract</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">active</span><span class="p">(),</span> <span class="nx">input</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">tracer</span> <span class="o">=</span> <span class="nx">trace</span><span class="p">.</span><span class="nx">getTracer</span><span class="p">(</span><span class="s1">&#39;app-name&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">span</span> <span class="o">=</span> <span class="nx">tracer</span><span class="p">.</span><span class="nx">startSpan</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">  <span class="nx">spanName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">attributes</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">activeContext</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Встановіть створений спан як активний у десереалізованому контексті.
</span></span></span><span class="line"><span class="cl"><span class="nx">trace</span><span class="p">.</span><span class="nx">setSpan</span><span class="p">(</span><span class="nx">activeContext</span><span class="p">,</span> <span class="nx">span</span><span class="p">);</span>
</span></span></code></pre></div>
    </div>
</div>


З цього моменту, коли у вас є десереалізований активний контекст, ви можете створювати відрізки, які будуть частиною того ж трасування з іншого сервісу.

Ви також можете використовувати [API контексту](/docs/languages/js/context) для модифікації або встановлення десереалізованого контексту іншими способами.

### Приклад з власним протоколом {#custom-protocol-example}

Звичайний випадок, коли вам потрібно вручну поширювати контекст, це коли ви використовуєте власний протокол між сервісами для звʼязку. Наступний приклад використовує базовий текстовий TCP протокол для надсилання сереалізованого обʼєкта від одного сервісу до іншого.

Почніть зі створення нової теки з назвою `propagation-example` та ініціалізуйте її залежностями наступним чином:

```shell
npm init -y
npm install @opentelemetry/api @opentelemetry/sdk-node
```

Далі створіть файли `client.js` та `server.js` з наступним вмістом:

```javascript
// client.js
const net = require('net');
const { context, propagation, trace } = require('@opentelemetry/api');

let tracer = trace.getTracer('client');

// Підключення до сервера
const client = net.createConnection({ port: 8124 }, () => {
  // Відправка сереалізованого обʼєкта на сервер
  let span = tracer.startActiveSpan('send', { kind: 1 }, (span) => {
    const output = {};
    propagation.inject(context.active(), output);
    const { traceparent, tracestate } = output;

    const objToSend = { key: 'value' };

    if (traceparent) {
      objToSend._meta = { traceparent, tracestate };
    }

    client.write(JSON.stringify(objToSend), () => {
      client.end();
      span.end();
    });
  });
});
```

```javascript
// server.js
const net = require('net');
const { context, propagation, trace } = require('@opentelemetry/api');

let tracer = trace.getTracer('server');

const server = net.createServer((socket) => {
  socket.on('data', (data) => {
    const message = data.toString();
    // Розбір JSON обʼєкта, отриманого від клієнта
    try {
      const json = JSON.parse(message);
      let activeContext = context.active();
      if (json._meta) {
        activeContext = propagation.extract(context.active(), json._meta);
        delete json._meta;
      }
      span = tracer.startSpan('receive', { kind: 1 }, activeContext);
      trace.setSpan(activeContext, span);
      console.log('Розібраний JSON:', json);
    } catch (e) {
      console.error('Помилка розбору JSON:', e.message);
    } finally {
      span.end();
    }
  });
});

// Прослуховування на порту 8124
server.listen(8124, () => {
  console.log('Сервер слухає на порту 8124');
});
```

Запустіть перший термінал для запуску сервера:

```console
$ node server.js
Сервер слухає на порту 8124
```

Потім у другому терміналі запустіть клієнт:

```shell
node client.js
```

Клієнт повинен завершити роботу негайно, а сервер повинен вивести наступне:

```text
Розібраний JSON: { key: 'value' }
```

Оскільки приклад до цього моменту взяв залежність лише від OpenTelemetry API, всі виклики до нього є [no-op інструкціями](<https://en.wikipedia.org/wiki/NOP_(code)>) і клієнт та сервер поводяться так, ніби OpenTelemetry не використовується.

> [!IMPORTANT]
>
> Це особливо важливо, якщо ваш серверний та клієнтський код є бібліотеками, оскільки вони повинні використовувати лише OpenTelemetry API. Щоб зрозуміти чому, прочитайте [сторінку концепції про те, як додати інструментування до вашої бібліотеки](/docs/concepts/instrumentation/libraries/).

Щоб увімкнути OpenTelemetry та побачити поширення контексту в дії, створіть додатковий файл з назвою `instrumentation.js` з наступним вмістом:

```javascript
// instrumentation.mjs
import { NodeSDK } from '@opentelemetry/sdk-node';
import {
  ConsoleSpanExporter,
  SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-node';

const sdk = new NodeSDK({
  spanProcessors: [new SimpleSpanProcessor(new ConsoleSpanExporter())],
});

sdk.start();
```

Використовуйте цей файл для запуску як сервера, так і клієнта, з увімкненим інструментуванням:

```console
$ node --import ./instrumentation.mjs server.js
Сервер слухає на порту 8124
```

та

```shell
node --import ./instrumentation.mjs client.js
```

Після того, як клієнт відправив дані на сервер і завершив роботу, ви повинні побачити відрізки у виводі консолі обох терміналів.

Вивід для клієнта виглядає наступним чином:

```javascript {hl_lines=[7,11]}
{
  resource: {
    attributes: {
      // ...
    }
  },
  traceId: '4b5367d540726a70afdbaf49240e6597',
  parentId: undefined,
  traceState: undefined,
  name: 'send',
  id: '92f125fa335505ec',
  kind: 1,
  timestamp: 1718879823424000,
  duration: 1054.583,
  // ...
}
```

Вивід для сервера виглядає наступним чином:

```javascript {hl_lines=[7,8]}
{
  resource: {
    attributes: {
      // ...
    }
  },
  traceId: '4b5367d540726a70afdbaf49240e6597',
  parentId: '92f125fa335505ec',
  traceState: undefined,
  name: 'receive',
  id: '53da0c5f03cb36e5',
  kind: 1,
  timestamp: 1718879823426000,
  duration: 959.541,
  // ...
}
```

Подібно до [ручного прикладу](#manual-context-propagation) відрізки підключені за допомогою `traceId` та `id`/`parentId`.

## Наступні кроки {#next-steps}

Щоб дізнатися більше про поширення, прочитайте [Специфікацію API поширювачів](/docs/specs/otel/context/api-propagators/).
