Repository: locustio/locust
File: locust/stats.py (Python)

Code before:
            num_requests=self.num_requests,
        )

        # We'll use a cache size of CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + 10 since - in the extreme case -
        # we might still use response times (from the cache) for t-CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW-10
        # to calculate the current response time percentile, if we're missing cached values for the subsequent
        # 20 seconds
        cache_size = CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + 10

        if len(self.response_times_cache) > cache_size:
            # only keep the latest 20 response_times dicts
            for _ in range(len(self.response_times_cache) - cache_size):
                self.response_times_cache.popitem(last=False)

    def to_dict(self, escape_string_values=False):
        response_time_percentiles = {
            f"response_time_percentile_{percentile}": self.get_response_time_percentile(percentile)
            for percentile in PERCENTILES_TO_STATISTICS
        }

        return {
            "method": escape(self.method or "") if escape_string_values else self.method,
            "name": escape(self.name) if escape_string_values else self.name,
            "safe_name": escape(self.name, quote=False),
            "num_requests": self.num_requests,
            "num_failures": self.num_failures,
            "avg_response_time": self.avg_response_time,
            "min_response_time": 0 if self.min_response_time is None else proper_round(self.min_response_time),
            "max_response_time": proper_round(self.max_response_time),
            "current_rps": self.current_rps,
            "current_fail_per_sec": self.current_fail_per_sec,
            **response_time_percentiles,
            "avg_content_length": self.avg_content_length,
        }


class StatsError:
    def __init__(self, method: str, name: str, error: Exception | str | None, occurrences: int = 0):
        self.method = method
        self.name = name
        self.error = error
        self.occurrences = occurrences

    @classmethod
    def parse_error(cls, error: Exception | str | None) -> str:
        string_error = repr(error)
        target = "object at 0x"
        target_index = string_error.find(target)
        if target_index < 0:
            return string_error
        start = target_index + len(target) - 2

Review comment (suggestion):
Maybe we should keep median response time? As the code is right now, users don't have any way of adding this statistic if they want to see it (not sure if @cyberw agrees as he said we may want to remove it)

Code after:

        # We'll use a cache size of CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + 10 since - in the extreme case -
        # we might still use response times (from the cache) for t-CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW-10
        # to calculate the current response time percentile, if we're missing cached values for the subsequent
        # 20 seconds
        cache_size = CURRENT_RESPONSE_TIME_PERCENTILE_WINDOW + 10

        if len(self.response_times_cache) > cache_size:
            # only keep the latest 20 response_times dicts
            for _ in range(len(self.response_times_cache) - cache_size):
                self.response_times_cache.popitem(last=False)

    def to_dict(self, escape_string_values=False):
        response_time_percentiles = {
            f"response_time_percentile_{percentile}": self.get_response_time_percentile(percentile)
            for percentile in PERCENTILES_TO_STATISTICS
        }

        return {
            "method": escape(self.method or "") if escape_string_values else self.method,
            "name": escape(self.name) if escape_string_values else self.name,
            "safe_name": escape(self.name, quote=False),
            "num_requests": self.num_requests,
            "num_failures": self.num_failures,
            "avg_response_time": self.avg_response_time,
            "min_response_time": 0 if self.min_response_time is None else proper_round(self.min_response_time),
            "max_response_time": proper_round(self.max_response_time),
            "current_rps": self.current_rps,
            "current_fail_per_sec": self.current_fail_per_sec,
            "median_response_time": self.median_response_time,
            "ninetieth_response_time": self.get_response_time_percentile(0.9),  # for legacy ui
            "ninety_ninth_response_time": self.get_response_time_percentile(0.99),  # for legacy ui
            **response_time_percentiles,  # for modern ui
            "avg_content_length": self.avg_content_length,
        }


class StatsError:
    def __init__(self, method: str, name: str, error: Exception | str | None, occurrences: int = 0):
        self.method = method
        self.name = name
        self.error = error
        self.occurrences = occurrences

    @classmethod
    def parse_error(cls, error: Exception | str | None) -> str:
        string_error = repr(error)
        target = "object at 0x"
        target_index = string_error.find(target)
        if target_index < 0:
            return string_error