В цій публікації я розкажу про те як побудувати графік зміни якоїсь змінної в реальному часі. Наприклад якоїсь ціни, чи кількості запитів до сервера. Ключові слова: 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:
Внизу треба ще не забути вибрати базу даних “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