from typing import Sequence from .math_round_div import round_div from .monitor_status_code_summary_types import StatusCodeSummary def summarise_status_codes(statuses: Sequence[int]) -> StatusCodeSummary: """HTTP status codes counted by class, with the server error rate (5xx) and the client error rate (4xx) kept apart: only 5xx is the server's failure.""" counts = [0, 0, 0, 0, 0] for s in statuses: if not isinstance(s, int) or isinstance(s, bool): raise ValueError("status code must be a whole number") if s < 100 or s > 599: raise ValueError("status code must be 100 to 599, received %d" % s) counts[s // 100 - 1] += 1 total = len(statuses) def rate(n: int) -> int: return 0 if total == 0 else round_div(n * 10000, total, "half-up") return StatusCodeSummary( total=total, informational=counts[0], success=counts[1], redirect=counts[2], client_error=counts[3], server_error=counts[4], error_rate_basis_points=rate(counts[4]), client_error_rate_basis_points=rate(counts[3]), )