# Сбор метрик
1. при сборе о внешнем ip адресе, sh скрипт обрщается к внешнему сервису - `ifconfig.co` таким способом:
```curl --connect-timeout 3 --interface $1 ifconfig.co```
в итоге, все наши шлюзы обращаются к ненашему сервису, это может быть проблемой с защищенностью?
при этом `net.*.ip_global` метрика не встречается в текущих метриках. кажется не собирается это поле, но оно есть в описании протобафа, значит должно быть и в собираемых данных. это надо проверить.
2. sh собирает метрики в виде списка проперти,
для некоторых свойств типа информации о файловой системе и сетевых интерфейсах, можно использовать индекс в теге (сейчас точка монтирования, или имя интерфейса)
сейчас:
```
fs./.avail=6230016
fs./.used=40271872
fs./.size=46501888
fs./tmp.avail=262832128
fs./tmp.used=90112
fs./tmp.size=262922240
fs./configs.avail=17416192
fs./configs.used=81920
fs./configs.size=17498112
fs./var/log.avail=50794496
fs./var/log.used=39325696
fs./var/log.size=95006720
```
нужно, (так не будет проблем если path сама имеет точку)
```
fs.0.mount="/""
fs.0.avail=6230016
fs.0.used=40271872
fs.0.size=46501888
fs.1.mount="/tmp"
fs.1.avail=262832128
fs.1.used=90112
fs.1.size=262922240
fs.2.mount="/configs"
fs.2.avail=17416192
fs.2.used=81920
fs.2.size=17498112
fs.3.mount="/var/log"
fs.3.avail=50794496
fs.3.used=39325696
fs.3.size=95006720
```
также на индекс в именах метрик перейти и при сборе сетевых метрик, т.е. вместо
```
net.ppp.ping_max=151.650000
net.ppp.ready=false
net.ppp.ip_local=10.15.47.27
net.tun.exists=true
net.tun.carrier=true
net.tun.rx_errors=0
net.tun.rx_dropped=0
```
собирать метрики так:
```
net.0.iface=ppp
net.0.ping_max=151.650000
net.0.ready=false
net.0.ip_local=10.15.47.27
net.1.iface=tun
net.1.exists=true
net.1.carrier=true
net.1.rx_errors=0
net.1.rx_dropped=0
```
3. сейчас скрипт который собирает метрики, захламляет вывод с ошибками, и не понятно это ошибка при сборе метрик, или это правильный метод работы скрипта. такие строки сейчас просто игнорируются при разборе метрик.
```
net.ppp.ready=false
cat: can't open '/sys/class/net/ppp0/carrier': No such file or directory
net.ppp.carrier=false
```
```
net.ppp.ready=false
cat: can't open '/sys/class/net/wwan0/carrier': No such file or directory
net.ppp.carrier=false
```
4. если сохранить метрик в протобафа и в виде строк и сжать их gzip, то разница всего в 2 раза. 500 байт в виде протобафа и 1000 байт в виде сжатых строк. за месяц это `31*24*60` сбора метрик - 22 мегабайта в протобафе, 44 мегабайта в сжатых строк. в итоге добавление протобафа это экономия 22 мегабайта в месяц на шлюзе и сильно усложняется процесс обновления кода.
5. сейчас скрипт собирает метрики в виде строк, а lorawan агент посылает метрики в мониторинговый агент как json. непонятно зачем есть 2 варианта парсинга строк, из json и из property строк. надо придти к одному варианту. будет меньше кода при парсинге.
6. сейчас лораван агент посылает метрики в мониторинговый через unix сокет пушит метрики. было бы хорошо если бы все возможные метрики собирал скрипт. допустим, скрипт бы обращался бы к лораван агенту и вытягивал метрики. к примеру, ловаран агент предоставлял свои метрики по http или unix сокету, скрипт обращается раз в минут и забирает метрики, к примеру `curl` умеет читать данные по unix сокету. и в итоге мониторинговый агент почти исчезает, (в агенте остается только хранение метрик, пересылка) все метрики собирает скрипт.
7. сейчас монитринговый агент не собирает версии агентов, было бы хорошо если бы в метриках были бы версии агентов, тогда можно было отслеживать когда просходили обновления агентов. sh может спрашивать версии у самих агентов, а может просто читать текстовой файл, который распостраняется при обновлении вместе с агентами. (может быть собирать и другие данные)
8. нужно вести учет sh скриптов и их либ. типа ranmon_stat.sh, /lib/functions/wwan.sh
9. попробовать разделить скрипт на несколько частей и запускать скрипты сбора метрик параллельно.
10. можно упростить парсинг. сейчас парсинг идет в 2 стадии, сначала строки конвертируются в `map[string]interface{}`, а значения стразу парсится в float64, int, bool, string. фактически map of maps. а потом эти map of maps конвертируется в протобаф, и значения опять пытаются конвертироваться в нужные типы протобафа. получается двойное преобразование типов. и нагрузка на gc, из-за конвертации значений в interface{}. можно этого избежать и хранить просто строки и конвертировать сразу их в протобаф (на этом этапе ты знаешь типы значений) минуя стадию maps of maps. пример как можно сделать парсинг в протобаф
```
// example metrics:
// sys.version="fw.cloudcell@2020.1-canary"
// sys.uptime=671224.58
//
// path:=["sys","version"], v:="fw.cloudcell@2020.1-canary"
// path:=["sys","uptime"], v:="671224.58"
//
func FillSystem(path []string, v string, system *monitoring.System) error {
switch path[1] {
case "version":
system.Version = v
case "uptime":
value, err := strconv.ParseFloat(v, 32)
if err != nil {
return err
}
system.Uptime = uint64(value)
case "lrr":
value, err := strconv.ParseUint(v, 10, 32)
if err != nil {
return err
}
reason := monitoring.System_LastResetReason(value)
system.LastResetReason = reason
}
return nil
}
```
11. в протобафе несколько разных типов - string, bool, int32, uint32, uint64, float64. это усложняет парсинг, а к примеру victoria metrics умеет только float64 и это покрывает все возможные наши размеры значений.
12. метрики по сети собираются с name="Ehernet", и в итоговом протобафе отсутствуют какое либо поле с названиями "ppp", "eth", "tun". а ran в названиях использует именно "ppp","eth","tun". и поэтому неправильн обрабатывались сетевые метрики в ran. теперь приходится делать маппинг таких названий "Ehernet" -> "eth", "VPN"->"tun" в сервисе на стороне ran.
13. у нас отдельный демон написннаый на си для сбора метрик по power. он раз в 2 сек читает данные данные файла из /sys/* и если напряжение стало падать, пишет метрики в мониториговый агент через unix socket в виде json, но это может делать и сам мониторинговый агент, т.е. можно удалить отдельный сишный проект. (и sh скрипт тоже может читать эти данные)
14. можно сейчас удалить lora метрики, упростится мониторинговый агент, а через время, можно эту функциональность добавить.
15. в протобафе вместо списка сетевых интерфейсов описать 3 переменные. у нас в коде заложено что должно быть 3 метрики с особыми именами и параметрами. это сделает более явным описание метрик именно так как у нас и используется. для этого в протобафе https://gitlab.everynet.io/platform/ran/agent.protobuf/-/blob/master/monitoring.proto
вместо
```
message MonitoringData {
...
repeated Interface interface = 11;
...
}
```
описать так:
```
message MonitoringData {
...
Interface eth = 15;
Interface ppp = 16;
Interface tun = 17;
...
}
```
16. прилетела метрика с ошибочными сетевыми данными.
```
{
"id": 2,
"exists": true,
"carrier": true,
"rxBytes": "759035",
"txBytes": "2194792"
}
```
пропущены обязательные поля name, ifname. без этих полей не получается перевести метрики в старый формат и разпознать сетевые метрики в gw_updater.
**вопрос на обсуждение**: что должен делать в таких ситуациях сервер, если он не подтвердит такие метрики, то они будут присылаться постоянно и трафик сожрется. если подвердит, но не запишет в базу, то метрики потеряются. надо определиться с политикой ack метрик.
на текущий момент сервер игнорирует ошибочные метрики, пишет в лог ошибки
17. нужно добавить в сбор метрик статистику по лоре агенту: last_rx_timestamp, last_tx_timestamp. которая будет показывать как лора агент общается с ran-lorawan сервисом.
18. редно бывает ошибка валидации метрик (значение lrr строкой прилетает) - https://sentry.k8s.dev.everynet.io/sentry/ran/issues/227455/
надо проверить, может быть валидация неправильная
- https://gitlab.everynet.io/platform/ran/agent.protobuf/-/blob/v1/monitoring.proto
- https://gitlab.everynet.io/platform/ran/ran/-/blob/master/utils/validator.py
19. порой прилетает ошибка с метрикой csq, https://sentry.k8s.dev.everynet.io/sentry/ran/issues/227455/?query=is%3Aunresolved
invalid literal for int() with base 10: '2AT+QCCID'
csq: '2AT+QCCID'
20. надо ли добавить в метрики разницу между gps_time от железки и utc time от линукса, чтобы понимать что utc на шлюзе убежал от реального
## Идеал
текуший процесс добавления и удаления новых метрик:
- добавить сбор новой метрики в sh скрипт
- добавить метрику в протобаф описание
- обновить исходники с протобафом в агенте и в мониториговом сервисе в ran
- добавить парсинг этой метрики в агент (маппинг метрики на протобаф)
- добавить тест на сбор этой метрики
- обновить агент и sh скрипт на шлюзах
- обновить мониторинговый сервис в ran
- добавить поле в кликхауз и обновить метрикс-keeper, что бы новое поля сохранялось в clickhouse
- обновить/добавить графики в графане
а в идеале изменение метрик должно происходить горазбо быстрее и проще:
- добавить сбор новой метрики в sh скрипт
- добавить тест на сбор метрики
- обновить sh скрипт на шлюзах
- обновить/добавить графики в графане
этого можно добиться если:
- пересылка метрик будет не статическая (протобаф), а просто текстом или json, сжатым gzip(для экономии трафика на шлюзе) (ну еще сильнее сжатым с zstd со нашим словарем).
- метрики будут сохранять не в статический кликхауз, а допустим в victoria metrics. из-за статической схемы в кликхауз надо делать миграции и обновлять сервис сохранения метрик в кликхауз