# Специфікація для референтного застосунку

> Цей документ містить специфікацію референсного застосунку, який використовується в посібнику «Початок роботи».

---

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

---

Мета референсного застосунку — мати стандартизований зразок застосунку, який можна реалізувати всіма мовами, для яких існує SDK OpenTelemetry.

## Загальні вимоги {#general-requirements}

- Реалізації Референсного застосунку належать SIG відповідних мов програмування, що реалізують API та SDK OpenTelemetry. Це гарантує, що застосунок відповідає найкращим практикам екосистеми мови програмування, і ми можемо надати план того, як слід інструментувати застосунок.
- Повинна бути версія застосунку без інструментування та з інструментуванням. Вона буде використана в посібнику «Початок роботи» на opentelemetry.io для переходу від застосунку без OpenTelemetry до повністю інструментованого застосунку.
- Повинна бути специфічна для мови дія CI, яка перевіряє, що застосунок компілюється та працює в обох версіях.
- Застосунок повинен запускатися з інтерфейсу командного рядка.
- Має бути файл Dockerfile для запуску застосунку в контейнерному середовищі.
- Застосунок повинен працювати автономно. Іншими словами, він не може мати жорстких залежностей від будь-якого іншого вмісту репозиторію, що його оточує. Це дозволяє користувачам копіювати код у свій власний проєкт без розплутування управління залежностями.

## Вимоги до сервісу {#service-requirements}

- Застосунок повинен стандартно очікувати HTTP-запити на порту 8080. Порт повинен бути налаштований за допомогою змінної середовища APPLICATION_PORT.
- Для обробки HTTP-запитів слід використовувати бібліотеку, для якої доступна бібліотека інструментування. Застосунок повинен надавати точку доступу `/rolldice?rolls=<n>` через `GET` (та, за бажанням, `POST`) і повертати такі коди статусу HTTP та результати JSON:
  - якщо `rolls` не встановлено або має дійсне вхідне значення ( позитивне ціле число > 0): код статусу `200` і або одне число від 1 до 6, якщо `rolls` не встановлено, або 1, або масив з `n` чисел від 1 до 6, де `n` є значенням `rolls`
  - якщо `rolls` встановлено як недійсне вхідне значення (не число): код статусу `400` і `{"status": "error", "message": "Parameter rolls must be a positive integer"}`
  - якщо `rolls` встановлено як `0` або від’ємне ціле число: код статусу `500` і відсутність виводу JSON. Приклади помилок будуть використані для демонстрації того, як OpenTelemetry може бути використаний для виявлення помилок.
- До точки доступу `/rolldice` може бути доданий опціональний атрибут `player=name`.
- Застосунок повинен виводити наступні рядки журналу:
  - повідомлення рівня INFO для кожного HTTP-запиту зі статусом `<400`
  - повідомлення рівня WARN для кожного HTTP-запиту зі статусом від `400` до `499`, включаючи повідомлення, яке буде надіслано в результаті JSON
  - повідомлення рівня ERROR для кожного HTTP-запиту зі статусом вище `499`
  - якщо встановлено необовʼязковий атрибут `player`, повідомлення рівня DEBUG, яке виводить значення `player` та отримане число
  - якщо необовʼязковий атрибут `player` не встановлено, повідомлення рівня DEBUG, яке виводить статичне значення `anonymous player` та згенероване число. Рядки журналу будуть використані для додавання мосту журналу під час інструментування, щоб продемонструвати, як OpenTelemetry може підключатися до наявних фреймворків журналювання.
- Код застосунку повинен бути розділений на два файли:
  - файл `app`, що містить обробку HTTP-запитів;
  - файл `library`, що містить реалізацію функції кидання кубика. Назви цих файлів повинні бути ідіоматичними для мови реалізації, наприклад `app.js` і `roll-the-dice.js`. Важливим моментом є те, що завдяки розділенню коду файли демонструють, що `library` залежить тільки від API, а весь код SDK ініціалізується в коді `app`.
- Обробка помилок для `rolls` повинна бути розділена наступним чином:
  - `app` перевіряє, чи визначено `rolls`, і якщо ні, то встановлює його значення `1`.
  - `app` перевіряє тільки, чи `rolls` є числом. Якщо так, то викликає функцію для кидання кубика в `library`. Якщо ні, то виконує обробку помилки з помилкою `400`.
  - `library` перевіряє, чи `rolls` є додатним числом. Якщо ні, то генерує помилку. `app` виявляє помилку і відправляє назад помилку `500`.
- `library` повинна мати зовнішню функцію, яка виконує обробку помилок, як описано вище. Потім зовнішня функція виконує наступні дії залежно від значення `rolls`:
  - `rolls == 1`: Виконати внутрішню функцію один раз і повернути значення.
  - `rolls > 1`: Виконати цикл, який викликає внутрішню функцію `rolls` разів і повернути результати в масиві.
- Внутрішня функція `library` створює випадкове число від 1 до 6 і повертає це значення.

## Вимоги до інструментування {#instrumentation-requirements}

- За можливості, ініціалізація для OpenTelemetry SDK повинна міститися в окремому файлі та імпортуватися в файл `app`. В іншому випадку вона повинна бути частиною файлу `app`.
- Загальні детектори ресурсів повинні завантажуватися під час ініціалізації, наприклад для `process`, `container`, `os`, ...
- Файл "lib" повинен залежати тільки від API OpenTelemetry.
- Атрибути `service.*` повинні бути додані через змінні середовища
  (`OTEL_SERVICE_NAME`, `OTEL_RESOURCE_ATTRIBUTES`).
- Інші `resource detectors` повинні бути додані до ініціалізації SDK.
- Для експорту телеметрії застосунок повинен використовувати експортер для `stdout`/`console` та `otlp`.
- Повинна бути опція для увімкнення діагностичного логування для компонентів OpenTelemetry, якщо це реалізовано, ідеально через `OTEL_LOG_LEVEL`.
- Повинна бути можливість додати бібліотеку інструментування для використовуваної бібліотеки HTTP. Ця бібліотека інструментування повинна використовувати стабільні семантичні домовленості для HTTP. Віддайте перевагу бібліотеці, яка охоплює більшість сигналів, ідеально, якщо вона має трейси та метрики.
- Якщо бібліотека інструментування недоступна, тільки тоді функція в `app`, яка обробляє точку доступу`/rolldice`, інструментується користувачем шляхом додавання відрізку та метрик.
- Повинен бути міст для логу для використовуваного механізму логування, щоб усі журнали автоматично збиралися та експортувалися.
- Для зовнішньої функції в `library` повинен бути створений відрізок. Відрізок відстежує час роботи функції. Він записує помилку, якщо вона виникає. Він додає атрибути до відрізку, такі як значення `rolls`, `code.*`, ...
- Для внутрішньої функції в `library` повинен бути створений відрізок. Відрізок відстежує час роботи функції. Він додає випадкове число, яке він згенерував, як атрибут до відрізку.
- У файлі `library` повинні бути створені наступні метрики:
  - лічильник викликів зовнішньої функції
  - гістограма розподілу результатів (1-6)
  - індикатор останнього значення `rolls`
