Set a session variable before the performance test runs

Hi All, my application has known cookie in the test environment that I can use to start my performance test but part of that cookie changes in subsequent requests. Each virtual user I start can use that cookie the first time but then I have to change dynamically for the 2,3,4,nth time that vUser sends a request. In other words if I start with 10 vUsers I will get 10 passed requests but then All other requests will fail with a 401. This is my code, and I guess I am not setting the AWSALB after the first time through per vUser. Any suggestions? Will setting a flag at start time to false and using a doIfOrElse statement work?

This is the header stuff

public class BaseSimulation extends Simulation {
    public static Map<String, String> getSessionHeadersWithAWSALB(){
        Map<String, String> sessionHeaders = new HashMap<String, String>();
        sessionHeaders.put("Content-Type", "application/json");
        sessionHeaders.put("accept", "application/json");
        sessionHeaders.put("x-requested-with", "XMLHttpRequest" );
        sessionHeaders.put("pragma", "no-cache");
        return sessionHeaders;
    }
}

This is the API call

public class Metrics extends BaseSimulation {
    public static final ChainBuilder requestSomeMetricsHours =
            feed(jsonFile("cda/somemanager/zones.json").random())
                    .doIfEquals("#{accessible}", true).then(
                            feed(dateHourFeeder)
                                    .exec(http("Some Metrics Request")
                                                            .post("/api/v1/some/Metrics")
                                                            .headers(getSessionHeadersWithAWSALB())
                                                            .header("COOKIE", "X-Token=fdbcac451beba3c93e2f8b08a7919e210081f1813e4d6dddf83777cb3347e0f9; AWSALB=#{awsalb}; AWSALBCORS=#{awsalb}")
                                                            .body(ElFileBody("payloads/getSomeManagerMetrics.json")).asJson()
                                                            .check(status().is(200))
                                                            .check(status().saveAs("status"))
                                                            .check(bodyString().saveAs("responseBody"))
                                                            .check(headerRegex("Set-Cookie", "AWSALB=(.*?);").saveAs("awsalb"))
                                                            .check(jsonPath("$.endTime").exists().saveAs("endTime"))
                                                            .check(jsonPath("$.startTime").exists().saveAs("startTime"))
                                            ).exec(session -> {
                                                System.out.println(session.getString("awsalb"));
                                                return session;
                                            })
                                    );
}
public class SomeMetricsRequestsScenarios {
    public static final ScenarioBuilder scnSomeMetricsRequestsHoursScenario = SomeMetricsRequestsScenariosChains("Request Some Metrics Hourly",
            Metrics.requestSomeMetricsHours
    );

    public static ScenarioBuilder SomeMetricsRequestsScenariosChains(String name, ChainBuilder... chains) {
        return scenario(name).forever().on(
                exec(session -> {
                    Session awsalb = session.set("awsalb", "w5rhjuzJtx55UIcWx0jkmJHqXQrXavnXMma/XcR4WbZJofhSCo4aPbtNAmDIAhwGyuE9s0Y61s85D6qQOiAnZxqI6iOW3z6iqvBVPjoIeI+6UwuomNkz5xVs0aMT");
                    return awsalb;
                })
                        .exec(List.of(chains))
                .pause(2)
        );
    }
}

Simulation Code

public class EnergyMetricsRequestsSimulation {

    HashMap<String, List<PopulationBuilder>> scenario = new HashMap<>();

    {
        scenario.put("EnergyMetricsRequestHours",
                List.of(SomeMetricsRequestsScenarios.scnSomeMetricsRequestsHoursScenario.injectOpen(rampUsers(PerformanceProperties.userCount())
                                .during(PerformanceProperties.rampDuration()))
                        .protocols(httpProtocol))
        );
    }

    {
        setUp(scenario.get(PerformanceProperties.testScenario()))
                .maxDuration(Duration.ofSeconds(PerformanceProperties.testDuration()))
                .protocols(httpProtocol);
    }

I run the code with following mvn command

mvn gatling:test -Dgatling.simulationClass=com.cisco.performance.simulations.SomeMetricsRequestsSimulation -DvUsers="10" -DrampDuration="1" -DtestDuration="300" -DtestScenario="SomeMetricsRequestHours" -DmetricsHours="1"

Hi @gkandale!

Cookies are a wild beast over there!

Did you consult the documentation about them?

Cookie are naturally managed by gatling. In another word, the virtual user will send the cookie that the server ask in the Set-Cookie header of previous responses.

What I see is that your scenario management feel over-complicated (especially for a reproducer)

If I take your scenario:

  ScenarioBuilder scn = scenario("My scenario").forever().on(
    exec(session -> session.set("awsalb", "w5rhjuzJtx55UIcWx0jkmJHqXQrXavnXMma/XcR4WbZJofhSCo4aPbtNAmDIAhwGyuE9s0Y61s85D6qQOiAnZxqI6iOW3z6iqvBVPjoIeI+6UwuomNkz5xVs0aMT")), // <- this will reset the value at each loop
    feed(jsonFile("cda/somemanager/zones.json").random()),
    doIf("#{accessible}").then(
      feed(dateHourFeeder),
      http("Some Metrics Request")
        .post("/api/v1/some/Metrics")
        .headers(getSessionHeadersWithAWSALB())
        .header("COOKIE", "X-Token=fdbcac451beba3c93e2f8b08a7919e210081f1813e4d6dddf83777cb3347e0f9; AWSALB=#{awsalb}; AWSALBCORS=#{awsalb}")
        .body(ElFileBody("payloads/getSomeManagerMetrics.json")).asJson()
        .check(status().is(200))
        .check(status().saveAs("status"))
        .check(bodyString().saveAs("responseBody"))
        .check(headerRegex("Set-Cookie", "AWSALB=(.*?);").saveAs("awsalb")) // <- this won't work
        .check(jsonPath("$.endTime").exists().saveAs("endTime"))
        .check(jsonPath("$.startTime").exists().saveAs("startTime"))
      ),
      exec(session -> {
        System.out.println(session.getString("awsalb"));
        return session;
      })
   )
  );

This code reset the awsalb session variable in each loop.
And the headerRegex won’t capture the cookie

I hope that helps.

Cheers!

Hey Sébastien, yes it is a beast :frowning: Not happy about this…
Do you have any suggestions on how I can set session variable awsalb with the known cookie before the scenario starts for each vUser and then set with the result of the headerRegex the subsequent times?

BTW, the cookie is used to authenticate the api call

I figured it out. I just flush the Cookies at the end of each transaction using flushCookieJar(), essentially disabling Gatling’s automatic Cookie handling. I guess whatever cookie management Gatling does is not compatible with the application and throws errors.

Oh and I had to set Accept-Encoding to None because gzip kept giving me “j.u.z.DataFormatException: invalid stored block lengths” errors.

New code:

feed(jsonFile("cda/somemanager/zones.json").random())
        .doIfEquals("#{accessible}", true).then(
                 feed(dateHourFeeder)
                        .exec(http("Some Metrics #{numberOfHours} hour(s) Request")
                                  .post("/some/Metrics")
                                  .headers(getSessionHeaders)
                                  .body(ElFileBody("performancepayload/getSomeManagerMetrics.json")).asJson()
                                  .check(status().is(200))
                                  .check(jsonPath("$.endTime").exists().saveAs("endTime"))
                                  .check(jsonPath("$.startTime").exists().saveAs("startTime"))
                        ).exec(flushCookieJar())
        );
}

Accept Encoding Header:

sessionHeaders.put("Accept-Encoding", "None");

I guess whatever cookie management Gatling does is not compatible with the application and throws errors

I kind of doubt that there’s something wrong on the Gatling side if you’re using a recent version.

I had to set Accept-Encoding to None because gzip kept giving me “j.u.z.DataFormatException: invalid stored block lengths ” errors.

Same. I’d say your zipped data is somehow corrupted. If there was a regression there, I think it would have been massively reported.

I didn’t say that there is something wrong with Gatling. I said something is not compatible with cookie management in Gatling and the application I am testing. Sorry if it sounded like I blamed Gatling.

Again I did not blame Gatling for any issues. I am just telling people that if they see such an error message, check if Accept-Encoding: “gzip” is the issue and set to none to see if it is where the issue is coming from. It is a known issue in Java that gzip sometimes fails decompression (but on the other hand I only see this issue in Gatling and not in Chrome or Firefox)

Here are some of the known issues with gzip in Java:
Gzip:
High CPU utilization: Gzip compression can cause high CPU utilization on the server side, especially when compressing large files.
Performance degradation: Gzip compression can cause performance degradation on the server side, especially when handling many requests simultaneously.
Incorrect decompression: Gzip decompression can sometimes fail, resulting in incorrect data being returned to the client.

Sorry for any offence I caused :smiley: , I should stop sending responses late into the evening so I can word properly.

-GK

No offense taken.

Both regarding cookies and gzip, I’d be very curious to see what you’re actually doing. Would you be able to provide a reproducer?

but on the other hand I only see this issue in Gatling and not in Chrome or Firefox

Something I’d like to check for myself.

Here are some of the known issues with gzip in Java:
Gzip:
High CPU utilization: Gzip compression can cause high CPU utilization on the server side, especially when compressing large files.
Performance degradation: Gzip compression can cause performance degradation on the server side, especially when handling many requests simultaneously.
Incorrect decompression : Gzip decompression can sometimes fail, resulting in incorrect data being returned to the client.

This is FUD, I don’t know where you found this.

High CPU utilization / Performance degradation

This is the whole point of compression: you’re trading CPU usage for bandwidth, both on the client-side and the server-side (unless you store the content already compressed). The performance of the implementation in the JVM (it ships a version of the standard gzip library) is decent.

Incorrect decompression : Gzip decompression can sometimes fail, resulting in incorrect data being returned to the client.

Gzip decompression fails:

  • if the HTTP payload is corrupted
  • if the client is buggy

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.