I see this on every locust worker running 1.2:
$ locust --worker --locustfile=main.py
[2020-08-20 11:02:50,637] C02TD0F6GTDX/INFO/locust.main: Starting Locust 1.2
Traceback (most recent call last):
File "src/gevent/greenlet.py", line 854, in gevent._gevent_cgreenlet.Greenlet.run
File "/usr/local/lib/python3.8/site-packages/locust/stats.py", line 766, in stats_history
'response_time_percentile_95': stats.total.get_current_response_time_percentile(0.95) or 0,
File "/usr/local/lib/python3.8/site-packages/locust/stats.py", line 553, in get_current_response_time_percentile
raise ValueError("StatsEntry.use_response_times_cache must be set to True if we should be able to calculate the _current_ response time percentile")
ValueError: StatsEntry.use_response_times_cache must be set to True if we should be able to calculate the _current_ response time percentile
2020-08-20T09:02:50Z <Greenlet at 0x10803f6a0: stats_history(<locust.runners.WorkerRunner object at 0x10806da60)> failed with ValueError
Tried with very basic locust file, same issue:
from locust import HttpUser, TaskSet, task, between
class LoadTestTask(TaskSet):
def on_start(self):
pass
@task(3)
def get_token(self):
pass
class LoadTest(HttpUser):
tasks = [LoadTestTask]
wait_time = between(0.1, 1)
Any idea @cyberw or @vstepanov-lohika-tix?
This line of code was added in #1516. @taojy123 , any ideas?
Let me see.
I am trying to reproduce the problem first.
Sorry! In my development, I did not consider that the use_response_times_cache parameter of worker mode is False.
Solution to fix it:
Add two lines in stats_history function of locust/stats.py:
def stats_history(runner):
"""Save current stats info to history for charts of report."""
while True:
stats = runner.stats
if not stats.total.use_response_times_cache: # *** add this
break # *** add this
r = {
'time': datetime.datetime.now().strftime("%H:%M:%S"),
'current_rps': stats.total.current_rps or 0,
'current_fail_per_sec': stats.total.current_fail_per_sec or 0,
'response_time_percentile_95': stats.total.get_current_response_time_percentile(0.95) or 0,
'response_time_percentile_50': stats.total.get_current_response_time_percentile(0.5) or 0,
'user_count': runner.user_count or 0,
}
stats.history.append(r)
gevent.sleep(HISTORY_STATS_INTERVAL_SEC)
Should I make a new PR? @cyberw
Should I make a new PR?
Yes 🙂
I made a PR myself :)
Because this was in a release I made an emergency fix in my own PR & new release (1.2.1, on its way out now). @taojy123 , can you make a test case that excercises this scenario?
ok
I made the test case in https://github.com/taojy123/locust/commit/2cd724c97b099a4c4a7158b0ae16d4cf04e57d58
The code like this:
def test_stats_history(self):
env1 = Environment(events=locust.events, catch_exceptions=False)
runner1 = env1.create_master_runner("127.0.0.1", 5558)
env2 = Environment(events=locust.events, catch_exceptions=False)
runner2 = env2.create_worker_runner("127.0.0.1", 5558)
greenlet1 = gevent.spawn(stats_history, runner1)
greenlet2 = gevent.spawn(stats_history, runner2)
gevent.sleep(1)
hs1 = runner1.stats.history
hs2 = runner2.stats.history
gevent.kill(greenlet1)
gevent.kill(greenlet2)
self.assertEqual(1, len(hs1))
self.assertEqual(0, len(hs2))
Nice! Can you make a PR?
ok, I just woke up,I'll make a PR later.
@cyberw Hi~ I made the PR, see https://github.com/locustio/locust/pull/1538