How to force Jmeter to collect chart screenshots after tests

[*]My name is Ilya Ulizko, I am engaged in load testing of RBS LE in the Digital Transformation Block of RSHB-Intech. In this article, I will share with you the experience of automating the collection of graphs in Grafana in the absence of the grafana-image-render plugin installed on the server. In order to teach Apache Jmeter to take screenshots of panels in Grafana, we need selenium And Browsermob-proxy.

  • [*]Let’s start by downloading all the necessary dependencies. The jar files themselves can be downloaded from the official Maven repositories. However, this will not be enough, so you need to recursively download the dependencies for these jars themselves. This will help us service jar download. Paste into the Maven XML 3 window the dependencies from selenium, proxy, webdrivermanager.

    Click the Submit button, then Download project.[*]
    Click the Submit button, then Download project.

    [*]As a result, we get an archive with more than 40 jar files, which we put in apache-jmeter-5.4.3/lib/junit/.

  • [*]Now we need to download webdrivers for specific browsers: Firefox And Chrome. With the driver version for Chrome, everything is simple: what version of the browser, such version and drivers. For example, if you have Google Chrome 111, then version 111 is also needed. With Firefox, the task is a little more complicated, but Mozilla has table with correspondences, which will help you understand and select the right driver.
    For flexibility, I recommend downloading both drivers and installing both browsers.
    After everything is downloaded, put the drivers in a separate folder WebDriver/bin.

  • [*]Next, we need to create API key in Grafana, we will send it in the request header as an authorization. To do this, in Grafana on the left, click Configuration => API keys => New API key. We write down somewhere in our notebook so as not to forget the API key. We will further transfer it to the API_KEY variable.

  • [*]Now you need to set the path to the webdrivers and the API key in the environment variables, so that if necessary, you can change everything in one place without affecting the Jmeter scripts. I use Linux, so I give an example for this OS:
    echo 'export PATH=$PATH:/path/to/WebDriver/bin' >> ~/.profile
    echo 'export API_GRAFANA=eyJblablablablablablablablabla9' >> ~/.profile
    source ~/.profile

  • [*]We pull out all the id’s of the panels from the dashboard. All our dashboards for different microservices are templated, so the number and name of the panels are the same everywhere. We go to any dashboard and go to Dashboard settings => Json model. With JSONPath $.panels[*].[id,title] and online service get a list of all panel id’s. We will further transfer this array to the PANELIDS variable.

  • [*]Using the developer panel, we determine which selector or attribute is responsible for displaying the image inside the dashboard panel. By trial and error, the class=”panel-container” attribute was selected, unlike the css selector – it does not change in different panels. We will pass it to the SELECTOR variable.

  • [*]Let’s start writing a script in Jmeter. At the beginning of the test plan, we create a setUp Thread Group, inside which we create a JSR223 Sampler. In it, we set up a variable that will store the start time of the test and initialize the FROM variable:
    props.put("TESTSTART",'${__time()}')

  • [*]At the end of the test plan, we create a tearDown Thread Group, inside which we form a JSR223 Sampler. We write all the main code in it.
    Then we set up parameterized variables:
    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");
    Pay attention to the SCALE_MONITOR variable, it is needed to level out the scaling of high resolution monitors. For example, if you have a monitor with a resolution of 4K and a scale of 150% is set in the screen settings, then the value of this variable will be 1.5, for a scale of 125% you need to set it to 1.25, and so on.

  • [*]Let’s create and configure the BrowserMobProxy object, it is needed so that a header with authorization by API key is added to requests from Selenium:
    BrowserMobProxy proxy = new BrowserMobProxyServer();
    proxy.setTrustAllServers(true);
    proxy.start();
    proxy.addHeader("Authorization", "Bearer ".concat(API_KEY));

  • [*]Now let’s create a web driver with a specific implementation of Firefox and pass our proxy with the header added to it, as well as add a few settings:
    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);

  • [*]Through the web driver, open the browser, expand it to full screen, make an authorized request to the Grafana URL. Then we take screenshots of all panels, the id of which we collected in step 5.
    Next, save each screenshot under its own name in the specified directory:
    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")));
    }

  • [*]Close the browser and stop the proxy:
    driver.quit();
    proxy.stop();

  • [*]As a result, the JSR223 Sampler will look like this:

  • [*]Thus, we managed to automate the process of collecting graphs from the Grafana dashboard after the HT.

    [*]I hope that this material was useful to those who are engaged in load testing and work with Apache Jmeter. I will be glad to answer your questions in the comments.

    Similar Posts

    Leave a Reply

    Your email address will not be published. Required fields are marked *