Перейти до вмісту

Журналювання

запис подій у момент, коли вони стаються

Що це таке

Журналювання, або логування, — це безперервний облік, який програма веде про власну поведінку, по одному запису на кожну подію: обслужений запит, відхилений пароль, повторна спроба, аварійне завершення. Кожен такий запис, рядок журналу, містить щонайменше час і повідомлення, щоб згодом можна було відновити, що сталося і в якому порядку. Проєкт OpenTelemetry визначає журнал як текстовий запис із часовою міткою, структурований чи неструктурований, з необов’язковими метаданими, і зазначає, що з усіх сигналів телеметрії журнали мають найбільшу спадщину.

Ця спадщина має стандарт. Syslog, давній протокол для передавання повідомлень про події до збирача, у березні 2009 року стандартизовано як RFC 5424, що замінив старіший RFC 3164; він присвоює кожному повідомленню один із восьми рівнів серйозності, від 0 для Emergency до 7 для Debug. Більшість бібліотек журналювання мають коротшу драбину з тією самою ідеєю: debug, info, warning, error. Модель даних журналів OpenTelemetry відображає їх усі на одне число від 1 до 24, у шести смугах від TRACE до FATAL.

Неструктурований рядок — це вільний текст: людині його легко прочитати, а машина може розібрати його лише регулярним виразом, написаним саме під це формулювання. Структурований рядок дотримується схеми, тож кожен запис має ті самі іменовані поля з тими самими типами й значеннями. OpenTelemetry віддає перевагу структурованим журналам у продакшні й додає застереження, яке легко пропустити: рядок, закодований як JSON, не стає структурованим лише тому, що він розбирається; структурованим його робить стабільна схема. Тут запис показано в кількох рядках, а на диску це один рядок:

{
    "time": "2026-09-14T03:12:07.412Z",
    "severity": "WARN",
    "service": "checkout",
    "event": "payment.retry",
    "attempt": 3,
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}

Метрики й трасування — сигнали, які зазвичай збирають поруч із ним. Метрики — це числа, виміряні з плином часу, дешеві для зберігання й добрі для відповіді на питання «як часто». Трасування супроводжує один запит через кожен сервіс, якого він торкається. Журнал зберігає подробиці окремих подій, тож коли спрацювала тривога, саме до нього звертаються, щоб дізнатися чому. OpenTelemetry пов’язує журнали з трасуваннями, додаючи до кожного запису ідентифікатори активного трасування й спану.

Чому це важливо

Журнал — це єдина розповідь про минуле, яку залишає по собі більшість систем. Метрика може показати, що о 03:12 кількість помилок зросла; журнал скаже, який саме запит, від якого сервісу, з яким значенням і що програма зробила далі. Коли щось ламається вночі й до ранку відновлюється, журнал — той свідок, що досі на місці.

Ця розповідь має ціну, і сплачують її трьома способами. Кожен рядок коштує місця на диску, операцій введення-виведення й процесорного часу, а ще більше — якщо його надсилають до центрального сховища, де хостингова служба зазвичай виставляє рахунок за обсягом отриманих даних. Кожен рядок — це також дані про когось: журнал доступу вебсервера містить адреси й браузери всіх, хто до нього звертався. І кожен рядок треба захищати. OWASP Logging Cheat Sheet просить, щоб кожна подія фіксувала, коли, де, хто і що, а самі журнали були захищені від підробки та від несанкціонованого доступу, змін і видалення, бо вони можуть містити персональні та інші чутливі дані.

У масштабі організації NIST Special Publication 800-92, Guide to Computer Security Log Management, яку написали Karen Kent і Murugiah Souppaya і видали у вересні 2006 року, розглядає керування журналами як інфраструктуру й процеси в межах усього підприємства, а не як налаштування однієї програми.

Журнали також працюють найкраще поруч із числами. Посібник з інструментування проєкту Prometheus радить заводити лічильник для кожного рядка коду журналювання, щоб, коли трапиться цікаве повідомлення, можна було побачити, як часто воно з’являлося і як довго, а також порівнювати кількість рядків info, warning і error між релізами.

Як це виглядає на практиці

Власний журнал доступу сайту описано рядок за рядком на сторінці про конфіденційність. Для кожного запиту записуються сторінка й час, статус відповіді, самоопис браузера, назва сайту, з якого прийшов відвідувач, і розмита мережева адреса: останню частину замінюють нулями в момент запису рядка, ще до того, як щось потрапить на диск. Рядок живе приблизно тридцять днів. Файли ротуються приблизно на 10 МБ, а ротований файл видаляється, щойно з’являться чотирнадцять новіших або йому виповниться тридцять днів, і в цьому правилі була шпарина: малоактивні адреси набирали 10 МБ так повільно, що їхні файли жодного разу не ротувалися й досі містили кожен рядок відтоді, як увімкнули журналювання. Тепер щоденне завдання закриває кожен файл, найстаріший рядок якого має понад добу, і видаляє закриті файли через тридцять днів. Чотири адреси перебували в старому стані, і сторінка про це прямо каже.

У застосунку для macOS журналювання було однією з трьох причин того, що пам’ять заповнювалася приблизно на 41 МБ за секунду: зафіксований інцидент сягнув 111 ГБ стиснених сторінок на машині з 36 ГБ, а один короткий сеанс записав 610 996 рядків журналу. Кожна подія породжувала рядки журналу, тож обсяг журналювання був пропорційний обсягу того, що йшло не так. З обмеженими буферами подій, підпискою за типом події та бюджетом журналювання, який згортає повтори, той самий сеанс тепер записує 1 411 рядків. Сторінка чесно називає ціну: коли щось швидко йде не так, запис про це тепер навмисно неповний.

На робочому хості посилення захисту тринадцяти юнітів systemd виявило директиву, яку з помилкою писали у трьох шаблонах юнітів увесь час, скільки існували ці ролі. Менеджер служб відповідає на ключ, якого не розпізнає, записом у журнал і все одно запускає юніт, тож єдиним слідом помилки було попередження в журналі, а виявили її під час переписування юнітів. Тепер кожен юніт під час кожного зведення проходить через власний верифікатор менеджера служб, тож така сама помилка зупиняє прогін.

Де виникають проблеми

Журнал росте найшвидше, коли система вже дає збій. Цикл, що записує кожну повторну спробу, у добрий день дає жменю рядків, а в поганий — тисячі за секунду, забираючи диск, пам’ять і процесорний час у системи, якій їх і так бракує. OWASP просить перевіряти, що журналювання не можна використати для виснаження ресурсів системи, наприклад заповнивши диск. Дайте кожному гарячому шляху бюджет, згортайте повторювані повідомлення в один рядок із кількістю повторів і тримайте лічильник поруч із повідомленням, щоб частота збереглася, коли рядки відкидаються.

Секрети й персональні дані потрапляють у запис. Запит, записаний цілком, несе все, що в ньому було. Список OWASP того, що зазвичай слід видалити, замаскувати, гешувати чи зашифрувати, перш ніж воно потрапить до журналу, містить ідентифікатори сесій, токени доступу, паролі, рядки підключення до бази даних, ключі шифрування й дані платіжних карток. Робіть це в момент запису рядка, як журнал доступу вище робить з адресами, бо поки хтось візьметься за прибирання, рядок уже може лежати в резервній копії чи архіві.

Зовнішнє введення дописує фальшивий рядок. Значення від користувача з символом повернення каретки чи переведення рядка, записане без екранування в текстовий журнал, може почати новий рядок, точнісінько схожий на той, що написав сам застосунок. OWASP називає це log injection і просить очищати такі символи та кодувати дані під формат, у якому їх записують. Структурований логер, що записує кожне значення як екранований рядок JSON, робить це самою своєю будовою.

Журнал, що замовк, виглядає як здорова система. Повний диск, ротований файл, який програма так і не відкрила знову, чи збирач, що впав, ззовні виглядають однаково: рядки перестають надходити. OWASP просить мати спосіб помітити, що журналювання зупинилося. Рахуйте рядки за хвилину для кожного джерела й ставте тривогу на падіння цього числа до нуля, щоб пропуск у журналі сам ставав тривогою.

Що почитати далі

  • Logs — OpenTelemetry про те, що таке журнал, чому перевагу віддають структурованим журналам і як журнали пов’язують із трасуваннями.
  • Logs Data Model — поля запису журналу, дві його часові мітки й шкала серйозності від 1 до 24.
  • RFC 5424: The Syslog Protocol — формат повідомлень syslog і вісім рівнів серйозності.
  • NIST SP 800-92 — Guide to Computer Security Log Management.
  • Logging Cheat Sheet — OWASP про те, які події записувати, які дані тримати поза журналом і як захистити результат.
  • Instrumentation — практики проєкту Prometheus з інструментування коду, зокрема журналювання.

Словник