Підтримка трасування запитів (OpenTelemetry-підхід)

1. Загальна схема взаємодії

Інтеграція працює за наступною схемою:

  1. Сервіси Expirenza надсилають інтегратору команду через WebSocket.

  2. Інтеграція виконує необхідні дії (свій бізнес-процес, звернення до внутрішніх сервісів тощо).

  3. Інтеграція повертає результат у Expirenza через HTTP callback.

  4. Увесь шлях запиту має бути пов’язаний одним і тим самим trace-id.

Логічний ланцюжок виглядає так:

Expirenza (internal service) → Expirenza External Connector → API інтегратора → Expirenza External Connector → Expirenza (internal service)

На кожному новому сервісі створюється новий span-id, при цьому:

  • trace-id залишається незмінним протягом усього життєвого циклу запиту;

  • parent-span-id вказує, з якого span прийшов запит.


2. Структура повідомлень у WebSocket

Усі WebSocket-повідомлення від Expirenza до інтегратора мають службове поле __headers__.

Приклад вхідного повідомлення:

{
    "rID" : "2021-03-13 00:32:04.942046#UP57RxE",
    "operation" : "categoriesInfo",
    "__headers__": {
    "trace-id": "c0a8017f6f2c4d98bd70a35c90f1f01",
    "span-id": "7b9a3d3c4e2f1a90"
    }
}

2.1. Поля в __headers__

  • trace-id

    • Унікальний ідентифікатор всього запиту (end-to-end).

    • Є обов’язковим до збереження та передачі назад у відповідь (HTTP callback).

    • Інтеграція не повинна змінювати формат чи значення trace-id. Сприймайте його як “чорну скриньку”.

  • span-id

    • Ідентифікатор поточного етапу (span) усередині загального запиту.

    • Для інтеграції він виконує роль parent-span-id – тобто span, від якого “відгалужується” робота інтегратора.

    • Обробка span-id є рекомендованою, але не обов’язковою (див. розділ 4).


3. Обов’язкові вимоги до інтеграції

3.1. Збереження trace-id в контексті

Після отримання WebSocket-повідомлення інтеграція повинна:

  1. Прочитати trace-id з message.__headers__.['trace-id'].

  2. Зберегти його в контексті обробки запиту (thread context, request-scoped context, MDC/лог-контекст тощо).

  3. Використовувати цей trace-id при всіх логуваннях, що стосуються даного запиту.

3.2. Передача trace-id в HTTP callback

При формуванні HTTP-відповіді (callback) інтегратор обов’язково має додати заголовок:

Приклад HTTP callback:

Це дозволяє Expirenza “зшити” логи WebSocket-команди, внутрішніх сервісів та відповіді інтеграції в один наскрізний трейс.

Важливо: передача trace-id у callback – обов’язкова вимога. Якщо trace-id буде відсутній або змінений, трасування буде порушене.


4. Рекомендована (опційна) підтримка span-id та parent-span-id

Підтримка span-id/parent-span-id на стороні інтеграції рекомендована, але не є обов’язковою. Вона потрібна для більш детального трасування всередині системи інтеграції та між сервісами.

4.1. Що рекомендується робити

  1. Прочитати вхідний:

    • trace-id

    • span-id (як parent-span-id для інтеграції)

  2. Створити *новий * span-id для роботи інтеграції (наприклад, span-id інтеграції):

    • parent-span-id = вхідний span-id з WebSocket.

    • span-id = нове згенероване значення.

  3. Якщо інтеграція викликає свої внутрішні сервіси:

    • передавати:

      • той самий trace-id,

      • span-id (власний) (внутрішній сервіс запише його як parent-span-id)

      • Внутрішній сервіс сгенерує новий span-id для кожного дочірнього виклику.

  4. При поверненні відповіді в Expirenza (HTTP callback) можна (опційно) передавати:

Ще раз: для Expirenza обов’язковим є тільки trace-id. Передача/ланцюжок span-id та parent-span-id – опція, яка дозволить глибше аналізувати ланцюжок викликів, якщо інтегратор цього бажає.


5. Навіщо це потрібно інтеграції

Підтримка trace-id (мінімально) та span-id (опційно) дає інтеграції такі переваги:

  1. Швидкий пошук інцидентів

    • Можна отримати trace-id від Expirenza (наприклад, з технічного запиту) і швидко знайти всі пов’язані логи та виклики у своїй системі.

  2. Кореляція логів між системами

    • Expirenza та інтеграції дивляться на один і той самий trace-id, що спрощує спільну діагностику.

  3. Глибинний аналіз продуктивності (якщо використовуєте span-id)

    • Можна будувати детальні діаграми: скільки часу зайняла обробка в інтеграції, скільки – у внутрішніх сервісах інтеграції, де “вузьке місце”.

  4. Сумісність із OpenTelemetry та APM-системами

    • Якщо інтеграція вже використовує OpenTelemetry, trace-id, span-id та parent-span-id можна напряму мапити на відповідні сутності (trace/span/parent span).


6. Діаграма проходження запиту (послідовність)

spinner
circle-info

Якщо інтеграція не реалізує span-id/parent-span-id, ви все одно повинні зберігати і повертати trace-id – тоді всі вузли будуть пов’язані хоча б на рівні трейсів.


7. Підсумок вимог

Обов’язково для інтеграції:

  1. Прочитати trace-id із WebSocket-повідомлення (__headers__.trace-id).

  2. Зберігати trace-id в контексті обробки запиту.

  3. Логувати trace-id для всіх дій у межах одного запиту.

  4. Передавати trace-id у HTTP callback як заголовок trace-id.

Опційно (рекомендовано):

  1. Використовувати span-id із WebSocket-повідомлення як parent-span-id.

  2. Генерувати власні span-id для операцій інтеграції.

  3. Передавати span-id у HTTP callback.

  4. Інтегрувати цю схему з OpenTelemetry / APM системами для розширеної візуалізації трейсів.

Last updated