Debug request under SBT test

I was able to get the SBT plugin working, mostly following the example.

I understand by the documentation that I can use Gatling as a testing framework, without installing the Gatling server bundle. This seems like a great option. I’ve created a basic simulation that test via the Gatling / test command.

class BasicSimulation extends Simulation {

  val httpProtocol = http
    .baseUrl("https://computer-database.gatling.io") // Here is the root for all relative URLs
    .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") // Here are the common headers
    .acceptEncodingHeader("gzip, deflate")
    .acceptLanguageHeader("en-US,en;q=0.5")
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0")

  val scn = scenario("Simple Scenario Example") // A scenario is a chain of requests and pauses
    .exec(
      http("Step 1 - Root Page")
        .get("/")
    )
    .pause(7) // Note that Gatling has recorder real time pauses

  setUp(scn.inject(atOnceUsers(10)).protocols(httpProtocol))
}

The above case works, so I’m moving to another use case.

Now, in my second case, when I run a simulation, it fails to make a successful request.

object AuthRequests {

  private val payload =
    s"""{
     |  "refresh_token": "${Configuration.apiKey}"
     |}
     """.stripMargin

  val getAccessToken = {

    val tokenRequest = http("Get access token")
      .post("/v1/tokens/refresh")
      .body(StringBody(payload))
      .asJson
      .check(status.is(200)) // make sure it worked
      .check(bodyString.saveAs("responseBody"))
      .check(jsonPath("$.access_token").saveAs("token")) // save the response value to the same named key

    exec(tokenRequest) exec { session =>
      println(s"ResonseBody: ${session("responseBody").as[String]}")
      println(s"Saved session access_token: ${session("token").as[String]}")
      session
    }

  }

}

I get a timeout, and I’m unable to debug why. I am however able to hit the server from cURL and get a successful response. I don’t think my Gatling script is making an actual request, because I have logging on the server for that endpoint and it only report the hit from cURL. I built out a little simulation runner, which allows be to set breakpoints, but there is no easy way to inspect the actual request/response lifecycle. I’d like to see the actual request, e.g. headers, host, etc. Is there an easy way to do that? I’ve tried setting up a logback.xml file in the test resources folder.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
		</encoder>
		<immediateFlush>true</immediateFlush>
	</appender>

	<!-- uncomment and set to DEBUG to log all failing HTTP requests -->
	<!-- uncomment and set to TRACE to log all HTTP requests -->
	<logger name="io.gatling.http.engine.response" level="TRACE">
		<appender-ref ref="CONSOLE" />
	</logger>

	<logger name="io.gatling.http.ahc" level="TRACE">
		<appender-ref ref="CONSOLE" />
	</logger>

	<logger name="io.gatling.http.response" level="TRACE">
		<appender-ref ref="CONSOLE" />
	</logger>

	<root level="TRACE">
		<appender-ref ref="CONSOLE" />
	</root>

</configuration>

That does not seem to work.

I will also note, that the simulation test seems to run for 60s, with an update every 5 seconds. I don’t know why that is in this case… I haven’t setup any kind of loop.

================================================================================
2023-11-26 10:54:30                                           5s elapsed
---- Requests ------------------------------------------------------------------
> Global                                                   (OK=0      KO=0     )


---- List Projects -------------------------------------------------------------
[--------------------------------------------------------------------------]  0%
          waiting: 0      / active: 1      / done: 0
================================================================================

and at the end is see an error:

11:20:39.518 [gatling-1-2] ERROR io.gatling.core.action.builder.SessionHookBuilder$$anon$1 - 'hook-3' crashed with 'j.u.NoSuchElementException: No attribute named 'responseBody' is defined', forwarding to the next one

First question: are you a Scala developer and familiar with sbt? If not, I really recommend that you stick to Gatling Java and a more conventional JVM build tool such as maven or gradle.

I built out a little simulation runner, which allows be to set breakpoints

Debugger breakpoints won’t help you with Gatling as the engine is functional and non blocking.

I’ve tried setting up a logback.xml file in the test resources folder.
That does not seem to work.

This is the correct way to trace: https://github.com/gatling/gatling-maven-plugin-demo-java/blob/main/src/test/resources/logback-test.xml#L13

io.gatling.http.ahc is from Gatling 2 and no longer valid.

Then, this configuration should work (as you’ve even enable TRACE logging for the root logger) and the request should be logged.

For some reason, your configuration is ignored.

My2cents: you’re:

  • either not recompiling
  • or are editing a logback.xml while also having a logback-test.xml in the classpath. The latter has precedence.

j.u.NoSuchElementException: No attribute named ‘responseBody’ is defined’, forwarding to the next one

This error is expected. If the "Get access token" request times out, responseBody won’t be captured and session("responseBody").as[String] will crash.

Now for the possible reasons of this timeout:

  • incorrect baseUrl
  • forcing content-length header to an incorrect value
  • weird server that doesn’t like this user-agent header value
  • buggy server that doesn’t properly fail on a bad request, eg missing some request header, or:
s"""{
     |  "refresh_token": "${Configuration.apiKey}"
     |}
     """.stripMargin

Do you realize that you don’t have a pipe character on the last line? As a result, the actually String will end with a line feed and several white spaces. Maybe that’s what causing your application to choke. If so, I would also argue that your application should reply with 400: Bad Request instead of timing out.

Yes.

Got the logger to work and that found the issue. It was choking on the bad refresh token as you’re suggesting above. I don’t control that server, but I agree - it should be giving a 400 and/or trimming the noise.

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