Configuring loops with an external parameter

Hi everyone,

I’m trying to build a configurable scenario. I want the tester to be able to configure the number of loops but at execution time I get this ouput:

[INFO] --- gatling-maven-plugin:2.1.6:execute (default-cli) @ hawkular-metrics-load-tests --- 10:43:15.156 [main][ERROR][ZincCompiler.scala:108] i.g.c.ZincCompiler$ - /home/tsegismont/Projets/hawkular-metrics/load-tests/src/test/scala/org/hawkular/metrics/loadtest/MetricsSimulation.scala:25: type mismatch; found : Integer required: io.gatling.core.session.Expression[Int] (which expands to) io.gatling.core.session.Session => io.gatling.core.validation.Validation[Int] 10:43:15.161 [main][ERROR][ZincCompiler.scala:108] i.g.c.ZincCompiler$ - val simulation = repeat(loops, "n") { 10:43:15.163 [main][ERROR][ZincCompiler.scala:108] i.g.c.ZincCompiler$ - ^ 10:43:15.530 [main][ERROR][ZincCompiler.scala:108] i.g.c.ZincCompiler$ - one error found

I’m sure it’s something stupid but I have zero Scala knowledge… :frowning:

Here’s my simulation file:

`
package org.hawkular.metrics.loadtest

import scala.concurrent.duration._

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._

class MetricsSimulation extends Simulation {

val baseURI = System.getProperty(“baseURI”, “http://localhost:8080”)

val clients = Integer.getInteger(“clients”, 1)
val ramp = java.lang.Long.getLong(“ramp”, 0L)

val loops = Integer.getInteger(“loops”, 1000)
val interval = Integer.getInteger(“interval”, 1)

val httpProtocol = http
.baseURL(baseURI)
.header(“Hawkular-Tenant”, “default”)
.contentTypeHeader(“application/json;charset=utf-8”)

val simulation = repeat(loops, “n”) {
exec(http(“Report ${n}”)
.post("/hawkular/metrics/gauges/data")
.body(ELFileBody(“body.json”)).asJSON
).pause(interval)
}

val scn = scenario(“MetricsSimulation”).exec(simulation)

setUp(scn.inject(rampUsers(clients) over (ramp seconds))).protocols(httpProtocol)
}
`

Thanks in advance for your help and the awesome tool!

Best regards,
Thomas

Can you please try to change
`
val loops = Integer.getInteger(“loops”, 1000)

`

to:

`
val loops = Integer.getInteger(“loops”, 1000).toInt

`

?

Cheers,

Pierre

Salut Thomas,

TL;DR:
Scala types are different from the Java ones.

val loops = Integer.getInteger(“loops”, 1000).toInt // Scala way

or
val loops = Integer.getInteger(“loops”, 1000).intValue // Java way

Long explanation:
An implicit conversion between Integer and Int can automatically happen but only if there’s only one implicit conversion involved.
And there’s already one because repeat actually takes a function (so there’s an implicit conversion from raw value to function).

Have fun!

It works. Awesome, thanks!

Long explanation:
An implicit conversion between Integer and Int can automatically happen but only if there’s only one implicit conversion involved.
And there’s already one because repeat actually takes a function (so there’s an implicit conversion from raw value to function).

Good to know, thanks. I guess that’s why other parameters don’t need conversion.

Have fun!

I’m already having some :slight_smile: Now I need to figure out how to build a JSON string with a configurable number of metrics data points. Once this is done I’ll be in the Nirvana :stuck_out_tongue:

Now I need to figure out how to build a JSON string with a configurable

number of metrics data points. Once this is done I'll be in the Nirvana :stuck_out_tongue:

Many different possibilities, depending on your use case and your Scala
skills :slight_smile:

If your template is "almost" static, ie number of metrics doesn't depend on
user but only on System props, you can easily write a Gatling EL String
template (see StringBody).

I wrote this:

`
package org.hawkular.metrics.loadtest

import scala.concurrent.duration._

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._

class MetricsSimulation extends Simulation {

val baseURI = System.getProperty(“baseURI”, “http://localhost:8080”)

val clients = Integer.getInteger(“clients”, 1)
val ramp = java.lang.Long.getLong(“ramp”, 0L)

val loops = Integer.getInteger(“loops”, 10).toInt
val interval = Integer.getInteger(“interval”, 1)

val metrics = Integer.getInteger(“metrics”, 10)
val points = Integer.getInteger(“points”, 1)

val httpProtocol = http
.baseURL(baseURI)
.header(“Hawkular-Tenant”, “default”)
.contentTypeHeader(“application/json;charset=utf-8”)

val random = new util.Random
val genReport = (m: Int, p: Int) => {
val builder = new StringBuilder
builder += ‘[’
for (i ← 1 to m) {
builder ++= “”"{“id”:“metrics.load.test.”""
builder.append(i)
builder ++= “”".value",“data”:["""
for (j ← 1 to p) {
builder ++= “”"{“timestamp”:"""
builder.append(System.currentTimeMillis)
builder ++= “”",“value”:"""
builder.append(random.nextDouble)
builder += ‘}’
if (j < p) builder += ‘,’
}
builder ++= “]}”
if (i < m) builder += ‘,’
}
builder += ‘]’
builder.toString
}
val feeder = Iterator.continually(Map(“jsonReport” → genReport(metrics, points)))

val simulation = repeat(loops, “n”) {
feed(feeder)
.exec(http(“Report ${n}”)
.post("/hawkular/metrics/gauges/data")
.body(StringBody("""${jsonReport}"""))
).pause(interval)
}

val scn = scenario(“MetricsSimulation”).exec(simulation)

setUp(scn.inject(rampUsers(clients) over (ramp seconds))).protocols(httpProtocol)
}

`

I’m sure it’s not idiomatic Scala but it seems to work as expected.

I'm sure it's not idiomatic Scala but it seems to work as expected.

Well, it's not because Gatling is written in Scala that we enforce any
coding style on you.
The most important is you feel confident in the way you write and can
maintain.

Then, if I may: there's no need to store the generated body in the Sessions
with a Feeder.
You can just simply call genReport from StringBody:

    val simulation = repeat(loops, "n") {
        exec(http("Report ${n}")
            .post("/hawkular/metrics/gauges/data")
            .body(StringBody(session => genReport(metrics, points)))
        ).pause(interval)
    }

Also, note that, instead of writing:
if (i < m) builder += ','

you can simply move the StringBuilder's index after the loop:
builder.setLength(builder.length - 1)

Cheers,

Stéphane

Thanks for the tips!

Yeah, you keep:

`
builder += ‘,’

`
without the “if”

But after the loop:

builder.setLength(builder.length - 1)

Auto facepalm :slight_smile:

Hi All,
I am stuck here.
I want that user can input ‘userCount, repeatCount, testServerUrl and definitionId’ from command line while executing from Gatling. From command line I execute
`

export JAVA_OPTS="-DuserCount=1 -DflowRepeatCount=1 -DdefinitionId=10220101 -DtestServerUrl=‘https://someurl.com’"
sudo bash gatling.sh`

but there is runtime error,
Errors ------------------------------