Привет, Хабр!
Меня зовут Илья Улизко, я занимаюсь нагрузочным тестированием ДБО ЮЛ в блоке Цифровой Трансформации «РСХБ-Интех». В этой статье я поделюсь с вами опытом автоматизации сбора графиков в Grafana при отсутствии установленного grafana-image-render плагина на сервере. Для того, чтобы научить Apache Jmeter делать скриншоты панелей в Grafana, нам понадобится Selenium и Browsermob-proxy.
![Использовано в иллюстративных целях. Использовано в иллюстративных целях.](https://habrastorage.org/getpro/habr/upload_files/3dc/012/3ec/3dc0123ec6c709b30a7f5074a63a99a7.jpg)
-
Начнём со скачивания всех необходимых зависимостей. Сами jar файлы можно скачать с официальных Maven репозиториев. Однако этого будет мало, поэтому нужно рекурсивно скачать зависимости для самих этих jar’ников. В этом нам поможет сервис Jar-Download. Вставляем в окно Maven XML 3 зависимости из selenium, proxy, webdrivermanager.
Нажимаем кнопку Submit, затем Download project. В итоге получаем архив с более чем 40 jar файлами, которые кладём в apache-jmeter-5.4.3/lib/junit/.
-
Теперь нам необходимо скачать webdriver’ы под конкретные браузеры: Firefox и Chrome. С версией драйвера для Chrome всё просто: какая версия браузера, такая версия и драйвера. Например, если у вас Google Chrome 111, то и драйвер нужен версии 111. А вот с Firefox задача немного усложняется, но на сайте Mozilla есть таблица с соответствиями, которая поможет разобраться и выбрать нужный драйвер.
Для гибкости рекомендую скачать оба драйвера и установить оба браузера.
После того как всё скачано, складываем драйверы в отдельную папку WebDriver/bin. -
Далее нам нужно создать API ключ в Grafana, его мы будем отсылать в заголовке запросов в качестве авторизации. Для этого в Grafana слева нажимаем Configuration => API keys => New API key. Записываем где-нибудь у себя в блокноте, чтобы не забыть API ключ. Его мы будем далее передавать в переменную API_KEY.
-
Теперь надо прописать в переменных окружения путь до webdriver’ов и API-ключа, чтобы при необходимости всё поменять в одном месте, не затрагивая скрипты Jmeter. Я использую Linux, поэтому привожу пример для этой ОС:
echo 'export PATH=$PATH:/path/to/WebDriver/bin' >> ~/.profile
echo 'export API_GRAFANA=eyJblablablablablablablablabla9' >> ~/.profile
source ~/.profile -
Вытаскиваем все id’шники панелей из дашборда. У нас все дашборды для разных микросервисов шаблонизированы, поэтому количество и название панелей везде одинаковое. Заходим на любой дашборд и переходим в Dashboard settings => Json model. С помощью JSONPath
$.panels[*].[id,title]
и онлайн сервиса получаем список всех id’шников панелей. Этот массив мы далее будем передавать в переменную PANELIDS. -
С помощью панели разработчика определяем какой селектор или атрибут отвечает за отображение картинки внутри панели дашборда. Методом проб и ошибок был подобран атрибут class=»panel-container», в отличие от css selector, — он не меняется в разных панелях. Его мы будем передавать в переменную SELECTOR.
-
Приступаем к написанию скрипта в Jmeter. В начале тест плана создаём setUp Thread Group, внутри которой создаём JSR223 Sampler. В нём мы заводим переменную, которая будет хранить время начала теста и инициализировать переменную FROM:
props.put("TESTSTART",'${__time()}')
-
В конце тест плана создаём tearDown Thread Group, внутри которой формируем JSR223 Sampler. В нём пишем весь основной код.
Затем заводим параметризованные переменные:final String URL = "http://10.10.10.10:3000/d/";
Обратите внимание на переменную SCALE_MONITOR, она нужна, чтобы нивелировать масштабирование мониторов с высоким разрешением. Например, если у вас монитор с разрешением 4K и в настройках параметров экрана выставлен масштаб в 150%, то значение этой переменной будет 1.5, для масштаб в 125% нужно выставить — 1.25, ну и т.д.
final String DASHBOARD = "VQB0x5pVz/settings";
final int[] PANELIDS = new int[]{26,28,38,37,29,4,2,23,39,40,36,25,27}; final String FROM = '${__P(TESTSTART)}';
final String TO = '${__time()}';
final String SELECTOR = "panel-container";
final String API_KEY = System.getenv("API_GRAFANA");
final double SCALE_MONITOR = 1;
final SimpleDateFormat formatter = new SimpleDateFormat("'_'dd.MM.yyyy"); -
Создадим и настроим объект BrowserMobProxy, он нужен для того, чтобы к запросам из Selenium добавлялся заголовок с авторизацией по API ключу:
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.setTrustAllServers(true);
proxy.start();
proxy.addHeader("Authorization", "Bearer ".concat(API_KEY)); -
Теперь создадим веб драйвер с конкретной реализацией Firefox и передадим в него наш прокси с добавленным заголовком, а также добавим несколько настроек:
WebDriver driver;
DesiredCapabilities caps = new DesiredCapabilities();
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
System.setProperty("sun.java2d.uiScale", "1");
System.setProperty(FirefoxDriver.SystemProperty.BROWSER_LOGFILE, "null");
FirefoxOptions firefoxOptions = new FirefoxOptions();
firefoxOptions.addArguments("-private");
caps.setCapability("moz:firefoxOptions", firefoxOptions);
caps.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, true);
caps.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
caps.setCapability(CapabilityType.PROXY, seleniumProxy);
driver = new FirefoxDriver(caps); -
Через веб драйвер открываем браузер, разворачиваем на весь экран, делаем авторизованный запрос на URL адрес Grafana. Затем снимаем скриншоты всех панелей, id которых мы собрали в п. 5.
Далее сохраняем каждый скриншот под собственным названием в указанную директорию:driver.manage().window().maximize();
for (int i = 0; i < PANELIDS.length; i++) {
driver.navigate().to(URL
.concat(DASHBOARD)
.concat("?orgId=1&viewPanel=")
.concat(String.valueOf(PANELIDS[i]))
.concat("&from=")
.concat(FROM)
.concat("&to=")
.concat(TO));
Thread.sleep(2000);
WebElement elem = new WebDriverWait(driver, 5)
.until(ExpectedConditions
.visibilityOfElementLocated(By.className(SELECTOR)));
File screenshot = ((org.openqa.selenium.TakesScreenshot) driver)
.getScreenshotAs(org.openqa.selenium.OutputType.FILE);
BufferedImage image = ImageIO.read(screenshot);
int x = (int) (elem.getLocation().getX() * SCALE_MONITOR);
int y = (int) (elem.getLocation().getY() * SCALE_MONITOR);
int width = (int) (elem.getSize().getWidth() * SCALE_MONITOR);
int height = (int) (elem.getSize().getHeight() * SCALE_MONITOR);
BufferedImage elemScreenshot = image.getSubimage(x, y, width, height);
ImageIO.write(elemScreenshot, "png", new File("/path/GrafanaScreenshots/"
.concat(elem.getAttribute("aria-label")
.substring(0,elem.getAttribute("aria-label").length()-6))
.concat(formatter.format(System.currentTimeMillis()))
.concat(".png")));
} -
Закрываем браузер и останавливаем прокси:
driver.quit();
proxy.stop(); -
В итоге JSR223 Sampler будет выглядеть следующим образом:
java code
import net.lightbody.bmp.BrowserMobProxy; import net.lightbody.bmp.BrowserMobProxyServer; import net.lightbody.bmp.core.har.HarEntry; import net.lightbody.bmp.client.ClientUtil; import org.openqa.selenium.*; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; final String URL = "http://10.10.10.10:3000/d/"; final String DASHBOARD = "VQB0x5pVz/settings"; final int[] PANELIDS = new int[]{4,23}; final String FROM = '${__P(TESTSTART)}'; final String TO = '${__time()}'; final String SELECTOR = "panel-container"; final String API_KEY = System.getenv("API_GRAFANA"); final double SCALE_MONITOR = 1; final SimpleDateFormat formatter = new SimpleDateFormat("'_'dd.MM.yyyy"); BrowserMobProxy proxy = new BrowserMobProxyServer(); proxy.setTrustAllServers(true); proxy.start(); proxy.addHeader("Authorization", "Bearer ".concat(API_KEY)); try { WebDriver driver = getDriver(proxy); driver.manage().window().maximize(); for (int i = 0; i < PANELIDS.length; i++) { driver.navigate().to(URL .concat(DASHBOARD) .concat("?orgId=1&viewPanel=") .concat(String.valueOf(PANELIDS[i])) .concat("&from=") .concat(FROM) .concat("&to=") .concat(TO)); WebElement elem = new WebDriverWait(driver, 5) .until(ExpectedConditions.visibilityOfElementLocated(By.className(SELECTOR))); File screenshot = ((org.openqa.selenium.TakesScreenshot) driver).getScreenshotAs(org.openqa.selenium.OutputType.FILE); BufferedImage image = ImageIO.read(screenshot); int x = (int) (elem.getLocation().getX() * SCALE_MONITOR); int y = (int) (elem.getLocation().getY() * SCALE_MONITOR); int width = (int) (elem.getSize().getWidth() * SCALE_MONITOR); int height = (int) (elem.getSize().getHeight() * SCALE_MONITOR); BufferedImage elemScreenshot = image.getSubimage(x, y, width, height); ImageIO.write(elemScreenshot, "png", new File("/path/to/GrafanaScreenshots/" .concat(elem.getAttribute("aria-label").substring(0,elem.getAttribute("aria-label").length()-6)) .concat(formatter.format(System.currentTimeMillis())) .concat(".png"))); } driver.quit(); } catch (IOException | InterruptedException ignored) { } finally { proxy.stop(); } final WebDriver getDriver(BrowserMobProxy proxy) { WebDriver driver; DesiredCapabilities caps = new DesiredCapabilities(); Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy); System.setProperty("sun.java2d.uiScale", "1"); System.setProperty(FirefoxDriver.SystemProperty.BROWSER_LOGFILE, "null"); FirefoxOptions firefoxOptions = new FirefoxOptions(); firefoxOptions.addArguments("-private"); caps.setCapability("moz:firefoxOptions", firefoxOptions); caps.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, true); caps.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); caps.setCapability(CapabilityType.PROXY, seleniumProxy); driver = new FirefoxDriver(caps); return driver; }
Заключение
Таким образом у нас получилось автоматизировать процесс сбора графиков из дашборда Grafana без установленного grafana-image-render плагина.
![](https://habrastorage.org/getpro/habr/upload_files/38c/f00/523/38cf00523d58e3218cd82a687c886dd7.gif)
Надеюсь, что это материал был полезен тем, кто занимается нагрузочным тестированием и работает с Apache Jmeter. Буду рад ответить на ваши вопросы в комментариях.
ссылка на оригинал статьи https://habr.com/ru/articles/729196/
Добавить комментарий