Load testing of SSE events: in a report just one matched message instead of N (many)

Hi, together!

Does Gatling has a limitations to show in a report how many SSE events came in a stream? I set a check, unfortunately I see just 1 execution (1 matched message) in a log and report , although I get many same events…

Code:

  val sseCheckPushmessages = sse.checkMessage("checkPushmessages")
    .matching(substring("pushmessage"))
    .check(regex("NEWS(.+?)"))
	
  val scnListener = scenario("ServerSentEvents-news")
    .exec(http("01_Login_GET")
        .get("/lp/wt/login")
        .headers(sentHeadersLoginGET)
        .check(
            currentLocationRegex("execution=(.*)").saveAs("execution"),
            regex("""ViewState" id=".*?" value="(.+?)"""").saveAs("viewstate"),
            regex("name=\"csfCsrfToken\" value=\"(.+?)\"").saveAs("csfCsrfToken"),
            substring(">Anmelden<")
        )
    )
	//...... some code	
    .exec(sse("05_sse_connect_to_/push/sse").connect("/push/sse")
         .await(60)(
               sse.checkMessage("checkHeartbeatMitConnectionId")
                   .check(
                       regex("connectionId\\\\\":\\\\\"(.*)\\\\\",\\\\\"pushFeId").saveAs("myresponse"),
                       substring("heartbeat")
                   )
         )
    )
	//...... some code
    .exec(http("07_API_pushenginesubscriptions_PUT")
        .put("/api/messages/v1/pushenginesubscriptions/${myresponse}")
        .headers(sentHeadersPushenginesubscriptions)
        .body(StringBody(newsession3 => newsession3("api_put_data").as[String]))
        .check(
            substring("pushengineSubscriptionId"))
    )
    .exec(sse("SetCheck").setCheck
          .await(60)(sseCheckPushmessages)
    )
    .pause(15)
    .exec(sse("Close").close)

Report:
---- Requests ------------------------------------------------------------------

Global (OK=7 KO=0 )
01_Login_GET (OK=1 KO=0 )
01_Login_GET Redirect 1 (OK=1 KO=0 )
05_sse_connect_to_/push/sse (OK=1 KO=0 )
checkHeartbeatMitConnectionId (OK=1 KO=0 )
07_API_pushenginesubscriptions_PUT (OK=1 KO=0 )
> checkPushmessages (OK=1 KO=0 )
Close (OK=1 KO=0 )

Log:

Used: gatling-charts-highcharts-bundle-3.9.0

That’s how the SSE support works: 1 check per inbound message.

[:thinking: hm, how can I see 100 incoming messages in a report?

A. If I use “repeat”

.exec(
  sse("SetCheck")
    .setCheck.await(60)(
      sseCheckPushmessages.repeat(100) 
    )
)

ERROR: value repeat is not a member of io.gatling.http.check.sse.SseMessageCheck

B. Ugly variant: paste check-block 100-1000 times in code
If I paste 3 times

  .exec(sse("SetCheck").setCheck
          .await(60)(sseCheckPushmessages)
    )
    .exec(sse("SetCheck").setCheck
          .await(60)(sseCheckPushmessages)
    )
    .exec(sse("SetCheck").setCheck
          .await(60)(sseCheckPushmessages)
    )
    .pause(15)

Report as I wish
checkPushmessages (OK=3 KO=0 )

If I paste more than 120, I get an Error. If I set JAVA_OPTS=-Xss128Mb, I get an error again
15:55:21.461 [ERROR] i.g.c.ZincCompiler$ - Compilation crashed
java.lang.StackOverflowError: null
at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:675)
at scala.tools.nsc.typechecker.Typers$Typer.normalTypedApply$1(Typers.scala:5080)
at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:5110)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5991)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6047)
at scala.tools.nsc.typechecker.Typers$Typer.typedSelectOrSuperCall$1(Typers.scala:6145)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5992)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:6047)
at scala.tools.nsc.typechecker.Typers$Typer.$anonfun$typed1$41(Typers.scala:5078)
at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:698)

@slandelle Thank you for advice about methods. It is clear me now why =)
from documentation (Gatling - Functions):

"Sometimes, you might want to dynamic parameters that are too complex to compute for Gatling EL. Most Gatling DSL methods can also be passed a function to compute your parameter value programmatically.

Those functions are executed in Gatling’s shared threads, so you must absolutely avoid performing long blocking operations in there]

To be turned into a method:

  var acc: SseSetCheckBuilder = sse("SetCheck").setCheck
  for (_ <- 0 to 60) {
    acc = acc.await(60)(sseCheckPushmessages)
  }

Thank you!

According to SseSetCheckBuilder - gatling-http 3.9.0 javadoc

I found that SseSetCheckBuilder is a class in package io.gatling.http.action.sse for Gatling 3.9.0.

I added
import io.gatling.http.action.async.sse.SseSetCheckBuilder


var acc: SseSetCheckBuilder = sse("SetCheck").setCheck

val sseCheckPushmessages = sse.checkMessage("checkPushmessages")
    .matching(substring("pushmessage"))
    .check(regex("NEWS(.+?)"))

val scnListener = scenario("ServerSentEvents-news")
   //...some code
   .exec(http("07_API_pushenginesubscriptions_PUT")
        .put("/api/messages/v1/pushenginesubscriptions/${myresponse}")
        //some code
    )
    .exec(
        for (_ <- 0 to 200) {
          acc = acc.await(60)(sseCheckPushmessages)
        }
    )
    .pause(15)
    .exec(sse("Close").close)

Unfortunately I get a compilation error

23:39:51.163 [ERROR] i.g.c.ZincCompiler$ - D:/Tools/gatling-charts-highcharts-bundle-3.9.0/user-files/simulations/news/sse_news.scala:104:6: overloaded method exec with alternatives:
[T <: io.gatling.core.structure.Execs[]](execs: Iterable[T]): io.gatling.core.structure.ScenarioBuilder
[T <: io.gatling.core.structure.Execs[
]](execs: T*): io.gatling.core.structure.ScenarioBuilder
(actionBuilder: io.gatling.core.action.builder.ActionBuilder)io.gatling.core.structure.ScenarioBuilder
(sessionFunction: io.gatling.core.session.Expression[io.gatling.core.session.Session])io.gatling.core.structure.ScenarioBuilder
cannot be applied to (Unit)
.exec(
^

Unfortunately I can not go through compilation error which I mentioned above…

I am confused if I can get a normal expecting report of SSE load test with Gatling.

Honestly, your core issue is that you’re trying to use Gatling Scala and code things without any knowledge about the Scala syntax.

For almost 2 years, Gatling has had a Java API.
Nowadays, this Java API is the recommended one.
The Scala API should only be used by Scala developers. Gatling users shouldn’t have to first learn Scala in order to use Gatling.

cannot be applied to (Unit)

exec takes a parameter. You’re not passing any (Unit is similar to “nothing” in Scala).
You should be writing:

.exec(
    var acc: SseSetCheckBuilder = sse("SetCheck").setCheck
    for (_ <- 0 to 200) {
      acc = acc.await(60)(sseCheckPushmessages)
    }
    // in Scala, no need for "return",
    // the result of the last operation in a block is returned
   acc
)

There are many examples of load testing with Gatling in Scala, but not in Java. That’s why I selected Scala.
But there is no examples how to use SseSetCheckBuilder neither in Scala nor in Java.

I did not find any example for usage of SseSetCheckBuilder in Java/Scala (Gatling).

No examples of subject which I posted here. I am surprised that nobody met my problem before. Is someone tested SSE with Gatling or just high-level (connect - 1 check - close) ? =)

  1. When I use Scala-version
    sse_gatling/sse_sandbox_gatling.scala at main · yanawr/sse_gatling · GitHub
    Line 25: var acc: SseSetCheckBuilder = sse(“SetCheck”).setCheck
00:39:54.087 [ERROR] i.g.c.ZincCompiler$ - c:/Distrib/gatling-charts-highcharts-bundle-3.9.2/user-files/simulations/sandbox/sse_sandbox_gatling.scala:25:9: illegal start of simple expression
        var acc: SseSetCheckBuilder = sse("SetCheck").setCheck
  1. Then I use {} instead of suggested () for the block
.exec {
      var acc: SseSetCheckBuilder = sse("SetCheck").setCheck
      for (_ <- 0 to 200) {
        acc = acc.await(60)(sseCheckPushmessages)
      }
      acc
    }

and I get same error as in Java-version =)

10:14:09.857 [ERROR] i.g.c.ZincCompiler$ - c:/Distrib/gatling-charts-highcharts-bundle-3.9.2/user-files/simulations/sandbox/SseSandboxGatlingJ.java:27:1: cannot find symbol
  symbol:   variable setCheck
  location: class io.gatling.javaapi.http.Sse
  1. When I use Java-version, I get an error
    sse_gatling/SseSandboxGatlingJ.java at main · yanawr/sse_gatling · GitHub
> 00:27:01.892 [ERROR] i.g.c.ZincCompiler$ - c:/Distrib/gatling-charts-highcharts-bundle-3.9.2/user-files/simulations/sandbox/SseSandboxGatlingJ.java:27:1: cannot find symbol
  symbol:   variable setCheck
  location: class io.gatling.javaapi.http.Sse
sse("SetCheck").setCheck
00:27:01.979 [ERROR] i.g.c.ZincCompiler$ - c:/Distrib/gatling-charts-highcharts-bundle-3.9.2/user-files/simulations/sandbox/SseSandboxGatlingJ.java:35:1: cannot find symbol
  symbol:   method sseCheckPushmessages()
  location: class sandbox.SseSandboxGatlingJ
sseCheckPushmessages
00:27:01.989 [ERROR] i.g.c.ZincCompiler$ - c:/Distrib/gatling-charts-highcharts-bundle-3.9.2/user-files/simulations/sandbox/SseSandboxGatlingJ.java:35:1: no suitable method found for await(int) 
method io.gatling.http.action.sse.SseAwaitActionBuilder.await(scala.concurrent.duration.FiniteDuration,scala.collection.immutable.Seq<io.gatling.http.check.sse.SseMessageCheck>) is not applicable
>       (actual and formal argument lists differ in length)
>     method io.gatling.http.action.sse.SseAwaitActionBuilder.await(scala.Function1<io.gatling.core.session.Session,io.gatling.commons.validation.Validation<scala.concurrent.duration.FiniteDuration>>,scala.collection.immutable.Seq<io.gatling.http.check.sse.SseMessageCheck>) is not applicable
>       (actual and formal argument lists differ in length)
>     method io.gatling.http.action.sse.SseSetCheckBuilder.await(scala.concurrent.duration.FiniteDuration,scala.collection.immutable.Seq) is not applicable
>       (actual and formal argument lists differ in length)
>     method io.gatling.http.action.sse.SseSetCheckBuilder.await(scala.Function1,scala.collection.immutable.Seq) is not applicable
>       (actual and formal argument lists differ in length)

There are many examples of load testing with Gatling in Scala, but not in Java. That’s why I selected Scala.

There’s indeed lots of outdated third party blog posts about Gatling Scala.
All the official documentation and online courses are available in Java.
If you’re not already gone too far with Scala, I would really recommend switching to Java, things will probably get way clearer for you wrt custom code.

sse(“SetCheck”).setCheck

Indeed, this doesn’t compile in Java.
Please have a look at the documentation, you’ll see that you’re missing the parens :slight_smile:

I can not believe =) I commented lines with acc (SSECheckBuilder) in Java version.

And it finally WORKED!!! It is simpler as with Scala-version.

2023-04-03 12:37:43                                         211s elapsed
---- Requests ------------------------------------------------------------------
> Global                                                   (OK=137    KO=66    )
> 01_connect                                               (OK=1      KO=0     )
> checkCustom                                              (OK=1      KO=0     )
> checkPushmessages                                        (OK=134    KO=66    )
> 02_Close                                                 (OK=1      KO=0     )

Thank you for your support!

From my experience I used your documentation (quickstart, advanced, Academy, javadoc) and could not understand why I see only 1 check. Only with your support here I could find the solution. Now I see that Gatling can be applied for load testing of SSE!

Have a nice week!

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