-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add streams support in Generic Journey #279
Changes from 1 commit
b0fa39a
73a9ccc
2ea8728
96c0d6c
f7a534d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ import io.gatling.core.structure.{ | |
} | ||
import io.gatling.http.Predef._ | ||
import io.gatling.http.protocol.HttpProtocolBuilder | ||
import io.gatling.http.request.builder.HttpRequestBuilder | ||
import org.kibanaLoadTest.KibanaConfiguration | ||
import org.kibanaLoadTest.helpers.Helper | ||
import org.kibanaLoadTest.helpers.HttpHelper | ||
|
@@ -25,22 +26,40 @@ import scala.util.Using | |
|
||
object ApiCall { | ||
def execute( | ||
request: mapping.Request, | ||
requests: List[mapping.Request], | ||
config: KibanaConfiguration | ||
): ChainBuilder = { | ||
val defaultHeaders = request.headers.-( | ||
// Workaround for https://github.com/gatling/gatling/issues/3783 | ||
val httpParentRequest = httpRequest(requests(0).http, config) | ||
val children = requests.drop(1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: You can use |
||
if (children.isEmpty) { | ||
exec(httpParentRequest) | ||
} else { | ||
val childHttpRequests: Seq[HttpRequestBuilder] = | ||
(children.map(request => httpRequest(request.http, config))).toSeq | ||
exec(httpParentRequest.resources(childHttpRequests: _*)) | ||
} | ||
} | ||
|
||
def httpRequest( | ||
request: mapping.Http, | ||
config: KibanaConfiguration | ||
): HttpRequestBuilder = { | ||
val excludeHeaders = List( | ||
"Content-Length", | ||
"Kbn-Version", | ||
"Traceparent", | ||
"Authorization", | ||
"Cookie", | ||
"X-Kbn-Context" | ||
) | ||
val defaultHeaders = request.headers.--(excludeHeaders.iterator) | ||
|
||
val headers = | ||
if (request.headers.contains("Kbn-Version")) | ||
defaultHeaders + ("Kbn-Version" -> config.version) | ||
else defaultHeaders | ||
val httpRequestBuilder = request.method match { | ||
request.method match { | ||
case "GET" => | ||
http(requestName = s"${request.method} ${request.path}") | ||
.get(request.path) | ||
|
@@ -66,7 +85,6 @@ object ApiCall { | |
case _ => | ||
throw new IllegalArgumentException(s"Invalid method ${request.method}") | ||
} | ||
exec(httpRequestBuilder) | ||
} | ||
} | ||
|
||
|
@@ -87,20 +105,19 @@ class GenericJourney extends Simulation { | |
config: KibanaConfiguration | ||
): ChainBuilder = { | ||
var steps: ChainBuilder = exec() | ||
var priorRequest: Option[mapping.Request] = | ||
var priorStream: Option[mapping.RequestStream] = | ||
Option.empty | ||
for (trace <- journey.requests) { | ||
val request = trace.request | ||
val priorTimestamp = | ||
priorRequest.map(_.timestamp).getOrElse(request.timestamp) | ||
for (stream <- journey.streams) { | ||
val priorDate = | ||
priorStream.map(_.endTime).getOrElse(stream.endTime) | ||
val pauseDuration = | ||
Math.max(0L, request.timestamp.getTime - priorTimestamp.getTime) | ||
Math.max(0L, stream.startTime.getTime - priorDate.getTime) | ||
if (pauseDuration > 0L) { | ||
steps = steps.pause(pauseDuration.toString, TimeUnit.MILLISECONDS) | ||
} | ||
Comment on lines
114
to
118
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I hope that using previous stream end time (point in time when the last request was finished) and the next stream start time (point in time when the first request was started) difference is valid for pause between requests? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems reasonable to me. |
||
|
||
steps = steps.exec(ApiCall.execute(request, config)) | ||
priorRequest = Option(request) | ||
steps = steps.exec(ApiCall.execute(stream.requests, config)) | ||
priorStream = Option(stream) | ||
} | ||
steps | ||
} | ||
|
@@ -162,7 +179,11 @@ class GenericJourney extends Simulation { | |
private val httpProtocol: HttpProtocolBuilder = | ||
new HttpHelper(config).getProtocol | ||
.baseUrl(config.baseUrl) | ||
// Gatling automatically follow redirects in case of 301, 302, 303, 307 or 308 response status code | ||
// Disabling this behavior since we run the defined sequence of requests | ||
.disableFollowRedirect | ||
// Mimic real Chrome browser | ||
.maxConnectionsPerHostLikeChrome | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gatling should allow up to 6 connections per host name by default, but I thought it is better to use Chrome value for visibility. But it basically changes nothing https://github.com/gatling/gatling/blob/045603bc5c9d4466cb97d1e54902451f9b18dadd/gatling-http/src/main/scala/io/gatling/http/protocol/HttpProtocolBuilder.scala#L108 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good idea but I wonder whether we should use it as it's a deprecated property? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Funny I missed that comment. I will just remove it, let's use the default value |
||
private val steps = scenarioSteps(journey, config) | ||
private val warmupScenario = scenarioForStage( | ||
steps, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.kibanaLoadTest.simulation.generic.mapping | ||
|
||
import spray.json.DefaultJsonProtocol | ||
|
||
case class Http( | ||
path: String, | ||
headers: Map[String, String], | ||
method: String, | ||
body: Option[String], | ||
statusCode: Int | ||
) | ||
|
||
object HttpJsonProtocol extends DefaultJsonProtocol { | ||
implicit val httpFormat = jsonFormat5(Http) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.kibanaLoadTest.simulation.generic.mapping | ||
|
||
import spray.json.DefaultJsonProtocol | ||
import org.kibanaLoadTest.simulation.generic.mapping.RequestJsonProtocol._ | ||
import org.kibanaLoadTest.simulation.generic.mapping.DateJsonProtocol._ | ||
|
||
import java.util.Date | ||
|
||
case class RequestStream( | ||
startTime: Date, | ||
endTime: Date, | ||
requests: List[Request] | ||
) | ||
|
||
object RequestStreamJsonProtocol extends DefaultJsonProtocol { | ||
implicit val requestStreamFormat = jsonFormat3(RequestStream) | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using array indices we could also use
.head
and.tail
which would improve readability IMHO.