Gatling Performance - flushHttpCache - scala

New to Gatling and trying to understand how to get "exec(flushHttpCache)" incorporated into my script as I am trying to stop redirects from occurring as these will skew my results.
I have:
val getStartPage = feed(feeder).exec(http("Test start page (start-page)")
.exec(flushHttpCache) // <- this fails on compile "flushHttpCache is not a member of io.gatling.http.request.builder.Http"
.get("/start-page?id=${userId}")
.check(status.is(200))
.check(regex("Start now").exists))
.pause(longPause)
then:
class myPerformanceTest extends Simulation with HttpConfiguration
{
val happyPath = scenario("testUsers")
.exec(getStartPage)
setUp(
happyPath.inject(atOnceUsers(1))
).protocols(httpconf)
}
I tried moving ".exec(flushHttpCache)" to: val happyPath = scenario("testUsers").exec(flushHttpCache) still no luck.
How do I incorporate the "flushHttpCache" into a script?
Any help appreciated

You should import
import io.gatling.http.Predef._
not
import io.gatling.http.request.builder.Http
The second part of question will work as you tried, with this import.

Related

Celery Add new tasks dinamically

Is it possible to schedule a task in celery from another task?
I've got this Python script:
import logging
from celery import Celery
from datetime import datetime
logger = logging.getLogger(__name__)
app = Celery('app', backend='amqp://', broker='pyamqp://guest#localhost:5672//')
#app.task()
def add(x, y):
result = x + y
logger.info(f'Add: {x} + {y} = {result}')
return result
#app.task()
def setPeriodicTask():
#option 1
app.add_periodic_task(10, add.s(30, 1))
#option 2
app.conf.beat_schedule = {
'add-every-5-seconds': {
'task': 'app.add',
'schedule': 5.0,
'args': (now.hour, now.second)
}
}
logger.info(f'setPeriodicTask succeeded')
return 1
When I call the add task, it works OK.
If I call the setPeriodicTask task it does not throw any error but the add task is not scheduled.
I've tried both options, none is working:
add_periodic_task
modify the beat_schedule
If I add this code to my Python script (as I've seen in the celery docs):
#app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
sender.add_periodic_task(5.0, add.s(10, 1))
I can see the add task running scheduled as expected. So celery and celery beat seem to be working fine.
But I want to enable/disable the task on demand.
Is it possible? And if so, what am I doing wrong?
In case someone else faces this issue.
I ended up using a database with a similar approach as the one mention in the django -celery-beat doc: django-celery-beat - Database-backed Periodic Tasks
Slightly off topic question here but I'm looking to mock the calls to the sender.add_periodic_task(5.0, add.s(10, 1)) and I can not find anything that would tell me where it is
I'm using #mock.patch("celery.add_periodic_task")
any ideas would be welcome
import pytest
from ddt import ddt, data, unpack
from unittest import mock
from django.test import TestCase
from myapp.celery import setup_periodic_tasks
class CeleryTasksTest(TestCase):
#mock.patch("celery.add_periodic_task")
#mock.patch("os.environ.get")
#data(
{"env_to_test":"local", "number_of_tasks":0},
{"env_to_test":"TEST", "number_of_tasks":0},
{"env_to_test":"STAGING", "number_of_tasks":5},
{"env_to_test":"LIVE", "number_of_tasks":1},
)
#unpack
def test_setup_periodic_tasks_per_environment(self, mock_os_environ_get, mock_add_periodic_task, env_to_test, number_of_tasks):
setup_periodic_tasks([])
mock_os_environ_get.return_value=env_to_test
self.assertEqual(mock_add_periodic_task.call_count, number_of_tasks)

Gatling - exit Iteration on error and start new iteration and logging

In gatling,I want to exit the interation on failure and start a new iteration. I have used exitHereIfFailed but see that it completely stops the scenario. althought my scenario is configured to run for 30 minutes. Please advice if I have got this right.
Also how do I handle the errors in Gatling, and print to a file with relavent details. In my example below on check failure, I want to exit the iteration and write the details to a file will details like username, timestamp etc.. Kindly help.
import scala.concurrent.duration._
import io.gatling.core.Predef.{exec, _}
import io.gatling.http.Predef.{http, _}
import io.gatling.jdbc.Predef._
import scala.language.postfixOps
object Login {
val login = group("ABC_Login") {
feed(userFeeder)
.exec(http("Login")
.post(uri16 + "/login")
.formParam("username", "${username}")
.formParam("password", "${password}")
.formParam("login", "Login")
.check(substring("Welcome to ABC Professionalllll")))
.exitHereIfFailed
}
//scenario definition and injection setup
val BP01AddSearch = scenario("BP01Search").during(30 minutes)
{
pace(50 seconds)
.exec(Homepage.homepage, Login.login, SearchLink.search, Logout.logout)
}
setUp(BP01AddSearch.inject(atOnceUsers(1)).protocols(httpProtocol) )
Use tryMax, see https://gatling.io/docs/gatling/reference/current/general/scenario/#trymax
during(30 minutes) {
tryMax(5) {
pace(50 seconds)
.exec(Homepage.homepage, Login.login, SearchLink.search, Logout.logout)
}
}

I can't get a value from one of two feeders

I have two feeders in my test scenario
When i use one of them in first request it works alright, however when I use it in the next request block it doesn't work
I have tried changing the feed(feederName) position but still having the same problem
Here is a snippet of my test scenario with some comment to explain what's not working
//the Two feeders
val kmPerYearFeeder = Iterator.continually(
Map("kmPerYear" -> Random.shuffle(List("10000", "15000", "20000", "25000", "30000", "35000", "40000", "45000", "50000")).head)
)
val customerTypes = Iterator.continually(
Map("customerType" -> Random.shuffle(List("P","B")).head)
)
//here the customerTypes feeder is working
val homepage = feed(customerTypes)
.exec(http("homepage")
.get("/?customer_type=${customerType}"))
//this block is not really important but working alright
val pdp = exec(http("homepage")
....
// the feeder here doesn't work
val calculate_rate = feed(kmPerYearFeeder)
.exec(http("calculate_random_rate")
.get(session => session("random_pdp_link").as[String] + "?inquiry_type=&km_per_year=${kmPerYear}")
.check(status.is(200)))
val pdp_scenario = scenario("PDP").exec(homepage).exec(pdp).exec(calculate_rate)
setUp(
pdp_scenario.inject(
rampUsers(10) during (5 seconds),
).protocols(httpProtocol),
)
these are the get requests that are executed (got them from the logger)
GET ********?inquiry_type=&km_per_year=$%7BkmPerYear%7D
GET ********?inquiry_type=&km_per_year=$%7BkmPerYear%7D
GET ********?inquiry_type=&km_per_year=$%7BkmPerYear%7D
Your issue is that in where you attempt to use the Gatling EL to reference the kmPerYear session var in
.get(session => session("random_pdp_link").as[String] + "?inquiry_type=&km_per_year=${kmPerYear}")
this version of .get takes a session function (which you are using to get "random_pdp_link"), but the Gatling EL doesn't work in session functions.
You either need to get it manually using
session("kmPerYear").as[String]
or to reference "random_pdp_link" via the EL and not use the session function get. eg:
.get("${random_pdp_link}?inquiry_type=&km_per_year=${kmPerYear}")

Push message to websocket client without a request

I am making a Play web-socket app. When a client connects, I want to send a welcome message.
The code I use is below:
package controllers
import play.api._
import play.api.mvc._
import play.api.libs.iteratee.Concurrent
import play.api.libs.iteratee.Iteratee
import play.api.libs.concurrent.Execution.Implicits.defaultContext
object Test extends Controller {
def index = WebSocket.using[String] { _ =>
val (out,channel) = Concurrent.broadcast[String]
channel.push("Welcome to MyWebSocket")
val in = Iteratee.foreach[String] {
_ match {
case any => channel.push(any)
}
}
(in, out)
}
}
The code works fine when a client sends a message and the server has to respond to it. However, the initial welcome message Welcome to MyWebSocket is not sent. How can I fix this code?
[EDIT]
I kind of figured out the problem, but not a solution yet. The problem probably occurs because the websocket is not yet initialized when the welcome message is being pushed. I modified the code and replaced:
channel.push("Welcome to MyWebSocket")
with
val a = scala.concurrent.Future {
Thread.sleep(1000)
channel.push("Welcome to MyWebSocket")
}
After this I get the expected results (welcome message received by client). I think using the above approach (Thread.sleep and Future) is not the right way to solve this problem, so other solutions are welcome. It could also be a problem with the client side code which takes a while to initialize the socket. I used Firefox and echo web-socket test for the client.
You can use WebSocket.acceptWithActor helper method (have a look at this) and in actor body make something like
out ! "Welcome to MyWebSocket"
It works nicely.

Is there a way to prevent Play from auto-reloading?

While working on some projects, I would sometimes prefer to disable by the auto-reloading feature of Play (and only reload manually).
Is there a way to quickly achieve this? (Other than typing start at the play prompt, which adds some overhead as it packages the app.)
Create a new Scala app that will start the Play app:
import play.api.{Application, ApplicationLoader, Environment, Mode, Play}
import play.core.server.{ServerConfig, ServerProvider}
object MyPlayApp extends App {
val config = ServerConfig(mode = Mode.Dev)
val application: Application = {
val environment = Environment(config.rootDir, this.getClass.getClassLoader, Mode.Dev)
val context = ApplicationLoader.createContext(environment)
val loader = ApplicationLoader(context)
loader.load(context)
}
Play.start(application)
val serverProvider: ServerProvider = ServerProvider.fromConfiguration(this.getClass.getClassLoader, config.configuration)
serverProvider.createServer(config, application)
}
Then run it: sbt "runMain MyPlayApp"