-
-
Save infomaven/69132e142b369d8ebfd7 to your computer and use it in GitHub Desktop.
Contains boolean logic to determine which workload will be used . Optimized for Gatling 2.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.gatling.core.Predef._ | |
import io.gatling.http.Predef._ | |
import io.gatling.core.scenario._ | |
import io.gatling.core.structure.PopulatedScenarioBuilder | |
import scala.concurrent.duration._ | |
class Gatling_WorkloadPicker extends Simulation { | |
/* The API we are testing has 1 POST and 3 GET endpoints. In this example, we only are considering 3 types of workloads. | |
1. gets only | |
2. posts only | |
3. mixed workload | |
For simplicity, we are ignoring other http verbs, but they could easily be implemented the same way. | |
Our API endpoints are fed into Gatling from some external source (like a build server or external file). | |
- An endpoint having RPS >= 1 is intended to be used. | |
- RPS < 1 means the endpoint should be SUPPRESSED or SKIPPED | |
Our primary method of detecting this condition is to compare the RPS total for each type of request (write/read) to the total number of | |
endpoints that are cataloged at the global level. | |
For simplicity of testing and running this code example, values are hardcoded | |
Note: this file is set up to run as a stand-alone Simulation using a local installation of Gatling | |
*/ | |
// ------writes/POSTs | |
val writeRequests = List(9) // one POST endpoint configured @ 9 rps | |
//val writeRequests = List(0.1 ) // uncomment to make this code "skip" running POST calls | |
val writeCount = writeRequests.length // number of Post endpoints in the catalog (API) | |
val writeSum = writeRequests.sum // RPS sum for the cataloged Post endpoints | |
// -------reads/GETs | |
val readRequests = List( 5, 5, 10) // 3 GET endpoints configured @ 5, 5, 10 rps respectively | |
// val readRequests = List(0.1,0.1,0.1) // uncomment to make this code "skip" running GET calls | |
val readCount = readRequests.length // number of Get endpoints in the catalog (API) | |
val readSum = readRequests.sum // RPS sum for the cataloged Get endpoints | |
// Characterize the workload according to rps totals found in the Lists (for Get and Post endpoints) | |
// if neither one of these conditions is triggered, fall back to *mixed* workload | |
val readsOnly = writeSum < writeCount // extremely low sum for Writes means that this is a READ workload | |
val writesOnly = readSum < readCount // extremenly low sum for Reads means this is a WRITE workload | |
val httpConf = http | |
.baseURL("http://computer-database.herokuapp.com") // 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 | |
.doNotTrackHeader("1") | |
.acceptLanguageHeader("en-US,en;q=0.5") | |
.acceptEncodingHeader("gzip, deflate") | |
.userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0") | |
val headers_10 = Map("Content-Type" -> """application/x-www-form-urlencoded""") // Note the headers specific to a given request | |
//// basic READ request | |
// GET | |
object Scenario1 { | |
val scenario1 = exec( http("request_3") | |
.get("/computers/6")) | |
.pause(3) | |
.exec(http("request_4") | |
.get("/")) | |
.pause(2) | |
} | |
// GET | |
object Scenario3 { | |
val scenario3 = exec(http("request_6") | |
.get("/computers?p=2")) | |
.pause(629 milliseconds) | |
.exec(http("request_7") | |
.get("/computers?p=3")) | |
.pause(734 milliseconds) | |
} | |
//GET | |
object Scenario4 { | |
val scenario4 = exec(http("request_5") | |
.get("/computers?p=1")) | |
.pause(670 milliseconds) | |
.exec(http("request_8") | |
.get("/computers?p=4")) | |
.pause(5) | |
.exec(http("request_9") | |
.get("/computers/new")) | |
.pause(1) | |
} | |
///// WRITE requests | |
// POST | |
object Scenario2 { | |
val scenario2 = exec(http("request_10") | |
.post("/computers") | |
.headers(headers_10) | |
.formParam("""name""", """Beautiful Computer""") | |
.formParam("""introduced""", """2012-05-30""") | |
.formParam("""discontinued""", """""") | |
.formParam("""company""", """37""")) | |
} | |
///// create load injection profiles | |
val scnWriteWL = scenario( "Writes") | |
.exec( Scenario2.scenario2 ) | |
.inject( atOnceUsers(writeSum)) | |
val scnReadWL = scenario("Reads") | |
.exec( Scenario1.scenario1, Scenario3.scenario3, Scenario4.scenario4 ) | |
.inject( atOnceUsers(readSum)) | |
//// fallthrough condition | |
val scnMixedWL = scenario( "loadMIXED") | |
.exec( Scenario1.scenario1, Scenario2.scenario2, Scenario3.scenario3, Scenario4.scenario4 ) | |
.inject( atOnceUsers( readSum + writeSum )) | |
/** | |
Sets workload composition according to workload characterization. | |
Receives multiple flag inputs (true/false) and deterines final workload based on the values it receives. | |
**/ | |
val workload = (readsOnly, writesOnly ) match { | |
case (true, false) => scnReadWL.protocols( httpConf ) | |
case( false, true) => scnWriteWL.protocols( httpConf ) | |
case( _) => scnMixedWL.protocols( httpConf ) | |
} | |
setUp( | |
workload | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package buffer.example | |
import scala.collection.mutable.ListBuffer | |
/** | |
* Created by nadine on 7/28/15. | |
* This program cotnains supporting objects to encapsulate common settings needed for REST endpoints. | |
No services are actually called. | |
* To run this program in REPL, copy and paste the entire thing at scala prompt. | |
* Then type: BufferExample.main(null) | |
* Purpose: build a dynamic list of Endpoint objects that can be used as injection steps for a Simulation | |
*/ | |
object BufferExample extends App { | |
case class Endpoint( name: String, rps: Double ) | |
def getSubList( nameList: List[String], criteria: String ): List[String] = { | |
// create new ListBuffer | |
val nameBuffer: ListBuffer[String] = ListBuffer[String]() | |
// add elements to ListBuffer that meet the criteria | |
nameList.foreach( name => | |
if( name.contains( criteria )) { | |
nameBuffer += name | |
}); | |
nameBuffer.toList | |
} | |
//// todo: fix evaluation of Tuple._2 value to work with decimals (it currently only works with Int) | |
def convertListToEndpoints( nameList: List[ (String, Double ) ], criteria: String): List[Endpoint] = { | |
// create new ListBuffer | |
val endpointBuffer: ListBuffer[Endpoint] = ListBuffer[Endpoint]() | |
// add elements to ListBuffer that meet the criteria | |
nameList.foreach( entry => | |
if( entry._1.contains( criteria ) && (entry._2 >= 1) ) { | |
val endpoint = Endpoint( entry._1, entry._2 ) | |
endpointBuffer += endpoint | |
}) | |
endpointBuffer.toList | |
} | |
override def main( args: Array[String]) { | |
val exampleList = List("peakRPSGet1", "peakRPSPost2", "peakRPSPut3", "peakRPSGet4", "peakRPSGet5", "peakRPSDelete6", "peakRPSPost7", "peakRPSPost8", "peakRPSPost9", "peakRPSGet10") | |
val reads = getSubList(exampleList, "Get") | |
println("Reads: " + reads) | |
val posts = getSubList(exampleList, "Post") | |
val puts = getSubList(exampleList, "Put") | |
val deletes = getSubList(exampleList, "Delete") | |
val writes = List(posts, puts, deletes) | |
println("Writes: " + writes) | |
///---------- | |
val list2 = List( ("peakRPSGet1", 0.1 ), ("peakRPSPost2", 0.1), ("peakRPSPut3", 0.1), ("peakRPSGet4", 0.1), ("peakRPSGet5", 0.1), ("peakRPSDelete6", 1.0), ("peakRPSPost7", 5.6), ("peakRPSPost8", 0.1)) | |
// list2 | |
val get = convertListToEndpoints( list2, "Get") | |
val post = convertListToEndpoints( list2, "Post") | |
val put = convertListToEndpoints( list2, "Put") | |
val delete = convertListToEndpoints( list2, "Delete") | |
val mutate = List(post , put , delete) | |
println( "ReadEndpoints: " + get ) | |
println("WriteEndpoints: " + mutate ) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Another pass at load selection. This time instead of boolean values, we're using in Integer (like someting selected from a menu) | |
*/ | |
// create injection profiles | |
val scnTwoProfiles = scenario( "push") | |
.exec( Scenario2.scenario2 ).inject( rampUsersPerSec(10) to 20 during(5 seconds) , constantUsersPerSec(20) during (20 seconds)) | |
// .exec( Scenario1.scenario1).inject( atOnceUsers(1)) | |
val scnListOfFour = scenario("store") | |
.exec( Scenario1.scenario1, Scenario3.scenario3, Scenario4.scenario4 ) | |
//.inject( atOnceUsers(3)) | |
.inject( rampUsersPerSec(10) to 20 during(5 seconds) , constantUsersPerSec(20) during (20 seconds)) | |
val scnMixedWL = scenario( "email") | |
.exec( Scenario1.scenario1 ) | |
// .inject( atOnceUsers(5)) | |
.inject( rampUsersPerSec(10) to 20 during(5 seconds) , constantUsersPerSec(20) during (20 seconds)) | |
val menuId = 5 | |
val workload = (menuId ) match { | |
case (1) => scnTwoProfiles.protocols( httpConf ) | |
case( 2) => scnListOfFour.protocols( httpConf ) | |
case( _) => scnMixedWL.protocols( httpConf ) | |
} | |
setUp( | |
workload | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If using this in Gatling 2.2, be alert for class name changes.