Как заставить Jmeter собирать скриншоты графиков после тестов

от автора

Привет, Хабр!

Меня зовут Илья Улизко, я занимаюсь нагрузочным тестированием ДБО ЮЛ в блоке Цифровой Трансформации «РСХБ-Интех». В этой статье я поделюсь с вами опытом автоматизации сбора графиков в Grafana при отсутствии установленного grafana-image-render плагина на сервере. Для того, чтобы научить Apache Jmeter делать скриншоты панелей в Grafana, нам понадобится Selenium и Browsermob-proxy.

Использовано в иллюстративных целях.

Использовано в иллюстративных целях.
  1. Начнём со скачивания всех необходимых зависимостей. Сами jar файлы можно скачать с официальных Maven репозиториев. Однако этого будет мало, поэтому нужно рекурсивно скачать зависимости для самих этих jar’ников. В этом нам поможет сервис Jar-Download. Вставляем в окно Maven XML 3 зависимости из selenium, proxy, webdrivermanager.

    Нажимаем кнопку Submit, затем Download project.

    Нажимаем кнопку Submit, затем Download project.

    В итоге получаем архив с более чем 40 jar файлами, которые кладём в apache-jmeter-5.4.3/lib/junit/.

  2. Теперь нам необходимо скачать webdriver’ы под конкретные браузеры: Firefox и Chrome. С версией драйвера для Chrome всё просто: какая версия браузера, такая версия и драйвера. Например, если у вас Google Chrome 111, то и драйвер нужен версии 111. А вот с Firefox задача немного усложняется, но на сайте Mozilla есть таблица с соответствиями, которая поможет разобраться и выбрать нужный драйвер.
    Для гибкости рекомендую скачать оба драйвера и установить оба браузера.
    После того как всё скачано, складываем драйверы в отдельную папку WebDriver/bin.

  3. Далее нам нужно создать API ключ в Grafana, его мы будем отсылать в заголовке запросов в качестве авторизации. Для этого в Grafana слева нажимаем Configuration => API keys => New API key. Записываем где-нибудь у себя в блокноте, чтобы не забыть API ключ. Его мы будем далее передавать в переменную API_KEY.

  4. Теперь надо прописать в переменных окружения путь до webdriver’ов и API-ключа, чтобы при необходимости всё поменять в одном месте, не затрагивая скрипты Jmeter. Я использую Linux, поэтому привожу пример для этой ОС:
    echo 'export PATH=$PATH:/path/to/WebDriver/bin' >> ~/.profile
    echo 'export API_GRAFANA=eyJblablablablablablablablabla9' >> ~/.profile
    source ~/.profile

  5. Вытаскиваем все id’шники панелей из дашборда. У нас все дашборды для разных микросервисов шаблонизированы, поэтому количество и название панелей везде одинаковое. Заходим на любой дашборд и переходим в Dashboard settings => Json model. С помощью JSONPath $.panels[*].[id,title] и онлайн сервиса получаем список всех id’шников панелей. Этот массив мы далее будем передавать в переменную PANELIDS.

  6. С помощью панели разработчика определяем какой селектор или атрибут отвечает за отображение картинки внутри панели дашборда. Методом проб и ошибок был подобран атрибут class=»panel-container», в отличие от css selector, — он не меняется в разных панелях. Его мы будем передавать в переменную SELECTOR.

  7. Приступаем к написанию скрипта в Jmeter. В начале тест плана создаём setUp Thread Group, внутри которой создаём JSR223 Sampler. В нём мы заводим переменную, которая будет хранить время начала теста и инициализировать переменную FROM:
    props.put("TESTSTART",'${__time()}')

  8. В конце тест плана создаём tearDown Thread Group, внутри которой формируем JSR223 Sampler. В нём пишем весь основной код.
    Затем заводим параметризованные переменные:
    final String URL = "http://10.10.10.10:3000/d/";
    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");
    Обратите внимание на переменную SCALE_MONITOR, она нужна, чтобы нивелировать масштабирование мониторов с высоким разрешением. Например, если у вас монитор с разрешением 4K и в настройках параметров экрана выставлен масштаб в 150%, то значение этой переменной будет 1.5, для масштаб в 125% нужно выставить — 1.25, ну и т.д.

  9. Создадим и настроим объект BrowserMobProxy, он нужен для того, чтобы к запросам из Selenium добавлялся заголовок с авторизацией по API ключу:
    BrowserMobProxy proxy = new BrowserMobProxyServer();
    proxy.setTrustAllServers(true);
    proxy.start();
    proxy.addHeader("Authorization", "Bearer ".concat(API_KEY));

  10. Теперь создадим веб драйвер с конкретной реализацией 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);

  11. Через веб драйвер открываем браузер, разворачиваем на весь экран, делаем авторизованный запрос на 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")));
    }

  12. Закрываем браузер и останавливаем прокси:
    driver.quit();
    proxy.stop();

  13. В итоге 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 плагина.

Надеюсь, что это материал был полезен тем, кто занимается нагрузочным тестированием и работает с Apache Jmeter. Буду рад ответить на ваши вопросы в комментариях.


ссылка на оригинал статьи https://habr.com/ru/articles/729196/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *