Практический результат — собственная учебная схема событий и правило сопоставления трёх записей. Они сохраняют отдельные попытки, неизвестное время и повторяющиеся записи. Это не разбор реального инцидента, не испытание поставщика и не универсальный стандарт журналирования.
Широкие таблицы, схема и код прокручиваются горизонтально. С клавиатуры: раскройте нужный блок, нажмите Tab до области и используйте стрелки влево и вправо.
Операция, попытка и запись — три разные единицы
Человек нажал кнопку, приложение отправило запрос, а после ожидания повторило его. Одна операция в таком сценарии может включать несколько попыток. Для каждой попытки появятся разные записи: ожидание клиента, решение промежуточного узла, обработка на сервере. Количество строк не равно количеству операций, а совпадение операции ещё не связывает конкретную попытку.
В учебной модели operation_id объединяет операцию, attempt_id отделяет её попытку, event_id обозначает отдельную запись. Идентичность записи задаётся вместе с её источником и областью идентификаторов. Эти названия и правила придуманы для упражнения. Они не являются форматом Cloudflare, OTLP или обязательной схемой для любого приложения.
OWASP рекомендует сохранять контекст взаимодействия и документировать свойства событий. Это поддерживает постановку задачи, но не задаёт наши operation_id и attempt_id. В реальной системе отдельно проверяют, кто формирует идентификатор, где он сохраняется и можно ли доверять значению из другой зоны. Простого совпадения строк для такого доверия недостаточно.
Зафиксируйте смысл каждого поля до объединения
Для одного небольшого упражнения достаточно следующего явно ограниченного контракта. Он содержит одиннадцать полей. Условие модели — доверенное сохранение общего operation_id и attempt_id в трёх точках. Это заданная предпосылка, а не обнаруженная возможность продукта. Точка наблюдения source здесь принимает только client, edge или origin; origin — сервер приложения за промежуточным узлом.
| Поле | Смысл в упражнении | Ограничение |
|---|---|---|
| schema_version | Версия data01.demo.v1 | Область действия именно этих правил |
| namespace | Придуманная область data01.synthetic | Одинаковые строки вне области не объединяются |
| event_id | Идентификатор отдельной записи | Identity: namespace + source + event_id |
| source | client, edge или origin | Показывает, чьё наблюдение записано |
| operation_id | Операция demo-op-001 | Внутри неё возможны разные попытки |
| attempt_id | Попытка demo-attempt-a либо null | Не восстанавливается по соседним строкам |
| event_name | Что именно зафиксировано | Имя класса события, не identity экземпляра |
| event_at | Время события по часам источника либо null | Смещение этих часов неизвестно |
| observed_at | Время наблюдения записи сборщиком | Не время записи в базу данных |
| response_code_recorded | Локально зафиксированный HTTP-код либо null | Смысл зависит от event_name |
| duration_ms | Локальная длительность в миллисекундах либо null | Нужны отдельные границы интервала |
Все одиннадцать ключей обязательны в этом формате. attempt_id:null допустим и означает отсутствие значения; физическое удаление ключа attempt_id — ошибка схемы. Это разные случаи. Неизвестное значение остаётся null, нулём его не заменяют. Правило не означает, что любое поле со значением 0 в чужой схеме ошибочно: перед переносом данных требуется прочитать исходную семантику.
Два времени не создают общие часы
В модели журналов OpenTelemetry различаются Timestamp — время события по часам источника — и ObservedTimestamp, когда событие наблюдал код сбора. Это помогает разделить возникновение и наблюдение. Наши event_at и observed_at используют ту же смысловую границу, но JSON ниже не заявлен совместимым с OTLP.
У клиента, edge и origin смещения часов неизвестны. Даже одинаковый формат UTC не подтверждает их синхронизацию. Поэтому сортировка event_at не доказывает порядок событий между компонентами. Единственный вымышленный сборщик даёт только порядок наблюдения записей по observed_at; равные значения не устанавливают порядок между собой.
OWASP отдельно отмечает ситуации, когда синхронизация недоступна, и необходимость учитывать смещение или уверенность во времени. В нашем контракте неизвестный event_at не подменяется observed_at, чтобы не потерять неизвестность. Это правило выбранного упражнения, а не универсальный запрет преобразования данных OpenTelemetry.
Прочитайте три вымышленные записи одной попытки
Полное текстовое описание схемы
Вымышленное упражнение: три источника передают записи одному сборщику. Стрелки обозначают только передачу и наблюдение записей, а не HTTP-путь или причинность. client, e1: timeout · код не зафиксирован; event_name=client_timeout; event_at=2000-01-01T10:00:02.000Z; observed_at=2000-01-01T10:00:02.100Z. edge, e2: записан 504; event_name=edge_response_recorded; event_at=2000-01-01T10:00:02.050Z; observed_at=2000-01-01T10:00:02.200Z. origin, e3: подготовлен 200; event_name=origin_response_prepared; event_at=2000-01-01T10:00:01.700Z; observed_at=2000-01-01T10:00:04.000Z. Сборщик наблюдает поступление e1, затем e2, затем e3. Смещения часов client, edge и origin неизвестны; порядок самих событий, причина отказа, доставка клиенту и бизнес-результат не установлены. Метрики скорости или задержки не рассчитываются. Общая связь задана условием: schema_version=data01.demo.v1, namespace=data01.synthetic, operation_id=demo-op-001, attempt_id=demo-attempt-a. Идентичность отдельной записи: namespace+source+event_id. schema_version относится только к этому редакционному контракту. Учебная схема подготовлена с помощью ИИ. Все записи, идентификаторы и времена вымышлены; схема не описывает инфраструктуру поставщика.
Все идентификаторы и значения ниже придуманы. Дата 1 января 2000 года выбрана только для учебного набора; реального инцидента не было. Для трёх строк общими заданы schema_version=data01.demo.v1, namespace=data01.synthetic, operation_id=demo-op-001 и attempt_id=demo-attempt-a. Времена в таблице — UTC в этот вымышленный день.
| Запись / источник / событие | event_at | observed_at | Код / duration_ms |
|---|---|---|---|
| e1 · client · client_timeout | 10:00:02.000Z | 10:00:02.100Z | null / 2000 |
| e2 · edge · edge_response_recorded | 10:00:02.050Z | 10:00:02.200Z | 504 / null |
| e3 · origin · origin_response_prepared | 10:00:01.700Z | 10:00:04.000Z | 200 / 1700 |
Клиентская запись сообщает о локальном timeout без полученного кода. Запись edge фиксирует 504. Запись origin — подготовку ответа 200, а не его отправку или получение клиентом. Эти значения могут находиться в одной группе и описывать разные границы наблюдения; выбор одного «правильного» кода уничтожил бы часть сведений.
Нельзя вычесть 1700 из 2000 и назвать разность сетевой задержкой. Первый интервал в модели — ожидание клиентской попытки до timeout, второй — локальная обработка origin до подготовки ответа. Их начала и окончания различаются. Неизвестные смещения часов дополнительно запрещают считать межкомпонентную разность timestamp измеренной задержкой.
Три полные учебные записи; один JSON-объект в строке
{"schema_version":"data01.demo.v1","namespace":"data01.synthetic","event_id":"e1","source":"client","operation_id":"demo-op-001","attempt_id":"demo-attempt-a","event_name":"client_timeout","event_at":"2000-01-01T10:00:02.000Z","observed_at":"2000-01-01T10:00:02.100Z","response_code_recorded":null,"duration_ms":2000}
{"schema_version":"data01.demo.v1","namespace":"data01.synthetic","event_id":"e2","source":"edge","operation_id":"demo-op-001","attempt_id":"demo-attempt-a","event_name":"edge_response_recorded","event_at":"2000-01-01T10:00:02.050Z","observed_at":"2000-01-01T10:00:02.200Z","response_code_recorded":504,"duration_ms":null}
{"schema_version":"data01.demo.v1","namespace":"data01.synthetic","event_id":"e3","source":"origin","operation_id":"demo-op-001","attempt_id":"demo-attempt-a","event_name":"origin_response_prepared","event_at":"2000-01-01T10:00:01.700Z","observed_at":"2000-01-01T10:00:04.000Z","response_code_recorded":200,"duration_ms":1700}Свяжите записи, сохранив несовпадения
Правило для этого набора: группировать только по полному ненулевому ключу schema_version + namespace + operation_id + attempt_id. Отдельно проверять identity каждой записи: namespace + source + event_id. Одинаковая identity — повод отметить повтор или конфликт значений, а не молча удалить строку.
- Проверить версию схемы, наличие всех одиннадцати ключей, типы и область упражнения. Недопустимый вход отметить как ошибку проверки и сохранить его отдельно в рамках учебного разбора; не превращать его в достоверное событие.
- Сохранить допустимую строку с attempt_id:null отдельно с причиной отсутствия связи. Не достраивать значение из operation_id, IP-адреса, времени или кода. Отсутствующий JSON-ключ не проходит предшествующую проверку схемы.
- Сопоставить только полностью совпавшие ключи. Группировка по одной операции здесь недостаточна.
- Внутри выбранной группы оставить три источника, исходные времена и локальные результаты. Повторы identity отметить и сохранить для разбора.
Для базового набора получается одна группа из e1, e2 и e3; неполных ключей и повторов identity нет. По часам сборщика записи наблюдались в порядке e1 → e2 → e3. Позднее поступление e3 не означает, что само событие origin произошло последним.
| Вопрос | Что известно в модели |
|---|---|
| Связь записей | Одна вымышленная попытка по заданным доверенным ключам |
| Порядок наблюдения сборщиком | e1, затем e2, затем e3 |
| Порядок событий между компонентами | Не установлен: смещения часов неизвестны |
| Причина timeout или кода 504 | Не установлена |
| Доставка 200 клиенту и результат операции | Не установлены |
| Сетевая задержка | Не измерена |
Измените по одному условию и проверьте вывод
Полезно проверить правило на входах, которые должны изменить связь или оставить неизвестность. Следующие четыре изменения применяются по отдельности к исходным трём строкам. Они не являются наблюдениями реальных повторов запроса, сетевых отказов или атак.
| Изменение | Ожидаемый результат | Недопустимый вывод |
|---|---|---|
| В e3 attempt_id заменить на demo-attempt-b | Две группы размером 2 и 1; e3 не относится к попытке a | Приписать 200 клиентской попытке a или объявить реальный retry |
| В e2 attempt_id сделать null | e2 сохранить без связи по выбранному правилу; e1/e3 остаются группой | Заполнить попытку по близкому времени или одному operation_id |
| Добавить точную копию e2 | Сохранить все 4 строки, отметить одну повторяющуюся identity | Посчитать новый запрос или удалить повтор без проверки контракта |
| В e3 event_at сделать null | Сохранить неизвестное время события; observed_at остаётся временем наблюдения | Выдать время сборщика за время origin или восстановить причинный порядок |
Для неполного ключа результат «без связи» относится именно к этому правилу. Он не доказывает невозможность другой корреляции при наличии дополнительных данных. При повторяющейся identity отдельно различают одинаковые данные и конфликт значений; ни один случай не исправляется автоматически в этом упражнении.
Поля поставщика читают в его собственной семантике
Документация Cloudflare предупреждает, что Ray ID не гарантированно уникален для каждого запроса. Поэтому его нельзя без проверки области и контекста объявить универсальным уникальным ключом. В ней также отмечена выборка в Security Events: отсутствие строки в таком поиске само по себе не доказывает отсутствия события.
В наборе Cloudflare HTTP Requests различаются EdgeResponseStatus и OriginResponseStatus. Второй относится к ответу upstream; его 0 имеет описанные условия, включая отдельный контекст Workers. Наше origin_response_prepared означает подготовку ответа в учебном приложении и не является переименованием этого поля. Локальный HTTP-код сам по себе не устанавливает причину отказа или защитное действие.
Объявление Cloudflare Log Explorer от 18 июня 2025 года описывало отдельное дополнение и возможности работы с журналами. Исторический материал Qrator о ClickHouse от 4 марта 2019 года объяснял выбранное аналитическое хранилище. Эти тексты дают контекст инструментов, но не подтверждают нашу схему полей, текущий тариф, полноту данных или результат испытаний. База данных и интерфейс поиска не задают смысл записей за автора их контракта.
Результат — проверяемый контракт для выбранной задачи
После упражнения должны остаться три самостоятельных результата: описание полей и их границ, сохранённые исходные записи и результат сопоставления с неизвестными значениями. Для нового источника сначала описывают его условия, затем адаптируют правило. Наличие похожего названия поля ещё не разрешает объединить данные.
- Назвать выбранную единицу связи: операция, конкретная попытка или запись. Зафиксировать область и версию идентификаторов.
- Указать источник, класс события, смысл каждого локального результата и происхождение доверия к ключу.
- Разделить время события и наблюдения, описать часы и неизвестные смещения. Для длительности назвать обе границы интервала.
- Отделить нарушение схемы от допустимого null. Явно определить, что делать с отсутствием значения ключа связи, повтором identity и конфликтом значений. Проверить четыре отрицательных контроля.
- Записать охват: какие точки, период и виды событий представлены, есть ли выборка или потери. Без этого отсутствие строки остаётся ограниченным свидетельством.
- Отдельно перечислить недоказанное: причина, доставка клиенту, завершение бизнес-операции и эффективность защиты. Не заполнять эти строки локальным кодом ответа.
В учебный набор не включены реальные IP-адреса, URL с параметрами, заголовки, cookies, токены, тела запросов, персональные профили или материалы рабочих кабинетов. OWASP перечисляет секреты и чувствительные сведения, которые требуют исключения либо специальной обработки. Для реального журнала состав данных, доступ и хранение определяются отдельно; этот пример не является юридической оценкой или готовой политикой сбора.
Проверьте сопоставление в автономном упражнении
В архиве — три вымышленные записи, контракт из одиннадцати полей, инструкция и Python-программа на стандартной библиотеке. Четыре изменения применяются по отдельности: другая попытка, неизвестный ключ, повтор записи и неизвестное время события.
Распакуйте ZIP и выполните в его папке python3 -B exercise.py. Упражнение читает только соседние файлы, выводит результат в терминал и не обращается к сети. Реальные журналы, токены и данные клиентов ему не нужны.
Откроется публичная страница Яндекс Диска. Версия учебного контракта: data01.demo.v1. Это редакционный пример, не программа расследования реального отказа.
Первоисточники
- Logging Cheat Sheet
Контекст события, идентификатор взаимодействия, ограничения часов и данные, требующие исключения или специальной обработки.
OWASP. Дата публикации не указана. Проверено .
Дата публикации на прочитанной странице не указана.
- Logs Data Model
Различие Timestamp и ObservedTimestamp; источник и класс события. Собственный JSON не заявлен форматом OTLP.
OpenTelemetry. Дата публикации не указана. Проверено .
Дата публикации не указана; прочитана спецификация со статусом Stable.
- Cloudflare Ray ID
Ограничение уникальности Ray ID и выборка в Security Events.
Cloudflare. Дата публикации не указана. Обновлено . Проверено .
15 октября 2026 — указанная дата обновления, не первоначальной публикации.
- HTTP Requests — Logpush dataset
Отдельная семантика полей статуса edge и upstream. Она не переносится на origin_response_prepared.
Cloudflare. Дата публикации не указана. Обновлено . Проверено .
14 сентября 2026 — указанная дата обновления, не первоначальной публикации.
- Cloudflare Log Explorer is now GA, providing native observability and forensics
Контекст работы с журналами и отдельного дополнения на дату объявления; не обещание текущих функций Free.
Cloudflare. Опубликовано . Проверено .
Историческое объявление от 18 июня 2025 года.
- БД ClickHouse в нейтрализации DDoS
Описание выбранного аналитического хранилища. Не документация текущей схемы событий, SLA или измеренная сравнительная оценка.
Curator; исторический текст Qrator Labs. Опубликовано . Проверено .
Исторический текст от 4 марта 2019 года.
