owned this note
owned this note
Published
Linked with GitHub
---
tags: terminology, godeep
---
# Времена
В НОКе время связано с двумя основными потоками данных.
1. События FM
2. Метрики PM
Поскольку эти потоки оседают в разных БД, то отношения со временем у них отличаются.
## Создание (генерация)
### События (FM)
Поток событий выглядит так:
1. Регистратор (Ping, Syslog или SNMP коллектор)
2. Транспорт до Классификатора (NSQ)
3. Классификатор -> Событие (Event)
4. БД и/или Коррелятор
5. Транспорт до Коррелятора (NSQ)
6. Коррелятор
7. Оперативное хранилище
8. Выгрузка
9. Транспорт до постоянного хранилища
10. Писатель (CHWRITER)
11. Хранище (Clickhouse)
Так выглядит полный путь потока. Если `Регистратором выступает процесс Дискавери`, то поток начинается с пункта 7.
#### Регистрация
Время регистрации формируется на регистраторе, путём вызова метода `time.time()`. На выходе мы получаем **время в GMT** (время по Гринвичу) в виде целого числа секунд от начала времён. Оно вставляется в сообщение с информацией и уходит по транспорту дальше.
В случае регистрации по сокращённому пути (регистрация процессом дискавери) ...
#### Классификация
Сообщение с регистраторов поступает в классификатор. Он извлекает время регистрации события (timestamp UTC) и производит преобразование его методом `datetime.datetime.fromtimestamp(ts)`. Данное преобразование проводится с учётом часового пояса. Т.е. мы получаем **локальное время** на сервере классификатора.
В таком виде сообщение сохраняется в оперативной БД, в коллекции `NewEvents`.
#### Оперативное хранилище
В качестве *оперативного хранилища* используется база данных `Mongo`. Время внутри себя хранится в [UTC](https://docs.mongodb.com/manual/tutorial/model-time-data/#model-time-data) как 64 битное целое - число миллисекунд с момента начала эпохи.
При сохранении времени, оно сохраняется как есть. Т.е. преобразований с учётом часового пояса не происходит. [pymongo](http://api.mongodb.com/python/current/examples/datetimes.html).
> Вместе с временем возможно сохранение смещения. Но в НОКе этот функционал не используется.
>
#### Корреляция
Событие из классификатора следует в коррелятор. Время создания аварии берётся из события. Т.е. они получаются равными локальному времени на сервере классификатора.
После обработки событие попадает в Оперативное хранилище в виде аларма.
#### Эскалация
При эскалации время извлекается из аларма.
#### Выгрузка
При выгрузке преобразования времени не происходит. Т.е. они извлекается прямо из базы.
При вгрузке в CH действуют правила согласно пункту `Хранилище` раздела `Метрики`
### Метрики (PM)
Поток метрик выглядит так:
1. Сбощик (Активатор)
2. Транспорт до источника (HTTP)
3. Источник (Дискавери или Ping)
4. Транспорт до CHWRITER (NSQ канал PMWRITER)
5. Писатель (CHWRITER)
6. Хранилище (Clickhouse)
#### Сбор
Время метрики формируется методом `time.time()`, который возвращает время с начала времён (в формате ssss.mmmm, GMT - время по Гринвичу). Полученное значение преобразуется в **локальное время** (время, с учётом часового пояса) методом `time.localtime()`, которое и вставляется в сообщение с метрикой.
С временем метрик, считываемых с оборудования, происходит аналогичное преобразование, но, на сервере дискавери, который эту метрики получил от сборщика.
Поскольку транспорт и Писатель, не меняют передаваемые/обрабатываемые данные, то можно утверждать, что на **этапе записи в БД**:
* **Время измерения метрики с оборудования равно локальному времени на сервере дискавери**
* **Время измерения RTT и Attempts равно локальному времени на сервере пингера**
#### Хранилище
В качестве склада метрик используется база данных `ClickHouse` (CH). В её документации содержится следующая информация по [работе с временем](https://clickhouse.yandex/docs/ru/single/#date).
```
Date
Дата. Хранится в двух байтах в виде (беззнакового) числа дней, прошедших от 1970-01-01. Позволяет хранить значения от чуть больше, чем начала unix-эпохи до верхнего порога, определяющегося константой на этапе компиляции (сейчас - до 2038 года, но может быть расширено до 2106 года). Минимальное значение выводится как 0000-00-00.
Дата хранится без учёта часового пояса.
DateTime
Дата-с-временем. Хранится в 4 байтах, в виде (беззнакового) unix timestamp. Позволяет хранить значения в том же интервале, что и для типа Date. Минимальное значение выводится как 0000-00-00 00:00:00. Время хранится с точностью до одной секунды (без учёта секунд координации).
Часовые пояса
Дата-с-временем преобразуется из текстового (разбитого на составляющие) в бинарный вид и обратно, с использованием системного часового пояса на момент старта клиента или сервера. В текстовом виде, теряется информация о том, был ли произведён перевод стрелок.
```
>Пояснение
>В CH необходимо обязательное присутствие поля `Date`. По-умолчанию, оно является *первичным ключевым полем* и по нему происходит *партиционирование* (разбиение данных на отделённые друг от друга части).
>
При формировании сообщения с метриками на стороне *Источника* - `Date` получается отсеченем лишней информации (времени) от *времени метрики*. В итоге, в базу поступает условно, 2 поля *Дата* и *Дата время* *Источника*. Они преобразуются во внутренний формат хранения с учётом **системного часового пояса** на сервере с БД.
В идеале (Если часовой пояс на *Источнике* и *БазеДанных* совпадает), у нас происходит 2 одинаковых преобразования времени в разные стороны:
1. НА стороне Источника (из GMT в локальное)
2. НА стороне БД (ИЗ локального в GMT)
Получается, что в базе лежит **время по GMT**.
## Телеметрия
Для телеметрии действуют правила аналогичные `Метрикам` с поправкой на то, что при создании сообщения используется локальное время сервера на котором запущен процесс.