Кореляція трейсів і логів
Інструментування OpenTelemetry eBPF Instrumentation (OBI) корелює логи застосунків з розподіленими трейсами, збагачуючи JSON та plain-text логи контекстом трасування. OBI не експортує логи; він записує збагачені логи назад до того самого потоку, тоді як трейси експортуються через OTLP.
Огляд
Кореляція trace-log зʼєднує два доповнюючи сигнали спостережуваності:
- Трасування: Показує проходження запиту крізь сервіси з таймінгом і структурою
- Логи: Надають детальну інформацію про події та стан застосунку
За допомогою OBI trace-log correlation, логи з інструментованих процесів автоматично збагачуються контекстом трасування:
- Trace ID: Повʼязує запис логу з розподіленим трейсом
- Span ID: Повʼязує запис логу з конкретним відрізком трейсу
Це дозволяє вашому бекенду спостережуваності корелювати логи з трейсами з яких вони походять без будь-яких змін у вашому застосунку.
Як це працює
OBI використовує eBPF для того щоб робити інʼєкцію контексту трейсів в логи застосунку на рівні ядра:
- Захоплення трасування: OBI захоплює контекст трасування (ідентифікатор трасування та ідентифікатор відрізка) для всіх відстежуваних операцій
- Перехоплення логів: OBI перехоплює системні виклики запису для збору логів застосунків.
- Додавання контексту: OBI вводить поля
trace_idтаspan_idв JSON обʼєкти або додаєkey=valueполя, які можна налаштовувати, до обраних plain-text рядків - Експорт трасування: логи продовжують надходити через поточний конвеєр логів.
- Звʼязування бекенду: бекенд спостережності повʼязує логи з трасуваннями за допомогою цих ідентифікаторів.
Технічний підхід
OBI виконує кореляцію на рівні ядра без модифікації бінарних файлів застосунків:
- Використовує проби eBPF для перехоплення операцій запису
- Підтримує кешування дескрипторів файлів для покращення продуктивності
- Працює з фреймворками логування, що записують JSON або plain text
OBI зберігає сконфігуровані trace та span поля, які вже існують. JSON ключі збігаються літерально; у plain text OBI розпізнає name=value токени на початку рядка або після пробілу. Для сервісу, який виявлено як такий, що безпосередньо експортує OpenTelemetry трейси, OBI вставляє лише trace_id: його eBPF-згенерований span ID не ідентифікує SDK span.
Налаштування
Щоб зіставити логи з трейсами, експортуйте трейси та налаштуйте OBI для додавання контексту трейсу до логів із вибраних робочих навантажень. Поля конфігурації відрізняються у Config v1 та Config v2. Якщо ви використовуєте Config v2, див. Довідник по Config v2. Щоб перетворити наявний файл Config v1, дотримуйтесь посібника з міграції.
Config v1
# Увімкнення експорту трасувань
otel_traces_export:
endpoint: http://otel-collector:4318/v1/traces
# Оберіть сервіс для інструментування
discovery:
instrument:
- open_ports: '8380'
# Увімкнення збагачення логів для цих сервісів
ebpf:
log_enricher:
services:
- service:
- open_ports: '8380'
Збагачення логів може бути далі налаштоване у ebpf.log_enricher:
cache_ttl: час існування дескрипторів файлів кешуванняcache_size: максимальна кількість кешованих дескрипторів файлівasync_writer_workers: кількість асинхронних фрагментів записувачаasync_writer_channel_len: розмір черги на кожен фрагментfield_names: імена полів, що використовуються для розпізнавання та інʼєкції trace та span IDplain_text.enabled: чи анотувати не-JSON логи; зазвичайtrueplain_text.placement: додавати поля якprefixабоsuffixplain_text.multiline: анотуватиfirst_line,last_line, абоeach_lineв кожному перехопленому записі
Наприклад:
ebpf:
log_enricher:
field_names:
trace_id: trace_id
span_id: span_id
plain_text:
enabled: true
placement: suffix
multiline: first_line
Plain-text збагачення стандартно увімкнено для обраних сервісів у v0.11.0. Встановіть plain_text.enabled: false перед оновленням, якщо non-JSON записи повинні зберегти попередню поведінку pass-through. Імена полів застосовуються до JSON та plain-text виводу і мають бути непорожніми, унікальними і не містити пробілів, =, або контрольних символів.
Вибір сервісів
OBI збагачує JSON та plain-text логи для сервісів, перелічених у ebpf.log_enricher.services. Зберігайте вибір сервісів узгодженим з discovery.instrument, щоб збагачення відстежувало ті самі процеси.
Config v2
З Config v2, анотація логів трасування доступна лише коли ви запускаєте OBI як самостійний процес. Вона стандартно вимкнена. Налаштуйте її в extensions.obi.correlation.log_trace_annotation:
extensions:
obi:
correlation:
log_trace_annotation:
enabled: true
field_names:
trace_id: trace_id
span_id: span_id
plain_text:
enabled: true
placement: suffix
multiline: first_line
Config v2 вибір захоплення визначає, які робочі навантаження є придатними для анотації логів. Поле log_trace_annotation.filter зарезервоване у v0.11.0 і повинно залишатися порожнім.
Вимоги
1. Підтримуваний формат логів
Для логів у форматі JSON, OBI вводить поля trace_id та span_id в JSON обʼєкти:
До OBI:
{ "level": "info", "message": "Request processed", "duration_ms": 125 }
Після збагачення OBI:
{
"level": "info",
"message": "Request processed",
"duration_ms": 125,
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7"
}
Для логів у вигляді простого тексту OBI додає ідентифікатори з малими літерами та фіксованою шириною у вигляді полів key=value, розділених пробілами. Розташування та вибір кількох рядків можна налаштувати:
request processed trace_id=4bf92f3577b34da6a3ce929d0e0e4736 span_id=00f067aa0ba902b7
JSON, розділений символами нового рядка, обробляється як структурований JSON. OBI доповнює кожен запис обʼєкта окремо і не застосовує анотації у вигляді простого тексту до валідного NDJSON. Багаторядкове виділення здійснюється для непорожніх фізичних рядків за один перехоплений запис; OBI не відтворює логічні події між окремими записами.
Обмеження буферизації часу виконання
OBI бачить контекст трейсів лише тоді, коли запис логу відбувається в потоці обробки запиту. Середовища виконання, які буферизують stdout асинхронно, можуть порушити це припущення.
- Python у Docker зазвичай потребує
PYTHONUNBUFFERED=1 - .NET
Console.Outзазвичай буферизується, коли stdout є pipe; використовуйтеStreamWriterзAutoFlush = true - Стандартний конвеєр
Microsoft.Extensions.Logging.AddConsole()у ASP.NET Core не сумісний, оскільки запис відбувається з фонового потоку - Логи віртуальних потоків Java не збагачуються, оскільки потік ядра-носій може виконувати роботу з декількох віртуальних потоків; збагачення звичайних потоків не порушується
2. Експорт трасування та збагачення логів увімкнено {2-trace-export-and-log-enrichment-enabled}
Для кореляції трасування та логів необхідні як експорт трасування, так і збагачення логів. Для Config v1:
otel_traces_export:
endpoint: http://collector:4318/v1/traces # Обовʼязково
ebpf:
log_enricher:
services:
- service:
- open_ports: '8380' # Обовʼязково
3. Ядро Linux
Кореляція trace-log вимагає певних функцій ядра Linux:
- Linux ядро 6.0+ (потрібне для роботи trace-log кореляції)
- Підтримувані архітектури: x86_64, ARM64
- BPFFS монтування: Ядро повинне мати файлову систему BPF змонтовану у
/sys/fs/bpf - Ядро без блокування безпеки: Потрібне ядро, яке не працює в режимі блокування безпеки (типово для більшості робочих дистрибутивів).
4. Фреймворк, що генерує підтримувані логи
Застосунки можуть використовувати фреймворк логування, налаштований для виводу JSON або plain text. Наступні JSON приклади створюють структуровані поля:
import json
import logging
class JSONFormatter(logging.Formatter):
def format(self, record):
log_entry = {
'timestamp': self.formatTime(record),
'level': record.levelname,
'message': record.getMessage(),
'module': record.module,
}
return json.dumps(log_entry)
logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setFormatter(JSONFormatter())
logger.addHandler(handler)
import "go.uber.org/zap"
logger, _ := zap.NewProduction() // Outputs JSON by default
defer logger.Sync()
logger.Info("Request processed", zap.Duration("duration", 125*time.Millisecond))
<appender name="FILE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
const pino = require('pino');
const logger = pino();
logger.info({ duration_ms: 125 }, 'Request processed');
5. Конвеєр постачання логів
OBI збагачує логи на місці. Використовуйте наявний лог-форвардер або колектор для передачі логів у ваш бекенд.
Коли OBI пригнічує оригінальний рядок, файли контейнерних логів містять рядок з NUL байтів на його місці. Для записів до 8 KiB фільтруйте ці рядки-заповнювачі на етапі доставки за допомогою ^[\x00\s]*$. Наприклад, з приймачем file_log колектора OpenTelemetry:
receivers:
file_log:
include:
- /var/log/pods/*/*/*.log
start_at: end
operators:
- type: container
- type: filter
expr: 'body matches "^[\\x00\\s]*$"'
CRI та Docker JSON конверти логів кодують NUL як \u0000; оператор container декодує тіло перед виконанням фільтра.
Зауваження щодо продуктивності
- Мінімальні накладні витрати: кореляція використовує проби ядра eBPF з ефективним кешуванням файлових дескрипторів
- Обмеження кешу: кеш файлових дескрипторів має обмеження розміру та TTL, щоб запобігти необмеженому використанню памʼяті
- Асинхронна обробка: збагачення журналів використовує асинхронні робочі процеси, щоб уникнути переповнення ringbuffer ядра
Відомі обмеження
- Per-write багаторядковий вибір: OBI не реконструює логічні багаторядкові події між окремими записами
- Кеш файлових дескрипторів: Налаштовано на продуктивність, з налаштованим TTL (типово: 30 хвилин)
- Тільки в межах відрізку: Логи збагачуються тільки поки відрізок є активним; логи поза межами відрізку не збагачуються.
- Обмеження 8 KiB на один запис: OBI збагачує та пригнічує максимум перші 8 KiB одного виклику
write()абоwritev(). Решта байтів проходять без збагачення та не відповідають фільтру рядків-заповнювачів. - Віртуальні потоки Java: Логи, записані з віртуальних потоків, не збагачуються.
Розвʼязання проблем
Вміст трасування не зʼявляється в логах
Перевірте налаштований формат: Для JSON логів, переконайтесь, що застосунок виводить валідний JSON. Для plain text, підтвердьте, що
plain_text.enabledєtrueта перевірте налаштування placement та multiline.# Перевка на наявність пошкдження JSON cat app.log | jq empty && echo "Valid JSON" || echo "Invalid JSON"Перевірте експорт трасування та збагачення логів:
otel_traces_export: endpoint: http://collector:4318/v1/traces ebpf: log_enricher: services: - service: - open_ports: '8380'Перевірте ядро Linux: Кореляція trace-log вимагає Linux
uname -s # У відповід маєте отримати "Linux"Перевірте конвеєр логів: Перевірте ваш лог-форвардер, чи пересилає він логи до бекенду
Що далі?
- Встановлення місця призначення експорту для трасувань та метрик
- Більше про OBI як приймач Колектора для централізованої обробки
Зворотний зв’язок
Чи була ця сторінка корисною?
Дякуємо. Ми цінуємо ваші відгуки!
Будь ласка, дайте нам знати як ми можемо покращити цю сторінку. Ми цінуємо ваші відгуки!