mite 2.0.2__tar.gz → 2.1.0__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.
- {mite-2.0.2 → mite-2.1.0}/PKG-INFO +1 -1
- {mite-2.0.2 → mite-2.1.0}/docker_compose.yml +0 -1
- {mite-2.0.2 → mite-2.1.0}/docker_compose_monitoring.yml +0 -1
- {mite-2.0.2 → mite-2.1.0}/mite/__main__.py +39 -35
- {mite-2.0.2 → mite-2.1.0}/mite/cli/test.py +55 -1
- {mite-2.0.2 → mite-2.1.0}/mite/logoutput.py +65 -8
- {mite-2.0.2 → mite-2.1.0}/mite.egg-info/PKG-INFO +1 -1
- {mite-2.0.2 → mite-2.1.0}/mite_http/__init__.py +1 -0
- {mite-2.0.2 → mite-2.1.0}/.dockerignore +0 -0
- {mite-2.0.2 → mite-2.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/.github/pull_request_template.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/.gitignore +0 -0
- {mite-2.0.2 → mite-2.1.0}/.isort.cfg +0 -0
- {mite-2.0.2 → mite-2.1.0}/.pre-commit-config.yaml +0 -0
- {mite-2.0.2 → mite-2.1.0}/.travis.yml +0 -0
- {mite-2.0.2 → mite-2.1.0}/CODE_OF_CONDUCT.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/CONTRIBUTING.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/DEV.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/Dockerfile +0 -0
- {mite-2.0.2 → mite-2.1.0}/Dockerfile.perftest +0 -0
- {mite-2.0.2 → mite-2.1.0}/LICENSE +0 -0
- {mite-2.0.2 → mite-2.1.0}/MANIFEST.in +0 -0
- {mite-2.0.2 → mite-2.1.0}/README.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/cd-scripts/cdBuild-1.sh +0 -0
- {mite-2.0.2 → mite-2.1.0}/cd-scripts/cdRelease.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/cd-scripts/cdTagRelease.sh +0 -0
- {mite-2.0.2 → mite-2.1.0}/cd-scripts/runTests.sh +0 -0
- {mite-2.0.2 → mite-2.1.0}/cd.yml +0 -0
- {mite-2.0.2 → mite-2.1.0}/dev-requirements.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/Makefile +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/components.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/conf.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/config.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/design-deployment.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/index.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/journeys.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/notes.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/prometheus.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/stats.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/docs/volume-model.rst +0 -0
- {mite-2.0.2 → mite-2.1.0}/grafana/Dockerfile +0 -0
- {mite-2.0.2 → mite-2.1.0}/grafana/config.ini +0 -0
- {mite-2.0.2 → mite-2.1.0}/grafana/provisioning/dashboards/dashboards.yml +0 -0
- {mite-2.0.2 → mite-2.1.0}/grafana/provisioning/dashboards/grafana_dashboard_template.json +0 -0
- {mite-2.0.2 → mite-2.1.0}/grafana/provisioning/dashboards/mite_docker.json +0 -0
- {mite-2.0.2 → mite-2.1.0}/grafana/provisioning/datasources/datasources.yml +0 -0
- {mite-2.0.2 → mite-2.1.0}/local/Makefile +0 -0
- {mite-2.0.2 → mite-2.1.0}/local/README.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/local/demo.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/local/run_mite.sh +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/cli/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/cli/cat.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/cli/collector.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/cli/common.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/cli/duplicator.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/cli/receiver.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/cli/stats.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/collector.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/config.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/context.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/controller.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/datapools.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/example.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/exceptions.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/har_to_mite.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/nanomsg.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/recorder.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/runner.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/scenario.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/stats.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/test.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/utils.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/volume_model.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/web/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/web/prometheus.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite/zmq.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite.egg-info/SOURCES.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite.egg-info/dependency_links.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite.egg-info/entry_points.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite.egg-info/requires.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite.egg-info/top_level.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_amqp/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_browser/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/README.md +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/mux.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/stats.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/conftest.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/foo_service/Foo-remote +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/foo_service/Foo.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/foo_service/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/foo_service/constants.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/foo_service/ttypes.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/foo_service.thrift +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/test_integration.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/test_mux.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/tests/test_thrift.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_finagle/thrift.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_http/stats.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_kafka/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_kafka/kafka_test_scenario.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_kafka/stats.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_selenium/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_selenium/stats.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/mite_websocket/__init__.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/prometheus/Dockerfile +0 -0
- {mite-2.0.2 → mite-2.1.0}/prometheus/prometheus_config_docker.yml +0 -0
- {mite-2.0.2 → mite-2.1.0}/prometheus/prometheus_config_template.yml +0 -0
- {mite-2.0.2 → mite-2.1.0}/pyproject.toml +0 -0
- {mite-2.0.2 → mite-2.1.0}/requirements.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/setup.cfg +0 -0
- {mite-2.0.2 → mite-2.1.0}/setup.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/legacy.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/mocks/mock_collector.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/mocks/mock_context.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/mocks/mock_direct_receiver.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/mocks/mock_direct_runner_transport.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/mocks/mock_recorder_msg_http.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/mocks/mock_selenium.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/mocks/mock_sender.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/perf/.gitignore +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/perf/http_server.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/perf/http_server_aiohttp.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/perf/mite_perftest.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/perf/perftest.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/perf/run-perftest.sh +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/perf/test-requirements.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test.har +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_collector.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_config.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_context.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_controller.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_datapools.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_har_to_mite.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_logging.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_mite_amqp.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_mite_browser.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_mite_http.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_mite_kafka.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_mite_utils.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_mite_websockets.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_prometheus_mite.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_recorder.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_runner.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_runner_tracker.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_scenario.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_stats.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_volume_model.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_webdriver.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test/test_work_tracker.py +0 -0
- {mite-2.0.2 → mite-2.1.0}/test-requirements.txt +0 -0
- {mite-2.0.2 → mite-2.1.0}/test.har +0 -0
- {mite-2.0.2 → mite-2.1.0}/tox.ini +0 -0
|
@@ -56,41 +56,45 @@ Examples:
|
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
Options:
|
|
59
|
-
-h --help
|
|
60
|
-
--version
|
|
61
|
-
--debugging
|
|
62
|
-
--memory-tracing
|
|
63
|
-
--log-level=LEVEL
|
|
64
|
-
--config=CONFIG_SPEC
|
|
65
|
-
--add-to-config=NEW_VALUE
|
|
66
|
-
--spawn-rate=NUM_PER_SECOND
|
|
67
|
-
--max-loop-delay=SECONDS
|
|
68
|
-
--min-loop-delay=SECONDS
|
|
69
|
-
--runner-max-journeys=NUMBER
|
|
70
|
-
--controller-socket=SOCKET
|
|
71
|
-
--message-socket=SOCKET
|
|
72
|
-
--collector-socket=SOCKET
|
|
73
|
-
--stats-in-socket=SOCKET
|
|
74
|
-
--stats-out-socket=SOCKET
|
|
75
|
-
--stats-include-processors=PROCESSORS
|
|
76
|
-
--stats-exclude-processors=PROCESSORS
|
|
77
|
-
--recorder-socket=SOCKET
|
|
78
|
-
--delay-start-seconds=DELAY
|
|
79
|
-
--volume=VOLUME
|
|
80
|
-
--web-address=HOST_PORT
|
|
81
|
-
--message-backend=BACKEND
|
|
82
|
-
--exclude-working-directory
|
|
83
|
-
--collector-dir=DIRECTORY
|
|
84
|
-
--collector-filter=SPEC
|
|
85
|
-
--collector-roll=NUM_LINES
|
|
86
|
-
--collector-use-json
|
|
87
|
-
--recorder-dir=DIRECTORY
|
|
88
|
-
--sleep-time=SLEEP
|
|
89
|
-
--logging-webhook=URL
|
|
90
|
-
--message-processors=PROCESSORS
|
|
91
|
-
--prettify-timestamps
|
|
92
|
-
--journey-logging
|
|
93
|
-
--
|
|
59
|
+
-h --help Show this screen
|
|
60
|
+
--version Show version
|
|
61
|
+
--debugging Drop into debugger (pdb) on journey error and exit. Select debugger with PYTHONBREAKPOINT and PYTHONPOSTMORTEM
|
|
62
|
+
--memory-tracing Print heap alloc diffs every 60 seconds
|
|
63
|
+
--log-level=LEVEL Set logger level, one of DEBUG, INFO, WARNING, ERROR, CRITICAL [default: INFO]
|
|
64
|
+
--config=CONFIG_SPEC Set a config loader to a callable loaded via a spec [default: mite.config:default_config_loader]
|
|
65
|
+
--add-to-config=NEW_VALUE Add a key:value to the config map, in addition to what's loaded from a file
|
|
66
|
+
--spawn-rate=NUM_PER_SECOND Maximum spawn rate [default: 1000]
|
|
67
|
+
--max-loop-delay=SECONDS Runner internal loop delay maximum [default: 1]
|
|
68
|
+
--min-loop-delay=SECONDS Runner internal loop delay minimum [default: 0]
|
|
69
|
+
--runner-max-journeys=NUMBER Max number of concurrent journeys a runner can run
|
|
70
|
+
--controller-socket=SOCKET Controller socket [default: tcp://127.0.0.1:14301]
|
|
71
|
+
--message-socket=SOCKET Message socket [default: tcp://127.0.0.1:14302]
|
|
72
|
+
--collector-socket=SOCKET Socket [default: tcp://127.0.0.1:14303]
|
|
73
|
+
--stats-in-socket=SOCKET Socket [default: tcp://127.0.0.1:14304]
|
|
74
|
+
--stats-out-socket=SOCKET Socket [default: tcp://127.0.0.1:14305]
|
|
75
|
+
--stats-include-processors=PROCESSORS Stats processor names to include, as a comma separated list (no spaces)
|
|
76
|
+
--stats-exclude-processors=PROCESSORS Stats processor names to exclude, as a comma separated list (no spaces)
|
|
77
|
+
--recorder-socket=SOCKET Socket [default: tcp://127.0.0.1:14306]
|
|
78
|
+
--delay-start-seconds=DELAY Delay start allowing others to connect [default: 0]
|
|
79
|
+
--volume=VOLUME Volume to run journey at [default: 1]
|
|
80
|
+
--web-address=HOST_PORT Web bind address [default: 127.0.0.1:9301]
|
|
81
|
+
--message-backend=BACKEND Backend to transport messages over [default: ZMQ]
|
|
82
|
+
--exclude-working-directory By default mite puts the current directory on the python path
|
|
83
|
+
--collector-dir=DIRECTORY Set the collectors output directory [default: collector_data]
|
|
84
|
+
--collector-filter=SPEC Function spec to filter messages collected by the collector
|
|
85
|
+
--collector-roll=NUM_LINES How many lines per collector output file [default: 100000]
|
|
86
|
+
--collector-use-json Output in json format rather than msgpack
|
|
87
|
+
--recorder-dir=DIRECTORY Set the recorders output directory [default: recorder_data]
|
|
88
|
+
--sleep-time=SLEEP Set the second to await between each request [default: 1]
|
|
89
|
+
--logging-webhook=URL URL of an HTTP server to log test runs to
|
|
90
|
+
--message-processors=PROCESSORS Classes to connect to the message bus for local testing [default: mite.logoutput:HttpStatsOutput,mite.logoutput:MsgOutput]
|
|
91
|
+
--prettify-timestamps Reformat unix timestamps to human readable dates
|
|
92
|
+
--journey-logging Log errors on a per journey basis
|
|
93
|
+
--report Report stats at the end of the test
|
|
94
|
+
--hide-constant-logs Hide logs that are printed every 2 seconds
|
|
95
|
+
--max-errors-threshold=THRESHOLD Set the maximum number of errors accepted before setting exit status to 1 [default: 0]
|
|
96
|
+
--max-response-time-threshold=THRESHOLD Set the maximum response time accepted before setting exit status to 1 [default: 0]
|
|
97
|
+
--mean-response-time-threshold=THRESHOLD Set the mean response time accepted before setting exit status to 1 [default: 0]
|
|
94
98
|
"""
|
|
95
99
|
import asyncio
|
|
96
100
|
import logging
|
|
@@ -2,6 +2,7 @@ import asyncio
|
|
|
2
2
|
import gc
|
|
3
3
|
import logging
|
|
4
4
|
import sys
|
|
5
|
+
import time
|
|
5
6
|
import tracemalloc
|
|
6
7
|
|
|
7
8
|
from mite.datapools import SingleRunDataPoolWrapper
|
|
@@ -142,7 +143,7 @@ def test_scenarios(test_name, opts, scenarios, config_manager):
|
|
|
142
143
|
|
|
143
144
|
tasks = [
|
|
144
145
|
loop.create_task(controller_report(controller, receiver)),
|
|
145
|
-
loop.create_task(_create_runner(opts, transport, receiver.recieve).run())
|
|
146
|
+
loop.create_task(_create_runner(opts, transport, receiver.recieve).run()),
|
|
146
147
|
]
|
|
147
148
|
|
|
148
149
|
if opts["--memory-tracing"]:
|
|
@@ -152,12 +153,28 @@ def test_scenarios(test_name, opts, scenarios, config_manager):
|
|
|
152
153
|
|
|
153
154
|
loop.run_until_complete(asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED))
|
|
154
155
|
|
|
156
|
+
http_stats_output._scenarios_completed_time = time.time()
|
|
157
|
+
|
|
155
158
|
# Run one last report before exiting
|
|
156
159
|
controller.report(receiver.recieve)
|
|
157
160
|
has_error = http_stats_output is not None and http_stats_output.error_total > int(
|
|
158
161
|
opts.get("--max-errors-threshold")
|
|
159
162
|
)
|
|
160
163
|
|
|
164
|
+
if opts.get("--max-response-time-threshold") != "0":
|
|
165
|
+
max_response_time = http_stats_output._resp_time_max * 1000
|
|
166
|
+
if max_response_time > int(opts["--max-response-time-threshold"]):
|
|
167
|
+
has_error = True
|
|
168
|
+
logging.error("Max response time exceeded: %sms", max_response_time)
|
|
169
|
+
if opts.get("--mean-response-time-threshold") != "0":
|
|
170
|
+
mean_response_time = http_stats_output.mean_resp_time * 1000
|
|
171
|
+
if mean_response_time > int(opts["--mean-response-time-threshold"]):
|
|
172
|
+
has_error = True
|
|
173
|
+
logging.error("Mean response time exceeded: %sms", mean_response_time)
|
|
174
|
+
|
|
175
|
+
if opts.get("--report"):
|
|
176
|
+
benchmark_report(opts, http_stats_output)
|
|
177
|
+
|
|
161
178
|
# Ensure any open files get closed
|
|
162
179
|
del receiver._raw_listeners
|
|
163
180
|
del receiver._listeners
|
|
@@ -165,6 +182,43 @@ def test_scenarios(test_name, opts, scenarios, config_manager):
|
|
|
165
182
|
sys.exit(int(has_error))
|
|
166
183
|
|
|
167
184
|
|
|
185
|
+
def human_readable_bytes(size):
|
|
186
|
+
for unit in ["B", "KB", "MB", "GB", "TB"]:
|
|
187
|
+
if size < 1024.0:
|
|
188
|
+
return size, unit
|
|
189
|
+
size /= 1024.0
|
|
190
|
+
return size, "PB"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def benchmark_report(opts, http_stats_output):
|
|
194
|
+
report_output = """
|
|
195
|
+
|
|
196
|
+
\t\tAvg\t\tMin\t\tMax
|
|
197
|
+
Latency\t\t{mean_resp_time:.2f}ms\t\t{min_resp_time:.2f}ms\t\t{max_resp_time:.2f}ms
|
|
198
|
+
Req/Sec\t\t{req_per_sec_mean:.2f}\t\t{min_req_per_sec:.2f}\t\t{max_req_per_sec:.2f}
|
|
199
|
+
|
|
200
|
+
{total_reqs} requests in {total_time:.2f}s, {data_transfer:.2f}{data_unit} data transfered
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
data_transfer, data_unit = human_readable_bytes(http_stats_output._data_transferred)
|
|
204
|
+
|
|
205
|
+
print(
|
|
206
|
+
report_output.format(
|
|
207
|
+
mean_resp_time=http_stats_output.mean_resp_time * 1000,
|
|
208
|
+
min_resp_time=http_stats_output._resp_time_min * 1000,
|
|
209
|
+
max_resp_time=http_stats_output._resp_time_max * 1000,
|
|
210
|
+
req_per_sec_mean=http_stats_output.req_sec_mean,
|
|
211
|
+
min_req_per_sec=http_stats_output._req_sec_min,
|
|
212
|
+
max_req_per_sec=http_stats_output._req_sec_max,
|
|
213
|
+
total_reqs=http_stats_output._req_total,
|
|
214
|
+
total_time=http_stats_output._scenarios_completed_time
|
|
215
|
+
- http_stats_output._init_time,
|
|
216
|
+
data_transfer=data_transfer,
|
|
217
|
+
data_unit=data_unit,
|
|
218
|
+
)
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
168
222
|
def scenario_test_cmd(opts):
|
|
169
223
|
scenario_spec = opts["SCENARIO_SPEC"]
|
|
170
224
|
config_manager = _create_config_manager(opts)
|
|
@@ -42,13 +42,23 @@ class GenericStatsOutput:
|
|
|
42
42
|
self._journey_logging = opts.get("--journey-logging", False)
|
|
43
43
|
if self._journey_logging is not False:
|
|
44
44
|
self._journey_logging = True
|
|
45
|
+
self._hide_constant_logs = opts.get("--hide-constant-logs")
|
|
45
46
|
self._logger = logging.getLogger(f"{self.log_name} Stats")
|
|
47
|
+
self._init_time = time.time()
|
|
46
48
|
self._start_t = None
|
|
47
49
|
self._req_total = 0
|
|
48
50
|
self._req_recent = 0
|
|
49
51
|
self._error_total = 0
|
|
50
52
|
self._error_recent = 0
|
|
51
53
|
self._resp_time_recent = []
|
|
54
|
+
self._resp_time_min = 0
|
|
55
|
+
self._resp_time_max = 0
|
|
56
|
+
self._resp_time_mean = 0
|
|
57
|
+
self._resp_time_mean_store = []
|
|
58
|
+
self._req_sec_min = 0
|
|
59
|
+
self._req_sec_max = 0
|
|
60
|
+
self._scenarios_completed_time = 0
|
|
61
|
+
self._data_transferred = 0
|
|
52
62
|
self._error_journeys = defaultdict(int)
|
|
53
63
|
|
|
54
64
|
def _pct(self, percentile):
|
|
@@ -80,18 +90,20 @@ class GenericStatsOutput:
|
|
|
80
90
|
def print_output(self, t):
|
|
81
91
|
dt = t - self._start_t
|
|
82
92
|
self._resp_time_recent.sort()
|
|
83
|
-
|
|
93
|
+
if not self._hide_constant_logs:
|
|
94
|
+
self._logger.info(f"Total> #Reqs:{self._req_total} #Errs:{self._error_total}")
|
|
84
95
|
# only output journey logs if the --journey_logging switch is set
|
|
85
96
|
if self._journey_logging:
|
|
86
97
|
for k, v in self._error_journeys.items():
|
|
87
98
|
self._logger.info(f"Total errors for {k} :{v}")
|
|
88
|
-
self.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
99
|
+
if not self._hide_constant_logs:
|
|
100
|
+
self._logger.info(
|
|
101
|
+
f"Last {self._period} Secs> #Reqs:{self._req_recent} #Errs:{self._error_recent} "
|
|
102
|
+
+ f"Req/S:{self._req_recent / dt:.1f} min:{self._pct(0)} "
|
|
103
|
+
+ f"25%:{self._pct(25)} 50%:{self._pct(50)} 75%:{self._pct(75)} "
|
|
104
|
+
+ f"90%:{self._pct(90)} 99%:{self._pct(99)} 99.9%:{self._pct(99.9)} "
|
|
105
|
+
+ f"max:{self._pct(100)}",
|
|
106
|
+
)
|
|
95
107
|
self._start_t = t
|
|
96
108
|
del self._resp_time_recent[:]
|
|
97
109
|
self._req_recent = 0
|
|
@@ -105,9 +117,32 @@ class GenericStatsOutput:
|
|
|
105
117
|
if self._start_t is None:
|
|
106
118
|
self._start_t = t
|
|
107
119
|
if self._start_t + self._period < t:
|
|
120
|
+
|
|
121
|
+
if self._resp_time_recent:
|
|
122
|
+
if self._resp_time_min == 0:
|
|
123
|
+
self._resp_time_min = self.min_resp_time
|
|
124
|
+
else:
|
|
125
|
+
self._resp_time_min = min(self.min_resp_time, self._resp_time_min)
|
|
126
|
+
|
|
127
|
+
self._resp_time_max = max(self.max_resp_time_recent, self._resp_time_max)
|
|
128
|
+
|
|
129
|
+
self._resp_time_mean_store.append(
|
|
130
|
+
sum(self._resp_time_recent) / len(self._resp_time_recent)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if self._req_recent:
|
|
134
|
+
req_sec = self._req_recent / (t - self._start_t)
|
|
135
|
+
if self._req_sec_min == 0:
|
|
136
|
+
self._req_sec_min = req_sec
|
|
137
|
+
else:
|
|
138
|
+
self._req_sec_min = min(req_sec, self._req_sec_min)
|
|
139
|
+
|
|
140
|
+
self._req_sec_max = max(req_sec, self._req_sec_max)
|
|
141
|
+
|
|
108
142
|
self.print_output(t)
|
|
109
143
|
if msg_type in self.message_types:
|
|
110
144
|
self._resp_time_recent.append(message["total_time"])
|
|
145
|
+
self._data_transferred += message.get("download_size", 0)
|
|
111
146
|
self._req_total += 1
|
|
112
147
|
self._req_recent += 1
|
|
113
148
|
elif msg_type in ("error", "exception"):
|
|
@@ -117,6 +152,28 @@ class GenericStatsOutput:
|
|
|
117
152
|
journey_name = message.get("journey")
|
|
118
153
|
self._error_journeys[journey_name] += 1
|
|
119
154
|
|
|
155
|
+
@property
|
|
156
|
+
def mean_resp_time(self):
|
|
157
|
+
if not self._resp_time_mean_store:
|
|
158
|
+
return 0
|
|
159
|
+
return sum(self._resp_time_mean_store) / len(self._resp_time_mean_store)
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def max_resp_time_recent(self):
|
|
163
|
+
if not self._resp_time_recent:
|
|
164
|
+
return 0
|
|
165
|
+
return max(self._resp_time_recent)
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def min_resp_time(self):
|
|
169
|
+
if not self._resp_time_recent:
|
|
170
|
+
return 0
|
|
171
|
+
return min(self._resp_time_recent)
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def req_sec_mean(self):
|
|
175
|
+
return self._req_total / (self._scenarios_completed_time - self._init_time)
|
|
176
|
+
|
|
120
177
|
|
|
121
178
|
class HttpStatsOutput(GenericStatsOutput):
|
|
122
179
|
message_types = {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mite-2.0.2 → mite-2.1.0}/DEV.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mite-2.0.2 → mite-2.1.0}/cd.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|