locust 2.43.5.dev10__tar.gz → 2.43.5.dev19__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/PKG-INFO +1 -1
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/_version.py +2 -2
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/fasthttp.py +4 -1
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/stats.py +41 -3
- locust-2.43.5.dev10/locust/webui/dist/assets/src-DAUMGNLx.js → locust-2.43.5.dev19/locust/webui/dist/assets/src-lBIzfjkZ.js +24 -24
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/auth.html +1 -1
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/index.html +1 -1
- locust-2.43.5.dev19/locust/webui/dist/report.html +124 -0
- locust-2.43.5.dev10/locust/webui/dist/report.html +0 -124
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/.gitignore +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/LICENSE +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/README.md +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/hatch_build.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/__init__.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/__main__.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/argument_parser.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/clients.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/__init__.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/dns.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/milvus.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/mongodb.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/mqtt.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/oai.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/postgres.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/qdrant.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/contrib/socketio.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/debug.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/dispatch.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/env.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/event.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/exception.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/html.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/input_events.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/log.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/main.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/opentelemetry.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/py.typed +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/rpc/__init__.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/rpc/protocol.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/rpc/zmqrpc.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/runners.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/shape.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/user/__init__.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/user/inspectuser.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/user/markov_taskset.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/user/sequential_taskset.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/user/task.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/user/users.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/user/wait_time.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/__init__.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/cache.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/date.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/deprecation.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/directory.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/exception_handler.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/load_locustfile.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/rounding.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/timespan.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/util/url.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/web.py +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/assets/favicon-dark.png +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/assets/favicon-light.png +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/assets/graphs-dark.png +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/assets/graphs-light.png +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/assets/terminal.gif +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/assets/testruns-dark.png +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/locust/webui/dist/assets/testruns-light.png +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/pyproject.toml +0 -0
- {locust-2.43.5.dev10 → locust-2.43.5.dev19}/pytest_locust/plugin.py +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.43.5.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 43, 5, '
|
|
21
|
+
__version__ = version = '2.43.5.dev19'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 43, 5, 'dev19')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -10,6 +10,7 @@ import re
|
|
|
10
10
|
import socket
|
|
11
11
|
import time
|
|
12
12
|
import traceback
|
|
13
|
+
import zlib
|
|
13
14
|
from base64 import b64encode
|
|
14
15
|
from contextlib import contextmanager
|
|
15
16
|
from http.cookiejar import CookieJar
|
|
@@ -84,6 +85,7 @@ FAILURE_EXCEPTIONS = (
|
|
|
84
85
|
SSLError,
|
|
85
86
|
Timeout,
|
|
86
87
|
HTTPConnectionClosed,
|
|
88
|
+
zlib.error,
|
|
87
89
|
)
|
|
88
90
|
|
|
89
91
|
|
|
@@ -254,7 +256,7 @@ class FastHttpSession:
|
|
|
254
256
|
|
|
255
257
|
if not allow_redirects:
|
|
256
258
|
old_redirect_response_codes = self.client.redirect_resonse_codes
|
|
257
|
-
self.client.redirect_resonse_codes =
|
|
259
|
+
self.client.redirect_resonse_codes = frozenset()
|
|
258
260
|
|
|
259
261
|
start_perf_counter = time.perf_counter()
|
|
260
262
|
# send request, and catch any exceptions
|
|
@@ -672,6 +674,7 @@ class LocustUserAgent(UserAgent):
|
|
|
672
674
|
response_type = FastResponse
|
|
673
675
|
request_type = FastRequest
|
|
674
676
|
valid_response_codes = frozenset([200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 301, 302, 303, 304, 307, 308])
|
|
677
|
+
redirect_resonse_codes = frozenset([301, 302, 303, 307, 308])
|
|
675
678
|
|
|
676
679
|
def __init__(self, client_pool: HTTPClientPool | None = None, **kwargs):
|
|
677
680
|
super().__init__(**kwargs)
|
|
@@ -69,6 +69,8 @@ class StatsEntryDict(StatsBaseDict):
|
|
|
69
69
|
class StatsErrorDict(StatsBaseDict):
|
|
70
70
|
error: str
|
|
71
71
|
occurrences: int
|
|
72
|
+
first_seen: float | None
|
|
73
|
+
last_seen: float | None
|
|
72
74
|
|
|
73
75
|
|
|
74
76
|
class StatsHolder(Protocol):
|
|
@@ -705,11 +707,21 @@ class StatsEntry:
|
|
|
705
707
|
|
|
706
708
|
|
|
707
709
|
class StatsError:
|
|
708
|
-
def __init__(
|
|
710
|
+
def __init__(
|
|
711
|
+
self,
|
|
712
|
+
method: str,
|
|
713
|
+
name: str,
|
|
714
|
+
error: Exception | str | None,
|
|
715
|
+
occurrences: int = 0,
|
|
716
|
+
first_seen: float | None = None,
|
|
717
|
+
last_seen: float | None = None,
|
|
718
|
+
):
|
|
709
719
|
self.method = method
|
|
710
720
|
self.name = name
|
|
711
721
|
self.error = error
|
|
712
722
|
self.occurrences = occurrences
|
|
723
|
+
self.first_seen = first_seen
|
|
724
|
+
self.last_seen = last_seen
|
|
713
725
|
|
|
714
726
|
@classmethod
|
|
715
727
|
def parse_error(cls, error: Exception | str | None) -> str:
|
|
@@ -735,6 +747,10 @@ class StatsError:
|
|
|
735
747
|
|
|
736
748
|
def occurred(self) -> None:
|
|
737
749
|
self.occurrences += 1
|
|
750
|
+
now = time.time()
|
|
751
|
+
if self.first_seen is None:
|
|
752
|
+
self.first_seen = now
|
|
753
|
+
self.last_seen = now
|
|
738
754
|
|
|
739
755
|
def to_name(self) -> str:
|
|
740
756
|
error = self.error
|
|
@@ -767,7 +783,14 @@ class StatsError:
|
|
|
767
783
|
|
|
768
784
|
@classmethod
|
|
769
785
|
def unserialize(cls, data: StatsErrorDict) -> StatsError:
|
|
770
|
-
return cls(
|
|
786
|
+
return cls(
|
|
787
|
+
data["method"],
|
|
788
|
+
data["name"],
|
|
789
|
+
data["error"],
|
|
790
|
+
data["occurrences"],
|
|
791
|
+
data.get("first_seen"),
|
|
792
|
+
data.get("last_seen"),
|
|
793
|
+
)
|
|
771
794
|
|
|
772
795
|
def to_dict(self):
|
|
773
796
|
return {
|
|
@@ -775,6 +798,8 @@ class StatsError:
|
|
|
775
798
|
"name": self.name,
|
|
776
799
|
"error": self.parse_error(self.error),
|
|
777
800
|
"occurrences": self.occurrences,
|
|
801
|
+
"first_seen": self.first_seen,
|
|
802
|
+
"last_seen": self.last_seen,
|
|
778
803
|
}
|
|
779
804
|
|
|
780
805
|
|
|
@@ -815,7 +840,16 @@ def setup_distributed_stats_event_listeners(events: Events, stats: RequestStats)
|
|
|
815
840
|
if error_key not in stats.errors:
|
|
816
841
|
stats.errors[error_key] = StatsError.unserialize(error)
|
|
817
842
|
else:
|
|
818
|
-
stats.errors[error_key]
|
|
843
|
+
existing = stats.errors[error_key]
|
|
844
|
+
existing.occurrences += error["occurrences"]
|
|
845
|
+
if incoming_first := error.get("first_seen"):
|
|
846
|
+
existing.first_seen = (
|
|
847
|
+
incoming_first if existing.first_seen is None else min(existing.first_seen, incoming_first)
|
|
848
|
+
)
|
|
849
|
+
if incoming_last := error.get("last_seen"):
|
|
850
|
+
existing.last_seen = (
|
|
851
|
+
incoming_last if existing.last_seen is None else max(existing.last_seen, incoming_last)
|
|
852
|
+
)
|
|
819
853
|
|
|
820
854
|
stats.total.extend(StatsEntry.unserialize(data["stats_total"]))
|
|
821
855
|
|
|
@@ -988,6 +1022,8 @@ class StatsCSV:
|
|
|
988
1022
|
"Name",
|
|
989
1023
|
"Error",
|
|
990
1024
|
"Occurrences",
|
|
1025
|
+
"First Seen",
|
|
1026
|
+
"Last Seen",
|
|
991
1027
|
]
|
|
992
1028
|
|
|
993
1029
|
self.exceptions_columns = [
|
|
@@ -1045,6 +1081,8 @@ class StatsCSV:
|
|
|
1045
1081
|
stats_error.name,
|
|
1046
1082
|
StatsError.parse_error(stats_error.error),
|
|
1047
1083
|
stats_error.occurrences,
|
|
1084
|
+
format_utc_timestamp(stats_error.first_seen) if stats_error.first_seen is not None else "",
|
|
1085
|
+
format_utc_timestamp(stats_error.last_seen) if stats_error.last_seen is not None else "",
|
|
1048
1086
|
]
|
|
1049
1087
|
)
|
|
1050
1088
|
|