Кратко

  • Обычный JSON-документ может стать неразбираемым без закрывающих конструкций; JSON-SEQ хранит события отдельными записями и лучше переживает обрыв потока.
  • Разбираемая последняя запись подтверждает сохранность этой записи, а не полноту предыдущей истории, своевременный старт capture или успешный результат сервиса.
  • Операторам нужны границы потока, счётчики пропусков, состояние буфера, политика событий и независимая проверка результата.

Процесс аварийно завершился, но последние двадцать семь событий открылись без ошибки. Каждая JSON-SEQ запись имела разделитель, корректный JSON и известное имя qlog. Последняя фиксировала изменение состояния соединения. В отчёте появился вывод: журнал полностью сохранился до момента сбоя.

Формат доказал меньше. Он сохранил двадцать семь самостоятельно разбираемых записей. До этого кольцевой буфер уже перезаписал начало соединения, а точка старта capture нигде не была оформлена как отдельная квитанция. Хвост пережил аварию. История — нет.

draft-ietf-quic-qlog-main-schema-14 — активный Internet-Draft рабочей группы QUIC, датированный июлем 2026 года и предназначенный для Proposed Standard. Это ещё не RFC. Документ задаёт общую модель структурированных журналов сетевых протоколов: файлы, traces, события, schemas, время и сериализацию. Помимо обычного JSON он описывает JSON Text Sequences, или JSON-SEQ.

Различие между форматами показывает, почему техническая надёжность всегда имеет конкретную область действия.

Закрытый документ и поток записей

Обычный JSON qlog представляет собой целый объект. Потоковый logger может открыть структуру, дописывать события и в конце добавить закрывающие скобки. Если процесс не успеет завершить документ, большинство обычных парсеров сочтёт его malformed.

JSON-SEQ решает именно эту проблему иначе. Каждый объект становится отдельной записью с ASCII Record Separator в начале и переводом строки в конце. События добавляются к потоку по одному. Инструмент может разделить поток на записи и передать каждый объект стандартному JSON-парсеру.

Это повышает вероятность, что уже выданные события останутся полезными после crash. Но запись не содержит автоматического утверждения: «до меня не было потерянных записей», «после меня не должно было быть других» или «logger работал с начала соединения». Устойчивость единицы сериализации — не непрерывность измерения.

Начало может исчезнуть раньше сбоя

qlog прямо предупреждает инструменты о неполных логах. При фиксированном кольцевом буфере ранние события, включая установление соединения, могут быть перезаписаны новыми. Другие события могут намеренно не записываться ради приватности или размера файла. Инструменты должны оставаться полезными в таких условиях.

Полезность не означает восстановление выдуманного начала. Если первая уцелевшая запись имеет время 0 после извлечения или выглядит как нормальная protocol event, это всё равно может быть первый сохранённый, а не первый произошедший факт. Нужен внешний статус буфера или явная граница capture.

Список event_schemas тоже не является оглавлением истории. Он подсказывает возможные пространства имён и типы. Перечисленный schema не гарантирует присутствие каждого типа; неперечисленный тип может всё же встретиться. Инструменты не должны считать это ошибкой.

Уровень Core не превращает отсутствие в доказательство. Не все Core events обязаны появляться в каждом trace. Реализация может заменять подробные Core события подходящими Base событиями из-за производительности или конфиденциальности. Два неповреждённых потока способны иметь разную наблюдаемость.

Счётчик времени зависит от сохранённой последовательности

Риск особенно заметен при relative_to_previous_event. В таком формате первое событие trace задаётся относительно reference time, а следующие значения — относительно предыдущего зарегистрированного. Экономия размера полезна для stateful logger, но интерпретация окна требует понимать его место в исходной последовательности.

Время может идти от system clock, который способен прыгать, или monotonic clock с неизвестной календарной эпохой. Приблизительный wall_clock_time нельзя считать безопасной календарной привязкой. В одном trace допустимы разные time formats, а между traces согласованность вообще не предполагается.

Поэтому двадцать семь записей могут дать надёжный локальный порядок и при этом не ответить, сколько времени прошло с начала инцидента. Склеивание с серверным или сетевым trace требует общего идентификатора, vantage point, направления, окна capture и оценки ошибок часов.

Конец протокольного потока не равен исходу услуги

Последнее уцелевшее событие может быть подлинным и всё же не быть последним существенным фактом. Logger мог упасть раньше приложения. Он мог записать отправку, но не получение. Состояние соединения могло измениться после того, как пользовательская операция уже завершилась — или не завершилась.

Чтобы сказать «сервис восстановился», нужен отдельный результат: подтверждённая транзакция, ответ клиенту, выполненный deadline, восстановленный SLO или внешний probe. qlog предоставляет protocol evidence. Оно ценно именно тогда, когда не заставляют его играть роль приложения.

Причина также требует осторожности. Некоторые определения событий могут включать optional trigger, потому что в параллельной реализации связанные сообщения могут далеко отстоять друг от друга. Когда trigger отсутствует, ближайшая запись не становится причиной автоматически. После crash соблазн выбрать последнюю видимую операцию особенно велик, хотя настоящий инициатор мог остаться в утраченной части.

Потоку нужны квитанции о границах

Для evidence-grade эксплуатации стоит сопровождать JSON-SEQ отдельным control record или внешним манифестом. Он фиксирует запуск logger, ожидаемый scope, идентификатор потока, vantage point, размер и число оборотов буфера, политику событий, sequence counters, число выданных и принятых записей, остановку, flush и причину завершения. Если graceful close не наступил, это отдельное состояние, а не молчание.

Это операторская рекомендация Daniel Kade, а не требование проекта qlog. Её смысл — отличить четыре результата: поток завершён по плану; поток оборвался, но префикс сохранён; сохранено только позднее окно; границы неизвестны. Все четыре могут содержать валидные JSON-SEQ события, но поддерживают разные утверждения.

Хеш-цепочка или монотонный sequence number может помочь обнаружить разрыв в транспортировке, если producer действительно её ведёт. Она всё равно не докажет события, которые capture policy решила не генерировать. Поэтому целостность доставки и полнота наблюдения должны оставаться разными осями.

Правильный вывод после аварии

В исходном случае отчёт должен был сказать: «После сбоя удалось разобрать 27 заключительных записей потока; последняя сохранённая запись имеет такой-то тип. Начало соединения было перезаписано, а подтверждения полного capture window нет. Эти данные описывают позднее локальное окно и не устанавливают первоначальную причину либо пользовательский исход».

Такой вывод не обесценивает JSON-SEQ. Он показывает, что формат выполнил свою задачу: уменьшил потерю данных при обрыве. Проблема возникла только в момент, когда устойчивость формата превратили в свидетельство о событиях за пределами файла.

Надёжные системы не обязаны знать всё. Они обязаны точно обозначать, что пережило сбой, что могло исчезнуть и какой следующий источник способен сократить неопределённость.

Источники