From 689edd778cb1e8780ca1f84ac30766613ce9abb9 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Fri, 27 Oct 2023 18:44:50 +0300 Subject: [PATCH 01/20] add test chart data; add healthcheck before docker build steps; update test_main --- dff/stats/utils.py | 4 +- dff/utils/docker/dockerfile_stats | 1 + dff/utils/docker/entrypoint_stats.sh | 2 +- dff/utils/docker/health_stats.sh | 18 ++ tests/stats/chart_data.py | 465 +++++++++++++++++++++++++++ tests/stats/test_main.py | 18 +- 6 files changed, 502 insertions(+), 6 deletions(-) create mode 100644 dff/utils/docker/health_stats.sh create mode 100644 tests/stats/chart_data.py diff --git a/dff/stats/utils.py b/dff/stats/utils.py index c4b3c472a..e0247ddfd 100644 --- a/dff/stats/utils.py +++ b/dff/stats/utils.py @@ -109,6 +109,8 @@ def get_superset_session(args: Namespace, base_url: str = "http://localhost:8088 :return: Authorized session - authorization headers tuple. """ + username = args.username + password = args.password healthcheck_url = parse.urljoin(base_url, "/healthcheck") login_url = parse.urljoin(base_url, "/api/v1/security/login") csrf_url = parse.urljoin(base_url, "/api/v1/security/csrf_token/") @@ -121,7 +123,7 @@ def get_superset_session(args: Namespace, base_url: str = "http://localhost:8088 access_request = session.post( login_url, headers={"Content-Type": "application/json", "Accept": "*/*"}, - data=json.dumps({"username": args.username, "password": args.password, "refresh": True, "provider": "db"}), + data=json.dumps({"username": username, "password": password, "refresh": True, "provider": "db"}), ) access_token = access_request.json()["access_token"] # get csrf_token diff --git a/dff/utils/docker/dockerfile_stats b/dff/utils/docker/dockerfile_stats index 9c40071ea..3a24a69df 100644 --- a/dff/utils/docker/dockerfile_stats +++ b/dff/utils/docker/dockerfile_stats @@ -1,6 +1,7 @@ FROM apache/superset:2.1.0rc1 USER root RUN cd /app && pip install .[clickhouse] +COPY health_stats.sh /app/docker/ COPY entrypoint_stats.sh /app/docker/ COPY --chown=superset superset_config_docker.py /app/pythonpath/ ENV SUPERSET_CONFIG_PATH /app/pythonpath/superset_config_docker.py diff --git a/dff/utils/docker/entrypoint_stats.sh b/dff/utils/docker/entrypoint_stats.sh index cac946f7d..519ae7721 100644 --- a/dff/utils/docker/entrypoint_stats.sh +++ b/dff/utils/docker/entrypoint_stats.sh @@ -2,7 +2,7 @@ export SERVER_THREADS_AMOUNT=8 set -m nohup /bin/bash /usr/bin/run-server.sh & -sleep 5 +/bin/bash /app/docker/health_stats.sh superset fab create-admin --firstname superset --lastname admin --username $SUPERSET_USERNAME --email admin@admin.com --password $SUPERSET_PASSWORD superset db upgrade superset init diff --git a/dff/utils/docker/health_stats.sh b/dff/utils/docker/health_stats.sh new file mode 100644 index 000000000..1033177f5 --- /dev/null +++ b/dff/utils/docker/health_stats.sh @@ -0,0 +1,18 @@ +#!/bin/bash +for itr in {1..10} +do +healthcheck=$(curl -X GET http://localhost:8088/health | grep "OK") +healthcheck=$? +if [ "$healthcheck" -ne 0 ] ; then +echo "Healthcheck failed. sleeping for 5 secs" +sleep 5 +echo 'Iteration' $itr +if [ $itr == 10 ]; then +echo 'Healthcheck suite unsuccessful.' +fi +else +echo "Healthcheck suite succesful." +break +exit 0 +fi +done \ No newline at end of file diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py new file mode 100644 index 000000000..71b8500a9 --- /dev/null +++ b/tests/stats/chart_data.py @@ -0,0 +1,465 @@ +CHART_DATA = { + 1: [ + { + "prev_label": "greeting_flow: node1", + "label": "greeting_flow: node1", + "flow_label": "greeting_flow", + "COUNT_DISTINCT(context_id)": 1, + }, + { + "prev_label": "greeting_flow: node2", + "label": "greeting_flow: node2", + "flow_label": "greeting_flow", + "COUNT_DISTINCT(context_id)": 1, + }, + { + "prev_label": "greeting_flow: node3", + "label": "greeting_flow: node3", + "flow_label": "greeting_flow", + "COUNT_DISTINCT(context_id)": 1, + }, + { + "prev_label": "greeting_flow: node4", + "label": "greeting_flow: node4", + "flow_label": "greeting_flow", + "COUNT_DISTINCT(context_id)": 1, + }, + ], + 2: [ + {"__timestamp": 1698316771000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698318377000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698319785000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698321340000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698321484000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698396046000, ", ": None, "greeting_flow, node1": 1}, + {"__timestamp": 1698397463000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698397683000, ", ": None, "greeting_flow, node1": 1}, + {"__timestamp": 1698397983000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698398067000, ", ": 1, "greeting_flow, node1": None}, + {"__timestamp": 1698402755000, ", ": None, "greeting_flow, node1": 1}, + {"__timestamp": 1698402875000, ", ": None, "greeting_flow, node1": 1}, + ], + 3: [ + {"flow_label": "greeting_flow", "node_label": "node1", "COUNT(context_id)": 9}, + {"flow_label": "greeting_flow", "node_label": "node2", "COUNT(context_id)": 8}, + {"flow_label": "greeting_flow", "node_label": "node4", "COUNT(context_id)": 3}, + {"flow_label": "greeting_flow", "node_label": "node3", "COUNT(context_id)": 3}, + ], + 4: [ + {"__timestamp": 1698316500000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698318300000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698319500000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698321300000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698396000000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698397200000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698397500000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698397800000, "COUNT_DISTINCT(context_id)": 1}, + {"__timestamp": 1698402600000, "COUNT_DISTINCT(context_id)": 1}, + ], + 5: [ + {"request_id": 0, "label": "greeting_flow: node1", "COUNT(context_id)": 5}, + {"request_id": 2, "label": "greeting_flow: node3", "COUNT(context_id)": 3}, + {"request_id": 3, "label": "greeting_flow: node4", "COUNT(context_id)": 3}, + {"request_id": 1, "label": "greeting_flow: node2", "COUNT(context_id)": 8}, + {"request_id": 4, "label": "greeting_flow: node1", "COUNT(context_id)": 4}, + ], + 6: [], + 7: [], + 8: [], + 9: [ + {"label": "greeting_flow: node3", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, + {"label": "greeting_flow: node4", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, + {"label": "greeting_flow: node2", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, + {"label": "greeting_flow: node1", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, + ], + 10: [], + 11: [ + {"label": "greeting_flow: node4", "prev_label": "greeting_flow: node4", "COUNT_DISTINCT(context_id)": 1}, + {"label": "greeting_flow: node2", "prev_label": "greeting_flow: node2", "COUNT_DISTINCT(context_id)": 1}, + {"label": "greeting_flow: node1", "prev_label": "greeting_flow: node1", "COUNT_DISTINCT(context_id)": 1}, + {"label": "greeting_flow: node3", "prev_label": "greeting_flow: node3", "COUNT_DISTINCT(context_id)": 1}, + ], + 12: [ + { + "prev_label": "greeting_flow: node1", + "label": "greeting_flow: node1", + "flow_label": "greeting_flow", + "COUNT(context_id)": 7, + }, + { + "prev_label": "greeting_flow: node2", + "label": "greeting_flow: node2", + "flow_label": "greeting_flow", + "COUNT(context_id)": 7, + }, + { + "prev_label": "greeting_flow: node3", + "label": "greeting_flow: node3", + "flow_label": "greeting_flow", + "COUNT(context_id)": 2, + }, + { + "prev_label": "greeting_flow: node4", + "label": "greeting_flow: node4", + "flow_label": "greeting_flow", + "COUNT(context_id)": 2, + }, + ], + 13: [ + {"__timestamp": 1698318360000, "greeting_flow": 0.09523809523809523}, + {"__timestamp": 1698319740000, "greeting_flow": 0.09523809523809523}, + {"__timestamp": 1698321300000, "greeting_flow": 0.047619047619047616}, + {"__timestamp": 1698321480000, "greeting_flow": 0.047619047619047616}, + {"__timestamp": 1698396000000, "greeting_flow": 0.047619047619047616}, + {"__timestamp": 1698397440000, "greeting_flow": 0.047619047619047616}, + {"__timestamp": 1698397680000, "greeting_flow": 0.14285714285714285}, + {"__timestamp": 1698398040000, "greeting_flow": 0.14285714285714285}, + {"__timestamp": 1698402720000, "greeting_flow": 0.09523809523809523}, + {"__timestamp": 1698402840000, "greeting_flow": 0.23809523809523808}, + ], + 14: [ + { + "__timestamp": 1698318360000, + "greeting_flow, node1": 0, + "greeting_flow, node2": 0.14285714285714285, + "greeting_flow, node3": 0, + "greeting_flow, node4": 0.3333333333333333, + }, + { + "__timestamp": 1698319740000, + "greeting_flow, node1": 0.125, + "greeting_flow, node2": 0.14285714285714285, + "greeting_flow, node3": 0, + "greeting_flow, node4": 0, + }, + { + "__timestamp": 1698321300000, + "greeting_flow, node1": 0, + "greeting_flow, node2": 0.14285714285714285, + "greeting_flow, node3": 0, + "greeting_flow, node4": 0, + }, + { + "__timestamp": 1698321480000, + "greeting_flow, node1": 0, + "greeting_flow, node2": 0.14285714285714285, + "greeting_flow, node3": 0, + "greeting_flow, node4": 0, + }, + { + "__timestamp": 1698396000000, + "greeting_flow, node1": 0.125, + "greeting_flow, node2": 0, + "greeting_flow, node3": 0, + "greeting_flow, node4": 0, + }, + { + "__timestamp": 1698397440000, + "greeting_flow, node1": 0, + "greeting_flow, node2": 0.14285714285714285, + "greeting_flow, node3": 0, + "greeting_flow, node4": 0, + }, + { + "__timestamp": 1698397680000, + "greeting_flow, node1": 0.25, + "greeting_flow, node2": 0, + "greeting_flow, node3": 0.3333333333333333, + "greeting_flow, node4": 0, + }, + { + "__timestamp": 1698398040000, + "greeting_flow, node1": 0, + "greeting_flow, node2": 0.14285714285714285, + "greeting_flow, node3": 0.3333333333333333, + "greeting_flow, node4": 0.3333333333333333, + }, + { + "__timestamp": 1698402720000, + "greeting_flow, node1": 0.25, + "greeting_flow, node2": 0, + "greeting_flow, node3": 0, + "greeting_flow, node4": 0, + }, + { + "__timestamp": 1698402840000, + "greeting_flow, node1": 0.25, + "greeting_flow, node2": 0.14285714285714285, + "greeting_flow, node3": 0.3333333333333333, + "greeting_flow, node4": 0.3333333333333333, + }, + ], + 15: [], + 16: [ + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402755000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003281"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698396045000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397983000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698396046000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698321340000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397983000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.011790"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698318377000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698318377000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node4","node":"node4"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402875000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397683000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397683000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003016"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402875000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node4","node":"node4"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397683000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node3","node":"node3"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402755000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003016"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397463000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698321484000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003016"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698396046000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698319785000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397983000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.004255"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397463000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003281"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698319785000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003016"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698316771000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698398067000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698398067000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698398067000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node4","node":"node4"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402755000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698316771000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003016"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698318377000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698321340000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402875000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397463000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402875000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node3","node":"node3"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397683000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.005099"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698321484000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698319785000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698319785000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698397463000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.011790"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698396046000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003016"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698316771000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698316771000, + "data_key": "get_current_label", + "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698402755000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698321340000, + "data_key": "get_current_label", + "data": '{"execution_time":"0:00:00.003016"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698321484000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + }, + { + "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", + "start_time": 1698398067000, + "data_key": "get_current_label", + "data": '{"flow":"greeting_flow","label":"greeting_flow: node3","node":"node3"}', + }, + ], + 17: [ + {"flow_label": "greeting_flow", "node_label": "node2", "COUNT(context_id)": 8}, + {"flow_label": "greeting_flow", "node_label": "node4", "COUNT(context_id)": 3}, + {"flow_label": "greeting_flow", "node_label": "node3", "COUNT(context_id)": 3}, + {"flow_label": "greeting_flow", "node_label": "node1", "COUNT(context_id)": 9}, + ], +} diff --git a/tests/stats/test_main.py b/tests/stats/test_main.py index c6539343e..5901e3270 100644 --- a/tests/stats/test_main.py +++ b/tests/stats/test_main.py @@ -12,6 +12,7 @@ except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) +from tests.stats.chart_data import CHART_DATA from tests.context_storages.test_dbs import ping_localhost from tests.test_utils import get_path_from_tests_to_current_dir @@ -52,7 +53,6 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): dashboard_res = session.get(dashboard_url, headers=headers) assert dashboard_res.status_code == 200 dashboard_json = dashboard_res.json() - print(dashboard_json["result"]["charts"]) assert sorted(dashboard_json["result"]["charts"]) == [ "Current topic [time series bar chart]", "Current topic slot [bar chart]", @@ -77,8 +77,6 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): datasets_result = session.get(datasets_url, headers=headers) datasets_json = datasets_result.json() assert datasets_json["count"] == 3 - assert datasets_json["ids"] == [1, 2, 3] - assert [item["id"] for item in datasets_json["result"]] == [1, 2, 3] assert sorted([item["table_name"] for item in datasets_json["result"]]) == [ "dff_final_nodes", "dff_node_stats", @@ -87,7 +85,19 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): charts_result = session.get(charts_url, headers=headers) charts_json = charts_result.json() assert charts_json["count"] == 17 - assert sorted(charts_json["ids"]) == list(range(1, 18)) + print(*charts_json["ids"]) + for _id in charts_json["ids"]: + data_result = session.get( + parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers + ) + assert data_result.status_code == 200 + data_result_json = data_result.json() + assert data_result_json["result"][-1]["status"] == "success" + assert data_result_json["result"][-1]["stacktrace"] is None + data = data_result_json["result"][-1]["data"] + ignored_keys = ["context_id", "__timestamp", "start_time", "data"] + filtered_data = [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] + # assert filtered_data == CHART_DATA[_id] session.close() From 735424ebc1102bff2ca9e5c19fe0936fac469eb6 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Mon, 30 Oct 2023 11:37:08 +0300 Subject: [PATCH 02/20] Update formatting --- tests/stats/chart_data.py | 1 + tests/stats/test_main.py | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py index 71b8500a9..b5c14c41a 100644 --- a/tests/stats/chart_data.py +++ b/tests/stats/chart_data.py @@ -1,3 +1,4 @@ +# flake8: noqa: E501 CHART_DATA = { 1: [ { diff --git a/tests/stats/test_main.py b/tests/stats/test_main.py index 5901e3270..189a4bc93 100644 --- a/tests/stats/test_main.py +++ b/tests/stats/test_main.py @@ -12,7 +12,7 @@ except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) -from tests.stats.chart_data import CHART_DATA +from tests.stats.chart_data import CHART_DATA # noqa: F401 from tests.context_storages.test_dbs import ping_localhost from tests.test_utils import get_path_from_tests_to_current_dir @@ -85,8 +85,8 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): charts_result = session.get(charts_url, headers=headers) charts_json = charts_result.json() assert charts_json["count"] == 17 - print(*charts_json["ids"]) for _id in charts_json["ids"]: + print(str(_id)) data_result = session.get( parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers ) @@ -96,8 +96,8 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): assert data_result_json["result"][-1]["stacktrace"] is None data = data_result_json["result"][-1]["data"] ignored_keys = ["context_id", "__timestamp", "start_time", "data"] - filtered_data = [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] - # assert filtered_data == CHART_DATA[_id] + _ = [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] + # assert _ == CHART_DATA[_id] session.close() From 6db2543f214eece2d9d5a7d828d97aa236447424 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Mon, 30 Oct 2023 11:54:08 +0300 Subject: [PATCH 03/20] sort chart ids for debugging --- tests/stats/test_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stats/test_main.py b/tests/stats/test_main.py index 189a4bc93..b26b3a286 100644 --- a/tests/stats/test_main.py +++ b/tests/stats/test_main.py @@ -85,7 +85,7 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): charts_result = session.get(charts_url, headers=headers) charts_json = charts_result.json() assert charts_json["count"] == 17 - for _id in charts_json["ids"]: + for _id in sorted(charts_json["ids"]): print(str(_id)) data_result = session.get( parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers From b7480a2e0127344da947b617ffa087ca834972a2 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Mon, 30 Oct 2023 14:21:13 +0300 Subject: [PATCH 04/20] add debug prints --- tests/stats/test_main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/stats/test_main.py b/tests/stats/test_main.py index b26b3a286..5d51b19f9 100644 --- a/tests/stats/test_main.py +++ b/tests/stats/test_main.py @@ -90,7 +90,9 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): data_result = session.get( parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers ) - assert data_result.status_code == 200 + print(data_result.reason) + print(data_result.text) + data_result.raise_for_status() data_result_json = data_result.json() assert data_result_json["result"][-1]["status"] == "success" assert data_result_json["result"][-1]["stacktrace"] is None From 57f778d50a0eb6e0500bed3c7c68bc883d64cdb7 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Mon, 30 Oct 2023 16:28:22 +0300 Subject: [PATCH 05/20] add chart tests --- tests/stats/test_charts.py | 44 ++++++++++++++++++++++++++++++++++++++ tests/stats/test_main.py | 16 -------------- 2 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 tests/stats/test_charts.py diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py new file mode 100644 index 000000000..acef85218 --- /dev/null +++ b/tests/stats/test_charts.py @@ -0,0 +1,44 @@ +import os +import time +from argparse import Namespace +from urllib import parse +import pytest +from dff.stats.utils import get_superset_session +from dff.stats.cli import DEFAULT_SUPERSET_URL +from tests.stats.chart_data import CHART_DATA # noqa: F401 +from tests.context_storages.test_dbs import ping_localhost + +SUPERSET_ACTIVE = ping_localhost(8088) + + +@pytest.mark.skipif(not SUPERSET_ACTIVE, reason="Superset server not active") +@pytest.mark.docker +def test_charts(): + charts_url = parse.urljoin(DEFAULT_SUPERSET_URL, "/api/v1/chart") + args = Namespace( + **{ + "username": os.environ["SUPERSET_USERNAME"], + "password": os.environ["SUPERSET_PASSWORD"], + } + ) + session, headers = get_superset_session(args) + charts_result = session.get(charts_url, headers=headers) + charts_json = charts_result.json() + + for _id in sorted(charts_json["ids"]): + time.sleep(0.1) + print(str(_id)) + data_result = session.get( + parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers + ) + print(data_result.reason) + print(data_result.text) + data_result.raise_for_status() + data_result_json = data_result.json() + assert data_result_json["result"][-1]["status"] == "success" + assert data_result_json["result"][-1]["stacktrace"] is None + data = data_result_json["result"][-1]["data"] + ignored_keys = ["context_id", "__timestamp", "start_time", "data"] + _ = [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] + # assert _ == CHART_DATA[_id] + session.close() diff --git a/tests/stats/test_main.py b/tests/stats/test_main.py index 5d51b19f9..c188a00d5 100644 --- a/tests/stats/test_main.py +++ b/tests/stats/test_main.py @@ -12,7 +12,6 @@ except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) -from tests.stats.chart_data import CHART_DATA # noqa: F401 from tests.context_storages.test_dbs import ping_localhost from tests.test_utils import get_path_from_tests_to_current_dir @@ -85,21 +84,6 @@ def dashboard_display_test(args: Namespace, session, headers, base_url: str): charts_result = session.get(charts_url, headers=headers) charts_json = charts_result.json() assert charts_json["count"] == 17 - for _id in sorted(charts_json["ids"]): - print(str(_id)) - data_result = session.get( - parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers - ) - print(data_result.reason) - print(data_result.text) - data_result.raise_for_status() - data_result_json = data_result.json() - assert data_result_json["result"][-1]["status"] == "success" - assert data_result_json["result"][-1]["stacktrace"] is None - data = data_result_json["result"][-1]["data"] - ignored_keys = ["context_id", "__timestamp", "start_time", "data"] - _ = [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] - # assert _ == CHART_DATA[_id] session.close() From ab416fcc45bd92ffce6ea02dbdc7f8e69b9bfa13 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Mon, 30 Oct 2023 18:03:52 +0300 Subject: [PATCH 06/20] update test charts --- tests/stats/test_charts.py | 78 +++++++++++++++---- .../stats/3_sample_data_provider.py | 3 +- 2 files changed, 67 insertions(+), 14 deletions(-) rename utils/stats/sample_data_provider.py => tutorials/stats/3_sample_data_provider.py (99%) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index acef85218..bbb3a44a7 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -1,32 +1,44 @@ import os import time +import importlib +import random +import asyncio from argparse import Namespace from urllib import parse import pytest -from dff.stats.utils import get_superset_session -from dff.stats.cli import DEFAULT_SUPERSET_URL + +try: + from aiochclient import ChClient + from httpx import AsyncClient + import omegaconf # noqa: F401 + from dff.stats.utils import get_superset_session + from dff.stats.cli import DEFAULT_SUPERSET_URL +except ImportError: + pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) + from tests.stats.chart_data import CHART_DATA # noqa: F401 from tests.context_storages.test_dbs import ping_localhost +from tests.test_utils import get_path_from_tests_to_current_dir + +random.seed(42) +dot_path_to_addon = get_path_from_tests_to_current_dir(__file__) SUPERSET_ACTIVE = ping_localhost(8088) +COLLECTOR_AVAILABLE = ping_localhost(4317) +CLICKHOUSE_AVAILABLE = ping_localhost(8123) +CLICKHOUSE_USER = os.getenv("CLICKHOUSE_USER") +CLICKHOUSE_PASSWORD = os.getenv("CLICKHOUSE_PASSWORD") +CLICKHOUSE_DB = os.getenv("CLICKHOUSE_DB") -@pytest.mark.skipif(not SUPERSET_ACTIVE, reason="Superset server not active") -@pytest.mark.docker -def test_charts(): +def charts_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): charts_url = parse.urljoin(DEFAULT_SUPERSET_URL, "/api/v1/chart") - args = Namespace( - **{ - "username": os.environ["SUPERSET_USERNAME"], - "password": os.environ["SUPERSET_PASSWORD"], - } - ) - session, headers = get_superset_session(args) + charts_result = session.get(charts_url, headers=headers) charts_json = charts_result.json() for _id in sorted(charts_json["ids"]): - time.sleep(0.1) + time.sleep(0.5) print(str(_id)) data_result = session.get( parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers @@ -42,3 +54,43 @@ def test_charts(): _ = [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] # assert _ == CHART_DATA[_id] session.close() + + +@pytest.mark.skipif(not SUPERSET_ACTIVE, reason="Superset server not active") +@pytest.mark.skipif(not CLICKHOUSE_AVAILABLE, reason="Clickhouse unavailable.") +@pytest.mark.skipif(not COLLECTOR_AVAILABLE, reason="OTLP collector unavailable.") +@pytest.mark.skipif( + not all([CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB]), reason="Clickhouse credentials missing" +) +@pytest.mark.asyncio +@pytest.mark.parametrize( + [ + "example_module_name", + ], + [ + ("3_sample_data_provider",), + ], +) +@pytest.mark.docker +async def test_charts(example_module_name, otlp_log_exp_provider, otlp_trace_exp_provider): + module = importlib.import_module(f"tutorials.{dot_path_to_addon}.{example_module_name}") + _, tracer_provider = otlp_trace_exp_provider + _, logger_provider = otlp_log_exp_provider + http_client = AsyncClient() + table = "otel_logs" + ch_client = ChClient(http_client, user=CLICKHOUSE_USER, password=CLICKHOUSE_PASSWORD, database=CLICKHOUSE_DB) + + await ch_client.execute(f"TRUNCATE {table}") + module.dff_instrumentor.uninstrument() + module.dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) + module.main(25) + await asyncio.sleep(1) + + args = Namespace( + **{ + "username": os.environ["SUPERSET_USERNAME"], + "password": os.environ["SUPERSET_PASSWORD"], + } + ) + session, headers = get_superset_session(args) + charts_data_test(session, headers) diff --git a/utils/stats/sample_data_provider.py b/tutorials/stats/3_sample_data_provider.py similarity index 99% rename from utils/stats/sample_data_provider.py rename to tutorials/stats/3_sample_data_provider.py index d778c922a..2c1de3dbd 100644 --- a/utils/stats/sample_data_provider.py +++ b/tutorials/stats/3_sample_data_provider.py @@ -1,6 +1,7 @@ -#!/usr/bin/env python # %% [markdown] """ +# 3. Sample data provider + This script demonstrates various instrumentation capabilities. It also provides data for the dashboard emulating simultaneous queries to the service by multiple users. From 6fecfb08e0b1dc716b12d07039db4b5208bb7e87 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Tue, 31 Oct 2023 12:14:18 +0300 Subject: [PATCH 07/20] update chart data && test charts --- tests/stats/chart_data.py | 547 +++++++++------------- tests/stats/test_charts.py | 2 +- tutorials/stats/3_sample_data_provider.py | 3 +- 3 files changed, 237 insertions(+), 315 deletions(-) diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py index b5c14c41a..909357e6d 100644 --- a/tests/stats/chart_data.py +++ b/tests/stats/chart_data.py @@ -1,466 +1,387 @@ # flake8: noqa: E501 CHART_DATA = { - 1: [ + 1: [], + 2: [ { - "prev_label": "greeting_flow: node1", - "label": "greeting_flow: node1", - "flow_label": "greeting_flow", - "COUNT_DISTINCT(context_id)": 1, + "__timestamp": 1698741640000, + "animals, have_pets": None, + "animals, like_animals": None, + "animals, what_animal": None, + "root, fallback": 1, }, { - "prev_label": "greeting_flow: node2", - "label": "greeting_flow: node2", - "flow_label": "greeting_flow", - "COUNT_DISTINCT(context_id)": 1, + "__timestamp": 1698741642000, + "animals, have_pets": None, + "animals, like_animals": None, + "animals, what_animal": None, + "root, fallback": 2, }, { - "prev_label": "greeting_flow: node3", - "label": "greeting_flow: node3", - "flow_label": "greeting_flow", - "COUNT_DISTINCT(context_id)": 1, + "__timestamp": 1698741647000, + "animals, have_pets": None, + "animals, like_animals": None, + "animals, what_animal": None, + "root, fallback": 1, }, { - "prev_label": "greeting_flow: node4", - "label": "greeting_flow: node4", - "flow_label": "greeting_flow", - "COUNT_DISTINCT(context_id)": 1, + "__timestamp": 1698741663000, + "animals, have_pets": None, + "animals, like_animals": None, + "animals, what_animal": None, + "root, fallback": 1, + }, + { + "__timestamp": 1698741667000, + "animals, have_pets": None, + "animals, like_animals": None, + "animals, what_animal": None, + "root, fallback": 2, + }, + { + "__timestamp": 1698741673000, + "animals, have_pets": None, + "animals, like_animals": None, + "animals, what_animal": None, + "root, fallback": 1, + }, + { + "__timestamp": 1698741674000, + "animals, have_pets": None, + "animals, like_animals": 1, + "animals, what_animal": 1, + "root, fallback": None, + }, + { + "__timestamp": 1698741678000, + "animals, have_pets": 1, + "animals, like_animals": None, + "animals, what_animal": None, + "root, fallback": None, }, - ], - 2: [ - {"__timestamp": 1698316771000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698318377000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698319785000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698321340000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698321484000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698396046000, ", ": None, "greeting_flow, node1": 1}, - {"__timestamp": 1698397463000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698397683000, ", ": None, "greeting_flow, node1": 1}, - {"__timestamp": 1698397983000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698398067000, ", ": 1, "greeting_flow, node1": None}, - {"__timestamp": 1698402755000, ", ": None, "greeting_flow, node1": 1}, - {"__timestamp": 1698402875000, ", ": None, "greeting_flow, node1": 1}, ], 3: [ - {"flow_label": "greeting_flow", "node_label": "node1", "COUNT(context_id)": 9}, - {"flow_label": "greeting_flow", "node_label": "node2", "COUNT(context_id)": 8}, - {"flow_label": "greeting_flow", "node_label": "node4", "COUNT(context_id)": 3}, - {"flow_label": "greeting_flow", "node_label": "node3", "COUNT(context_id)": 3}, - ], - 4: [ - {"__timestamp": 1698316500000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698318300000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698319500000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698321300000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698396000000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698397200000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698397500000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698397800000, "COUNT_DISTINCT(context_id)": 1}, - {"__timestamp": 1698402600000, "COUNT_DISTINCT(context_id)": 1}, + {"flow_label": "animals", "node_label": "what_animal", "COUNT(context_id)": 9}, + {"flow_label": "root", "node_label": "fallback", "COUNT(context_id)": 8}, + {"flow_label": "animals", "node_label": "ask_about_color", "COUNT(context_id)": 6}, + {"flow_label": "animals", "node_label": "have_pets", "COUNT(context_id)": 6}, + {"flow_label": "animals", "node_label": "like_animals", "COUNT(context_id)": 5}, + {"flow_label": "animals", "node_label": "ask_about_breed", "COUNT(context_id)": 3}, + {"flow_label": "animals", "node_label": "ask_about_training", "COUNT(context_id)": 2}, + {"flow_label": "small_talk", "node_label": "ask_some_questions", "COUNT(context_id)": 1}, ], + 4: [{"__timestamp": 1698741600000, "COUNT_DISTINCT(context_id)": 11}], 5: [ - {"request_id": 0, "label": "greeting_flow: node1", "COUNT(context_id)": 5}, - {"request_id": 2, "label": "greeting_flow: node3", "COUNT(context_id)": 3}, - {"request_id": 3, "label": "greeting_flow: node4", "COUNT(context_id)": 3}, - {"request_id": 1, "label": "greeting_flow: node2", "COUNT(context_id)": 8}, - {"request_id": 4, "label": "greeting_flow: node1", "COUNT(context_id)": 4}, + {"request_id": 4, "label": "animals: ask_about_training", "COUNT(context_id)": 1}, + {"request_id": 1, "label": "animals: like_animals", "COUNT(context_id)": 1}, + {"request_id": 2, "label": "animals: ask_about_breed", "COUNT(context_id)": 2}, + {"request_id": 0, "label": "animals: like_animals", "COUNT(context_id)": 4}, + {"request_id": 5, "label": "root: fallback", "COUNT(context_id)": 1}, + {"request_id": 3, "label": "animals: ask_about_training", "COUNT(context_id)": 1}, + {"request_id": 0, "label": "animals: have_pets", "COUNT(context_id)": 6}, + {"request_id": 3, "label": "animals: ask_about_breed", "COUNT(context_id)": 1}, + {"request_id": 2, "label": "animals: what_animal", "COUNT(context_id)": 1}, + {"request_id": 3, "label": "root: fallback", "COUNT(context_id)": 5}, + {"request_id": 0, "label": "small_talk: ask_some_questions", "COUNT(context_id)": 1}, + {"request_id": 2, "label": "animals: ask_about_color", "COUNT(context_id)": 5}, + {"request_id": 4, "label": "root: fallback", "COUNT(context_id)": 2}, + {"request_id": 1, "label": "animals: what_animal", "COUNT(context_id)": 8}, + {"request_id": 3, "label": "animals: ask_about_color", "COUNT(context_id)": 1}, ], 6: [], 7: [], 8: [], 9: [ - {"label": "greeting_flow: node3", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, - {"label": "greeting_flow: node4", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, - {"label": "greeting_flow: node2", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, - {"label": "greeting_flow: node1", "flow_label": "greeting_flow", "COUNT_DISTINCT(context_id)": 1}, + {"label": "root: fallback", "flow_label": "root", "COUNT_DISTINCT(context_id)": 8}, + {"label": "small_talk: ask_some_questions", "flow_label": "small_talk", "COUNT_DISTINCT(context_id)": 1}, + {"label": "animals: have_pets", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 6}, + {"label": "animals: ask_about_color", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 6}, + {"label": "animals: ask_about_breed", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 2}, + {"label": "animals: like_animals", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 5}, + {"label": "animals: ask_about_training", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 2}, + {"label": "animals: what_animal", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 9}, ], 10: [], - 11: [ - {"label": "greeting_flow: node4", "prev_label": "greeting_flow: node4", "COUNT_DISTINCT(context_id)": 1}, - {"label": "greeting_flow: node2", "prev_label": "greeting_flow: node2", "COUNT_DISTINCT(context_id)": 1}, - {"label": "greeting_flow: node1", "prev_label": "greeting_flow: node1", "COUNT_DISTINCT(context_id)": 1}, - {"label": "greeting_flow: node3", "prev_label": "greeting_flow: node3", "COUNT_DISTINCT(context_id)": 1}, - ], - 12: [ - { - "prev_label": "greeting_flow: node1", - "label": "greeting_flow: node1", - "flow_label": "greeting_flow", - "COUNT(context_id)": 7, - }, - { - "prev_label": "greeting_flow: node2", - "label": "greeting_flow: node2", - "flow_label": "greeting_flow", - "COUNT(context_id)": 7, - }, - { - "prev_label": "greeting_flow: node3", - "label": "greeting_flow: node3", - "flow_label": "greeting_flow", - "COUNT(context_id)": 2, - }, - { - "prev_label": "greeting_flow: node4", - "label": "greeting_flow: node4", - "flow_label": "greeting_flow", - "COUNT(context_id)": 2, - }, - ], + 11: [], + 12: [], 13: [ - {"__timestamp": 1698318360000, "greeting_flow": 0.09523809523809523}, - {"__timestamp": 1698319740000, "greeting_flow": 0.09523809523809523}, - {"__timestamp": 1698321300000, "greeting_flow": 0.047619047619047616}, - {"__timestamp": 1698321480000, "greeting_flow": 0.047619047619047616}, - {"__timestamp": 1698396000000, "greeting_flow": 0.047619047619047616}, - {"__timestamp": 1698397440000, "greeting_flow": 0.047619047619047616}, - {"__timestamp": 1698397680000, "greeting_flow": 0.14285714285714285}, - {"__timestamp": 1698398040000, "greeting_flow": 0.14285714285714285}, - {"__timestamp": 1698402720000, "greeting_flow": 0.09523809523809523}, - {"__timestamp": 1698402840000, "greeting_flow": 0.23809523809523808}, + {"__timestamp": 1698741600000, "animals": 0.7419354838709677, "root": 0.5, "small_talk": 1}, + {"__timestamp": 1698741660000, "animals": 0.25806451612903225, "root": 0.5, "small_talk": 0}, ], 14: [ { - "__timestamp": 1698318360000, - "greeting_flow, node1": 0, - "greeting_flow, node2": 0.14285714285714285, - "greeting_flow, node3": 0, - "greeting_flow, node4": 0.3333333333333333, - }, - { - "__timestamp": 1698319740000, - "greeting_flow, node1": 0.125, - "greeting_flow, node2": 0.14285714285714285, - "greeting_flow, node3": 0, - "greeting_flow, node4": 0, - }, - { - "__timestamp": 1698321300000, - "greeting_flow, node1": 0, - "greeting_flow, node2": 0.14285714285714285, - "greeting_flow, node3": 0, - "greeting_flow, node4": 0, - }, - { - "__timestamp": 1698321480000, - "greeting_flow, node1": 0, - "greeting_flow, node2": 0.14285714285714285, - "greeting_flow, node3": 0, - "greeting_flow, node4": 0, - }, - { - "__timestamp": 1698396000000, - "greeting_flow, node1": 0.125, - "greeting_flow, node2": 0, - "greeting_flow, node3": 0, - "greeting_flow, node4": 0, - }, - { - "__timestamp": 1698397440000, - "greeting_flow, node1": 0, - "greeting_flow, node2": 0.14285714285714285, - "greeting_flow, node3": 0, - "greeting_flow, node4": 0, - }, - { - "__timestamp": 1698397680000, - "greeting_flow, node1": 0.25, - "greeting_flow, node2": 0, - "greeting_flow, node3": 0.3333333333333333, - "greeting_flow, node4": 0, - }, - { - "__timestamp": 1698398040000, - "greeting_flow, node1": 0, - "greeting_flow, node2": 0.14285714285714285, - "greeting_flow, node3": 0.3333333333333333, - "greeting_flow, node4": 0.3333333333333333, - }, - { - "__timestamp": 1698402720000, - "greeting_flow, node1": 0.25, - "greeting_flow, node2": 0, - "greeting_flow, node3": 0, - "greeting_flow, node4": 0, - }, - { - "__timestamp": 1698402840000, - "greeting_flow, node1": 0.25, - "greeting_flow, node2": 0.14285714285714285, - "greeting_flow, node3": 0.3333333333333333, - "greeting_flow, node4": 0.3333333333333333, + "__timestamp": 1698741600000, + "animals, ask_about_breed": 0.6666666666666666, + "animals, ask_about_color": 0.8333333333333334, + "animals, ask_about_training": 0, + "animals, have_pets": 0.6666666666666666, + "animals, like_animals": 0.8, + "animals, what_animal": 0.8888888888888888, + "root, fallback": 0.5, + "small_talk, ask_some_questions": 1, + }, + { + "__timestamp": 1698741660000, + "animals, ask_about_breed": 0.3333333333333333, + "animals, ask_about_color": 0.16666666666666666, + "animals, ask_about_training": 1, + "animals, have_pets": 0.3333333333333333, + "animals, like_animals": 0.2, + "animals, what_animal": 0.1111111111111111, + "root, fallback": 0.5, + "small_talk, ask_some_questions": 0, }, ], 15: [], 16: [ { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402755000, - "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003281"}', - }, - { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698396045000, - "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', - }, - { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397983000, - "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', - }, - { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698396046000, - "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', - }, - { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698321340000, + "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", + "start_time": 1698741637000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397983000, + "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", + "start_time": 1698741637000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.011790"}', + "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698318377000, + "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", + "start_time": 1698741640000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698318377000, + "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", + "start_time": 1698741649000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node4","node":"node4"}', + "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402875000, + "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", + "start_time": 1698741633000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397683000, + "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", + "start_time": 1698741626000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397683000, + "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", + "start_time": 1698741654000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003016"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402875000, + "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", + "start_time": 1698741663000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node4","node":"node4"}', + "data": '{"flow":"animals","label":"animals: ask_about_training","node":"ask_about_training"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397683000, + "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", + "start_time": 1698741632000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node3","node":"node3"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402755000, + "context_id": "e9fdd58e-58db-403c-a965-1336c7f05501", + "start_time": 1698741674000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003016"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397463000, + "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", + "start_time": 1698741647000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698321484000, + "context_id": "6f311fc7-fb9b-48ee-9dcb-d1a80a40ece5", + "start_time": 1698741674000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003016"}', + "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698396046000, + "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", + "start_time": 1698741628000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698319785000, + "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", + "start_time": 1698741669000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"animals","label":"animals: ask_about_training","node":"ask_about_training"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397983000, + "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", + "start_time": 1698741667000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.004255"}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397463000, + "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", + "start_time": 1698741634000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003281"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698319785000, + "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", + "start_time": 1698741650000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003016"}', + "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698316771000, + "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", + "start_time": 1698741662000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"animals","label":"animals: ask_about_breed","node":"ask_about_breed"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698398067000, + "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", + "start_time": 1698741659000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698398067000, + "context_id": "e9fdd58e-58db-403c-a965-1336c7f05501", + "start_time": 1698741670000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698398067000, + "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", + "start_time": 1698741673000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node4","node":"node4"}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402755000, + "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", + "start_time": 1698741647000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698316771000, + "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", + "start_time": 1698741635000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003016"}', + "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698318377000, + "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", + "start_time": 1698741663000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698321340000, + "context_id": "26d11ea4-81e6-4e97-9520-384f82b006e4", + "start_time": 1698741678000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402875000, + "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", + "start_time": 1698741642000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397463000, + "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", + "start_time": 1698741642000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402875000, + "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", + "start_time": 1698741667000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node3","node":"node3"}', + "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397683000, + "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", + "start_time": 1698741659000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.005099"}', + "data": '{"flow":"animals","label":"animals: ask_about_breed","node":"ask_about_breed"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698321484000, + "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", + "start_time": 1698741653000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698319785000, + "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", + "start_time": 1698741633000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698319785000, + "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", + "start_time": 1698741627000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698397463000, + "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", + "start_time": 1698741658000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.011790"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698396046000, + "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", + "start_time": 1698741636000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003016"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698316771000, + "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", + "start_time": 1698741654000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698316771000, + "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", + "start_time": 1698741664000, "data_key": "get_current_label", - "data": '{"execution_state":{".pipeline":"RUNNING",".pipeline.actor_0":"FINISHED",".pipeline.service_group_0":"FINISHED",".pipeline.service_group_0.heavy_service_0":"FINISHED",".pipeline.service_group_0.heavy_service_1":"FINISHED"}}', + "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698402755000, + "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", + "start_time": 1698741657000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node1","node":"node1"}', + "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698321340000, + "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", + "start_time": 1698741629000, "data_key": "get_current_label", - "data": '{"execution_time":"0:00:00.003016"}', + "data": '{"flow":"small_talk","label":"small_talk: ask_some_questions","node":"ask_some_questions"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698321484000, + "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", + "start_time": 1698741642000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node2","node":"node2"}', + "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', }, { - "context_id": "142f7668-e832-4087-af85-bddbf36b0a7d", - "start_time": 1698398067000, + "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", + "start_time": 1698741658000, "data_key": "get_current_label", - "data": '{"flow":"greeting_flow","label":"greeting_flow: node3","node":"node3"}', + "data": '{"flow":"animals","label":"animals: ask_about_breed","node":"ask_about_breed"}', }, ], 17: [ - {"flow_label": "greeting_flow", "node_label": "node2", "COUNT(context_id)": 8}, - {"flow_label": "greeting_flow", "node_label": "node4", "COUNT(context_id)": 3}, - {"flow_label": "greeting_flow", "node_label": "node3", "COUNT(context_id)": 3}, - {"flow_label": "greeting_flow", "node_label": "node1", "COUNT(context_id)": 9}, + {"flow_label": "root", "node_label": "fallback", "COUNT(context_id)": 8}, + {"flow_label": "animals", "node_label": "ask_about_breed", "COUNT(context_id)": 3}, + {"flow_label": "animals", "node_label": "what_animal", "COUNT(context_id)": 9}, + {"flow_label": "animals", "node_label": "ask_about_color", "COUNT(context_id)": 6}, + {"flow_label": "animals", "node_label": "like_animals", "COUNT(context_id)": 5}, + {"flow_label": "small_talk", "node_label": "ask_some_questions", "COUNT(context_id)": 1}, + {"flow_label": "animals", "node_label": "ask_about_training", "COUNT(context_id)": 2}, + {"flow_label": "animals", "node_label": "have_pets", "COUNT(context_id)": 6}, ], } diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index bbb3a44a7..ac8e56a10 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -83,7 +83,7 @@ async def test_charts(example_module_name, otlp_log_exp_provider, otlp_trace_exp await ch_client.execute(f"TRUNCATE {table}") module.dff_instrumentor.uninstrument() module.dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) - module.main(25) + module.main(40) await asyncio.sleep(1) args = Namespace( diff --git a/tutorials/stats/3_sample_data_provider.py b/tutorials/stats/3_sample_data_provider.py index 2c1de3dbd..750acfdac 100644 --- a/tutorials/stats/3_sample_data_provider.py +++ b/tutorials/stats/3_sample_data_provider.py @@ -20,6 +20,7 @@ ) from dff.utils.testing.toy_script import MULTIFLOW_SCRIPT, MULTIFLOW_REQUEST_OPTIONS +random.seed(42) # %% # instrumentation code dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) @@ -109,7 +110,7 @@ async def worker(queue: asyncio.Queue): # %% # main loop -async def main(n_iterations: int = 100, n_workers: int = 4): +async def main(n_iterations: int = 40, n_workers: int = 4): """ The main loop that runs one or more worker coroutines in parallel. From 35724cf782ed0bafb4e209fe84e9f8a9ce36e948 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Tue, 31 Oct 2023 13:54:45 +0300 Subject: [PATCH 08/20] update data provider body --- tutorials/stats/3_sample_data_provider.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tutorials/stats/3_sample_data_provider.py b/tutorials/stats/3_sample_data_provider.py index 750acfdac..73f7dcbd5 100644 --- a/tutorials/stats/3_sample_data_provider.py +++ b/tutorials/stats/3_sample_data_provider.py @@ -8,6 +8,8 @@ """ +# %pip install dff[stats] + # %% import random import asyncio @@ -20,7 +22,6 @@ ) from dff.utils.testing.toy_script import MULTIFLOW_SCRIPT, MULTIFLOW_REQUEST_OPTIONS -random.seed(42) # %% # instrumentation code dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) @@ -110,7 +111,7 @@ async def worker(queue: asyncio.Queue): # %% # main loop -async def main(n_iterations: int = 40, n_workers: int = 4): +async def main(n_iterations: int = 100, n_workers: int = 4): """ The main loop that runs one or more worker coroutines in parallel. From 466a226570b983fac2d589b75ffff4105cd3ea49 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Tue, 31 Oct 2023 13:57:20 +0300 Subject: [PATCH 09/20] debug test --- tests/stats/test_charts.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index ac8e56a10..1df6526c9 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -11,6 +11,7 @@ from aiochclient import ChClient from httpx import AsyncClient import omegaconf # noqa: F401 + import tqdm # noqa: F401 from dff.stats.utils import get_superset_session from dff.stats.cli import DEFAULT_SUPERSET_URL except ImportError: @@ -83,7 +84,7 @@ async def test_charts(example_module_name, otlp_log_exp_provider, otlp_trace_exp await ch_client.execute(f"TRUNCATE {table}") module.dff_instrumentor.uninstrument() module.dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) - module.main(40) + await module.main(40) await asyncio.sleep(1) args = Namespace( From beb2a8da9f3723c6109843d48d461263401d1858 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Tue, 31 Oct 2023 14:54:20 +0300 Subject: [PATCH 10/20] Unlock data comparison statement --- tests/stats/chart_data.py | 15 +++++++++++++++ tests/stats/test_charts.py | 7 +++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py index 909357e6d..7336555c3 100644 --- a/tests/stats/chart_data.py +++ b/tests/stats/chart_data.py @@ -1,4 +1,19 @@ # flake8: noqa: E501 +from typing import List + +ignored_keys = ["context_id", "__timestamp", "start_time", "data"] + + +def filter_data(data: List[dict]): + """ + Exclude random and time-dependent fields from a superset chart data item. + + :param data: The data item: list of arbitrary dicts. + + """ + return [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] + + CHART_DATA = { 1: [], 2: [ diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 1df6526c9..cb97baf5b 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -17,7 +17,7 @@ except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) -from tests.stats.chart_data import CHART_DATA # noqa: F401 +from tests.stats.chart_data import CHART_DATA, filter_data from tests.context_storages.test_dbs import ping_localhost from tests.test_utils import get_path_from_tests_to_current_dir @@ -51,9 +51,8 @@ def charts_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): assert data_result_json["result"][-1]["status"] == "success" assert data_result_json["result"][-1]["stacktrace"] is None data = data_result_json["result"][-1]["data"] - ignored_keys = ["context_id", "__timestamp", "start_time", "data"] - _ = [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] - # assert _ == CHART_DATA[_id] + filtered_data = filter_data(data) + assert filtered_data == filter_data(CHART_DATA[_id]) session.close() From 0d1e096efbef2bea60f39a001d29e8bb51b14737 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Thu, 2 Nov 2023 16:26:00 +0300 Subject: [PATCH 11/20] update test charts --- tests/stats/test_charts.py | 43 +++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index cb97baf5b..ca2caef0f 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -12,7 +12,8 @@ from httpx import AsyncClient import omegaconf # noqa: F401 import tqdm # noqa: F401 - from dff.stats.utils import get_superset_session + from dff.stats.__main__ import main + from dff.stats.utils import get_superset_session, drop_superset_assets from dff.stats.cli import DEFAULT_SUPERSET_URL except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) @@ -64,15 +65,37 @@ def charts_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): ) @pytest.mark.asyncio @pytest.mark.parametrize( + ["example_module_name", "args"], [ - "example_module_name", - ], - [ - ("3_sample_data_provider",), + ( + "3_sample_data_provider", + Namespace( + **{ + "outfile": "1.zip", + "db.driver": "clickhousedb+connect", + "db.host": "clickhouse", + "db.port": "8123", + "db.name": "test", + "db.table": "otel_logs", + "host": "localhost", + "port": "8088", + "file": f"tutorials/{dot_path_to_addon}/example_config.yaml", + } + ), + ), ], ) @pytest.mark.docker -async def test_charts(example_module_name, otlp_log_exp_provider, otlp_trace_exp_provider): +async def test_charts(example_module_name, args, otlp_log_exp_provider, otlp_trace_exp_provider): + args.__dict__.update( + { + "db.password": os.environ["CLICKHOUSE_PASSWORD"], + "username": os.environ["SUPERSET_USERNAME"], + "password": os.environ["SUPERSET_PASSWORD"], + "db.user": os.environ["CLICKHOUSE_USER"], + } + ) + session, headers = get_superset_session(args, DEFAULT_SUPERSET_URL) module = importlib.import_module(f"tutorials.{dot_path_to_addon}.{example_module_name}") _, tracer_provider = otlp_trace_exp_provider _, logger_provider = otlp_log_exp_provider @@ -86,11 +109,15 @@ async def test_charts(example_module_name, otlp_log_exp_provider, otlp_trace_exp await module.main(40) await asyncio.sleep(1) - args = Namespace( - **{ + args.__dict__.update( + { + "db.password": os.environ["CLICKHOUSE_PASSWORD"], "username": os.environ["SUPERSET_USERNAME"], "password": os.environ["SUPERSET_PASSWORD"], + "db.user": os.environ["CLICKHOUSE_USER"], } ) session, headers = get_superset_session(args) + main(args) charts_data_test(session, headers) + drop_superset_assets(session, headers, DEFAULT_SUPERSET_URL) From edbbf88c182d4f22a7cbc8768295ac9f6b99a986 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Fri, 3 Nov 2023 16:07:17 +0300 Subject: [PATCH 12/20] add id reset to test_charts --- tests/stats/test_charts.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index ca2caef0f..1aa59dedd 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -1,6 +1,7 @@ import os import time import importlib +import subprocess import random import asyncio from argparse import Namespace @@ -121,3 +122,26 @@ async def test_charts(example_module_name, args, otlp_log_exp_provider, otlp_tra main(args) charts_data_test(session, headers) drop_superset_assets(session, headers, DEFAULT_SUPERSET_URL) + id_reset_cmd = """sh -c "psql --user={} --password -p {} --db=test -c \' + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + \'" + """ + command = [ + "docker-compose", + "exec", + "dashboard-metadata", + id_reset_cmd.format( + os.getenv("POSTGRES_USERNAME"), + os.getenv("SUPERSET_METADATA_PORT"), + "dashboards", + "slices", + "tables", + "dbs", + ), + ] + output, error = subprocess.Popen( + command, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ).communicate(os.getenv("POSGTRES_PASSWORD")) From bccfc248fd6b618e5842c0626bdc0144ebdd9cee Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Wed, 8 Nov 2023 13:20:35 +0300 Subject: [PATCH 13/20] update --- tests/stats/chart_data.py | 508 +++++++++---------------------------- tests/stats/test_charts.py | 142 ++++------- utils/stats/utils.py | 30 +++ 3 files changed, 201 insertions(+), 479 deletions(-) create mode 100644 utils/stats/utils.py diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py index 7336555c3..196bbfd5a 100644 --- a/tests/stats/chart_data.py +++ b/tests/stats/chart_data.py @@ -1,402 +1,124 @@ -# flake8: noqa: E501 -from typing import List +# %% +import random +import asyncio +from tqdm import tqdm +from dff.script import Context, Message, RESPONSE, TRANSITIONS +from dff.script import conditions as cnd +from dff.pipeline import Pipeline, ACTOR +from dff.stats import ( + OtelInstrumentor, +) -ignored_keys = ["context_id", "__timestamp", "start_time", "data"] +# %% +# instrumentation code +dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) +dff_instrumentor.instrument() -def filter_data(data: List[dict]): +def numbered_flow_factory(number: int): + return { + f"node_{str(n)}": { + RESPONSE: Message(text=f"node_{str(number)}_{str(n)}"), + TRANSITIONS: {f"node_{str(n+1)}": cnd.true()} if n != 4 else {("root", "fallback"): cnd.true()}, + } + for n in range(5) + } + + +numbered_script = { + "root": { + "start": { + RESPONSE: Message(text="Hi"), + TRANSITIONS: { + lambda ctx, pipeline: (f"flow_{random.choice(range(1, 11))}", "node_1"): cnd.exact_match( + Message(text="hi") + ), + }, + }, + "fallback": {RESPONSE: Message(text="Oops")}, + }, + **{f"flow_{str(n)}": numbered_flow_factory(n) for n in range(1, 11)}, +} + +transitions_script = { + "root": { + "start": { + RESPONSE: Message(text="Hi"), + TRANSITIONS: { + ("flow_1", "node"): cnd.exact_match(Message(text="hi")), + }, + }, + "fallback": {RESPONSE: Message(text="Oops")}, + }, + **{ + f"flow_{str(num)}": { + "node": { + RESPONSE: Message(text="Message."), + TRANSITIONS: {(f"flow_{str(num+1)}", "node"): cnd.true()} + if num != 100 + else {("root", "fallback"): cnd.true()}, + } + } + for num in range(1, 101) + }, +} + + +transition_test_pipeline = Pipeline.from_dict( + { + "script": transitions_script, + "start_label": ("root", "start"), + "fallback_label": ("root", "fallback"), + "components": [ACTOR], + } +) + +numbered_test_pipeline = Pipeline.from_dict( + { + "script": numbered_script, + "start_label": ("root", "start"), + "fallback_label": ("root", "fallback"), + "components": [ACTOR], + } +) + + +# %% +async def worker(pipeline: Pipeline, queue: asyncio.Queue): """ - Exclude random and time-dependent fields from a superset chart data item. + Worker function for dispatching one client message. + The client message is chosen randomly from a predetermined set of options. + It simulates pauses in between messages by calling the sleep function. - :param data: The data item: list of arbitrary dicts. + The function also starts a new dialog as a new user, if the current dialog + ended in the fallback_node. + :param queue: Queue for sharing context variables. """ - return [{key: value} for item in data for key, value in item.items() if key not in ignored_keys] + ctx: Context = await queue.get() + in_message = Message(text="Hi") + await asyncio.sleep(random.random() * 3) + ctx = await pipeline._run_pipeline(in_message, ctx.id) + await asyncio.sleep(random.random() * 3) + await queue.put(ctx) -CHART_DATA = { - 1: [], - 2: [ - { - "__timestamp": 1698741640000, - "animals, have_pets": None, - "animals, like_animals": None, - "animals, what_animal": None, - "root, fallback": 1, - }, - { - "__timestamp": 1698741642000, - "animals, have_pets": None, - "animals, like_animals": None, - "animals, what_animal": None, - "root, fallback": 2, - }, - { - "__timestamp": 1698741647000, - "animals, have_pets": None, - "animals, like_animals": None, - "animals, what_animal": None, - "root, fallback": 1, - }, - { - "__timestamp": 1698741663000, - "animals, have_pets": None, - "animals, like_animals": None, - "animals, what_animal": None, - "root, fallback": 1, - }, - { - "__timestamp": 1698741667000, - "animals, have_pets": None, - "animals, like_animals": None, - "animals, what_animal": None, - "root, fallback": 2, - }, - { - "__timestamp": 1698741673000, - "animals, have_pets": None, - "animals, like_animals": None, - "animals, what_animal": None, - "root, fallback": 1, - }, - { - "__timestamp": 1698741674000, - "animals, have_pets": None, - "animals, like_animals": 1, - "animals, what_animal": 1, - "root, fallback": None, - }, - { - "__timestamp": 1698741678000, - "animals, have_pets": 1, - "animals, like_animals": None, - "animals, what_animal": None, - "root, fallback": None, - }, - ], - 3: [ - {"flow_label": "animals", "node_label": "what_animal", "COUNT(context_id)": 9}, - {"flow_label": "root", "node_label": "fallback", "COUNT(context_id)": 8}, - {"flow_label": "animals", "node_label": "ask_about_color", "COUNT(context_id)": 6}, - {"flow_label": "animals", "node_label": "have_pets", "COUNT(context_id)": 6}, - {"flow_label": "animals", "node_label": "like_animals", "COUNT(context_id)": 5}, - {"flow_label": "animals", "node_label": "ask_about_breed", "COUNT(context_id)": 3}, - {"flow_label": "animals", "node_label": "ask_about_training", "COUNT(context_id)": 2}, - {"flow_label": "small_talk", "node_label": "ask_some_questions", "COUNT(context_id)": 1}, - ], - 4: [{"__timestamp": 1698741600000, "COUNT_DISTINCT(context_id)": 11}], - 5: [ - {"request_id": 4, "label": "animals: ask_about_training", "COUNT(context_id)": 1}, - {"request_id": 1, "label": "animals: like_animals", "COUNT(context_id)": 1}, - {"request_id": 2, "label": "animals: ask_about_breed", "COUNT(context_id)": 2}, - {"request_id": 0, "label": "animals: like_animals", "COUNT(context_id)": 4}, - {"request_id": 5, "label": "root: fallback", "COUNT(context_id)": 1}, - {"request_id": 3, "label": "animals: ask_about_training", "COUNT(context_id)": 1}, - {"request_id": 0, "label": "animals: have_pets", "COUNT(context_id)": 6}, - {"request_id": 3, "label": "animals: ask_about_breed", "COUNT(context_id)": 1}, - {"request_id": 2, "label": "animals: what_animal", "COUNT(context_id)": 1}, - {"request_id": 3, "label": "root: fallback", "COUNT(context_id)": 5}, - {"request_id": 0, "label": "small_talk: ask_some_questions", "COUNT(context_id)": 1}, - {"request_id": 2, "label": "animals: ask_about_color", "COUNT(context_id)": 5}, - {"request_id": 4, "label": "root: fallback", "COUNT(context_id)": 2}, - {"request_id": 1, "label": "animals: what_animal", "COUNT(context_id)": 8}, - {"request_id": 3, "label": "animals: ask_about_color", "COUNT(context_id)": 1}, - ], - 6: [], - 7: [], - 8: [], - 9: [ - {"label": "root: fallback", "flow_label": "root", "COUNT_DISTINCT(context_id)": 8}, - {"label": "small_talk: ask_some_questions", "flow_label": "small_talk", "COUNT_DISTINCT(context_id)": 1}, - {"label": "animals: have_pets", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 6}, - {"label": "animals: ask_about_color", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 6}, - {"label": "animals: ask_about_breed", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 2}, - {"label": "animals: like_animals", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 5}, - {"label": "animals: ask_about_training", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 2}, - {"label": "animals: what_animal", "flow_label": "animals", "COUNT_DISTINCT(context_id)": 9}, - ], - 10: [], - 11: [], - 12: [], - 13: [ - {"__timestamp": 1698741600000, "animals": 0.7419354838709677, "root": 0.5, "small_talk": 1}, - {"__timestamp": 1698741660000, "animals": 0.25806451612903225, "root": 0.5, "small_talk": 0}, - ], - 14: [ - { - "__timestamp": 1698741600000, - "animals, ask_about_breed": 0.6666666666666666, - "animals, ask_about_color": 0.8333333333333334, - "animals, ask_about_training": 0, - "animals, have_pets": 0.6666666666666666, - "animals, like_animals": 0.8, - "animals, what_animal": 0.8888888888888888, - "root, fallback": 0.5, - "small_talk, ask_some_questions": 1, - }, - { - "__timestamp": 1698741660000, - "animals, ask_about_breed": 0.3333333333333333, - "animals, ask_about_color": 0.16666666666666666, - "animals, ask_about_training": 1, - "animals, have_pets": 0.3333333333333333, - "animals, like_animals": 0.2, - "animals, what_animal": 0.1111111111111111, - "root, fallback": 0.5, - "small_talk, ask_some_questions": 0, - }, - ], - 15: [], - 16: [ - { - "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", - "start_time": 1698741637000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', - }, - { - "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", - "start_time": 1698741637000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', - }, - { - "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", - "start_time": 1698741640000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", - "start_time": 1698741649000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', - }, - { - "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", - "start_time": 1698741633000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', - }, - { - "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", - "start_time": 1698741626000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', - }, - { - "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", - "start_time": 1698741654000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", - "start_time": 1698741663000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_training","node":"ask_about_training"}', - }, - { - "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", - "start_time": 1698741632000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "e9fdd58e-58db-403c-a965-1336c7f05501", - "start_time": 1698741674000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", - "start_time": 1698741647000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "6f311fc7-fb9b-48ee-9dcb-d1a80a40ece5", - "start_time": 1698741674000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', - }, - { - "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", - "start_time": 1698741628000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', - }, - { - "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", - "start_time": 1698741669000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_training","node":"ask_about_training"}', - }, - { - "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", - "start_time": 1698741667000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", - "start_time": 1698741634000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", - "start_time": 1698741650000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', - }, - { - "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", - "start_time": 1698741662000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_breed","node":"ask_about_breed"}', - }, - { - "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", - "start_time": 1698741659000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', - }, - { - "context_id": "e9fdd58e-58db-403c-a965-1336c7f05501", - "start_time": 1698741670000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', - }, - { - "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", - "start_time": 1698741673000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", - "start_time": 1698741647000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', - }, - { - "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", - "start_time": 1698741635000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', - }, - { - "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", - "start_time": 1698741663000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "26d11ea4-81e6-4e97-9520-384f82b006e4", - "start_time": 1698741678000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', - }, - { - "context_id": "b06847b3-511c-4acd-ba13-7c62a3f0a571", - "start_time": 1698741642000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", - "start_time": 1698741642000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", - "start_time": 1698741667000, - "data_key": "get_current_label", - "data": '{"flow":"root","label":"root: fallback","node":"fallback"}', - }, - { - "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", - "start_time": 1698741659000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_breed","node":"ask_about_breed"}', - }, - { - "context_id": "be839804-d0a4-4071-a83d-d2fba4716540", - "start_time": 1698741653000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "a99852e7-60c7-4c92-aaee-3d6ee5658eac", - "start_time": 1698741633000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "212ba36e-3d1e-466a-94b3-c307a3d73e3b", - "start_time": 1698741627000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: like_animals","node":"like_animals"}', - }, - { - "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", - "start_time": 1698741658000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", - "start_time": 1698741636000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "7603ee18-a04f-4f2f-bb7e-56156f84dd11", - "start_time": 1698741654000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: what_animal","node":"what_animal"}', - }, - { - "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", - "start_time": 1698741664000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', - }, - { - "context_id": "deb71840-af8e-48b1-a491-c79c2ccced7b", - "start_time": 1698741657000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: have_pets","node":"have_pets"}', - }, - { - "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", - "start_time": 1698741629000, - "data_key": "get_current_label", - "data": '{"flow":"small_talk","label":"small_talk: ask_some_questions","node":"ask_some_questions"}', - }, - { - "context_id": "a5311796-0417-4023-a36e-ce0456c28ee4", - "start_time": 1698741642000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_color","node":"ask_about_color"}', - }, - { - "context_id": "b53c28cf-52b5-4201-99e8-4b360754aa55", - "start_time": 1698741658000, - "data_key": "get_current_label", - "data": '{"flow":"animals","label":"animals: ask_about_breed","node":"ask_about_breed"}', - }, - ], - 17: [ - {"flow_label": "root", "node_label": "fallback", "COUNT(context_id)": 8}, - {"flow_label": "animals", "node_label": "ask_about_breed", "COUNT(context_id)": 3}, - {"flow_label": "animals", "node_label": "what_animal", "COUNT(context_id)": 9}, - {"flow_label": "animals", "node_label": "ask_about_color", "COUNT(context_id)": 6}, - {"flow_label": "animals", "node_label": "like_animals", "COUNT(context_id)": 5}, - {"flow_label": "small_talk", "node_label": "ask_some_questions", "COUNT(context_id)": 1}, - {"flow_label": "animals", "node_label": "ask_about_training", "COUNT(context_id)": 2}, - {"flow_label": "animals", "node_label": "have_pets", "COUNT(context_id)": 6}, - ], -} +# %% +# main loop +async def loop(pipeline: Pipeline, n_iterations: int = 10, n_workers: int = 10): + """ + The main loop that runs one or more worker coroutines in parallel. + + :param n_iterations: Total number of coroutine runs. + :param n_workers: Number of parallelized coroutine runs. + """ + ctxs = asyncio.Queue() + parallel_iterations = n_iterations // n_workers + for _ in range(n_workers): + await ctxs.put(Context()) + for _ in tqdm(range(parallel_iterations)): + await asyncio.gather(*(worker(pipeline, ctxs) for _ in range(n_workers))) + + +if __name__ == "__main__": + asyncio.run(loop(numbered_test_pipeline)) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 1aa59dedd..787aff02c 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -1,7 +1,4 @@ import os -import time -import importlib -import subprocess import random import asyncio from argparse import Namespace @@ -13,15 +10,17 @@ from httpx import AsyncClient import omegaconf # noqa: F401 import tqdm # noqa: F401 + from dff.stats.instrumentor import OtelInstrumentor from dff.stats.__main__ import main from dff.stats.utils import get_superset_session, drop_superset_assets from dff.stats.cli import DEFAULT_SUPERSET_URL except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) -from tests.stats.chart_data import CHART_DATA, filter_data +from tests.stats.chart_data import numbered_test_pipeline, transition_test_pipeline, loop from tests.context_storages.test_dbs import ping_localhost from tests.test_utils import get_path_from_tests_to_current_dir +from utils.stats.utils import restart_pk random.seed(42) dot_path_to_addon = get_path_from_tests_to_current_dir(__file__) @@ -34,30 +33,55 @@ CLICKHOUSE_DB = os.getenv("CLICKHOUSE_DB") -def charts_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): +def transitions_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): charts_url = parse.urljoin(DEFAULT_SUPERSET_URL, "/api/v1/chart") - charts_result = session.get(charts_url, headers=headers) - charts_json = charts_result.json() - - for _id in sorted(charts_json["ids"]): - time.sleep(0.5) - print(str(_id)) - data_result = session.get( - parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{str(_id)}/data/"), headers=headers - ) - print(data_result.reason) - print(data_result.text) - data_result.raise_for_status() - data_result_json = data_result.json() - assert data_result_json["result"][-1]["status"] == "success" - assert data_result_json["result"][-1]["stacktrace"] is None - data = data_result_json["result"][-1]["data"] - filtered_data = filter_data(data) - assert filtered_data == filter_data(CHART_DATA[_id]) + result = session.get(charts_url, headers=headers) + result.raise_for_status() + result_json = result.json() + + target_chart_id = [item for item in result_json["result"] if item["slice_name"] == "Transition counts"][0]["id"] + target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") + data_result = session.get(target_url, headers=headers) + data_result.raise_for_status() + + session.close() + + +def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): + charts_url = parse.urljoin(DEFAULT_SUPERSET_URL, "/api/v1/chart") + + result = session.get(charts_url, headers=headers) + result.raise_for_status() + result_json = result.json() + + target_chart_id = [item for item in result_json["result"] if item["slice_name"] == ""][0]["id"] + target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") + data_result = session.get(target_url, headers=headers) + data_result.raise_for_status() + session.close() +config_namespace = Namespace( + **{ + "outfile": "1.zip", + "db.driver": "clickhousedb+connect", + "db.host": "clickhouse", + "db.port": "8123", + "db.name": "test", + "db.table": "otel_logs", + "host": "localhost", + "port": "8088", + "file": f"tutorials/{dot_path_to_addon}/example_config.yaml", + "db.password": os.environ["CLICKHOUSE_PASSWORD"], + "username": os.environ["SUPERSET_USERNAME"], + "password": os.environ["SUPERSET_PASSWORD"], + "db.user": os.environ["CLICKHOUSE_USER"], + } +) + + @pytest.mark.skipif(not SUPERSET_ACTIVE, reason="Superset server not active") @pytest.mark.skipif(not CLICKHOUSE_AVAILABLE, reason="Clickhouse unavailable.") @pytest.mark.skipif(not COLLECTOR_AVAILABLE, reason="OTLP collector unavailable.") @@ -66,82 +90,28 @@ def charts_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): ) @pytest.mark.asyncio @pytest.mark.parametrize( - ["example_module_name", "args"], + ["args", "pipeline", "func"], [ - ( - "3_sample_data_provider", - Namespace( - **{ - "outfile": "1.zip", - "db.driver": "clickhousedb+connect", - "db.host": "clickhouse", - "db.port": "8123", - "db.name": "test", - "db.table": "otel_logs", - "host": "localhost", - "port": "8088", - "file": f"tutorials/{dot_path_to_addon}/example_config.yaml", - } - ), - ), + (config_namespace, numbered_test_pipeline, numbered_data_test), + (config_namespace, transition_test_pipeline, transitions_data_test), ], ) @pytest.mark.docker -async def test_charts(example_module_name, args, otlp_log_exp_provider, otlp_trace_exp_provider): - args.__dict__.update( - { - "db.password": os.environ["CLICKHOUSE_PASSWORD"], - "username": os.environ["SUPERSET_USERNAME"], - "password": os.environ["SUPERSET_PASSWORD"], - "db.user": os.environ["CLICKHOUSE_USER"], - } - ) +async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_exp_provider): session, headers = get_superset_session(args, DEFAULT_SUPERSET_URL) - module = importlib.import_module(f"tutorials.{dot_path_to_addon}.{example_module_name}") _, tracer_provider = otlp_trace_exp_provider _, logger_provider = otlp_log_exp_provider http_client = AsyncClient() table = "otel_logs" ch_client = ChClient(http_client, user=CLICKHOUSE_USER, password=CLICKHOUSE_PASSWORD, database=CLICKHOUSE_DB) + dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) await ch_client.execute(f"TRUNCATE {table}") - module.dff_instrumentor.uninstrument() - module.dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) - await module.main(40) + dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) + await loop(pipeline=pipeline) # run with a test-specific pipeline await asyncio.sleep(1) - args.__dict__.update( - { - "db.password": os.environ["CLICKHOUSE_PASSWORD"], - "username": os.environ["SUPERSET_USERNAME"], - "password": os.environ["SUPERSET_PASSWORD"], - "db.user": os.environ["CLICKHOUSE_USER"], - } - ) - session, headers = get_superset_session(args) main(args) - charts_data_test(session, headers) + func(session, headers) # run with a test-specific function with equal signature drop_superset_assets(session, headers, DEFAULT_SUPERSET_URL) - id_reset_cmd = """sh -c "psql --user={} --password -p {} --db=test -c \' - ALTER SEQUENCE {}_id_seq RESTART WITH 1; - ALTER SEQUENCE {}_id_seq RESTART WITH 1; - ALTER SEQUENCE {}_id_seq RESTART WITH 1; - ALTER SEQUENCE {}_id_seq RESTART WITH 1; - \'" - """ - command = [ - "docker-compose", - "exec", - "dashboard-metadata", - id_reset_cmd.format( - os.getenv("POSTGRES_USERNAME"), - os.getenv("SUPERSET_METADATA_PORT"), - "dashboards", - "slices", - "tables", - "dbs", - ), - ] - output, error = subprocess.Popen( - command, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ).communicate(os.getenv("POSGTRES_PASSWORD")) + restart_pk() diff --git a/utils/stats/utils.py b/utils/stats/utils.py new file mode 100644 index 000000000..c0cf55c5d --- /dev/null +++ b/utils/stats/utils.py @@ -0,0 +1,30 @@ +import os +import subprocess + + +def restart_pk(): + id_reset_cmd = """sh -c "psql --user={} --password -p {} --db=test -c \' + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + ALTER SEQUENCE {}_id_seq RESTART WITH 1; + \'" + """ + formatted_id_reset = id_reset_cmd.format( + os.getenv("POSTGRES_USERNAME"), + os.getenv("SUPERSET_METADATA_PORT"), + "dashboards", + "slices", + "tables", + "dbs", + ) + command = ["docker-compose", "exec", "dashboard-metadata", formatted_id_reset] + _, error = subprocess.Popen( + command, + shell=True, + universal_newlines=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ).communicate(os.getenv("POSGTRES_PASSWORD")) + assert len(error) == 0 From 06f0f95ebca6384ebd356c8e666e68746e4db302 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Wed, 8 Nov 2023 15:42:29 +0300 Subject: [PATCH 14/20] Avoid using psql metadata db in testing environment --- .env_file | 3 ++- dff/utils/docker/superset_config_docker.py | 13 ++++++----- tests/stats/test_charts.py | 27 +++++++++++----------- tests/stats/test_tutorials.py | 3 ++- utils/stats/utils.py | 8 +++++++ 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/.env_file b/.env_file index 6295e4946..660e81211 100644 --- a/.env_file +++ b/.env_file @@ -20,4 +20,5 @@ CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1 CLICKHOUSE_PASSWORD=pass SUPERSET_USERNAME=superset SUPERSET_PASSWORD=superset -SUPERSET_METADATA_PORT=5433 \ No newline at end of file +SUPERSET_METADATA_PORT=5433 +ENVIRONMENT=test \ No newline at end of file diff --git a/dff/utils/docker/superset_config_docker.py b/dff/utils/docker/superset_config_docker.py index ca138927f..ddd662e6c 100644 --- a/dff/utils/docker/superset_config_docker.py +++ b/dff/utils/docker/superset_config_docker.py @@ -24,9 +24,10 @@ # import os -SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{0}:{1}@dashboard-metadata:{2}/{3}".format( - os.getenv("POSTGRES_USERNAME"), - os.getenv("POSTGRES_PASSWORD"), - os.getenv("SUPERSET_METADATA_PORT"), - os.getenv("POSTGRES_DB"), -) +if os.getenv("ENVIRONMENT") == "prod": + SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{0}:{1}@dashboard-metadata:{2}/{3}".format( + os.getenv("POSTGRES_USERNAME"), + os.getenv("POSTGRES_PASSWORD"), + os.getenv("SUPERSET_METADATA_PORT"), + os.getenv("POSTGRES_DB"), + ) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 787aff02c..8b05b84ef 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -6,21 +6,19 @@ import pytest try: - from aiochclient import ChClient - from httpx import AsyncClient import omegaconf # noqa: F401 import tqdm # noqa: F401 from dff.stats.instrumentor import OtelInstrumentor from dff.stats.__main__ import main from dff.stats.utils import get_superset_session, drop_superset_assets from dff.stats.cli import DEFAULT_SUPERSET_URL + from utils.stats.utils import cleanup_clickhouse except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) from tests.stats.chart_data import numbered_test_pipeline, transition_test_pipeline, loop from tests.context_storages.test_dbs import ping_localhost from tests.test_utils import get_path_from_tests_to_current_dir -from utils.stats.utils import restart_pk random.seed(42) dot_path_to_addon = get_path_from_tests_to_current_dir(__file__) @@ -55,7 +53,7 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): result.raise_for_status() result_json = result.json() - target_chart_id = [item for item in result_json["result"] if item["slice_name"] == ""][0]["id"] + target_chart_id = [item for item in result_json["result"] if item["slice_name"] == "Table"][0]["id"] target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") data_result = session.get(target_url, headers=headers) data_result.raise_for_status() @@ -74,10 +72,6 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): "host": "localhost", "port": "8088", "file": f"tutorials/{dot_path_to_addon}/example_config.yaml", - "db.password": os.environ["CLICKHOUSE_PASSWORD"], - "username": os.environ["SUPERSET_USERNAME"], - "password": os.environ["SUPERSET_PASSWORD"], - "db.user": os.environ["CLICKHOUSE_USER"], } ) @@ -98,20 +92,27 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): ) @pytest.mark.docker async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_exp_provider): + args.__dict__.update( + { + "db.password": os.environ["CLICKHOUSE_PASSWORD"], + "username": os.environ["SUPERSET_USERNAME"], + "password": os.environ["SUPERSET_PASSWORD"], + "db.user": os.environ["CLICKHOUSE_USER"], + } + ) session, headers = get_superset_session(args, DEFAULT_SUPERSET_URL) _, tracer_provider = otlp_trace_exp_provider _, logger_provider = otlp_log_exp_provider - http_client = AsyncClient() + table = "otel_logs" - ch_client = ChClient(http_client, user=CLICKHOUSE_USER, password=CLICKHOUSE_PASSWORD, database=CLICKHOUSE_DB) + await cleanup_clickhouse(table, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB) dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) - await ch_client.execute(f"TRUNCATE {table}") dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) await loop(pipeline=pipeline) # run with a test-specific pipeline await asyncio.sleep(1) + drop_superset_assets(session, headers, DEFAULT_SUPERSET_URL) main(args) func(session, headers) # run with a test-specific function with equal signature - drop_superset_assets(session, headers, DEFAULT_SUPERSET_URL) - restart_pk() + # restart_pk() diff --git a/tests/stats/test_tutorials.py b/tests/stats/test_tutorials.py index 969dc6bf5..423448491 100644 --- a/tests/stats/test_tutorials.py +++ b/tests/stats/test_tutorials.py @@ -12,6 +12,7 @@ from aiochclient import ChClient from httpx import AsyncClient from dff import stats # noqa: F401 + from utils.stats.utils import cleanup_clickhouse except ImportError: pytest.skip(allow_module_level=True, reason="There are dependencies missing.") @@ -49,7 +50,7 @@ async def test_examples_ch(example_module_name: str, expected_logs, otlp_log_exp ch_client = ChClient(http_client, user=CLICKHOUSE_USER, password=CLICKHOUSE_PASSWORD, database=CLICKHOUSE_DB) try: - await ch_client.execute(f"TRUNCATE {table}") + await cleanup_clickhouse(table, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB) pipeline = module.pipeline module.dff_instrumentor.uninstrument() module.dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) diff --git a/utils/stats/utils.py b/utils/stats/utils.py index c0cf55c5d..2d5cb2ddf 100644 --- a/utils/stats/utils.py +++ b/utils/stats/utils.py @@ -1,5 +1,13 @@ import os import subprocess +from aiochclient import ChClient +from httpx import AsyncClient + + +async def cleanup_clickhouse(table: str, user: str, password: str, database: str): + http_client = AsyncClient() + ch_client = ChClient(http_client, user=user, password=password, database=database) + await ch_client.execute(f"TRUNCATE {table}") def restart_pk(): From 8db3a787d3b05d99b7b4af1e364f4b58fabaa84c Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Wed, 8 Nov 2023 18:35:22 +0300 Subject: [PATCH 15/20] get data --- tests/stats/chart_data.py | 21 ++++++++++++++++++--- tests/stats/test_charts.py | 11 ++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py index 196bbfd5a..1fbff50f4 100644 --- a/tests/stats/chart_data.py +++ b/tests/stats/chart_data.py @@ -4,9 +4,10 @@ from tqdm import tqdm from dff.script import Context, Message, RESPONSE, TRANSITIONS from dff.script import conditions as cnd -from dff.pipeline import Pipeline, ACTOR +from dff.pipeline import Pipeline, ACTOR, Service from dff.stats import ( OtelInstrumentor, + default_extractors ) # %% @@ -69,7 +70,14 @@ def numbered_flow_factory(number: int): "script": transitions_script, "start_label": ("root", "start"), "fallback_label": ("root", "fallback"), - "components": [ACTOR], + "components": [ + Service( + handler=ACTOR, + after_handler=[ + default_extractors.get_current_label, + ], + ), + ], } ) @@ -78,7 +86,14 @@ def numbered_flow_factory(number: int): "script": numbered_script, "start_label": ("root", "start"), "fallback_label": ("root", "fallback"), - "components": [ACTOR], + "components": [ + Service( + handler=ACTOR, + after_handler=[ + default_extractors.get_current_label, + ], + ), + ], } ) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 8b05b84ef..509d1f682 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -42,8 +42,9 @@ def transitions_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") data_result = session.get(target_url, headers=headers) data_result.raise_for_status() - + print(data_result.json()) session.close() + assert False def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): @@ -57,8 +58,9 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") data_result = session.get(target_url, headers=headers) data_result.raise_for_status() - + print(data_result.json()) session.close() + assert False config_namespace = Namespace( @@ -107,12 +109,11 @@ async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_ex table = "otel_logs" await cleanup_clickhouse(table, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB) dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) - + dff_instrumentor.uninstrument() dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) await loop(pipeline=pipeline) # run with a test-specific pipeline - await asyncio.sleep(1) + await asyncio.sleep(5) drop_superset_assets(session, headers, DEFAULT_SUPERSET_URL) main(args) func(session, headers) # run with a test-specific function with equal signature - # restart_pk() From 0251c0b1d0b0c065c160f329a08952161a6ff20a Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Wed, 8 Nov 2023 18:45:47 +0300 Subject: [PATCH 16/20] Update chart data tests --- tests/stats/chart_data.py | 5 +---- tests/stats/test_charts.py | 15 +++++---------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py index 1fbff50f4..7a20e38f0 100644 --- a/tests/stats/chart_data.py +++ b/tests/stats/chart_data.py @@ -5,10 +5,7 @@ from dff.script import Context, Message, RESPONSE, TRANSITIONS from dff.script import conditions as cnd from dff.pipeline import Pipeline, ACTOR, Service -from dff.stats import ( - OtelInstrumentor, - default_extractors -) +from dff.stats import OtelInstrumentor, default_extractors # %% # instrumentation code diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 509d1f682..335c5e2d8 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -8,7 +8,6 @@ try: import omegaconf # noqa: F401 import tqdm # noqa: F401 - from dff.stats.instrumentor import OtelInstrumentor from dff.stats.__main__ import main from dff.stats.utils import get_superset_session, drop_superset_assets from dff.stats.cli import DEFAULT_SUPERSET_URL @@ -42,9 +41,9 @@ def transitions_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") data_result = session.get(target_url, headers=headers) data_result.raise_for_status() - print(data_result.json()) + data_result_json = data_result.json() + assert len(data_result_json["result"]["data"]) == 10 session.close() - assert False def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): @@ -58,9 +57,9 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") data_result = session.get(target_url, headers=headers) data_result.raise_for_status() - print(data_result.json()) + data_result_json = data_result.json() + assert len(data_result_json) == 1 session.close() - assert False config_namespace = Namespace( @@ -106,11 +105,7 @@ async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_ex _, tracer_provider = otlp_trace_exp_provider _, logger_provider = otlp_log_exp_provider - table = "otel_logs" - await cleanup_clickhouse(table, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB) - dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) - dff_instrumentor.uninstrument() - dff_instrumentor.instrument(logger_provider=logger_provider, tracer_provider=tracer_provider) + await cleanup_clickhouse("otel_logs", CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB) await loop(pipeline=pipeline) # run with a test-specific pipeline await asyncio.sleep(5) From cf04d5ec746b84aabf6130f8b37efab6e12b3093 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Thu, 9 Nov 2023 12:06:54 +0300 Subject: [PATCH 17/20] update chart tests --- tests/stats/chart_data.py | 6 ++---- tests/stats/test_charts.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/stats/chart_data.py b/tests/stats/chart_data.py index 7a20e38f0..deab85959 100644 --- a/tests/stats/chart_data.py +++ b/tests/stats/chart_data.py @@ -28,9 +28,7 @@ def numbered_flow_factory(number: int): "start": { RESPONSE: Message(text="Hi"), TRANSITIONS: { - lambda ctx, pipeline: (f"flow_{random.choice(range(1, 11))}", "node_1"): cnd.exact_match( - Message(text="hi") - ), + lambda ctx, pipeline: (f"flow_{random.choice(range(1, 11))}", "node_1", 1): cnd.true(), }, }, "fallback": {RESPONSE: Message(text="Oops")}, @@ -43,7 +41,7 @@ def numbered_flow_factory(number: int): "start": { RESPONSE: Message(text="Hi"), TRANSITIONS: { - ("flow_1", "node"): cnd.exact_match(Message(text="hi")), + ("flow_1", "node"): cnd.true(), }, }, "fallback": {RESPONSE: Message(text="Oops")}, diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 335c5e2d8..2388ee7cf 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -1,5 +1,6 @@ import os import random +import json import asyncio from argparse import Namespace from urllib import parse @@ -42,7 +43,10 @@ def transitions_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): data_result = session.get(target_url, headers=headers) data_result.raise_for_status() data_result_json = data_result.json() - assert len(data_result_json["result"]["data"]) == 10 + data = data_result_json["result"][0]["data"] + assert (len(data)) > 0 + assert "COUNT_DISTINCT(context_id)" in data[0] + assert data[0]["COUNT_DISTINCT(context_id)"] == 10 session.close() @@ -58,7 +62,14 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): data_result = session.get(target_url, headers=headers) data_result.raise_for_status() data_result_json = data_result.json() - assert len(data_result_json) == 1 + grouped_dict = dict() + for item in data_result_json["result"][0]["data"]: + if item["context_id"] not in grouped_dict: + grouped_dict[item["context_id"]] = [item] + else: + grouped_dict[item["context_id"]].append(item) + unique_flows = list(map(lambda x: set(map(lambda y: json.loads(y["data"])["flow"], x)), grouped_dict.values())) + assert all(map(lambda x: len(x) == 1, unique_flows)) session.close() From ed32172f0207fc6cf9e5c8aa5ac309cf30bb80c8 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Thu, 9 Nov 2023 16:52:02 +0300 Subject: [PATCH 18/20] Update test charts; wait for longer time --- tests/stats/test_charts.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 2388ee7cf..2ab9933ca 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -10,7 +10,7 @@ import omegaconf # noqa: F401 import tqdm # noqa: F401 from dff.stats.__main__ import main - from dff.stats.utils import get_superset_session, drop_superset_assets + from dff.stats.utils import get_superset_session from dff.stats.cli import DEFAULT_SUPERSET_URL from utils.stats.utils import cleanup_clickhouse except ImportError: @@ -63,7 +63,9 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): data_result.raise_for_status() data_result_json = data_result.json() grouped_dict = dict() - for item in data_result_json["result"][0]["data"]: + data = data_result_json["result"][0]["data"] + assert len(data) > 0 + for item in data: if item["context_id"] not in grouped_dict: grouped_dict[item["context_id"]] = [item] else: @@ -75,7 +77,6 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): config_namespace = Namespace( **{ - "outfile": "1.zip", "db.driver": "clickhousedb+connect", "db.host": "clickhouse", "db.port": "8123", @@ -112,14 +113,15 @@ async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_ex "db.user": os.environ["CLICKHOUSE_USER"], } ) - session, headers = get_superset_session(args, DEFAULT_SUPERSET_URL) _, tracer_provider = otlp_trace_exp_provider _, logger_provider = otlp_log_exp_provider await cleanup_clickhouse("otel_logs", CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB) await loop(pipeline=pipeline) # run with a test-specific pipeline - await asyncio.sleep(5) + tracer_provider.force_flush() + logger_provider.force_flush() + await asyncio.sleep(6) - drop_superset_assets(session, headers, DEFAULT_SUPERSET_URL) main(args) + session, headers = get_superset_session(args, DEFAULT_SUPERSET_URL) func(session, headers) # run with a test-specific function with equal signature From 1e550957c96665b9275566aff3672006018378ea Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Fri, 10 Nov 2023 11:57:15 +0300 Subject: [PATCH 19/20] parametrize healthcheck; wait for endpoints in tests --- dff/utils/docker/entrypoint_stats.sh | 2 +- dff/utils/docker/health_stats.sh | 3 +- tests/stats/test_charts.py | 43 +++++++++++++++++++++------- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/dff/utils/docker/entrypoint_stats.sh b/dff/utils/docker/entrypoint_stats.sh index 519ae7721..262676796 100644 --- a/dff/utils/docker/entrypoint_stats.sh +++ b/dff/utils/docker/entrypoint_stats.sh @@ -2,7 +2,7 @@ export SERVER_THREADS_AMOUNT=8 set -m nohup /bin/bash /usr/bin/run-server.sh & -/bin/bash /app/docker/health_stats.sh +/bin/bash /app/docker/health_stats.sh http://localhost:8088/health superset fab create-admin --firstname superset --lastname admin --username $SUPERSET_USERNAME --email admin@admin.com --password $SUPERSET_PASSWORD superset db upgrade superset init diff --git a/dff/utils/docker/health_stats.sh b/dff/utils/docker/health_stats.sh index 1033177f5..d90c5066f 100644 --- a/dff/utils/docker/health_stats.sh +++ b/dff/utils/docker/health_stats.sh @@ -1,7 +1,8 @@ #!/bin/bash +if [[ $# = 0 ]] ; then printf "Specify healthcheck url;\n"; exit 1; fi; for itr in {1..10} do -healthcheck=$(curl -X GET http://localhost:8088/health | grep "OK") +healthcheck=$(curl -X GET "${1}" | grep "OK") healthcheck=$? if [ "$healthcheck" -ne 0 ] ; then echo "Healthcheck failed. sleeping for 5 secs" diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 2ab9933ca..0c11277aa 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -7,12 +7,14 @@ import pytest try: + from requests import Session import omegaconf # noqa: F401 import tqdm # noqa: F401 from dff.stats.__main__ import main from dff.stats.utils import get_superset_session from dff.stats.cli import DEFAULT_SUPERSET_URL - from utils.stats.utils import cleanup_clickhouse + from aiochclient import ChClient + from httpx import AsyncClient except ImportError: pytest.skip(reason="`OmegaConf` dependency missing.", allow_module_level=True) @@ -31,7 +33,7 @@ CLICKHOUSE_DB = os.getenv("CLICKHOUSE_DB") -def transitions_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): +async def transitions_data_test(session: Session, headers: dict, base_url=DEFAULT_SUPERSET_URL): charts_url = parse.urljoin(DEFAULT_SUPERSET_URL, "/api/v1/chart") result = session.get(charts_url, headers=headers) @@ -40,8 +42,14 @@ def transitions_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): target_chart_id = [item for item in result_json["result"] if item["slice_name"] == "Transition counts"][0]["id"] target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") - data_result = session.get(target_url, headers=headers) - data_result.raise_for_status() + result_status = 404 + attempts = 0 + while result_status != 200 and attempts < 10: + attempts += 1 + data_result = session.get(target_url, headers=headers) + result_status = data_result.status_code + await asyncio.sleep(1) + data_result_json = data_result.json() data = data_result_json["result"][0]["data"] assert (len(data)) > 0 @@ -50,7 +58,7 @@ def transitions_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): session.close() -def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): +async def numbered_data_test(session: Session, headers: dict, base_url=DEFAULT_SUPERSET_URL): charts_url = parse.urljoin(DEFAULT_SUPERSET_URL, "/api/v1/chart") result = session.get(charts_url, headers=headers) @@ -59,8 +67,14 @@ def numbered_data_test(session, headers, base_url=DEFAULT_SUPERSET_URL): target_chart_id = [item for item in result_json["result"] if item["slice_name"] == "Table"][0]["id"] target_url = parse.urljoin(DEFAULT_SUPERSET_URL, f"api/v1/chart/{target_chart_id}/data/") - data_result = session.get(target_url, headers=headers) - data_result.raise_for_status() + result_status = 404 + attempts = 0 + while result_status != 200 and attempts < 10: + attempts += 1 + data_result = session.get(target_url, headers=headers) + result_status = data_result.status_code + await asyncio.sleep(2) + data_result_json = data_result.json() grouped_dict = dict() data = data_result_json["result"][0]["data"] @@ -116,12 +130,21 @@ async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_ex _, tracer_provider = otlp_trace_exp_provider _, logger_provider = otlp_log_exp_provider - await cleanup_clickhouse("otel_logs", CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, CLICKHOUSE_DB) + table = "otel_logs" + http_client = AsyncClient() + ch_client = ChClient(http_client, user=CLICKHOUSE_USER, password=CLICKHOUSE_PASSWORD, database=CLICKHOUSE_DB) + await ch_client.execute(f"TRUNCATE {table}") await loop(pipeline=pipeline) # run with a test-specific pipeline tracer_provider.force_flush() logger_provider.force_flush() - await asyncio.sleep(6) + num_records = 0 + + attempts = 0 + while num_records == 0 and attempts < 10: + attempts += 1 + await asyncio.sleep(2) + num_records = await ch_client.fetchval(f"SELECT COUNT (*) FROM {table}") main(args) session, headers = get_superset_session(args, DEFAULT_SUPERSET_URL) - func(session, headers) # run with a test-specific function with equal signature + await func(session, headers) # run with a test-specific function with equal signature From 73d8d6920266979d014cc84168b2133bbda96c78 Mon Sep 17 00:00:00 2001 From: ruthenian8 Date: Wed, 15 Nov 2023 12:36:38 +0300 Subject: [PATCH 20/20] update wait; use dff.stats command --- makefile | 1 + tests/stats/test_charts.py | 46 ++++++++--------------- tutorials/stats/3_sample_data_provider.py | 18 +++++++-- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/makefile b/makefile index ca568c1b2..d80a4d8b2 100644 --- a/makefile +++ b/makefile @@ -55,6 +55,7 @@ docker_up: wait_db: docker_up while ! docker-compose exec psql pg_isready; do sleep 1; done > /dev/null + while ! docker-compose exec dashboard /bin/bash -c "curl localhost:8088/health | grep OK"; do sleep 1; done > /dev/null while ! docker-compose exec mysql bash -c 'mysql -u $$MYSQL_USERNAME -p$$MYSQL_PASSWORD -e "select 1;"'; do sleep 1; done &> /dev/null .PHONY: wait_db diff --git a/tests/stats/test_charts.py b/tests/stats/test_charts.py index 0c11277aa..b431bbb60 100644 --- a/tests/stats/test_charts.py +++ b/tests/stats/test_charts.py @@ -10,7 +10,6 @@ from requests import Session import omegaconf # noqa: F401 import tqdm # noqa: F401 - from dff.stats.__main__ import main from dff.stats.utils import get_superset_session from dff.stats.cli import DEFAULT_SUPERSET_URL from aiochclient import ChClient @@ -31,6 +30,8 @@ CLICKHOUSE_USER = os.getenv("CLICKHOUSE_USER") CLICKHOUSE_PASSWORD = os.getenv("CLICKHOUSE_PASSWORD") CLICKHOUSE_DB = os.getenv("CLICKHOUSE_DB") +SUPERSET_USERNAME = os.getenv("SUPERSET_USERNAME") +SUPERSET_PASSWORD = os.getenv("SUPERSET_PASSWORD") async def transitions_data_test(session: Session, headers: dict, base_url=DEFAULT_SUPERSET_URL): @@ -89,20 +90,6 @@ async def numbered_data_test(session: Session, headers: dict, base_url=DEFAULT_S session.close() -config_namespace = Namespace( - **{ - "db.driver": "clickhousedb+connect", - "db.host": "clickhouse", - "db.port": "8123", - "db.name": "test", - "db.table": "otel_logs", - "host": "localhost", - "port": "8088", - "file": f"tutorials/{dot_path_to_addon}/example_config.yaml", - } -) - - @pytest.mark.skipif(not SUPERSET_ACTIVE, reason="Superset server not active") @pytest.mark.skipif(not CLICKHOUSE_AVAILABLE, reason="Clickhouse unavailable.") @pytest.mark.skipif(not COLLECTOR_AVAILABLE, reason="OTLP collector unavailable.") @@ -111,22 +98,14 @@ async def numbered_data_test(session: Session, headers: dict, base_url=DEFAULT_S ) @pytest.mark.asyncio @pytest.mark.parametrize( - ["args", "pipeline", "func"], + ["pipeline", "func"], [ - (config_namespace, numbered_test_pipeline, numbered_data_test), - (config_namespace, transition_test_pipeline, transitions_data_test), + (numbered_test_pipeline, numbered_data_test), + (transition_test_pipeline, transitions_data_test), ], ) @pytest.mark.docker -async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_exp_provider): - args.__dict__.update( - { - "db.password": os.environ["CLICKHOUSE_PASSWORD"], - "username": os.environ["SUPERSET_USERNAME"], - "password": os.environ["SUPERSET_PASSWORD"], - "db.user": os.environ["CLICKHOUSE_USER"], - } - ) +async def test_charts(pipeline, func, otlp_log_exp_provider, otlp_trace_exp_provider): _, tracer_provider = otlp_trace_exp_provider _, logger_provider = otlp_log_exp_provider @@ -140,11 +119,18 @@ async def test_charts(args, pipeline, func, otlp_log_exp_provider, otlp_trace_ex num_records = 0 attempts = 0 - while num_records == 0 and attempts < 10: + while num_records < 10 and attempts < 10: attempts += 1 await asyncio.sleep(2) num_records = await ch_client.fetchval(f"SELECT COUNT (*) FROM {table}") - main(args) - session, headers = get_superset_session(args, DEFAULT_SUPERSET_URL) + os.system( + f"dff.stats tutorials/stats/example_config.yaml \ + -U {SUPERSET_USERNAME} \ + -P {SUPERSET_PASSWORD} \ + -dP {CLICKHOUSE_PASSWORD}" + ) + session, headers = get_superset_session( + Namespace(**{"username": SUPERSET_USERNAME, "password": SUPERSET_PASSWORD}), DEFAULT_SUPERSET_URL + ) await func(session, headers) # run with a test-specific function with equal signature diff --git a/tutorials/stats/3_sample_data_provider.py b/tutorials/stats/3_sample_data_provider.py index 73f7dcbd5..b46bd289c 100644 --- a/tutorials/stats/3_sample_data_provider.py +++ b/tutorials/stats/3_sample_data_provider.py @@ -20,22 +20,32 @@ default_extractors, OtelInstrumentor, ) -from dff.utils.testing.toy_script import MULTIFLOW_SCRIPT, MULTIFLOW_REQUEST_OPTIONS +from dff.utils.testing.toy_script import ( + MULTIFLOW_SCRIPT, + MULTIFLOW_REQUEST_OPTIONS, +) # %% # instrumentation code -dff_instrumentor = OtelInstrumentor.from_url("grpc://localhost:4317", insecure=True) +dff_instrumentor = OtelInstrumentor.from_url( + "grpc://localhost:4317", insecure=True +) dff_instrumentor.instrument() def slot_processor_1(ctx: Context): - ctx.misc["slots"] = {**ctx.misc.get("slots", {}), "rating": random.randint(1, 10)} + ctx.misc["slots"] = { + **ctx.misc.get("slots", {}), + "rating": random.randint(1, 10), + } def slot_processor_2(ctx: Context): ctx.misc["slots"] = { **ctx.misc.get("slots", {}), - "current_topic": random.choice(["films", "games", "books", "smalltalk"]), + "current_topic": random.choice( + ["films", "games", "books", "smalltalk"] + ), }