Log Replay, Simulation And Stress Testing With Gatling

A new addition to my DevOps toolbox – the amazing Gatling Open Source Stress Testing tool. The tool came with a very high recommendation and certainly exceeded my expectations.

My current project requires collection of HTTP logs, run a log replay against a new release of the App and finally generate report. The simulation report would qualify the App for release into production.

So began the search for Open Source utilities and frameworks that could do the job…

  1. HTTPerf: A very nifty and light tool for benchmarking from the command line. Reports are console based also. Not very useful for the job.
  2. HP Load Runner: A very popular but expensive commercial tool from HP which probably is an overkill for my needs
  3. Apache Jmeter: Skipped as am not a fan of XML
  4. Gatling: The last tool I checked, fantastic reports and easy to use configuration

After a quick look at the Gatling documentation and some minimal DSL changes I had my first simulation going.

  1. Based on the HTTP access logs, create a CSV file with the site URL, status code etc. See Gatling Feeders Wiki. There are quite a few Apache access log to CSV convertors out there. It is simple enough to write one on your own if the log format happens to be non-standard
  2. Create the Scala simulation definition that uses the CSV feed
    package foo
    
    import io.gatling.core.Predef._
    import io.gatling.http.Predef._
    import io.gatling.jdbc.Predef._
    import io.gatling.http.Headers.Names._
    import scala.concurrent.duration._
    import bootstrap._
    import assertions._
    
    class foo extends Simulation {
      // your code starts here
      val accessLog = csv("access_log.csv").queue
      val scn = scenario("${site}")
                .feed(accessLog)
                .exec(http("${site}")
                  .get("http://${site}${url}")
                  .check(status.is(200)))
      
      setUp(scn.inject(ramp(600 users) over (300 seconds)))
      // your code ends here
    }
    
  3. Ran the simulation for 600 seconds
  4. Enjoy the pretty reports
    Gatling Report Screenshot

Shanker Balan

Shanker Balan is a devops and infrastructure freelancer with over 14 years of industry experience in large scale Internet systems. He is available for both short term and long term projects on contract. Please use the Contact Form for any enquiry.

More Posts - Website

Follow Me:
TwitterLinkedIn

Published by

Shanker Balan

Shanker Balan is a devops and infrastructure freelancer with over 14 years of industry experience in large scale Internet systems. He is available for both short term and long term projects on contract. Please use the Contact Form for any enquiry.

3 thoughts on “Log Replay, Simulation And Stress Testing With Gatling”

  1. Hi,

    I am getting following error

    21:48:05.811 [ERROR] c.e.e.g.a.ZincCompiler$ – /home/leap/Downloads/gatling-charts-highcharts-1.5.3/user-files/simulations/test.scala:18: value inject is not a member of com.excilys.ebi.gatling.core.structure.ScenarioBuilder
    21:48:05.814 [ERROR] c.e.e.g.a.ZincCompiler$ – setUp(scn.inject(ramp(600 users) over (300 seconds)))
    21:48:05.816 [ERROR] c.e.e.g.a.ZincCompiler$ – ^
    21:48:05.853 [ERROR] c.e.e.g.a.ZincCompiler$ – one error found
    Exception in thread “main” Compilation failed
    at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:76)
    at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:35)
    at sbt.compiler.AnalyzingCompiler.compile(AnalyzingCompiler.scala:29)
    at sbt.compiler.AggressiveCompile$$anonfun$4$$anonfun$compileScala$1$1.apply$mcV$sp(AggressiveCompile.scala:71)
    at sbt.compiler.AggressiveCompile$$anonfun$4$$anonfun$compileScala$1$1.apply(AggressiveCompile.scala:71)
    at sbt.compiler.AggressiveCompile$$anonfun$4$$anonfun$compileScala$1$1.apply(AggressiveCompile.scala:71)
    at sbt.compiler.AggressiveCompile.sbt$compiler$AggressiveCompile$$timed(AggressiveCompile.scala:101)
    at sbt.compiler.AggressiveCompile$$anonfun$4.compileScala$1(AggressiveCompile.scala:70)
    at sbt.compiler.AggressiveCompile$$anonfun$4.apply(AggressiveCompile.scala:88)
    at sbt.compiler.AggressiveCompile$$anonfun$4.apply(AggressiveCompile.scala:60)
    at sbt.inc.IncrementalCompile$$anonfun$doCompile$1.apply(Compile.scala:24)
    at sbt.inc.IncrementalCompile$$anonfun$doCompile$1.apply(Compile.scala:22)
    at sbt.inc.Incremental$.cycle(Incremental.scala:52)
    at sbt.inc.Incremental$.compile(Incremental.scala:29)
    at sbt.inc.IncrementalCompile$.apply(Compile.scala:20)
    at sbt.compiler.AggressiveCompile.compile2(AggressiveCompile.scala:96)
    at sbt.compiler.AggressiveCompile.compile1(AggressiveCompile.scala:44)
    at com.typesafe.zinc.Compiler.compile(Compiler.scala:158)
    at com.typesafe.zinc.Compiler.compile(Compiler.scala:142)
    at com.excilys.ebi.gatling.app.ZincCompiler$.apply(ZincCompiler.scala:104)
    at com.excilys.ebi.gatling.app.SimulationClassLoader$.fromSourcesDirectory(SimulationClassLoader.scala:34)
    at com.excilys.ebi.gatling.app.Gatling$$anonfun$12.apply(Gatling.scala:89)
    at com.excilys.ebi.gatling.app.Gatling$$anonfun$12.apply(Gatling.scala:89)
    at scala.Option.getOrElse(Option.scala:108)
    at com.excilys.ebi.gatling.app.Gatling.start(Gatling.scala:89)
    at com.excilys.ebi.gatling.app.Gatling$.fromMap(Gatling.scala:54)
    at com.excilys.ebi.gatling.app.Gatling$.runGatling(Gatling.scala:74)
    at com.excilys.ebi.gatling.app.Gatling$.main(Gatling.scala:49)
    at com.excilys.ebi.gatling.app.Gatling.main(Gatling.scala)

  2. Hi,

    Iam getting following error

    Exception in thread “AWT-EventQueue-0” org.jboss.netty.channel.ChannelException:
    Failed to bind to: 0.0.0.0/0.0.0.0:8000
    at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:2
    72)
    at io.gatling.recorder.http.HttpProxy.(HttpProxy.scala:43)
    at io.gatling.recorder.controller.RecorderController.startRecording(Reco
    rderController.scala:79)
    at io.gatling.recorder.ui.RecorderFrontend.startRecording(RecorderFrontE
    nd.scala:69)
    at io.gatling.recorder.ui.swing.frame.ConfigurationFrame.io$gatling$reco
    rder$ui$swing$frame$ConfigurationFrame$$reloadConfigurationAndStart(Configuratio
    nFrame.scala:594)
    at io.gatling.recorder.ui.swing.frame.ConfigurationFrame$$anonfun$9.appl
    y$mcV$sp(ConfigurationFrame.scala:111)
    at scala.swing.Action$$anon$2.apply(Action.scala:60)
    at scala.swing.Action$$anon$1.actionPerformed(Action.scala:78)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Sour
    ce)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$300(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Sour
    ce)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Sour
    ce)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Sour
    ce)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    Caused by: java.net.BindException: Address already in use: bind
    at sun.nio.ch.Net.bind0(Native Method)
    at sun.nio.ch.Net.bind(Unknown Source)
    at sun.nio.ch.Net.bind(Unknown Source)
    at sun.nio.ch.ServerSocketChannelImpl.bind(Unknown Source)
    at sun.nio.ch.ServerSocketAdaptor.bind(Unknown Source)
    at org.jboss.netty.channel.socket.nio.NioServerBoss$RegisterTask.run(Nio
    ServerBoss.java:193)
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQue
    ue(AbstractNioSelector.java:391)
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNi
    oSelector.java:315)
    at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.ja
    va:42)
    at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnabl
    e.java:108)
    at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProof
    Worker.java:42)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Leave a Reply