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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

2.1. Поля в __headers__

  • traceId

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

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

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

  • spanId

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

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

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


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

3.1. Збереження traceId в контексті

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

  1. Прочитати traceId з message.__headers__.['traceId'].

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

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

3.2. Передача traceId в HTTP callback

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

Приклад HTTP callback:

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

circle-exclamation

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

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

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

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

    • traceId

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

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

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

    • spanId = нове згенероване значення.

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

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

      • той самий traceId,

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

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

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

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


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

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

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

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

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

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

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

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

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

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


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

spinner
circle-info

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


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

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

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

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

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

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

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

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

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

  3. Передавати spanId у HTTP callback.

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

Last updated