В цій публікації я розкажу про те як побудувати графік зміни якоїсь змінної в реальному часі. Наприклад якоїсь ціни, чи кількості запитів до сервера. Ключові слова: Docker, Docker compose, time series database, InfluxDB, Grafana, Telegraf. Всі крім докера будуть пояснені детально, докер – лише використовуватись для економії часу на інсталяцію.
В тренді зараз криптовалюти, тому давайте для прикладу будемо моніторити курс Litecoin до гривні. Для цього достатньо зробити GET запит https://api.coinmarketcap.com/v2/ticker/2/?convert=UAH. Для Bitcoin замініть id після /ticker/ з 2 на 1. (Документація з API). Він повертає JSON, формат якого розберемо трохи пізнішео. Бо нам ще треба встановити, налаштувати і запустити три програми для того щоб вони одна з одною працювали. Ну звісно в наш час це вручну ніхто не робить, тому ось вам готова конфігурація docker-compose.yml
:
version: '3'
services:
influxdb:
image: influxdb:latest
container_name: influxdb
ports:
- "8086:8086"
networks:
- back-tier
telegraf:
image: telegraf:latest
container_name: telegraf
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
networks:
- back-tier
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
networks:
- back-tier
networks:
back-tier:
Записуєте його в директорію проекту, командуєте docker-compose up
, і насолоджуєтесь логами всіх трьох сервісів. Правда вискочить помилка, бо конфігурація
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
означає “покласти файл telegraf.conf з поточної директорії, в контейнер за шляхом /etc/telegraf/telegraf.conf”, а ми цей файл не написали. Для того треба спершу розібратись що таке Telegraf, чим він займатиметься, і як.
Telegraf, як пишуть на його сайті – це агент для збирання метрик і запису їх в InfluxDB, чи якісь інші можливі місця. Його файл конфігурації довгий, але важливі лише два місця:
[[outputs.influxdb]]
# Конфігурація виведення даних в InfluxDB
urls = ["http://influxdb:8086"] # HTTP інтерфейс InfluxDB.
## Ім'я домену influxdb буде показувати на контейнер influxdb, тому що docker-compose так робить мережі
## База даних в яку писати метрики (telegraf її створить якщо буде потреба).
database = "telegraf"
...
[[inputs.http]]
## Брати дані http запитами
urls = [ # звідки
"https://api.coinmarketcap.com/v2/ticker/2/?convert=UAH"
]
method = "GET" # методом GET
data_format = "json" # розшифровувати як JSON
Якщо такий файл в нас є, то композ запустить всі три сервіси успішно, і Telegraf почне писати щось в InfluxDB. Пора подивитись що з того вийде. Щоб зайти в інтерфейс командного рядка Influxdb треба виконати команду
docker exec -it influxdb influx
А тоді:
> SHOW DATABASES
name: databases
name
----
_internal
telegraf
> use telegraf
Using database telegraf
> SHOW MEASUREMENTS
name: measurements
name
----
http
Бачим що Telegraf пише все в одну “таблицю” (measurement) – http. Але це насправді не страшно, бо в InfluxDB важливі не так measurements, як series – measurement з унікальним набором тегів (полів що індексуються). Крім них ще є fields (поля, які містять дані і не індексуються). Подивимось які в нас теги і поля (це майже те саме що схема таблиці в реляційних БД):
> SHOW FIELD KEYS FROM http
name: http
fieldKey fieldType
-------- ---------
data_circulating_supply float
data_id float
data_last_updated float
data_max_supply float
data_quotes_UAH_market_cap float
data_quotes_UAH_percent_change_1h float
data_quotes_UAH_percent_change_24h float
data_quotes_UAH_percent_change_7d float
data_quotes_UAH_price float
data_quotes_UAH_volume_24h float
data_quotes_USD_market_cap float
data_quotes_USD_percent_change_1h float
data_quotes_USD_percent_change_24h float
data_quotes_USD_percent_change_7d float
data_quotes_USD_price float
data_quotes_USD_volume_24h float
data_rank float
data_total_supply float
metadata_timestamp float
> SHOW TAG KEYS FROM http
name: http
tagKey
------
host
url
> SHOW TAG VALUES FROM http WITH KEY IN ("host", "url")
name: http
key value
--- -----
host 42bdec9c8910
url https://api.coinmarketcap.com/v2/ticker/2/?convert=UAH
Бачимо що теги – це хост на якому запущений агент телеграфа що прислав дані (дивне в нього id, але це id контейнера). Не знаю чому не ім’я, думаю якось можна змінити, але це не дуже важливо якщо в нас один сервер з Telegraf. І адреса ресурсу який моніторить Telegraf. Тому можна бути спокійним з “таблиці” http можна буде вибрати окремі значення за тегом.
А от fields – дійсно багато. Яке з них – ціна Litecoin? Ну, для цього треба подивитись який JSON нам віддав coinmarketcap:
{
"data": {
"id": 2,
"name": "Litecoin",
"symbol": "LTC",
"website_slug": "litecoin",
"rank": 6,
"circulating_supply": 57387708.0,
"total_supply": 57387708.0,
"max_supply": 84000000.0,
"quotes": {
"UAH": {
"price": 2041.6651371095,
"volume_24h": 6550472764.2681465,
"market_cap": 117166483500.0,
"percent_change_1h": 0.08,
"percent_change_24h": 1.43,
"percent_change_7d": -6.39
},
"USD": {
"price": 77.8638,
"volume_24h": 249818000.0,
"market_cap": 4468425048.0,
"percent_change_1h": 0.08,
"percent_change_24h": 1.43,
"percent_change_7d": -6.39
}
},
"last_updated": 1531505650
},
"metadata": {
"timestamp": 1531505337,
"error": null
}
}
Ціна лежить в data.quotes.UAH.price
, тому думаю нас цікавить поле data_quotes_UAH_price
. Спробуємо запит:
> SELECT data_quotes_UAH_price FROM http WHERE time >= now() - 1h
name: http
time data_quotes_UAH_price
---- ---------------------
1531595740000000000 2007.3576069685
1531595750000000000 2007.3576069685
1531595760000000000 2007.3576069685
1531595770000000000 2006.7466581361
1531595780000000000 2006.7466581361
1531595790000000000 2006.7466581361
1531595800000000000 2006.7466581361
1531595810000000000 2006.7466581361
...
О, це щось з чого можна будувати графік! І цим займеться Grafana.
Вона в нашій системі працює на порті 3000, тому заходимо на http://localhost:3000/ , входимо як USER: admin, PASSWORD: admin, змінюємо пароль, натискаємо “Create datasource”, заповнюємо форму для InfluxDB:

Заповнення джерела даних в Grafana
Внизу треба ще не забути вибрати базу даних “telegraf”, і натиснути “Save & test”. Якщо вискочило зелене повідомлення (а не червоне про помилку), то можна продовжувати.
Натискаємо плюсик -> Create -> Dashboard, додаємо панель “Graph”. У вкладці “Metrics” вибираємо датасорс InfluxDB і пишемо запит. Там є конструктор запитів, виглядає все так:

Побудова графіка за запитом
Але при бажанні можна справа натиснути кнопку меню, вибрати “Toggle edit mode”, і відредагувати запит як SQL:
SELECT mean("data_quotes_UAH_price") FROM "http" WHERE $timeFilter GROUP BY time($__interval) fill(null)
Бачимо що Grafanа вставляє в запит свої змінні, що дозволяє інтерактивно перебудовувати графік. Змінна $timeFilter
містить щось на зразок now() - 1h
залежно від того що користувач вибере в полі вгорі дашборда:

Вибір інтервалу часу
Ну як, почуваєтесь трошки фінансистами? Я ні, я аналіз даних в універі проспав :(, і взагалі мені це все для того аби рахувати запити до сервера.
А, ну і ввесь код, можна взяти на https://github.com/bunyk/docker-influxdb-grafana