From 93c7f5f47544db4be30c57f9029accddfd1269d3 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 14:28:14 +0200 Subject: [PATCH 01/14] Load test (try 1). --- .github/workflows/ci.yml | 9 ++++ load-test/grpc_user.py | 62 +++++++++++++++++++++++++++ load-test/locustfile.py | 41 ++++++++++++++++++ load-test/requirements.in | 8 ++++ load-test/requirements.txt | 86 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 load-test/grpc_user.py create mode 100644 load-test/locustfile.py create mode 100644 load-test/requirements.in create mode 100644 load-test/requirements.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c89c2e9..d887a9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,15 @@ jobs: - name: Test client runs without errors run: docker compose run --rm client + - name: Run load test + uses: apardo04/locust-github-action@master + with: + LOCUSTFILE: "load-test/locustfile.py" + REQUIREMENTS: "load-test/requirements.txt" + USERS: "1" + RATE: "1" + RUNTIME: "10s" + - name: Cleanup if: always() run: docker compose down --volumes diff --git a/load-test/grpc_user.py b/load-test/grpc_user.py new file mode 100644 index 0000000..708ebfd --- /dev/null +++ b/load-test/grpc_user.py @@ -0,0 +1,62 @@ +import time +from typing import Any, Callable +import grpc +import grpc.experimental.gevent as grpc_gevent +from grpc_interceptor import ClientInterceptor +from locust import User +from locust.exception import LocustError + +# patch grpc so that it uses gevent instead of asyncio +grpc_gevent.init_gevent() + + +class LocustInterceptor(ClientInterceptor): + def __init__(self, environment, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.env = environment + + def intercept( + self, + method: Callable, + request_or_iterator: Any, + call_details: grpc.ClientCallDetails, + ): + response = None + exception = None + start_perf_counter = time.perf_counter() + response_length = 0 + try: + response = method(request_or_iterator, call_details) + response_length = response.result().ByteSize() + except grpc.RpcError as e: + exception = e + + self.env.events.request.fire( + request_type="grpc", + name=call_details.method, + response_time=(time.perf_counter() - start_perf_counter) * 1000, + response_length=response_length, + response=response, + context=None, + exception=exception, + ) + return response + + +class GrpcUser(User): + abstract = True + stub_class = None + + def __init__(self, environment): + super().__init__(environment) + for attr_value, attr_name in ((self.host, "host"), (self.stub_class, "stub_class")): + if attr_value is None: + raise LocustError(f"You must specify the {attr_name}.") + + self._channel = grpc.insecure_channel(self.host) + interceptor = LocustInterceptor(environment=environment) + self._channel = grpc.intercept_channel(self._channel, interceptor) + + self.stub = self.stub_class(self._channel) + diff --git a/load-test/locustfile.py b/load-test/locustfile.py new file mode 100644 index 0000000..bad9ecc --- /dev/null +++ b/load-test/locustfile.py @@ -0,0 +1,41 @@ +import random +from datetime import datetime +import gevent + +import grpc_user +import datastore_pb2 as dstore +import datastore_pb2_grpc as dstore_grpc +from locust import events, task + +from google.protobuf.timestamp_pb2 import Timestamp + + +class StoreGrpcUser(grpc_user.GrpcUser): + host = "localhost:50050" + stub_class = dstore_grpc.DatastoreStub + + @task + def find_debilt_humidity(self): + ts_request = dstore.FindTSRequest( + station_ids=["06260"], + param_ids=["rh"] + ) + ts_response = self.stub.FindTimeSeries(ts_request) + assert len(ts_response.tseries) == 1 + + @task + def get_data_random_timeserie(self): + ts_id = random.randint(1, 55*44) + + from_time = Timestamp() + from_time.FromDatetime(datetime(2022, 12, 31)) + to_time = Timestamp() + to_time.FromDatetime(datetime(2023, 11, 1)) + request = dstore.GetObsRequest( + tsids=[ts_id], + fromtime=from_time, + totime=to_time, + ) + response = self.stub.GetObservations(request) + assert len(response.tsobs[0].obs) == 144 + diff --git a/load-test/requirements.in b/load-test/requirements.in new file mode 100644 index 0000000..e48d52b --- /dev/null +++ b/load-test/requirements.in @@ -0,0 +1,8 @@ +# Generate requirements.txt using: +# pip-compile --upgrade --no-emit-index-url +# Install using: +# pip-sync + +grpcio-tools~=1.56 +grpc-interceptor~=0.15.3 +locust~=2.16 diff --git a/load-test/requirements.txt b/load-test/requirements.txt new file mode 100644 index 0000000..777130c --- /dev/null +++ b/load-test/requirements.txt @@ -0,0 +1,86 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --no-emit-index-url +# +blinker==1.6.2 + # via flask +brotli==1.1.0 + # via geventhttpclient +certifi==2023.7.22 + # via + # geventhttpclient + # requests +charset-normalizer==3.2.0 + # via requests +click==8.1.7 + # via flask +configargparse==1.7 + # via locust +flask==2.3.3 + # via + # flask-basicauth + # flask-cors + # locust +flask-basicauth==0.2.0 + # via locust +flask-cors==4.0.0 + # via locust +gevent==23.9.0.post1 + # via + # geventhttpclient + # locust +geventhttpclient==2.0.10 + # via locust +greenlet==2.0.2 + # via gevent +grpc-interceptor==0.15.3 + # via -r requirements.in +grpcio==1.58.0 + # via + # grpc-interceptor + # grpcio-tools +grpcio-tools==1.58.0 + # via -r requirements.in +idna==3.4 + # via requests +itsdangerous==2.1.2 + # via flask +jinja2==3.1.2 + # via flask +locust==2.16.1 + # via -r requirements.in +markupsafe==2.1.3 + # via + # jinja2 + # werkzeug +msgpack==1.0.5 + # via locust +protobuf==4.24.3 + # via grpcio-tools +psutil==5.9.5 + # via locust +pyzmq==25.1.1 + # via locust +requests==2.31.0 + # via locust +roundrobin==0.0.4 + # via locust +six==1.16.0 + # via geventhttpclient +typing-extensions==4.7.1 + # via locust +urllib3==2.0.4 + # via requests +werkzeug==2.3.7 + # via + # flask + # locust +zope-event==5.0 + # via gevent +zope-interface==6.0 + # via gevent + +# The following packages are considered to be unsafe in a requirements file: +# setuptools From 0370340dfe58ec65c77876e685c54296715e0293 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 16:08:34 +0200 Subject: [PATCH 02/14] Load test (try 2). --- .github/workflows/ci.yml | 8 +++++++- load-test/locustfile.py | 6 ++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d887a9b..adc5f92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,11 +29,17 @@ jobs: - name: Test client runs without errors run: docker compose run --rm client + - name: Set up for load test + run: | + python --version + pip install -r load-test/requirements.txt + python -m grpc_tools.protoc --proto_path=datastore/protobuf datastore.proto --python_out=load-test --grpc_python_out=load-test + - name: Run load test uses: apardo04/locust-github-action@master + run: with: LOCUSTFILE: "load-test/locustfile.py" - REQUIREMENTS: "load-test/requirements.txt" USERS: "1" RATE: "1" RUNTIME: "10s" diff --git a/load-test/locustfile.py b/load-test/locustfile.py index bad9ecc..79ebf97 100644 --- a/load-test/locustfile.py +++ b/load-test/locustfile.py @@ -1,11 +1,13 @@ +# Use the following command to generate the python protobuf stuff in the correct place (from the root of the repository) +# python -m grpc_tools.protoc --proto_path=datastore/protobuf datastore.proto --python_out=load-test --grpc_python_out=load-test + import random from datetime import datetime -import gevent import grpc_user import datastore_pb2 as dstore import datastore_pb2_grpc as dstore_grpc -from locust import events, task +from locust import task from google.protobuf.timestamp_pb2 import Timestamp From 5b4a6e00b003e2318e69eb8e17e5d4a0f9ce3960 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 16:09:14 +0200 Subject: [PATCH 03/14] Load test (try 3). --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index adc5f92..95d3f02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,6 @@ jobs: - name: Run load test uses: apardo04/locust-github-action@master - run: with: LOCUSTFILE: "load-test/locustfile.py" USERS: "1" From 60fb75b12e2defd35c1f41e7023fec3f4d86eea3 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 16:23:33 +0200 Subject: [PATCH 04/14] Load test (try 4). --- load-test/grpc_user.py | 124 ++++++++++++++++++++-------------------- load-test/locustfile.py | 66 ++++++++++++++++++++- 2 files changed, 126 insertions(+), 64 deletions(-) diff --git a/load-test/grpc_user.py b/load-test/grpc_user.py index 708ebfd..8498faa 100644 --- a/load-test/grpc_user.py +++ b/load-test/grpc_user.py @@ -1,62 +1,62 @@ -import time -from typing import Any, Callable -import grpc -import grpc.experimental.gevent as grpc_gevent -from grpc_interceptor import ClientInterceptor -from locust import User -from locust.exception import LocustError - -# patch grpc so that it uses gevent instead of asyncio -grpc_gevent.init_gevent() - - -class LocustInterceptor(ClientInterceptor): - def __init__(self, environment, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.env = environment - - def intercept( - self, - method: Callable, - request_or_iterator: Any, - call_details: grpc.ClientCallDetails, - ): - response = None - exception = None - start_perf_counter = time.perf_counter() - response_length = 0 - try: - response = method(request_or_iterator, call_details) - response_length = response.result().ByteSize() - except grpc.RpcError as e: - exception = e - - self.env.events.request.fire( - request_type="grpc", - name=call_details.method, - response_time=(time.perf_counter() - start_perf_counter) * 1000, - response_length=response_length, - response=response, - context=None, - exception=exception, - ) - return response - - -class GrpcUser(User): - abstract = True - stub_class = None - - def __init__(self, environment): - super().__init__(environment) - for attr_value, attr_name in ((self.host, "host"), (self.stub_class, "stub_class")): - if attr_value is None: - raise LocustError(f"You must specify the {attr_name}.") - - self._channel = grpc.insecure_channel(self.host) - interceptor = LocustInterceptor(environment=environment) - self._channel = grpc.intercept_channel(self._channel, interceptor) - - self.stub = self.stub_class(self._channel) - +# import time +# from typing import Any, Callable +# import grpc +# import grpc.experimental.gevent as grpc_gevent +# from grpc_interceptor import ClientInterceptor +# from locust import User +# from locust.exception import LocustError +# +# # patch grpc so that it uses gevent instead of asyncio +# grpc_gevent.init_gevent() +# +# +# class LocustInterceptor(ClientInterceptor): +# def __init__(self, environment, *args, **kwargs): +# super().__init__(*args, **kwargs) +# +# self.env = environment +# +# def intercept( +# self, +# method: Callable, +# request_or_iterator: Any, +# call_details: grpc.ClientCallDetails, +# ): +# response = None +# exception = None +# start_perf_counter = time.perf_counter() +# response_length = 0 +# try: +# response = method(request_or_iterator, call_details) +# response_length = response.result().ByteSize() +# except grpc.RpcError as e: +# exception = e +# +# self.env.events.request.fire( +# request_type="grpc", +# name=call_details.method, +# response_time=(time.perf_counter() - start_perf_counter) * 1000, +# response_length=response_length, +# response=response, +# context=None, +# exception=exception, +# ) +# return response +# +# +# class GrpcUser(User): +# abstract = True +# stub_class = None +# +# def __init__(self, environment): +# super().__init__(environment) +# for attr_value, attr_name in ((self.host, "host"), (self.stub_class, "stub_class")): +# if attr_value is None: +# raise LocustError(f"You must specify the {attr_name}.") +# +# self._channel = grpc.insecure_channel(self.host) +# interceptor = LocustInterceptor(environment=environment) +# self._channel = grpc.intercept_channel(self._channel, interceptor) +# +# self.stub = self.stub_class(self._channel) +# diff --git a/load-test/locustfile.py b/load-test/locustfile.py index 79ebf97..03e4c97 100644 --- a/load-test/locustfile.py +++ b/load-test/locustfile.py @@ -4,15 +4,77 @@ import random from datetime import datetime -import grpc_user +# import grpc_user import datastore_pb2 as dstore import datastore_pb2_grpc as dstore_grpc from locust import task from google.protobuf.timestamp_pb2 import Timestamp +import time +from typing import Any, Callable +import grpc +import grpc.experimental.gevent as grpc_gevent +from grpc_interceptor import ClientInterceptor +from locust import User +from locust.exception import LocustError -class StoreGrpcUser(grpc_user.GrpcUser): +# patch grpc so that it uses gevent instead of asyncio +grpc_gevent.init_gevent() + + +class LocustInterceptor(ClientInterceptor): + def __init__(self, environment, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.env = environment + + def intercept( + self, + method: Callable, + request_or_iterator: Any, + call_details: grpc.ClientCallDetails, + ): + response = None + exception = None + start_perf_counter = time.perf_counter() + response_length = 0 + try: + response = method(request_or_iterator, call_details) + response_length = response.result().ByteSize() + except grpc.RpcError as e: + exception = e + + self.env.events.request.fire( + request_type="grpc", + name=call_details.method, + response_time=(time.perf_counter() - start_perf_counter) * 1000, + response_length=response_length, + response=response, + context=None, + exception=exception, + ) + return response + + +class GrpcUser(User): + abstract = True + stub_class = None + + def __init__(self, environment): + super().__init__(environment) + for attr_value, attr_name in ((self.host, "host"), (self.stub_class, "stub_class")): + if attr_value is None: + raise LocustError(f"You must specify the {attr_name}.") + + self._channel = grpc.insecure_channel(self.host) + interceptor = LocustInterceptor(environment=environment) + self._channel = grpc.intercept_channel(self._channel, interceptor) + + self.stub = self.stub_class(self._channel) + + +class StoreGrpcUser(GrpcUser): host = "localhost:50050" stub_class = dstore_grpc.DatastoreStub From 6ef716c738f053ac9b1894afc3c6ef1063899f4e Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 16:29:14 +0200 Subject: [PATCH 05/14] Load test (try 5). --- .github/workflows/ci.yml | 12 +--- load-test/grpc_user.py | 124 +++++++++++++++++++-------------------- load-test/locustfile.py | 66 +-------------------- 3 files changed, 67 insertions(+), 135 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95d3f02..cd98dfa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,19 +29,13 @@ jobs: - name: Test client runs without errors run: docker compose run --rm client - - name: Set up for load test + - name: Run load test run: | python --version pip install -r load-test/requirements.txt python -m grpc_tools.protoc --proto_path=datastore/protobuf datastore.proto --python_out=load-test --grpc_python_out=load-test - - - name: Run load test - uses: apardo04/locust-github-action@master - with: - LOCUSTFILE: "load-test/locustfile.py" - USERS: "1" - RATE: "1" - RUNTIME: "10s" + cd load-test + locust --headless -u 5 -r 1 --run-time 60 - name: Cleanup if: always() diff --git a/load-test/grpc_user.py b/load-test/grpc_user.py index 8498faa..708ebfd 100644 --- a/load-test/grpc_user.py +++ b/load-test/grpc_user.py @@ -1,62 +1,62 @@ -# import time -# from typing import Any, Callable -# import grpc -# import grpc.experimental.gevent as grpc_gevent -# from grpc_interceptor import ClientInterceptor -# from locust import User -# from locust.exception import LocustError -# -# # patch grpc so that it uses gevent instead of asyncio -# grpc_gevent.init_gevent() -# -# -# class LocustInterceptor(ClientInterceptor): -# def __init__(self, environment, *args, **kwargs): -# super().__init__(*args, **kwargs) -# -# self.env = environment -# -# def intercept( -# self, -# method: Callable, -# request_or_iterator: Any, -# call_details: grpc.ClientCallDetails, -# ): -# response = None -# exception = None -# start_perf_counter = time.perf_counter() -# response_length = 0 -# try: -# response = method(request_or_iterator, call_details) -# response_length = response.result().ByteSize() -# except grpc.RpcError as e: -# exception = e -# -# self.env.events.request.fire( -# request_type="grpc", -# name=call_details.method, -# response_time=(time.perf_counter() - start_perf_counter) * 1000, -# response_length=response_length, -# response=response, -# context=None, -# exception=exception, -# ) -# return response -# -# -# class GrpcUser(User): -# abstract = True -# stub_class = None -# -# def __init__(self, environment): -# super().__init__(environment) -# for attr_value, attr_name in ((self.host, "host"), (self.stub_class, "stub_class")): -# if attr_value is None: -# raise LocustError(f"You must specify the {attr_name}.") -# -# self._channel = grpc.insecure_channel(self.host) -# interceptor = LocustInterceptor(environment=environment) -# self._channel = grpc.intercept_channel(self._channel, interceptor) -# -# self.stub = self.stub_class(self._channel) -# +import time +from typing import Any, Callable +import grpc +import grpc.experimental.gevent as grpc_gevent +from grpc_interceptor import ClientInterceptor +from locust import User +from locust.exception import LocustError + +# patch grpc so that it uses gevent instead of asyncio +grpc_gevent.init_gevent() + + +class LocustInterceptor(ClientInterceptor): + def __init__(self, environment, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.env = environment + + def intercept( + self, + method: Callable, + request_or_iterator: Any, + call_details: grpc.ClientCallDetails, + ): + response = None + exception = None + start_perf_counter = time.perf_counter() + response_length = 0 + try: + response = method(request_or_iterator, call_details) + response_length = response.result().ByteSize() + except grpc.RpcError as e: + exception = e + + self.env.events.request.fire( + request_type="grpc", + name=call_details.method, + response_time=(time.perf_counter() - start_perf_counter) * 1000, + response_length=response_length, + response=response, + context=None, + exception=exception, + ) + return response + + +class GrpcUser(User): + abstract = True + stub_class = None + + def __init__(self, environment): + super().__init__(environment) + for attr_value, attr_name in ((self.host, "host"), (self.stub_class, "stub_class")): + if attr_value is None: + raise LocustError(f"You must specify the {attr_name}.") + + self._channel = grpc.insecure_channel(self.host) + interceptor = LocustInterceptor(environment=environment) + self._channel = grpc.intercept_channel(self._channel, interceptor) + + self.stub = self.stub_class(self._channel) + diff --git a/load-test/locustfile.py b/load-test/locustfile.py index 03e4c97..79ebf97 100644 --- a/load-test/locustfile.py +++ b/load-test/locustfile.py @@ -4,77 +4,15 @@ import random from datetime import datetime -# import grpc_user +import grpc_user import datastore_pb2 as dstore import datastore_pb2_grpc as dstore_grpc from locust import task from google.protobuf.timestamp_pb2 import Timestamp -import time -from typing import Any, Callable -import grpc -import grpc.experimental.gevent as grpc_gevent -from grpc_interceptor import ClientInterceptor -from locust import User -from locust.exception import LocustError -# patch grpc so that it uses gevent instead of asyncio -grpc_gevent.init_gevent() - - -class LocustInterceptor(ClientInterceptor): - def __init__(self, environment, *args, **kwargs): - super().__init__(*args, **kwargs) - - self.env = environment - - def intercept( - self, - method: Callable, - request_or_iterator: Any, - call_details: grpc.ClientCallDetails, - ): - response = None - exception = None - start_perf_counter = time.perf_counter() - response_length = 0 - try: - response = method(request_or_iterator, call_details) - response_length = response.result().ByteSize() - except grpc.RpcError as e: - exception = e - - self.env.events.request.fire( - request_type="grpc", - name=call_details.method, - response_time=(time.perf_counter() - start_perf_counter) * 1000, - response_length=response_length, - response=response, - context=None, - exception=exception, - ) - return response - - -class GrpcUser(User): - abstract = True - stub_class = None - - def __init__(self, environment): - super().__init__(environment) - for attr_value, attr_name in ((self.host, "host"), (self.stub_class, "stub_class")): - if attr_value is None: - raise LocustError(f"You must specify the {attr_name}.") - - self._channel = grpc.insecure_channel(self.host) - interceptor = LocustInterceptor(environment=environment) - self._channel = grpc.intercept_channel(self._channel, interceptor) - - self.stub = self.stub_class(self._channel) - - -class StoreGrpcUser(GrpcUser): +class StoreGrpcUser(grpc_user.GrpcUser): host = "localhost:50050" stub_class = dstore_grpc.DatastoreStub From 7477c999e73bb78bd1e935160c000b36e0079e2f Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 16:40:13 +0200 Subject: [PATCH 06/14] Use Python 3.11 in the load test. --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd98dfa..f8df5be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,10 @@ jobs: - name: Check out the repo uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Build docker containers run: docker compose build From 8ded495e7caa2bd3e28bf27debb95cce86deee54 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 16:54:08 +0200 Subject: [PATCH 07/14] Archive output from load test. --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8df5be..1c6ab78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,13 @@ jobs: pip install -r load-test/requirements.txt python -m grpc_tools.protoc --proto_path=datastore/protobuf datastore.proto --python_out=load-test --grpc_python_out=load-test cd load-test - locust --headless -u 5 -r 1 --run-time 60 + locust --headless -u 5 -r 1 --run-time 60 --only-summary --csv store + + - name: Archive load test artifacts + uses: actions/upload-artifact@v3 + with: + name: performance + path: load-test/store_*.csv - name: Cleanup if: always() From fa0c40787d6e946c6d4badf59ca0e9b96154e4c4 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 17:47:29 +0200 Subject: [PATCH 08/14] Make nice output. --- .github/workflows/ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c6ab78..ec0d134 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,14 @@ jobs: name: performance path: load-test/store_*.csv + - name: Print results + run: | + pip install csvkit + response_time=$(csvgrep -c 2 -r "FindTimeSeries" store_stats.csv | csvcut -c 6 | tail -n +2) + echo echo "## FindTimeSeries average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY + response_time=$(csvgrep -c 2 -r "GetObservations" store_stats.csv | csvcut -c 6 | tail -n +2) + echo echo "## GetObservations average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY + - name: Cleanup if: always() run: docker compose down --volumes From 06f4fc484c5408468a2bf88ba603b4b97c8eba3c Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 17:56:37 +0200 Subject: [PATCH 09/14] Fix duplicate echo... --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec0d134..6805c1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,9 +51,9 @@ jobs: run: | pip install csvkit response_time=$(csvgrep -c 2 -r "FindTimeSeries" store_stats.csv | csvcut -c 6 | tail -n +2) - echo echo "## FindTimeSeries average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY + echo "## FindTimeSeries average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY response_time=$(csvgrep -c 2 -r "GetObservations" store_stats.csv | csvcut -c 6 | tail -n +2) - echo echo "## GetObservations average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY + echo "## GetObservations average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY - name: Cleanup if: always() From 378ef776bde370906afb3c661fb3620e53980643 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 18:04:47 +0200 Subject: [PATCH 10/14] Fix echo --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6805c1d..277d90e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,10 +50,8 @@ jobs: - name: Print results run: | pip install csvkit - response_time=$(csvgrep -c 2 -r "FindTimeSeries" store_stats.csv | csvcut -c 6 | tail -n +2) - echo "## FindTimeSeries average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY - response_time=$(csvgrep -c 2 -r "GetObservations" store_stats.csv | csvcut -c 6 | tail -n +2) - echo "## GetObservations average response time: $response_time ms" >> $GITHUB_STEP_SUMMARY + echo "## FindTimeSeries average response time: $(csvgrep -c 2 -r "FindTimeSeries" store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY + echo "## GetObservations average response time: $(csvgrep -c 2 -r "GetObservations" store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY - name: Cleanup if: always() From 998928a5b0ce6504a24ddce3d315c70cb6a6bf57 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 18:10:44 +0200 Subject: [PATCH 11/14] Fix path --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 277d90e..816755f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,8 +50,8 @@ jobs: - name: Print results run: | pip install csvkit - echo "## FindTimeSeries average response time: $(csvgrep -c 2 -r "FindTimeSeries" store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY - echo "## GetObservations average response time: $(csvgrep -c 2 -r "GetObservations" store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY + echo "## FindTimeSeries average response time: $(csvgrep -c 2 -r "FindTimeSeries" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY + echo "## GetObservations average response time: $(csvgrep -c 2 -r "GetObservations" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY - name: Cleanup if: always() From a07bd941da09854ee28514858963383976589811 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 18:13:25 +0200 Subject: [PATCH 12/14] Just print everything. --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 816755f..3aca447 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,6 +52,9 @@ jobs: pip install csvkit echo "## FindTimeSeries average response time: $(csvgrep -c 2 -r "FindTimeSeries" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY echo "## GetObservations average response time: $(csvgrep -c 2 -r "GetObservations" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY + csvlook load-test/store_stats.csv >> $GITHUB_STEP_SUMMARY + csvlook load-test/store_stats_history.csv >> $GITHUB_STEP_SUMMARY + csvlook load-test/store_failures.csv >> $GITHUB_STEP_SUMMARY - name: Cleanup if: always() From b3ccf081353043c6775657f8335e416c6c6ba0b8 Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 18:21:43 +0200 Subject: [PATCH 13/14] Clean up. --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3aca447..8a22e4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,10 +50,13 @@ jobs: - name: Print results run: | pip install csvkit - echo "## FindTimeSeries average response time: $(csvgrep -c 2 -r "FindTimeSeries" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY - echo "## GetObservations average response time: $(csvgrep -c 2 -r "GetObservations" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY +# echo "## FindTimeSeries average response time: $(csvgrep -c 2 -r "FindTimeSeries" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY +# echo "## GetObservations average response time: $(csvgrep -c 2 -r "GetObservations" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY + echo "## Stats" >> $GITHUB_STEP_SUMMARY csvlook load-test/store_stats.csv >> $GITHUB_STEP_SUMMARY + echo "## Stats history" >> $GITHUB_STEP_SUMMARY csvlook load-test/store_stats_history.csv >> $GITHUB_STEP_SUMMARY + echo "## Failures" >> $GITHUB_STEP_SUMMARY csvlook load-test/store_failures.csv >> $GITHUB_STEP_SUMMARY - name: Cleanup From b35b3451f14f540e6fc2906a66290b73393c20bf Mon Sep 17 00:00:00 2001 From: Lukas Phaf Date: Mon, 11 Sep 2023 18:23:59 +0200 Subject: [PATCH 14/14] Clean up (2) --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a22e4e..62c8198 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,8 +50,6 @@ jobs: - name: Print results run: | pip install csvkit -# echo "## FindTimeSeries average response time: $(csvgrep -c 2 -r "FindTimeSeries" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY -# echo "## GetObservations average response time: $(csvgrep -c 2 -r "GetObservations" load-test/store_stats.csv | csvcut -c 6 | tail -n +2) ms" >> $GITHUB_STEP_SUMMARY echo "## Stats" >> $GITHUB_STEP_SUMMARY csvlook load-test/store_stats.csv >> $GITHUB_STEP_SUMMARY echo "## Stats history" >> $GITHUB_STEP_SUMMARY