Пропоную ознайомитись із розшифровкою доповіді Романа Хавроненка "ExtendedPromQL"
Коротко про мене. Мене звати Роман. Я працюю в CloudFlare, мешкаю в Лондоні. Але також я мейтенер VictoriaMetrics.
І я автор
Ми почнемо з першої частини, яка називається «Складнощі перекладу» і в ній я розповідатиму про те, що будь-яка мова або навіть просто мова спілкування – це дуже важливо. Тому що це те, як ви передаєте іншій людині чи системі свої думки, як ви формулюєте запит. Люди в інтернеті сперечаються про те, яка мова краща – java чи якась інша. Для себе я вирішив, що треба вибирати під завдання, бо це все специфічно.
Почнемо із самого початку. Що таке PromQL? PromQL – це Prometheus Query Language. Це те, як ми формуємо запити в Prometheus, щоб отримати time series дані, тимчасові ряди.
Що таке time series дані? Якщо буквально, то це три параметри.
Це:
- На що ми дивимось.
- Коли ми дивимося на це.
- І яке значення вказує.
Якщо подивитися на цю діаграму (ця діаграма з мого телефону, яка показує статистику моїх кроків), можна швидко відповісти на ці запитання.
Ми дивимось на кроки. Ми бачимо значення та бачимо час, коли ми дивимося на це. Т. е. дивлячись на цю діаграму легко можна сказати, що в неділю я пройшов близько 15 000 кроків. Це time series дані.
Тепер давайте "розіб'ємо" (перетворимо) їх в іншу модель даних у вигляді таблиці. Тут ми також маємо те, на що ми дивимося. Тут я трохи додав додаткові дані, які ми називатимемо мета-даними, тобто це пройшов не я, а дві людини, припустимо, Jay і Silent Bob. Ось те, на що ми дивимося; що це показує, і коли воно показує це значення.
Тепер спробуємо зберегти всі ці дані в базі даних. Для прикладу я взяв ClickHouse синтаксис. І тут ми створюємо одну таблицю, яка називається "Steps", тобто на що ми дивимося. Тут є час, коли ми цього дивимося; що воно показує і якісь мета-дані, де ми зберігатимемо, хто це: Jay і Silent Bob.
І щоб спробувати візуалізувати це все, ми будемо використовувати Grafana, тому що, по-перше, це красиво.
Також ми будемо використовувати цей плагін. Для цього є дві причини. Перша – тому, що я його написав. І я точно знаю, як важко витягувати time series дані з ClickHouse, щоб показати Grafana.
Показувати ми будемо у Graph Panel. Це найпопулярніша панель у Grafana, яка показує залежність значення від часу, тому нам потрібно лише два параметри.
Давайте напишемо найпростіший запит - як показати статистику кроків у Grafana, зберігаючи ці дані в ClickHouse, в таблиці, що ми створили. І ми пишемо ось такий простий запит. Ми вибираємо з кроків. Ми вибираємо значення і вибираємо час цих значень, т. е. самі параметри, про які ми говорили.
І в результаті ми отримаємо такий графік. Хто знає, чому він такий дивний?
Правильно, треба відсортувати за часом.
І в результаті ми отримаємо вже краще, але все ще дивний графік. Хто знає чому? Правильно, там два учасники, і ми Grafana віддаємо два time series, тому що якщо розібратися з дата-моделлю ще раз, то кожна time series – це унікальна комбінація імені та всіх ключ-значень labels.
Тому нам треба вибрати конкретну людину. Ми вибираємо Jay.
І малюємо ще раз. Тепер графік схожий на правду. Тепер це нормальний графік, і все працює добре.
І, напевно, ви знаєте, як зробити приблизно те саме, але в Prometheus через PromQL. Приблизно так. Трохи простіше. І ще розіб'ємо це все. Ми брали Steps. І фільтруємо по Jay. Ми тут не вказуємо, що нам треба набути значення і ми не обираємо час.
А тепер спробуємо порахувати швидкість пересування Jay чи Silent Bob. У ClickHouse нам треба буде зробити runningDifference, тобто порахувати різницю між парами точок і розділити їх на час, щоб отримати точну швидкість. Запит виглядатиме приблизно ось так.
І покаже він приблизно такі значення, т. е. приблизно 1,8 кроку в секунду робить Silent Bob або Jay.
І в Prometheus ви знаєте, як це зробити теж. Набагато простіше, ніж було раніше.
І щоб це залишалося також просто робити в Grafana я додав таку обгортку, яка дуже схоже виглядає на PromQL. Вона називається Rate Macros або як хочете її називайте. У Grafana ви пишіть просто rate, але десь у глибині вона трансформується ось у такий великий запит. І вам не треба навіть на нього дивитися, він десь там є, але ви заощаджуєте купу часу, тому що писати такі величезні SQL-запити – це завжди затратно. Ви можете легко помилитись і потім довго не розуміти, що відбувається.
А це запит, який не помістився навіть в один слайд і мені довелося навіть розбити його на дві колонки. Це теж запит у ClickHouse, який робить той же rate, але по обох time series: і Silent Bob, і по Jay, щоб у нас на панелі були дві time series. І це вже дуже складно, як на мене.
І за Prometheus це буде sum (rate). Для ClickHouse я зробив окремий макрос, який називається RateColumns, який виглядає як запит у Prometheus.
Ми подивилися і як би PromQL весь такий класний, але у нього є, звичайно, обмеження.
Це:
- Limited SELECT.
- Прикордонні JOIN.
- Немає підтримки HAVING.
І якщо ви пропрацювали з ним довго, то ви знаєте, що іноді дуже важко зробити щось у PromQL, а SQL можна робити практично все, тому що всі ці варіанти, які ми зараз проговорили, можна було зробити в SQL. Але чи було б зручно цим користуватися? І це наштовхує мене на думку, що не завжди найпотужніша мова може бути найзручнішою.
Тому іноді треба вибирати мову під завдання. Це як битва Бетмена із Суперменом. Зрозуміло, що Супермен сильніший, але Бетмен зміг його перемогти, тому що він практичніший і достеменно знав, що він робить.
І така частина – це Extending PromQL.
Ще раз про VictoriaMetrics. Що таке VictoriaMetrics? Це time series бази даних, вона в OpenSource, ми дистрибутив її single і cluster-версії. За нашими бенчмарками вона найшвидше, що є на ринку зараз і за компресією аналогічно, тобто живі люди репортують компресію десь у 0,4 байт на точку, коли у Prometheus – це 1,2-1,4.
Ми підтримуємо не лише Prometheus. Ми підтримуємо InfluxDB, Graphite, OpenTSDB.
У нас можна "писати", тобто можна переносити старі дані.
І ще ми ідеально працюємо з Prometheus та Grafana, тобто ми підтримуємо PromQL engine. І у Grafana ви можете просто поміняти Prometheus endpoint на VictoriaMetrics і у вас усі дашборди працюватимуть, як і працювали.
Але ви можете використовувати додаткові фішки, які дає VictoriaMetrics.
Ми швидко пройдемо за функціями, які ми додали.
Omit interval param – ви можете пропускати інтервал параметрів Grafana. Якщо ви не бажаєте отримувати дивні графіки при zoom-in/out в панелі, то рекомендується використовувати змінну $__interval
. Це внутрішня зміна Grafana і сама вибирає діапазон даних. І VictoriaMetrics може сама розуміти, яким цей діапазон повинен бути. І вам не треба апдейтувати усі ваші запити. Буде набагато простіше.
Друга функція – це interval referencing. Ви можете використовувати цей інтервал у своїх виразах. Ви можете множити, ділити, передавати, посилатися нею.
Далі сімейство rollup function. Rollup function трансформує будь-який ваш time series на три окремі time series. Це min, max та avg. Я вважаю, що це дуже зручно, тому що іноді це може показати якісь outliers (аномалії) та неточності.
І якщо ви просто робите irate або rate, то ймовірно ви можете пропустити якісь випадки, коли time series поводиться не так, як ви припускали. З цією функцією набагато простіше побачити, скажімо, що max дуже сильно від avg.
Далі змінна default. Default – це означає, яке значення нам потрібно відмалювати в Grafana, якщо ми не маємо time series в даний момент. Коли це відбувається? Припустимо ви експортуєте якусь метрику помилково. І у вас така класна програма, що коли ви стартували, то у вас немає помилок і навіть немає помилок у наступні три години або навіть день. І у вас є дашборди, які показують відносини з успіхом до error. І вони вам показувати нічого, тому що у вас немає метрики error. А в default ви можете вказати будь-що.
Keep_last_Value – зберігає останнє значення метрики, якщо вона зникла. Якщо Prometheus після наступного скрейпу не знайшов її протягом 5 хвилин, то тут ми запам'ятовуватимемо її останнє значення і ваші графіки знову не зламаються.
Scrape_interval – показує, як часто Prometheus збирає дані за вашою метрикою, з якою частотою. Тут можна побачити перепустку, наприклад.
Label replace – популярна функція. Але ми вважаємо, що вона трохи складна, тому що вона набирає цілих аргументів. І вам треба не тільки пам'ятати 5 аргументів, але ще й пам'ятати їхню послідовність.
Тому чому б не зробити їх простіше? Т. е. розбити на дрібні функції зі зрозумілим синтаксисом.
І тепер найцікавіше. Чому ми вважаємо, що це extended PromQL? Тому що ми підтримуємо Common Table Expressions. Ви можете перейти за QR-кодом (
І що це таке? Ось цей зверху – це досить популярний запит. Я думаю, в будь-якому дашборді у багатьох компаній ви використовуєте той самий фільтр для всього. Зазвичай, так. Але коли вам потрібно додати якийсь новий фільтр, то доводиться оновлювати кожну панель або завантажувати дашборд, відкривати в JSON, робити find replace, що теж займає час. Чому б не зберігати це значення у змінній та перевикористовувати його? Це виглядає, на мій погляд, набагато простіше і зрозуміліше.
Наприклад, коли мені потрібно оновлювати фільтри в Grafana у всіх запитах, а дашборд при цьому може бути величезний або їх навіть кілька. І як би я хотів вирішувати цю проблему у Grafana?
Я вирішую цю проблему так: я роблю commonFilter і в ньому визначаю цей фільтр, а потім перевикористовую його в запитах. Але якщо ви зробите зараз так само, це не працюватиме, тому що Grafana не дозволяє вам використовувати змінні всередині змінних запитів. І це трохи дивно.
І тому я зробив такий варіант, що дозволяє це робити. І якщо вам цікаво чи ви хочете таку фічу, то підтримайте чи дизлайкніть, якщо вам не подобається така ідея.
Далі про PromQL extended. Тут ми визначаємо як змінну, а й прямо цілу функцію. І називаємо її ru (resource usage). І приймає ця функція вільні ресурси, обмеження ресурсу та фільтр. Начебто синтаксис весь простий. І дуже легко використовувати цю функцію та порахувати відсоток вільної пам'яті у нас. Т. е. скільки у нас є пам'яті, яке обмеження і як фільтрувати. Це виглядає набагато зручніше, якби ви писали це все, перевикористовуючи одні і ті ж фільтри, тому що це перетворилося б на великий-великий запит.
І ось приклад такого великого запиту. Він із офіційного дашборду NodeExporter для Grafana. Але я слабко розумію, що тут відбувається. Т. е., звичайно, розумію, якщо придивитися, але кількість дужок може відразу знизити мотивацію розбиратися в тому, що тут відбувається. І чому б не зробити його простіше та зрозуміліше?
Наприклад, ось так, виділивши значні речі або частини змінні. І потім зробити свою базову математику. Це вже більше схоже на програмування, це те, що я хотів би бачити в майбутньому в Grafana.
Ось другий приклад, як ми можемо зробити це ще простіше, якби у нас вже була ця функція ru, а вона вже є безпосередньо у VictoriaMetrics. І ви тоді просто передаєте закешоване значення, яке ви оголосили у CTE.
Я вже говорив про те, як важливо використовувати потрібну мову програмування. І, напевно, у кожній компанії в Grafana коїться щось своє. І, напевно, ви ще даєте доступ до Grafana своїм розробникам і розробники роблять щось своє. І всі вони роблять це по-різному. А хотілося, щоби якось однаково, тобто звести до загального стандарту.
Припустимо, у вас є навіть не просто системні інженери, можливо у вас навіть є експерти, девопси або SRE. Може у вас є експерти, які знають, що таке моніторинг, знають, що таке Grafana, тобто вони працюють із цими роками і вони точно знають, як робити правильно. І вони вже писали це сто разів і всім пояснювали, але чомусь ніхто не слухає.
А що, якби вони змогли ці знання безпосередньо покласти до Grafana, щоб інші користувачі могли перевикористовувати функції? І якби треба було порахувати відсоток вільної пам'яті, то вони просто застосували б функцію. А що, якщо творці експортерів, разом зі своїм продуктом надавали також і набір функцій, як працювати з їхніми метриками, бо вони точно знають, що це за метрики та як їх правильно рахувати?
Ось цього насправді не існує. Оце я зробив сам. Це підтримка бібліотек у Grafana. Допустимо, хлопці, які зробили NodeExporter, зробили те, що я розповів. І надали також набір функцій.
Т. е. виглядає це приблизно так. Ви підключаєте цю бібліотеку в Grafana, ви заходите в редагування і тут дуже просто в JSON написано, як працювати з цією метрикою. Т. е. якийсь набір функцій, їх опис і у що вони розгортаються.
На мою думку, це могло бути корисним, тому що тоді в Grafana ви б писали просто так. І вам Grafana "каже", що є ось така функція з такої бібліотеки - давайте її використовувати. Мені здається, що це було б дуже добре.
Трохи про VictoriaMetrics. Ми робимо багато цікавих речей. Почитайте наші статті про compression, про наші змагання з іншими time series програмами даних, наше пояснення як працювати з PromQL, тому що в цьому багато ще новачків, а також про vertical scalability та протистояння з Thanos.
Питання:
Я почну своє питання з простої життєвої історії. Коли я вперше почав використовувати Grafana, я написав дуже переконливий запит завдовжки 5 рядків. У результаті вийшов переконливий графік. Цей графік майже поїхав у виробництво. Але при найближчому розгляді виявилося, що цей графік показує абсолютну ахінею, яка не має жодного відношення до реальності, хоча цифри потрапляють у діапазон, який ми очікували побачити. І моє запитання. У нас є бібліотеки, ми маємо функції, а як ми пишемо тести для Grafana? Ви написали складний запит, від якого залежить бізнес-рішення – замовити контейнер серверів або не замовляти. І як ми знаємо, ця функція, яка малює графік, схожа на правду. Дякую.
Дякую за питання. Тут дві частини. Перша – у мене складається враження, виходячи з моєї практики, що більшість користувачів, коли дивляться на свої графіки, не розуміють, що вони показують. Чомусь люди дуже гарні в тому, щоб придумати виправдання будь-якої аномалії, яка відбувається на графіках, навіть якщо це помилка всередині функції. І друга частина - мені здається, що використання таких функцій набагато краще підійшло б до вирішення вашої проблеми, замість того, щоб кожен з ваших розробників робив свій capacity planning і помилявся з якоюсь ймовірністю.
Як перевірити?
Як перевірити? Напевно, ніяк.
У вигляді тесту у Grafana.
До чого тут Grafana? Grafana транслює цей запит безпосередньо у DataSource.
Додаючи трохи до параметрів.
Ні, Grafana нічого не додають. Там можуть бути GET-параметри, як, скажімо, step. Він явно не вказується, але ви його можете перевизначити, можете не перевизначати, але він автоматично додається. Ви не напишіть тут тести. Я думаю, що не варто покладатися тут на Grafana як на джерело правди.
Дякую за доповідь! Дякую за компресію! Ви згадували про mapping змінної у графіку, що у Grafana не можна використовувати змінну у змінній. Розумієте, що я?
Так.
Це було спочатку головним болем, коли я хотів зробити alert у Grafana. І там потрібно alert робити для кожного хоста окремо. Ось ця штука, яку ви зробили, вона працює для alerts у Grafana?
Якщо Grafana не звертається до змінних якось інакше, то – так, вона працюватиме. Але моя порада не використовувати алертинг у Grafana взагалі, вам краще використовувати alertmanager.
Так, я його використовую, але просто це в Grafana здалося легше в налаштуванні, але дякую за пораду!
Джерело: habr.com