diff --git a/locust/example.py b/locust/example.py index 80af5f4f90..8adad2cc76 100644 --- a/locust/example.py +++ b/locust/example.py @@ -7,6 +7,9 @@ def login(l): def index(l): l.client.get("/") +def stats(l): + l.client.get("/stats/requests") + @require_once(login) def profile(l): l.client.get("/profile") @@ -14,6 +17,6 @@ def profile(l): class WebsiteUser(Locust): host = "http://127.0.0.1:8089" #tasks = [(index, 2), (profile, 1)] - tasks = [index] + tasks = [index, stats] min_wait=2000 max_wait=5000 diff --git a/locust/stats.py b/locust/stats.py index 7f0c463314..8ec7fc35ac 100644 --- a/locust/stats.py +++ b/locust/stats.py @@ -115,18 +115,7 @@ def median_response_time(self): if not self.response_times: return 0 - def median(total, count): - """ - total is the number of requests made - count is a dict {response_time: count} - """ - pos = (total - 1) / 2 - for k in sorted(count.iterkeys()): - if pos < count[k]: - return k - pos -= count[k] - - return median(self.num_reqs, self.response_times) + return median_from_dict(self.num_reqs, self.response_times) @property def current_rps(self): @@ -250,6 +239,17 @@ def sum_stats(cls, name="Total", full_request_history=False): def avg(values): return sum(values, 0.0) / max(len(values), 1) +def median_from_dict(total, count): + """ + total is the number of requests made + count is a dict {response_time: count} + """ + pos = (total - 1) / 2 + for k in sorted(count.iterkeys()): + if pos < count[k]: + return k + pos -= count[k] + # TODO Use interpolation or not? def percentile(N, percent, key=lambda x:x): """ diff --git a/locust/web.py b/locust/web.py index 41c12bce73..d5e163e48d 100644 --- a/locust/web.py +++ b/locust/web.py @@ -4,11 +4,12 @@ import os.path from time import time from itertools import chain +from collections import defaultdict from gevent import wsgi from flask import Flask, make_response, request, render_template -from locust.stats import RequestStats +from locust.stats import RequestStats, median_from_dict from locust import version DEFAULT_CACHE_TIME = 2.0 @@ -128,6 +129,7 @@ def request_stats(): if not _request_stats_context_cache or _request_stats_context_cache["last_time"] < time() - _request_stats_context_cache.get("cache_time", DEFAULT_CACHE_TIME): cache_time = _request_stats_context_cache.get("cache_time", DEFAULT_CACHE_TIME) now = time() + stats = [] for s in chain(_sort_stats(locust_runner.request_stats), [RequestStats.sum_stats("Total")]): stats.append({ @@ -152,6 +154,17 @@ def request_stats(): report["fail_ratio"] = 100 else: report["fail_ratio"] = 0 + + # since generating a total response times dict with all response times from all + # urls is slow, we make a new total response time dict which will consist of one + # entry per url with the median response time as key and the numbe fo requests as + # value + response_times = defaultdict(int) # used for calculating total median + for i in xrange(len(stats)-1): + response_times[stats[i]["median_response_time"]] += stats[i]["num_reqs"] + + # calculate total median + stats[len(stats)-1]["median_response_time"] = median_from_dict(stats[len(stats)-1]["num_reqs"], response_times) is_distributed = isinstance(locust_runner, MasterLocustRunner) if is_distributed: