From db0218b82dd4758bba162f9d88045fe00e9528ce Mon Sep 17 00:00:00 2001 From: anhhchu Date: Mon, 15 Jan 2024 12:46:39 -0800 Subject: [PATCH 01/20] git commit -m "Fix setSchema and query execution from directory issues; resolve Benchmark import error in beaker v0.0.3; correct warehouse name creation" --- .gitignore | 1 + dist/Beaker-0.0.4-py3-none-any.whl | Bin 0 -> 11478 bytes setup.py | 8 ++++++ src/beaker/__init__.py | 1 + src/beaker/benchmark.py | 33 +++++++++++++++++++------ src/beaker/sqlwarehouseutils.py | 38 ++++++++++++++++++++++------- 6 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 dist/Beaker-0.0.4-py3-none-any.whl create mode 100644 setup.py diff --git a/.gitignore b/.gitignore index 788efde..0c09d88 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ # Build helpers *beaker.egg-info* +build/* diff --git a/dist/Beaker-0.0.4-py3-none-any.whl b/dist/Beaker-0.0.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..2847808132df6c25d30750764f2c2d04b43c0b8f GIT binary patch literal 11478 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 z zH7IZ`JQ532Uk`YHe}W23##he7--a!-5}Xf^XDUvTCcVuh`k+wA;m@*2L}@#lNyb6M zRnDJ26KVHFG_9K2!CFBYuUb*1y*u$E@`;GYlJKtJN3OtA8%rATCtTJYk-mkr#=lbzPaPHW z*|{QHlWp4P*<6ONWz)FXCZ#XFaf9Sdz6UKYn5X(&*Qz`bk_?3jShX)B5#`J@eu;yIS*8&RLYW`E+ahNITn5%LjWv0N&dQ}jtWYX~ph8nR3#pceEyxyI22?#T7d z+0dRywIfZF@3o6-HjHqhZXSYapHRJG=V6e|0>|*>5ndty>FQSp=6nMqr2`zP(DoS!hJc%Mx)+dz^Sc*nVV}ntTS=drZh{@xj;|0CN1!L-5>Ci^gSF*p zV&0XZfXJZFkAb4S+d?pa+{s+BeomE3#L%vg5-p0U8 zO#&a_;dFSOT-KQ9zG-|afV{Fl@KqyjLj+6PK4zB&D9xl+)iQXaMQ{CNRA@(ZDaMX3JtKsab;j8(N zRX8UQ9vC?vYrmD>y@c$BX(?&_(T@=_w!w$A1SyP|#2(etB9-L96D#H9_JCYClbIr$ zBMU_L*w0@}VpmlwLO+G%`j5Bqu=1pRl9a=YJP$X9Kki?5)jpyg=^L9(F=-qZUEFiE z?-F=2Cbv8Bhoz7+VeXyjVg?ZuGF0vp>80hQ>7*BtWa(+ACubU!ndVs!?qnzBo0X+xT3-)G7Qu!X40157lE<1l0<;HG=R>Fm^B)czMU*&o_FN|B{P_jiJS#2+TLe@IkAN?cqHVMa=RYVOYz7g=|l z6{ckAW$4Bj8-C|GM#m7r2ve>!%QVZ%vBElg06#v%IQKxej0B{YnHrO8PzKV_${)f@ z%e5*4%h;BuCT3)pc+_Wo*_`y(sb?w)+;-`PO^4vK%y%GJTqz}D=OnJt5>yDNx6 z=IHMnJzO$^%irT5gx}*JqJQQni;F5Ki@D8?#TEzw0JELj;2g5TyZI>LP=N(Q1+X~a z+9WY~BK0RL3e*@F)Odb7MEV2rl8$nhx5hP>V7o*LMvzt6v^Gcv?NuHT$ z@m+3jL#h5k6{xzef}P!6YE(CKYP$vcO$n^tAoHO;A@M30i0TQq$r;Zf&l zEl6I|x(q^#NRMq+5@WH`e#H3P&$gXj6-Lz_bvzWus08e^wTKS{s0AgV_J!n!iLa(1 z9*8kL+caz@X9k{@Thiz(u07b;SzGSsy9^t-I}usZGX`nZaUZ=?N>)NRd*VG86#Gd z1p~)~_-B{r@0aEOK1Bh4eErSy`Paq&%i;O2r2s%tfbhQ;|Lbq{SHI_98UM@G`6nac zzZrk^c>Wdgzs8?`LaLGe^%Vb3ePeC|(>+HVi+A3w)`K>uS}_gC2e>hJvt zGyd&g{fCP4?{44US${9Af3n!A{*m>cGW&Pf-;3X$uy6ki`@d57chcVr)}JI->VHh@ pzslF&iGMF${~ Date: Mon, 15 Jan 2024 16:29:50 -0800 Subject: [PATCH 02/20] Rebuild v0.0.4 wheel file --- dist/Beaker-0.0.4-py3-none-any.whl | Bin 11478 -> 13987 bytes dist/beaker-0.0.4.tar.gz | Bin 0 -> 12328 bytes setup.py | 8 -------- src/__init__.py | 2 +- 4 files changed, 1 insertion(+), 9 deletions(-) create mode 100644 dist/beaker-0.0.4.tar.gz delete mode 100644 setup.py diff --git a/dist/Beaker-0.0.4-py3-none-any.whl b/dist/Beaker-0.0.4-py3-none-any.whl index 2847808132df6c25d30750764f2c2d04b43c0b8f..aee85581069a2fc41d5d891da7f194e1a21e5e31 100644 GIT binary patch delta 4136 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 Date: Thu, 18 Jan 2024 18:36:19 -0800 Subject: [PATCH 03/20] Feature: Enable pro and classic warehouse creation --- dist/beaker-0.0.5-py3-none-any.whl | Bin 0 -> 14652 bytes dist/beaker-0.0.5.tar.gz | Bin 0 -> 12943 bytes src/__init__.py | 2 +- src/beaker/benchmark.py | 1 + src/beaker/sqlwarehouseutils.py | 67 ++++++++++++++++++++++++++++- 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 dist/beaker-0.0.5-py3-none-any.whl create mode 100644 dist/beaker-0.0.5.tar.gz diff --git a/dist/beaker-0.0.5-py3-none-any.whl b/dist/beaker-0.0.5-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..472a3484c083a40f571837c9e3319e7e0a86ab2a GIT binary patch literal 14652 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 literal 0 HcmV?d00001 diff --git a/src/__init__.py b/src/__init__.py index 49e1103..6e83b38 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +1 @@ -VERSION = '0.0.4' +VERSION = '0.0.5' diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index 3da256c..3170f5e 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -62,6 +62,7 @@ def _create_dbc(self): self.schema, self.results_cache_enabled, ) + # Check for the warehouse state # establish connection on the existing warehouse sql_warehouse.setConnection() logging.info(f"Returning new sqlwarehouseutils: {sql_warehouse}") diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index d95d4bb..774ce7f 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -2,6 +2,7 @@ import datetime from databricks import sql import logging +import time class SQLWarehouseUtils: _LATEST_RUNTIME = "13.3.x-scala2.12" @@ -50,7 +51,19 @@ def setConnection(self): else: results_caching = "false" - # If the warehouse already exists: + assert self.http_path, ("Warehouse doesn't exist to create connection") + # # If the warehouse already exists + # ## Start the warehouse + # warehouse_id = self.http_path.split("/")[-1] + # self._start_warehouse(warehouse_id) + # # Give a few seconds for serverless warehouse to start + # time.sleep(5) + # # Wait for warehouse to start, for pro and classic + # while self._get_warehouse_state(warehouse_id) != "RUNNING": + # print(f"Waiting for warehouse {warehouse_id} to start (40s)...") + # time.sleep(40) + + ## Create connection after warehouse is started connection = sql.connect( server_hostname=self.hostname, http_path=self.http_path, @@ -106,6 +119,23 @@ def _get_spark_runtimes(self): ) result = list(map(lambda v: v["key"], response.json()["versions"])) return result + + def _get_warehouse_state(self, warehouse_id): + """ Check for warehouse state""" + response = requests.get(f"https://{self.hostname}/api/2.0/sql/warehouses/{warehouse_id}", + headers={"Authorization": f"Bearer {self.access_token}"}) + warehouse_state = response.json()["state"] + return warehouse_state + + def _start_warehouse(self, warehouse_id): + """ Check for warehouse state""" + warehouse_state = _get_warehouse_state(warehouse_id) + if warehouse_state != "RUNNING": + print("Warehouse in state: ", warehouse_state) + print(f"Starting warehouse {warehouse_id}...") + response = requests.post(f"https://{self.hostname}/api/2.0/sql/warehouses/{warehouse_id}/start", + headers={"Authorization": f"Bearer {self.access_token}"}) + assert response.status_code == 200, (f"Warehouse {warehouse_id} failed to start") def launch_warehouse(self, config): """Creates a new SQL warehouse based upon a config.""" @@ -135,6 +165,27 @@ def launch_warehouse(self, config): "Allowed types include: ['warehouse', 'cluster']." ) + # Determine the Warehouse type (classic, pro, serverless) to launch + # warehouse_type: PRO or CLASSIC. If you want to use serverless compute, you must set to PRO and also set the field enable_serverless_compute to true. + enable_serverless_compute = True + if type == "warehouse": + # default to serverless + if "warehouse" not in config or config["warehouse"] == "serverless": + warehouse_type = "PRO" + enable_serverless_compute = True + elif config["warehouse"] == "pro": + warehouse_type = "PRO" + enable_serverless_compute = False + elif config["warehouse"] == "classic": + warehouse_type = "CLASSIC" + enable_serverless_compute = False + else: + assert config["warehouse"] == "classic" or config["warehouse"] == "pro" or config["warehouse"] == "serverless", ( + "Invalid warehouse compute 'type' provided. " + "Allowed types include: ['classic', 'pro', 'serverless']." + ) + + # Determine the Spark runtime to install latest_runtimes = self._get_spark_runtimes() if "runtime" not in config: @@ -189,10 +240,22 @@ def launch_warehouse(self, config): }, "enable_photon": enable_photon, "channel": {"name": "CHANNEL_NAME_CURRENT"}, + # specify the warehouse type + "warehouse_type": warehouse_type, + "enable_serverless_compute": enable_serverless_compute }, ) + warehouse_id = response.json().get("id") + + # Wait for warehouse to start, for pro and classic + if config["warehouse"] and config["warehouse"] != "serverless": + while self._get_warehouse_state(warehouse_id) != "RUNNING": + print(f"Waiting for warehouse {warehouse_id} to run (40s)...") + time.sleep(40) + if not warehouse_id: raise Exception(f"did not get back warehouse_id ({response.json()})") - self.http_path = f"/sql/1.0/warehouses/{warehouse_id}" + + # self.http_path = f"/sql/1.0/warehouses/{warehouse_id}" return warehouse_id From b676f0159357bcfd7d75eaf3e6f44e3c31ae8c41 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Thu, 18 Jan 2024 18:39:56 -0800 Subject: [PATCH 04/20] Feature: Enable pro and classic warehouse creation --- src/beaker/sqlwarehouseutils.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index 774ce7f..b5f5d58 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -52,16 +52,6 @@ def setConnection(self): results_caching = "false" assert self.http_path, ("Warehouse doesn't exist to create connection") - # # If the warehouse already exists - # ## Start the warehouse - # warehouse_id = self.http_path.split("/")[-1] - # self._start_warehouse(warehouse_id) - # # Give a few seconds for serverless warehouse to start - # time.sleep(5) - # # Wait for warehouse to start, for pro and classic - # while self._get_warehouse_state(warehouse_id) != "RUNNING": - # print(f"Waiting for warehouse {warehouse_id} to start (40s)...") - # time.sleep(40) ## Create connection after warehouse is started connection = sql.connect( From d5396de97b67d72d58f1a2ad20646547ee8800f1 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Thu, 18 Jan 2024 18:44:43 -0800 Subject: [PATCH 05/20] Fix method call in SQLWarehouseUtils --- src/beaker/sqlwarehouseutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index b5f5d58..31aaf42 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -119,7 +119,7 @@ def _get_warehouse_state(self, warehouse_id): def _start_warehouse(self, warehouse_id): """ Check for warehouse state""" - warehouse_state = _get_warehouse_state(warehouse_id) + warehouse_state = self._get_warehouse_state(warehouse_id) if warehouse_state != "RUNNING": print("Warehouse in state: ", warehouse_state) print(f"Starting warehouse {warehouse_id}...") From 6f590c82095913eaf49137346acdcd35a7bea7a0 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Thu, 18 Jan 2024 21:38:58 -0800 Subject: [PATCH 06/20] Replace warehouse status check with WorkspaceClient().warehouses.start_and_wait --- src/beaker/sqlwarehouseutils.py | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index 31aaf42..0016aa9 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -3,6 +3,7 @@ from databricks import sql import logging import time +from databricks.sdk import WorkspaceClient class SQLWarehouseUtils: _LATEST_RUNTIME = "13.3.x-scala2.12" @@ -109,23 +110,6 @@ def _get_spark_runtimes(self): ) result = list(map(lambda v: v["key"], response.json()["versions"])) return result - - def _get_warehouse_state(self, warehouse_id): - """ Check for warehouse state""" - response = requests.get(f"https://{self.hostname}/api/2.0/sql/warehouses/{warehouse_id}", - headers={"Authorization": f"Bearer {self.access_token}"}) - warehouse_state = response.json()["state"] - return warehouse_state - - def _start_warehouse(self, warehouse_id): - """ Check for warehouse state""" - warehouse_state = self._get_warehouse_state(warehouse_id) - if warehouse_state != "RUNNING": - print("Warehouse in state: ", warehouse_state) - print(f"Starting warehouse {warehouse_id}...") - response = requests.post(f"https://{self.hostname}/api/2.0/sql/warehouses/{warehouse_id}/start", - headers={"Authorization": f"Bearer {self.access_token}"}) - assert response.status_code == 200, (f"Warehouse {warehouse_id} failed to start") def launch_warehouse(self, config): """Creates a new SQL warehouse based upon a config.""" @@ -238,11 +222,9 @@ def launch_warehouse(self, config): warehouse_id = response.json().get("id") - # Wait for warehouse to start, for pro and classic - if config["warehouse"] and config["warehouse"] != "serverless": - while self._get_warehouse_state(warehouse_id) != "RUNNING": - print(f"Waiting for warehouse {warehouse_id} to run (40s)...") - time.sleep(40) + warehouse_start_time = time.time() + WorkspaceClient().warehouses.start_and_wait(warehouse_id) + print(f"{int(time.time() - warehouse_start_time)}s Warehouse Startup Time") if not warehouse_id: raise Exception(f"did not get back warehouse_id ({response.json()})") From 80cb6e9bc0aaf16ce9e92c75963b08f229f05663 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Thu, 18 Jan 2024 21:42:05 -0800 Subject: [PATCH 07/20] Replace beaker v0.0.5 --- dist/beaker-0.0.5-py3-none-any.whl | Bin 14652 -> 14371 bytes dist/beaker-0.0.5.tar.gz | Bin 12943 -> 12673 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/dist/beaker-0.0.5-py3-none-any.whl b/dist/beaker-0.0.5-py3-none-any.whl index 472a3484c083a40f571837c9e3319e7e0a86ab2a..46f0669a95fdea9b656322b8007cf1d61c8fad64 100644 GIT binary patch delta 2938 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 delta 3254 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 diff --git a/dist/beaker-0.0.5.tar.gz b/dist/beaker-0.0.5.tar.gz index c49eb98233cf4f2b0206be87a5ba895f44c51117..f1dcc865d84685180332553ebee0c69108901c44 100644 GIT binary patch literal 12673 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 Z9&P`79{e8xxGM-muBFBz0J#GJ`5%`o literal 12943 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 From 96a4a99dcbd4dc676ed183d4c625b24214227306 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Thu, 18 Jan 2024 21:50:34 -0800 Subject: [PATCH 08/20] Add option to specify warehouse type in new SQL warehouse provisioning --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 524a57d..70db902 100644 --- a/README.md +++ b/README.md @@ -61,10 +61,13 @@ benchmark.setCatalog(catalog="hive_metastore") benchmark.preWarmTables(tables=["table_1", "table_2", "table_3"]) ``` -You may even choose to provision a new SQL warehouse. +You may even choose to provision a new SQL warehouse. +You can choose the warehouse type (pro, classic, serverless) by specify the warehouse parameter. Default to serverless if "warehouse" param is not specified + ```python new_warehouse_config = { "type": "warehouse", + "warehouse": "serverless", # -> specify the warehouse type (pro, classic, serverless). Default to serverless "runtime": "latest", "size": "Large", "min_num_clusters": 1, From 9b02b08a9d3f05ea69afd59f3367e1e3f1751ad6 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Sun, 21 Jan 2024 16:40:57 -0800 Subject: [PATCH 09/20] Add auth option to workspace client --- dist/beaker-0.0.5-py3-none-any.whl | Bin 14371 -> 14466 bytes dist/beaker-0.0.5.tar.gz | Bin 12673 -> 12747 bytes src/beaker/sqlwarehouseutils.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/beaker-0.0.5-py3-none-any.whl b/dist/beaker-0.0.5-py3-none-any.whl index 46f0669a95fdea9b656322b8007cf1d61c8fad64..d257cc15c54e2a7e4cd5df05c6d166af1f5e2e8a 100644 GIT binary patch delta 6065 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 delta 5992 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 WqyhIclaVDElV&&;2FEo30001SA9(Bl diff --git a/dist/beaker-0.0.5.tar.gz b/dist/beaker-0.0.5.tar.gz index f1dcc865d84685180332553ebee0c69108901c44..4866de036a43f74633f8da5fa7d5b8e0f4644f09 100644 GIT binary patch delta 12718 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 Q|GcriI4T~9YY2${0oR+mPXGV_ literal 12673 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 Z9&P`79{e8xxGM-muBFBz0J#GJ`5%`o diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index 0016aa9..b7c2e9e 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -223,7 +223,7 @@ def launch_warehouse(self, config): warehouse_id = response.json().get("id") warehouse_start_time = time.time() - WorkspaceClient().warehouses.start_and_wait(warehouse_id) + WorkspaceClient(host=f"https://{self.hostname}", token=self.access_token).warehouses.start_and_wait(warehouse_id) print(f"{int(time.time() - warehouse_start_time)}s Warehouse Startup Time") if not warehouse_id: From d4ddee280140e5badc7ce00d70eb98305ac34f37 Mon Sep 17 00:00:00 2001 From: "anhhoang.chu@databricks.com" Date: Wed, 24 Jan 2024 01:24:08 +0000 Subject: [PATCH 10/20] Pull query metrics from history using /api/2.0/sql/history/queries --- src/beaker/benchmark.py | 50 +++++++++++++++++++++++---------- src/beaker/spark_fixture.py | 55 +++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index 3da256c..cc2eee1 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -5,9 +5,10 @@ import logging from concurrent.futures import ThreadPoolExecutor import threading +import datetime from beaker.sqlwarehouseutils import SQLWarehouseUtils -from beaker.spark_fixture import get_spark_session, metrics_to_df_view +from beaker.spark_fixture import get_spark_session, metrics_to_df_view, get_query_history # Create thread-local storage thread_local = threading.local() @@ -176,11 +177,12 @@ def _execute_single_query(self, query, id=None): sql_warehouse = self._get_thread_local_connection() - # TODO: instead of using perf counter, we might want to get the query duration from /api/2.0/sql/history/queries API + ## Instead of using perf counter, we want to get the query duration from /api/2.0/sql/history/queries API start_time = time.perf_counter() - sql_warehouse.execute_query(query) + result = sql_warehouse.execute_query(query) end_time = time.perf_counter() elapsed_time = f"{end_time - start_time:0.3f}" + metrics = { "id": id, "hostname": self.hostname, @@ -191,6 +193,7 @@ def _execute_single_query(self, query, id=None): } return metrics + def _set_default_catalog(self): if self.catalog: query = f"USE CATALOG {self.catalog}" @@ -252,7 +255,7 @@ def _get_queries_from_file(self, query_file): def _execute_queries_from_file(self, query_file): queries = self._get_queries_from_file(query_file) metrics = self._execute_queries(queries, self.concurrency) - return metrics + return queries def _get_query_filenames_from_dir(self, query_file_dir): return [os.path.join(query_file_dir, f) for f in os.listdir(query_file_dir)] @@ -269,11 +272,11 @@ def _get_queries_from_dir(self, query_dir): def _execute_queries_from_dir(self, query_dir): queries = self._get_queries_from_dir(query_dir) metrics = self._execute_queries(queries, self.concurrency) - return metrics + return queries def _execute_queries_from_query(self, query): metrics = self._execute_queries([(query, "query")], 1) - return metrics + return [(query, "query")] def _execute_queries(self, queries, num_threads): # Duplicate queries `query_repeat_count` number of times @@ -284,7 +287,7 @@ def _execute_queries(self, queries, num_threads): metrics_list = list( executor.map(lambda x: self._execute_single_query(*x), queries) ) - return metrics_list + return queries def execute(self): """Executes the benchmark test.""" @@ -292,21 +295,40 @@ def execute(self): logging.info("Set default catalog and schema") self._set_default_catalog() self._set_default_schema() - metrics = None + + start_ts_ms = int(time.time() * 1000) + start_dt = datetime.datetime.fromtimestamp(start_ts_ms/1000).strftime('%Y-%m-%d %H:%M:%S') + if self.query_file_dir is not None: logging.info("Loading query files from directory.") - metrics = self._execute_queries_from_dir(self.query_file_dir) + queries = self._execute_queries_from_dir(self.query_file_dir) elif self.query_file is not None: logging.info("Loading query file.") - metrics = self._execute_queries_from_file(self.query_file) + queries = self._execute_queries_from_file(self.query_file) elif self.query is not None: logging.info("Executing single query.") - metrics = self._execute_queries_from_query(self.query) + queries = self._execute_queries_from_query(self.query) else: raise ValueError("No query specified.") - metrics_df = metrics_to_df_view(metrics, f"{self.name}_vw") - print(f"Query the metrics view at: ", f"{self.name}_vw") - return metrics + queries_df = spark.createDataFrame(queries, ["query", "id"]) + history_df = get_query_history(self.hostname, self.token, self.http_path[17:]) + + # inner join history_df with query_df + # select warehouse_id, id, query_text, duration_sec, query_execution_time_sec, + # planning_time_sec, photon_total_time_sec + metrics_df = (history_df.join(queries_df, history_df.query_text == queries_df.query, "inner") + .select(queries_df["id"].alias("id"), + history_df["warehouse_id"].alias("warehouse_id"), + queries_df["query"].alias("query_text"), + (history_df.duration / 1000).alias("duration_sec"), + (history_df.metrics.execution_time_ms / 1000).alias("query_execution_time_sec"), + (history_df.metrics.planning_time_ms / 1000).alias("planning_time_sec"), + (history_df.metrics.photon_total_time_ms / 1000).alias("photon_total_time_sec")) + ) + + df_view = metrics_to_df_view(metrics_df, self.name + "_vw") + print(f"Query the metrics view starting {start_dt} UTC at: ", self.name + "_view") + return metrics_df def preWarmTables(self, tables): """Delta caches the table before running a benchmark test.""" diff --git a/src/beaker/spark_fixture.py b/src/beaker/spark_fixture.py index ae0f6ce..16204bb 100644 --- a/src/beaker/spark_fixture.py +++ b/src/beaker/spark_fixture.py @@ -17,11 +17,62 @@ def get_spark_session(): return SparkSession.builder.appName("beaker").getOrCreate() +def get_query_history(hostname, token, warehouse_id, start_ts_ms): + """ + Retrieves the Query History for a given workspace and Data Warehouse. + + Parameters: + ----------- + hostname (str): The URL of the Databricks workspace where the Data Warehouse is located. + token(str): The Personal Access Token (token) to access the Databricks API. + warehouse_id (str): The ID of the Data Warehouse for which to retrieve the Query History. + start_ts_ms (int): The Unix timestamp (milliseconds) value representing the start of the query history. + view_name (str, optional): The name of the view created from the Spark DataFrame containing Query History. Defaults to "demo_query". + + Returns: + -------- + None + """ + ## Put together request + request_string = { + "filter_by": { + "query_start_time_range": { + # "end_time_ms": end_ts_ms, + "start_time_ms": start_ts_ms + }, + "statuses": [ + "FINISHED" + ], + "warehouse_ids": warehouse_id + }, + "include_metrics": "true", + "max_results": "1000" + } + + ## Convert dict to json + v = json.dumps(request_string) + + uri = f"https://{hostname}/api/2.0/sql/history/queries" + headers_auth = {"Authorization":f"Bearer {token}"} + + #### Get Query History Results from API + response = requests.get(uri, data=v, headers=headers_auth) + + df = None + if (response.status_code == 200) and ("res" in response.json()): + end_res = response.json()['res'] + history_df = spark.createDataFrame(end_res) + # df.createOrReplaceTempView(f"{view_name}_hist_view") + # print(f"""View Query History at: {view_name}_hist_view""" ) + else: + print("Failed to retrieve query history") + return history_df + def metrics_to_df_view(metrics, view_name): """Convert a list of dicts to a results dataframe. Create a view and return the dataframe. """ spark = get_spark_session() - df = spark.createDataFrame(metrics) - df.createOrReplaceTempView(view_name) + # df = spark.createDataFrame(metrics) + metrics.createOrReplaceTempView(view_name) return df From 211d9a8442e99041b6a0dfa0756b534b747c60be Mon Sep 17 00:00:00 2001 From: "anhhoang.chu@databricks.com" Date: Sat, 27 Jan 2024 00:24:26 +0000 Subject: [PATCH 11/20] Add query history, update examples to reflect the changes --- examples/beaker_getting_started.dbc | Bin 4074 -> 0 bytes examples/beaker_getting_started.py | 52 ++-- examples/beaker_standalone.py | 12 +- examples/getting_started.ipynb | 378 +++++++++++++++++++++------- examples/requirements.txt | 2 + examples/standalone_dist_test.py | 4 +- src/beaker/benchmark.py | 105 +++++--- src/beaker/spark_fixture.py | 71 ++---- src/beaker/sqlwarehouseutils.py | 4 +- 9 files changed, 432 insertions(+), 196 deletions(-) delete mode 100644 examples/beaker_getting_started.dbc mode change 100755 => 100644 examples/beaker_standalone.py create mode 100644 examples/requirements.txt diff --git a/examples/beaker_getting_started.dbc b/examples/beaker_getting_started.dbc deleted file mode 100644 index 7b1f71b34ab64d98ef2973b3ac415fa40f2934e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4074 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 diff --git a/examples/beaker_getting_started.py b/examples/beaker_getting_started.py index fcb1065..35bca86 100644 --- a/examples/beaker_getting_started.py +++ b/examples/beaker_getting_started.py @@ -1,5 +1,7 @@ # Databricks notebook source -# MAGIC %pip install databricks-sql-connector +# MAGIC %pip install databricks-sql-connector -q +# MAGIC %pip install databricks-sdk -q +# MAGIC dbutils.library.restartPython() # COMMAND ---------- @@ -31,6 +33,10 @@ # COMMAND ---------- +importlib.reload(spark_fixture) + +# COMMAND ---------- + # MAGIC %md # MAGIC ## Create a new Benchmark Test @@ -47,11 +53,14 @@ # COMMAND ---------- # Change hostname and http_path to your dbsql warehouse -hostname = "your-dbsql-hostname" -http_path = "your-dbsql-http-path" +hostname = spark.conf.get('spark.databricks.workspaceUrl') +# Extract token from dbutils +pat = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().get() +# OR Add the appropriate scope and key for your token if configured in databricks secrets +# pat = dbutils.secrets.get(scope="your-scope", key="your-token") -# Add the appropriate scope and key for your token -pat = dbutils.secrets.get(scope="your-scope", key="your-token") +# warehouse http path example, replace with your own +http_path = "/sql/1.0/warehouses/7f5789ee19b3b19c" # COMMAND ---------- @@ -75,11 +84,7 @@ # COMMAND ---------- # Run the benchmark! -metrics = bm.execute() - -# COMMAND ---------- - -metrics +beaker_metrics, history_metrics = bm.execute() # COMMAND ---------- @@ -88,7 +93,7 @@ # COMMAND ---------- -df_simple_test = spark_fixture.metrics_to_df_view(metrics, "simple_test_vw") +df_simple_test = spark_fixture.metrics_to_df_view(beaker_metrics, history_metrics, "simple_test_vw") df_simple_test.display() # COMMAND ---------- @@ -109,10 +114,19 @@ # COMMAND ---------- +hostname = spark.conf.get('spark.databricks.workspaceUrl') +pat = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().get() +query_str = """ +SELECT count(*) + FROM delta.`/databricks-datasets/nyctaxi/tables/nyctaxi_yellow` + WHERE passenger_count > 2 +""" + new_warehouse_config = { "type": "warehouse", "runtime": "latest", - "size": "Large", + "size": "2X-Small", + "warehouse": "serverless", "min_num_clusters": 1, "max_num_clusters": 3, "enable_photon": True, @@ -132,8 +146,8 @@ # benchmark.preWarmTables(tables=["table_a", "table_b", "table_c"]) # Run the benchmark! -metrics = bm.execute() -print(metrics) +beaker_metrics, history_metrics = bm.execute() +print(history_metrics) # COMMAND ---------- @@ -189,7 +203,13 @@ # COMMAND ---------- -metrics = bm.execute() -print(metrics) +beaker_metrics, history_metrics = bm.execute() +history_df = spark_fixture.metrics_to_df_view(beaker_metrics, history_metrics, view_name="metrics_view") + +# COMMAND ---------- + +# MAGIC %sql select * from metrics_view # COMMAND ---------- + + diff --git a/examples/beaker_standalone.py b/examples/beaker_standalone.py old mode 100755 new mode 100644 index 75cf15f..ddceb3e --- a/examples/beaker_standalone.py +++ b/examples/beaker_standalone.py @@ -30,18 +30,18 @@ bm.setQuery(query=query_str) bm.setCatalog(catalog="hive_metastore") -metrics = bm.execute() -print(metrics) +beaker_metrics, history_metrics = bm.execute() +print(history_metrics) print("---- Specify a single query file ------") bm.query_file_format = "semicolon-delimited" bm.setQueryFile("queries/q1.sql") -metrics = bm.execute() -print(metrics) +beaker_metrics, history_metrics = bm.execute() +print(history_metrics) print("---- Specify a query directory ------") bm.setQueryFileDir("queries") -metrics = bm.execute() -print(metrics) +beaker_metrics, history_metrics = bm.execute() +print(history_metrics) diff --git a/examples/getting_started.ipynb b/examples/getting_started.ipynb index 7f9973f..c319c3e 100644 --- a/examples/getting_started.ipynb +++ b/examples/getting_started.ipynb @@ -2,9 +2,59 @@ "cells": [ { "cell_type": "code", - "execution_count": null, - "id": "c1f35f99-4af0-4dca-923f-1d38963ba4d6", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "419dc4ed-3e7b-4ee0-825a-186e9bce875d", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "%pip install -r requirements.txt -q" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "b0b8e357-baf1-4bde-afa8-e83a9569e70f", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "dbutils.library.restartPython()" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "f61e57fe-b420-4019-b5f2-30e675245201", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "import os, sys" @@ -12,9 +62,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "8985fd77-f702-495c-940f-92400ba472a9", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "a2b5b664-16e8-4475-a139-f8362b598acc", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "import logging\n", @@ -24,9 +84,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "58fb1eb8-aac6-4a36-8103-c2a15c34c6db", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "0036c4db-840d-43aa-a8f7-689af7c42a12", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "sys.path.append('../src/')" @@ -34,9 +104,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "7e5fef46-98c2-44f3-a5ae-7b44b1b08366", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "3582a127-4232-4dec-aa3e-1338e6a701cd", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "from beaker import benchmark" @@ -44,9 +124,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "2e08370d-d302-4f72-a3d0-f5ebb18cf0f6", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "0e5351e2-cc32-494f-a4a0-0e9e1c85e4ff", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "bm = benchmark.Benchmark()" @@ -54,9 +144,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "4135ff45-95be-47e9-8b3a-24fae504e613", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "0cf52295-d4c6-477b-98e6-d3937ea2d43c", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "import importlib\n", @@ -65,9 +165,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "58f65a8d-e3db-490a-879c-0714d27aa37d", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "ae05a0a6-bb77-4f4b-b162-70d4383a7db1", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "hostname = os.getenv(\"DATABRICKS_HOST\")\n", @@ -79,9 +189,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "bd04cc75-1331-45f9-be0b-389f55bb6e35", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "e5b84533-ed24-4ea3-88d6-01bf4277cca1", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "bm.setName(name=\"simple_test\")\n", @@ -93,9 +213,19 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "881feb1d-f3e7-4506-9df9-eafdeef9115a", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "81365f27-ef0b-432d-9440-d72916670b0e", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "query_str=\"\"\"\n", @@ -109,37 +239,53 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "fd31721a-0701-4bea-a880-0caed688afb4", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "b5e93556-19ff-4add-bc6b-78fc6b21ca6c", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ - "metrics = bm.execute()" + "beaker_metrics, history_metrics = bm.execute()" ] }, { "cell_type": "code", - "execution_count": null, - "id": "2a8b5eb7-359f-4dab-a1ff-0b4e2e8bd595", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "2a7d47e2-e338-4a3a-8463-8ca8be3ae9a1", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ - "metrics" + "history_metrics" ] }, { "cell_type": "code", - "execution_count": null, - "id": "8df2bd2c-03b5-4032-bfcb-ca880442fe95", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "48280d72-1497-4c9a-8471-08c53eb10db7", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "c2f71cd4-5b87-4e98-a6b7-1d079fbfd05c", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "bm.query_file_format = \"semicolon-delimited\"" @@ -147,9 +293,16 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "e4bf5ddb-15fa-4c0f-805d-6411955a3232", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "59f008bd-460d-454b-80e4-0bbec5f0c155", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "bm.setQueryFile('queries/q1.sql')" @@ -157,9 +310,16 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "361b06ee-d388-48de-93b0-bd1b03ce2527", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "b023c128-b6db-4664-bb18-bea1c4994ee1", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "bm.execute()" @@ -167,9 +327,16 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "d4753bb4-a833-4f06-9408-6ee3a3d157e1", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "150794cd-7d2e-4d38-8bf9-0ef4de40ea58", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "bm.setQueryFileDir('queries')" @@ -177,37 +344,50 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "232368e3-85de-454e-ba52-3903d451c2c1", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "ae66fd20-ee78-4df1-9bc7-b873cd3f08f0", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ - "metrics = bm.execute()" + "beaker_metrics, history_metrics = bm.execute()" ] }, { "cell_type": "code", - "execution_count": null, - "id": "b0b203eb-992c-41e0-8038-40ce733d076c", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "8356cc87-099f-4d28-902b-4f4b34a1e80e", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ - "metrics" + "history_metrics" ] }, { "cell_type": "code", - "execution_count": null, - "id": "1b4de6a3-1ac9-4ad7-89cd-b8cfaad5e3ba", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cabfde2b", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "6bf0f336-7732-4e24-bdf5-00ca81870bba", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "from beaker import sqlwarehouseutils" @@ -215,9 +395,16 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "d80b78ab", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "3e796340-dbd4-40c0-a140-56648522eb50", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "sql_warehouse = sqlwarehouseutils.SQLWarehouseUtils(\n", @@ -232,9 +419,16 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "c0004348", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "7744be3c-7f67-4345-8930-c51499fc8e75", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "x = sql_warehouse.get_rows(\"\"\"\n", @@ -248,9 +442,16 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "20df6e8f", - "metadata": {}, + "execution_count": 0, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "4116033a-c709-4ced-b2b3-c45ba72445c9", + "showTitle": false, + "title": "" + } + }, "outputs": [], "source": [ "x" @@ -258,6 +459,15 @@ } ], "metadata": { + "application/vnd.databricks.v1+notebook": { + "dashboards": [], + "language": "python", + "notebookMetadata": { + "pythonIndentUnit": 2 + }, + "notebookName": "getting_started", + "widgets": {} + }, "kernelspec": { "display_name": "Python [conda env:mr-delta]", "language": "python", @@ -277,5 +487,5 @@ } }, "nbformat": 4, - "nbformat_minor": 5 + "nbformat_minor": 0 } diff --git a/examples/requirements.txt b/examples/requirements.txt new file mode 100644 index 0000000..a5f1a44 --- /dev/null +++ b/examples/requirements.txt @@ -0,0 +1,2 @@ +databricks-sql-connector +databricks-sdk \ No newline at end of file diff --git a/examples/standalone_dist_test.py b/examples/standalone_dist_test.py index 1b7a0ba..433cfcc 100644 --- a/examples/standalone_dist_test.py +++ b/examples/standalone_dist_test.py @@ -29,6 +29,6 @@ bm.setQuery("select now(), 'foo';") bm.setQueryRepeatCount(100) -metrics = bm.execute() -#print(metrics) +beaker_metrics, history_metrics = bm.execute() +#print(history_metrics) diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index cc2eee1..9992e2d 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -1,3 +1,4 @@ +from databricks.sdk.runtime import * import os import time import re @@ -6,9 +7,12 @@ from concurrent.futures import ThreadPoolExecutor import threading import datetime +import json +from pyspark.sql.types import StructType, StructField, StringType, LongType +from pyspark.sql.functions import col from beaker.sqlwarehouseutils import SQLWarehouseUtils -from beaker.spark_fixture import get_spark_session, metrics_to_df_view, get_query_history +from beaker.spark_fixture import get_spark_session, metrics_to_df_view # Create thread-local storage thread_local = threading.local() @@ -65,7 +69,7 @@ def _create_dbc(self): ) # establish connection on the existing warehouse sql_warehouse.setConnection() - logging.info(f"Returning new sqlwarehouseutils: {sql_warehouse}") + self.warehouse_id = self.http_path.split("/")[-1] return sql_warehouse def _get_thread_local_connection(self): @@ -244,7 +248,6 @@ def _get_queries_from_file_format_semi(self, f, filter_comment_lines=False): return queries def _get_queries_from_file(self, query_file): - print("Get queries from file:", query_file) if self.query_file_format == self.QUERY_FILE_FORMAT_SEMICOLON_DELIM: return self._get_queries_from_file_format_semi(query_file) elif self.query_file_format == self.QUERY_FILE_FORMAT_ORIGINAL: @@ -255,28 +258,27 @@ def _get_queries_from_file(self, query_file): def _execute_queries_from_file(self, query_file): queries = self._get_queries_from_file(query_file) metrics = self._execute_queries(queries, self.concurrency) - return queries + return metrics def _get_query_filenames_from_dir(self, query_file_dir): return [os.path.join(query_file_dir, f) for f in os.listdir(query_file_dir)] def _get_queries_from_dir(self, query_dir): - print("Get queries from dir:", query_dir) query_files = self._get_query_filenames_from_dir(query_dir) queries = [] for qf in query_files: qs = self._get_queries_from_file(qf) queries += qs - return queries + return metrics def _execute_queries_from_dir(self, query_dir): queries = self._get_queries_from_dir(query_dir) metrics = self._execute_queries(queries, self.concurrency) - return queries + return metrics def _execute_queries_from_query(self, query): metrics = self._execute_queries([(query, "query")], 1) - return [(query, "query")] + return metrics def _execute_queries(self, queries, num_threads): # Duplicate queries `query_repeat_count` number of times @@ -287,7 +289,61 @@ def _execute_queries(self, queries, num_threads): metrics_list = list( executor.map(lambda x: self._execute_single_query(*x), queries) ) - return queries + return metrics_list + + def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): + """ + Retrieves the Query History for a given workspace and Data Warehouse. + + Parameters: + ----------- + warehouse_id (str): The ID of the Data Warehouse for which to retrieve the Query History. + start_ts_ms (int): The Unix timestamp (milliseconds) value representing the start of the query history. + end_ts_ms (int): The Unix timestamp (milliseconds) value representing the end of the query history. + + Returns: + -------- + history_df : dataframe of the query history + """ + user_id = self._get_user_id() + logging.info("Extracting Query History") + ## Put together request + request_string = { + "filter_by": { + "query_start_time_range": { + "end_time_ms": end_ts_ms, + "start_time_ms": start_ts_ms + }, + "warehouse_ids": warehouse_id, + "user_ids": [user_id], + }, + "include_metrics": "true", + "max_results": "1000" + } + + # ## Convert dict to json + v = json.dumps(request_string) + + uri = f"https://{self.hostname}/api/2.0/sql/history/queries" + headers_auth = {"Authorization":f"Bearer {self.token}"} + + #### Get Query History Results from API + response = requests.get(uri, data=v, headers=headers_auth) + logging.info("Await completion of all queries...") + while True: + results = response.json()['res'] + if all([item['is_final'] for item in results]): + break + time.sleep(5) + response = requests.get(uri, data=v, headers=headers_auth) + + if (response.status_code == 200) and ("res" in response.json()): + logging.info("Query history extracted successfully") + end_res = response.json()['res'] + return end_res + else: + raise Exception("Failed to retrieve successful query history") + def execute(self): """Executes the benchmark test.""" @@ -301,34 +357,21 @@ def execute(self): if self.query_file_dir is not None: logging.info("Loading query files from directory.") - queries = self._execute_queries_from_dir(self.query_file_dir) + metrics = self._execute_queries_from_dir(self.query_file_dir) elif self.query_file is not None: logging.info("Loading query file.") - queries = self._execute_queries_from_file(self.query_file) + metrics = self._execute_queries_from_file(self.query_file) elif self.query is not None: logging.info("Executing single query.") - queries = self._execute_queries_from_query(self.query) + metrics = self._execute_queries_from_query(self.query) else: raise ValueError("No query specified.") - queries_df = spark.createDataFrame(queries, ["query", "id"]) - history_df = get_query_history(self.hostname, self.token, self.http_path[17:]) - - # inner join history_df with query_df - # select warehouse_id, id, query_text, duration_sec, query_execution_time_sec, - # planning_time_sec, photon_total_time_sec - metrics_df = (history_df.join(queries_df, history_df.query_text == queries_df.query, "inner") - .select(queries_df["id"].alias("id"), - history_df["warehouse_id"].alias("warehouse_id"), - queries_df["query"].alias("query_text"), - (history_df.duration / 1000).alias("duration_sec"), - (history_df.metrics.execution_time_ms / 1000).alias("query_execution_time_sec"), - (history_df.metrics.planning_time_ms / 1000).alias("planning_time_sec"), - (history_df.metrics.photon_total_time_ms / 1000).alias("photon_total_time_sec")) - ) - - df_view = metrics_to_df_view(metrics_df, self.name + "_vw") - print(f"Query the metrics view starting {start_dt} UTC at: ", self.name + "_view") - return metrics_df + + end_ts_ms = int(time.time() * 1000) + print("Monitor warehouse at: ", f"https://{self.hostname}/sql/warehouses/{self.warehouse_id}/monitoring") + logging.info("Getting Query Metrics") + history_metrics = self.get_query_history(self.warehouse_id, start_ts_ms, end_ts_ms) + return metrics, history_metrics def preWarmTables(self, tables): """Delta caches the table before running a benchmark test.""" diff --git a/src/beaker/spark_fixture.py b/src/beaker/spark_fixture.py index 16204bb..7bc2db7 100644 --- a/src/beaker/spark_fixture.py +++ b/src/beaker/spark_fixture.py @@ -1,7 +1,7 @@ import os from pyspark.sql import SparkSession from functools import lru_cache - +from pyspark.sql.functions import col @lru_cache(maxsize=None) def get_spark_session(): @@ -16,63 +16,22 @@ def get_spark_session(): else: return SparkSession.builder.appName("beaker").getOrCreate() - -def get_query_history(hostname, token, warehouse_id, start_ts_ms): - """ - Retrieves the Query History for a given workspace and Data Warehouse. - - Parameters: - ----------- - hostname (str): The URL of the Databricks workspace where the Data Warehouse is located. - token(str): The Personal Access Token (token) to access the Databricks API. - warehouse_id (str): The ID of the Data Warehouse for which to retrieve the Query History. - start_ts_ms (int): The Unix timestamp (milliseconds) value representing the start of the query history. - view_name (str, optional): The name of the view created from the Spark DataFrame containing Query History. Defaults to "demo_query". - - Returns: - -------- - None - """ - ## Put together request - request_string = { - "filter_by": { - "query_start_time_range": { - # "end_time_ms": end_ts_ms, - "start_time_ms": start_ts_ms - }, - "statuses": [ - "FINISHED" - ], - "warehouse_ids": warehouse_id - }, - "include_metrics": "true", - "max_results": "1000" - } - - ## Convert dict to json - v = json.dumps(request_string) - - uri = f"https://{hostname}/api/2.0/sql/history/queries" - headers_auth = {"Authorization":f"Bearer {token}"} - - #### Get Query History Results from API - response = requests.get(uri, data=v, headers=headers_auth) - df = None - if (response.status_code == 200) and ("res" in response.json()): - end_res = response.json()['res'] - history_df = spark.createDataFrame(end_res) - # df.createOrReplaceTempView(f"{view_name}_hist_view") - # print(f"""View Query History at: {view_name}_hist_view""" ) - else: - print("Failed to retrieve query history") - return history_df - -def metrics_to_df_view(metrics, view_name): +def metrics_to_df_view(beaker_metrics, history_metrics, view_name): """Convert a list of dicts to a results dataframe. Create a view and return the dataframe. """ spark = get_spark_session() - # df = spark.createDataFrame(metrics) - metrics.createOrReplaceTempView(view_name) - return df + metrics_df = spark.createDataFrame(beaker_metrics) + history_df = spark.createDataFrame(history_metrics) + history_metrics_df = ( + history_df.alias("v1") + .join(metrics_df.select("id", "query").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") + .select("v1.warehouse_id", "v2.id", "v1.query_text", + (col("v1.duration") / 1000).alias("duration_sec"), + (col("metrics.execution_time_ms") / 1000).alias("query_execution_time_sec"), + (col("metrics.planning_time_ms") / 1000).alias("planning_time_sec"), + (col("metrics.photon_total_time_ms") / 1000).alias("photon_total_time_sec")) + ) + history_metrics_df.createOrReplaceTempView(view_name) + return history_metrics_df diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index 251631c..8b968af 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -78,7 +78,9 @@ def close_connection(self): def execute_query(self, query_str): with self.connection.cursor() as cursor: - result = cursor.execute(query_str) + cursor.execute(query_str) + result = cursor.fetchall() + return result def get_rows(self, query_str): with self.connection.cursor() as cursor: From 741026b7c0198a276ad7a2b79fe0d5c3588c10cc Mon Sep 17 00:00:00 2001 From: anhhchu Date: Fri, 26 Jan 2024 17:49:19 -0800 Subject: [PATCH 12/20] Add warehouse_type option --- .gitignore | 5 +++++ examples/beaker_getting_started.dbc | Bin 0 -> 7837 bytes examples/beaker_standalone.py | 8 +++++--- examples/requirements.txt | 4 +++- src/beaker/benchmark.py | 7 +++---- src/beaker/spark_fixture.py | 2 +- 6 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 examples/beaker_getting_started.dbc diff --git a/.gitignore b/.gitignore index 0c09d88..c3d03be 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ # Build helpers *beaker.egg-info* build/* + +myvenv/ + +*/.env +.env diff --git a/examples/beaker_getting_started.dbc b/examples/beaker_getting_started.dbc new file mode 100644 index 0000000000000000000000000000000000000000..596317aff16b4fa1142076f0bab6e172105cca26 GIT binary patch literal 7837 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 L{F5R7*Z+S25KQQK literal 0 HcmV?d00001 diff --git a/examples/beaker_standalone.py b/examples/beaker_standalone.py index ddceb3e..ce07342 100644 --- a/examples/beaker_standalone.py +++ b/examples/beaker_standalone.py @@ -4,17 +4,19 @@ logger = logging.getLogger() logger.setLevel(logging.INFO) -sys.path.append("../src") +from dotenv import load_dotenv +load_dotenv() -from beaker import benchmark +sys.path.append("../src") -bm = benchmark.Benchmark() +# from beaker import benchmark hostname = os.getenv("DATABRICKS_HOST") http_path = os.getenv("DATABRICKS_HTTP_PATH") # Don't put tokens in plaintext in code access_token = os.getenv("DATABRICKS_ACCESS_TOKEN") +bm = benchmark.Benchmark() bm.setName(name="simple_test") bm.setHostname(hostname=hostname) bm.setWarehouse(http_path=http_path) diff --git a/examples/requirements.txt b/examples/requirements.txt index a5f1a44..993065b 100644 --- a/examples/requirements.txt +++ b/examples/requirements.txt @@ -1,2 +1,4 @@ databricks-sql-connector -databricks-sdk \ No newline at end of file +databricks-sdk +pyspark +python-dotenv \ No newline at end of file diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index 9992e2d..f8b8016 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -8,8 +8,6 @@ import threading import datetime import json -from pyspark.sql.types import StructType, StructField, StringType, LongType -from pyspark.sql.functions import col from beaker.sqlwarehouseutils import SQLWarehouseUtils from beaker.spark_fixture import get_spark_session, metrics_to_df_view @@ -186,11 +184,12 @@ def _execute_single_query(self, query, id=None): result = sql_warehouse.execute_query(query) end_time = time.perf_counter() elapsed_time = f"{end_time - start_time:0.3f}" - + warehouse_type = "serverless" if "warehouse" not in self.new_warehouse_config else self.new_warehouse_config["warehouse"] metrics = { "id": id, "hostname": self.hostname, "http_path": self.http_path, + "warehouse_type": warehouse_type, "concurrency": self.concurrency, "query": query, "elapsed_time": elapsed_time, @@ -269,7 +268,7 @@ def _get_queries_from_dir(self, query_dir): for qf in query_files: qs = self._get_queries_from_file(qf) queries += qs - return metrics + return queries def _execute_queries_from_dir(self, query_dir): queries = self._get_queries_from_dir(query_dir) diff --git a/src/beaker/spark_fixture.py b/src/beaker/spark_fixture.py index 7bc2db7..49948fd 100644 --- a/src/beaker/spark_fixture.py +++ b/src/beaker/spark_fixture.py @@ -26,7 +26,7 @@ def metrics_to_df_view(beaker_metrics, history_metrics, view_name): history_df = spark.createDataFrame(history_metrics) history_metrics_df = ( history_df.alias("v1") - .join(metrics_df.select("id", "query").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") + .join(metrics_df.select("id", "query", "warehouse_type").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") .select("v1.warehouse_id", "v2.id", "v1.query_text", (col("v1.duration") / 1000).alias("duration_sec"), (col("metrics.execution_time_ms") / 1000).alias("query_execution_time_sec"), From adf0319995b57609eb0312bfc7072ddd049a1202 Mon Sep 17 00:00:00 2001 From: "anhhoang.chu@databricks.com" Date: Sat, 27 Jan 2024 01:57:29 +0000 Subject: [PATCH 13/20] Remove warehouse_type in metrics --- src/beaker/benchmark.py | 3 +-- src/beaker/spark_fixture.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index f8b8016..cf05c7b 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -184,12 +184,11 @@ def _execute_single_query(self, query, id=None): result = sql_warehouse.execute_query(query) end_time = time.perf_counter() elapsed_time = f"{end_time - start_time:0.3f}" - warehouse_type = "serverless" if "warehouse" not in self.new_warehouse_config else self.new_warehouse_config["warehouse"] + metrics = { "id": id, "hostname": self.hostname, "http_path": self.http_path, - "warehouse_type": warehouse_type, "concurrency": self.concurrency, "query": query, "elapsed_time": elapsed_time, diff --git a/src/beaker/spark_fixture.py b/src/beaker/spark_fixture.py index 49948fd..7bc2db7 100644 --- a/src/beaker/spark_fixture.py +++ b/src/beaker/spark_fixture.py @@ -26,7 +26,7 @@ def metrics_to_df_view(beaker_metrics, history_metrics, view_name): history_df = spark.createDataFrame(history_metrics) history_metrics_df = ( history_df.alias("v1") - .join(metrics_df.select("id", "query", "warehouse_type").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") + .join(metrics_df.select("id", "query").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") .select("v1.warehouse_id", "v2.id", "v1.query_text", (col("v1.duration") / 1000).alias("duration_sec"), (col("metrics.execution_time_ms") / 1000).alias("query_execution_time_sec"), From edce81d8c8720e559a6566674bfcb0f89371e410 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Sat, 3 Feb 2024 10:25:41 -0800 Subject: [PATCH 14/20] Update v0.0.6 --- dist/beaker-0.0.6-py3-none-any.whl | Bin 0 -> 15453 bytes dist/beaker-0.0.6.tar.gz | Bin 0 -> 13733 bytes src/__init__.py | 2 +- src/beaker/benchmark.py | 26 +++++++++++++++++++++----- src/beaker/spark_fixture.py | 5 +++-- src/beaker/sqlwarehouseutils.py | 2 +- 6 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 dist/beaker-0.0.6-py3-none-any.whl create mode 100644 dist/beaker-0.0.6.tar.gz diff --git a/dist/beaker-0.0.6-py3-none-any.whl b/dist/beaker-0.0.6-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..eb57b8557a502580eaf540f4c8e044cf93f5b3ac GIT binary patch literal 15453 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 literal 0 HcmV?d00001 diff --git a/dist/beaker-0.0.6.tar.gz b/dist/beaker-0.0.6.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..d724ea9be31e1ef8f1765f128afb1e4010c1e7bf GIT binary patch literal 13733 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
x&ucGp@^3^thGwpnYutiCr)`h! zZYOy(_2jt&`DEH2F#-K{p8obh$(fc^6QkxrjyaLFlY8W8KQ@B%tq(QaU31D*gki~D zn3*$m#%ON`6)+ecpupO9@g+`t=bANZOlh+kw2& z+;m7=g4d^##K>6aT;W#leX27ow%?WL*qR6*N$D!}lYL&N%?eQE)*EMkU|(cJKv#ml z9+7ItI%DWBFgMG&-ABkE6T$FA=jQ4<<_VB?z3HN`s2aJ5(&VP)pF{@JC3W&dt-s8( zOJS4P;yFxNVq#$-I?IFBQ%EIWI9 z9T)~)_bfPZ8*)j`jjOIFJj)a7K|$V2*x^PO28Mk`E6P!i4N2X@ zg*q#J%c76wEOMF?dBpn}FK3EQS)Z+@s}wqRV#?AUE;cgGHMZ7uo`e0Tq}S3Fo;w~H z40M;*Vw)tods9A2?nZ8V^W{t=+YHg*TK@i;gq{`sM@$Fhhnr@mL>-nk83`qSz~Tq_ z9%>F|pb=e1X(Z%hJpQAJIb;s+<-ZDczu_Iu|fFi)SY`s9uktP;hnwxFdR$P2~hR+tGo?drpcV3y zBi#ifXq1p3Fq|{5^huet=N}kJc5-{IQfLB9r~sH!*1AY$&oE)RJG6j{hem$hFh5e! zA%Cz!rtC@nwEaj%UNFa5Zc+<^S}CgxHLG%OB}P-9!Rj4j=04P& zVvZu*5pMh?$Hnhf6T@S}Ge%XjB;PejjV@13=bRxxWKtv8j zPf;xg;IhhZQdv-0hyLimNTgn8;JJObK-Ehy`rp$Jq)jGj%1>zuHKV7L@3aLLErSXh z6s54#rJ9xKIzwEOTx>lB_pj=MDf2MOFqJ81z-h{LE&gzd0bJNrX(cPsl|ubB#MwDg ze7F(RTk66fxrAmR1Cz#72+JMkx41Zbp1a9ZZe1iwQ7?vTQu5}i*-{PbP4e!1HwxbR zv`+rKC&dOl!WoTKk$4=Z&W-(EH-IM>l(;CL4NOR?U*)%-?pK=_fq1JOtowgV`W?=Khon3 z=a`JZNsWXlnEY4bKRN{ankV47#dUu_01sLKiUT5VrnJBjyjxi<0`g~7bK!}JPef|n zllJ%}P%7VQlT&WW`Z??-`q2w!AF8`FMj)*5Q^US~ar+94vrR(qh<`I-@*Zsi-)3izx2b3;5qK;pTH#r@Xe-HQr1k9f})6RCp&;B6{P%3#Gqi zeDe)-->R5@xn@Q;A z2NQCkl3XNS5O*vQdN7--f3YbPfFi%C+153o4uh&5dEqS!L!CBqyq73Z_jPA4i~c!q z*Q1xSVXK`J*WZ8YHb~F$xsu6}LNoYKT-P1%OZ^6a`#&8aV!io2iaz<<`GG$6o)5Uu2H$H?$SM?$PK$ciw)&!1w*#^4G$2+H+rfbcwfn z-byyFi+de6(toDD6k)z?k0kCA1MaYo-z1RlUt1#fUIlb@cvkPyH{>25&yja4lkUEq zwkR*`^zMSewq7wMAH2AzXRqpC=-$?5L4Wx89aja4VTbRrF1d@C=ImLdOnYJCbwb7K zhDg;9607egR6UMqc%9G*I{#05{!){#+We&^Z?)M=?f(+_Pv3;qI+a#HSinI41K(|{ AasU7T literal 0 HcmV?d00001 diff --git a/src/__init__.py b/src/__init__.py index 6e83b38..0cdff65 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +1 @@ -VERSION = '0.0.5' +VERSION = '0.0.6' diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index cf05c7b..227db43 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -67,7 +67,7 @@ def _create_dbc(self): ) # establish connection on the existing warehouse sql_warehouse.setConnection() - self.warehouse_id = self.http_path.split("/")[-1] + return sql_warehouse def _get_thread_local_connection(self): @@ -111,14 +111,18 @@ def setWarehouseConfig(self, config): """Launches a new cluster/warehouse from a JSON config.""" self.new_warehouse_config = config logging.info(f"Creating new warehouse with config: {config}") - warehouse_id = self._launch_new_warehouse() - logging.info(f"The warehouse Id is: {warehouse_id}") - self.http_path = f"/sql/1.0/warehouses/{warehouse_id}" + self.warehouse_id = self._launch_new_warehouse() + self.warehouse_name = self._get_warehouse_info() + logging.info(f"The warehouse Id is: {self.warehouse_id}") + self.http_path = f"/sql/1.0/warehouses/{self.warehouse_id}" def setWarehouse(self, http_path): """Sets the SQL Warehouse http path to use for the benchmark.""" assert self._validate_warehouse(id), "Invalid HTTP path for SQL Warehouse." self.http_path = http_path + if self.http_path: + self.warehouse_id = self.http_path.split("/")[-1] + self.warehouse_name = self._get_warehouse_info() def setConcurrency(self, concurrency): """Sets the query execution parallelism.""" @@ -189,6 +193,7 @@ def _execute_single_query(self, query, id=None): "id": id, "hostname": self.hostname, "http_path": self.http_path, + "warehouse_name": self.warehouse_name, "concurrency": self.concurrency, "query": query, "elapsed_time": elapsed_time, @@ -342,6 +347,14 @@ def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): else: raise Exception("Failed to retrieve successful query history") + def _get_warehouse_info(self): + """Gets the warehouse info.""" + response = requests.get( + f"https://{self.hostname}/api/2.0/sql/warehouses/{self.warehouse_id}", + headers={"Authorization": f"Bearer {self.token}"}, + ) + warehouse_name = response.json()["name"] + return warehouse_name def execute(self): """Executes the benchmark test.""" @@ -350,6 +363,8 @@ def execute(self): self._set_default_catalog() self._set_default_schema() + print(f"Monitor warehouse `{self.warehouse_name}` at: ", f"https://{self.hostname}/sql/warehouses/{self.warehouse_id}/monitoring") + start_ts_ms = int(time.time() * 1000) start_dt = datetime.datetime.fromtimestamp(start_ts_ms/1000).strftime('%Y-%m-%d %H:%M:%S') @@ -366,7 +381,8 @@ def execute(self): raise ValueError("No query specified.") end_ts_ms = int(time.time() * 1000) - print("Monitor warehouse at: ", f"https://{self.hostname}/sql/warehouses/{self.warehouse_id}/monitoring") + + logging.info("Getting Query Metrics") history_metrics = self.get_query_history(self.warehouse_id, start_ts_ms, end_ts_ms) return metrics, history_metrics diff --git a/src/beaker/spark_fixture.py b/src/beaker/spark_fixture.py index 7bc2db7..bc30cd3 100644 --- a/src/beaker/spark_fixture.py +++ b/src/beaker/spark_fixture.py @@ -26,12 +26,13 @@ def metrics_to_df_view(beaker_metrics, history_metrics, view_name): history_df = spark.createDataFrame(history_metrics) history_metrics_df = ( history_df.alias("v1") - .join(metrics_df.select("id", "query").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") - .select("v1.warehouse_id", "v2.id", "v1.query_text", + .join(metrics_df.select("id", "query", "warehouse_name").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") + .select("v2.warehouse_name", "v1.warehouse_id", "v2.id", "v1.query_text", (col("v1.duration") / 1000).alias("duration_sec"), (col("metrics.execution_time_ms") / 1000).alias("query_execution_time_sec"), (col("metrics.planning_time_ms") / 1000).alias("planning_time_sec"), (col("metrics.photon_total_time_ms") / 1000).alias("photon_total_time_sec")) ) history_metrics_df.createOrReplaceTempView(view_name) + print(f"Query metrics at: {view_name}") return history_metrics_df diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index e3bf327..6b81658 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -227,7 +227,7 @@ def launch_warehouse(self, config): WorkspaceClient(host=f"https://{self.hostname}", token=self.access_token).warehouses.start_and_wait(warehouse_id) - print(f"{int(time.time() - warehouse_start_time)}s Warehouse Startup Time") + print(f"{int(time.time() - warehouse_start_time)}s Warehouse {warehouse_id} Startup Time") if not warehouse_id: raise Exception(f"did not get back warehouse_id ({response.json()})") From d3c098e67f3bdf929578c5cd5480480ac42c4888 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Mon, 26 Feb 2024 14:04:18 -0800 Subject: [PATCH 15/20] Add query metrics history extraction --- .gitignore | 2 + dist/beaker-0.0.6-py3-none-any.whl | Bin 15453 -> 15454 bytes dist/beaker-0.0.6.tar.gz | Bin 13733 -> 13760 bytes dist/beaker-0.0.7-py3-none-any.whl | Bin 0 -> 15454 bytes dist/beaker-0.0.7.tar.gz | Bin 0 -> 13761 bytes examples/beaker_getting_started.dbc | Bin 7837 -> 0 bytes examples/beaker_getting_started.py | 17 ++++---- examples/beaker_standalone.py | 43 ++++++++++++++------ examples/getting_started.ipynb | 60 ++++++++++++---------------- examples/queries/q1.sql | 1 + examples/queries/test.py | 23 +++++++++++ examples/queries_orig/q1.sql | 2 + examples/queries_orig/q2.sql | 2 + examples/requirements.txt | 3 +- examples/standalone_dist_test.py | 12 +++--- src/__init__.py | 2 +- src/beaker/benchmark.py | 28 +++++++++---- src/beaker/spark_fixture.py | 22 +++------- 18 files changed, 133 insertions(+), 84 deletions(-) create mode 100644 dist/beaker-0.0.7-py3-none-any.whl create mode 100644 dist/beaker-0.0.7.tar.gz delete mode 100644 examples/beaker_getting_started.dbc create mode 100644 examples/queries/test.py create mode 100644 examples/queries_orig/q1.sql create mode 100644 examples/queries_orig/q2.sql diff --git a/.gitignore b/.gitignore index c3d03be..2051f29 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ myvenv/ */.env .env + +./examples/queries/test.py diff --git a/dist/beaker-0.0.6-py3-none-any.whl b/dist/beaker-0.0.6-py3-none-any.whl index eb57b8557a502580eaf540f4c8e044cf93f5b3ac..cfc6bef6ec97c469573f6f2c4abe159e15e0ad9c 100644 GIT binary patch delta 5380 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 delta 5390 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 delta 12582 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 IY5*7k01;MHz5oCK diff --git a/dist/beaker-0.0.7-py3-none-any.whl b/dist/beaker-0.0.7-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..bcc53878471251ec1560603831b67679ea9091c8 GIT binary patch literal 15454 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 literal 0 HcmV?d00001 diff --git a/dist/beaker-0.0.7.tar.gz b/dist/beaker-0.0.7.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..47b2b4b595e18aba38972819f94ba7e926f17563 GIT binary patch literal 13761 zcmbVSLvt<+vy6=s+qP}nwr$(CZ96%!ZQHg_Y&`c}++Xl5dzRBxGu>TH5Ca7Sgv727 z0=V_FaoHAcJMbNA7zm>wTM`jQ+@8cUOZ7pEif1E{iKnFCxmHs8vzW>V0So~|=A!yb z_vKXcx_+y$@pM4}q}-J9zPCk0jiw?fAYZ`mr|3_ia;U$ESNzXI6Z+S>dWer;}OH{jjh^Nzo3_t5w4{ecX)Ml?9c%1~1U zq6~On_w~olg-?)I_~r`;u{0e18vgvi@UFkQE-?5mw>=nq0r=Lm{T6`2YBm5E9%Q3^ zuOc*varR|Pj(Q7ZExeRI_G>V%(Ha&OJ_BB7pD-A%t^>|DwSNPWBK9nf7e9^=&9Q%^@(rBec65@HyMB2F1D z^;9EseD$Nf(n`CQ?#GV{RwLTq2kY2Dw+Q5t5jpYIPPJ7@eifseWFKqK6~xp?kDXOd zOFWso-IKQ?pP8S~xpC6xZUVc9=o^LK9N>YAI zE?6gGz|I(?L&(e`Le?c9E5<7*N`?m?7Hw*kqpg_dmU*woiRH?r$c#7DXvzDQFu0!~ z3Y1Gz@_%V!%8eNePvTi;f~W*bHhCsllzbpl5~Irq#GRB^_^q9B8D872-C&qPs<7go zywo=hj%ya>^wq)2w{y$$7vBdoP&3@}t(!f9Jc#>%6Z zi_!O{D@1c@_aT|J^kj%GK88UTpNd?QX8*Scej&qw_0pa}veYOiaN^krKsC-`45E}) zkR~(BPCQ0#8K@r4XvU!uArDJ?OPB|0c^fS*7UmU7&<7c z_=UEczv^SmAVlT{s>4|22lvoN%e8t;UB!M4!Ye46g3t%H(DJgaN$i#wC&|4mkQ3p< zchJAseimt+XY~O20lsk7+@f)~SR{3|CRSpQS(MbZ>_`Lum^uS6j$>}5Ll&y@1E5Vjlf)|F3$1+UkX*W7RY^}u= zV>l&`=xM`CV)?P~73#S0A_kpBS55O+k>kV?G)}TGCm<|vC;w%gEjPop z;O_;I1NM?_~ zZLp$NE{oQXb(Dfa;%IM7p%sPNer+HM73-r-zVk`O^mr-+i>y11Rq8VrfE()C$*)&U z!}$tkCYxR*PC;T5NXHqfWjz)N+Zh;@Q8L*mdr8yOq7H?(=raOy(6!6d=t%ZRX*lmp#fRe4>pkAQ461kgpPwpo*AqM#Hb`QWon zv&JJcDOF0UVy%izKOR;BsKl|TM*^kP6J?tr4FUS1d^-Y*=22tws3#9P|163nxw!H| zB$dsxOdgz%KXS_P%223?F8u2iBQd#|LzTe9#EY3fT+L$&#jg@X7egVA=rOL)t3`3< z-y3AH`F@dJL@<<@saD-`I9pzZi9Z&4TH8;Rhf)MX<+^PXTW}qJCxBZ*H7S2li~~qE z3rr#k?ZQEwad}|6W7VVJX5X9NndD+vvx9Cl#3%-P>o?kgc6MP3)hFZGvV+1E5-rI)YF)YdCGi=@_!Rrw!q`Mt#)M)*r)7te{VNlqMFjK0&X2-Bl z8v(3j0&5@PqL~(ShzCd{o!yMsI?9tTwVTFf?Vb5nYkLTgzk|OYzYmv)%9ztI1R>?W z+kLdRqbq^+tj;yyoWET#ZHI$3gV%o0*cbq`#2{q7M+r^kFE-{bve0e8^$qwd??7;U|>-=HylxAMhWP~50a<@uI9HdyJ;3&+On&pUSy z4|-gLh@JturrXpcQ4*c&DsHyBa$g?dJ`_IMZ~Ip5tSb7mZl}1;cmu7`}>jdr*mjNbDVQ zwaQDWf;%WT*(9|R)=AOHZCCUyauc9Mr8>F^27dVN6?K#<&QH=`Ae1=DKZYgHiB!cb zSTruL+l4w$`G8>Mrd6P%-*oA37-nOo{gd-bwCJ zhTXj-W0Z9MH$g;#kXK_lTUP-Wty<+3v;c?A#*~`x!GTb0np z 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 L{F5R7*Z+S25KQQK diff --git a/examples/beaker_getting_started.py b/examples/beaker_getting_started.py index 35bca86..30ebd2c 100644 --- a/examples/beaker_getting_started.py +++ b/examples/beaker_getting_started.py @@ -60,7 +60,7 @@ # pat = dbutils.secrets.get(scope="your-scope", key="your-token") # warehouse http path example, replace with your own -http_path = "/sql/1.0/warehouses/7f5789ee19b3b19c" +http_path = "/sql/1.0/warehouses/475b94ddc7cd5211" # COMMAND ---------- @@ -68,9 +68,9 @@ # Use the builder pattern to add parameters for connecting to the warehouse bm.setName(name="simple_test") bm.setHostname(hostname=hostname) +bm.setWarehouseToken(token=pat) bm.setWarehouse(http_path=http_path) bm.setConcurrency(concurrency=1) -bm.setWarehouseToken(token=pat) # Define the query to execute and target Catalog query_str = """ @@ -84,7 +84,7 @@ # COMMAND ---------- # Run the benchmark! -beaker_metrics, history_metrics = bm.execute() +metrics_pdf = bm.execute() # COMMAND ---------- @@ -93,7 +93,7 @@ # COMMAND ---------- -df_simple_test = spark_fixture.metrics_to_df_view(beaker_metrics, history_metrics, "simple_test_vw") +df_simple_test = spark_fixture.metrics_to_df_view(metrics_pdf, "simple_test_vw") df_simple_test.display() # COMMAND ---------- @@ -146,8 +146,8 @@ # benchmark.preWarmTables(tables=["table_a", "table_b", "table_c"]) # Run the benchmark! -beaker_metrics, history_metrics = bm.execute() -print(history_metrics) +metrics_pdf = bm.execute() +display(metrics_pdf) # COMMAND ---------- @@ -203,8 +203,9 @@ # COMMAND ---------- -beaker_metrics, history_metrics = bm.execute() -history_df = spark_fixture.metrics_to_df_view(beaker_metrics, history_metrics, view_name="metrics_view") +metrics_pdf = bm.execute() +# Create a spark dataframe of the returned metrics pandas dataframe +metrics_df = spark_fixture.metrics_to_df_view(metrics_pdf, view_name="metrics_view") # COMMAND ---------- diff --git a/examples/beaker_standalone.py b/examples/beaker_standalone.py index ce07342..75501c9 100644 --- a/examples/beaker_standalone.py +++ b/examples/beaker_standalone.py @@ -9,41 +9,60 @@ sys.path.append("../src") -# from beaker import benchmark +from beaker import benchmark hostname = os.getenv("DATABRICKS_HOST") http_path = os.getenv("DATABRICKS_HTTP_PATH") # Don't put tokens in plaintext in code access_token = os.getenv("DATABRICKS_ACCESS_TOKEN") +catalog_name = os.getenv("CATALOG") +schema_name = os.getenv("SCHEMA") + +print(http_path) bm = benchmark.Benchmark() bm.setName(name="simple_test") bm.setHostname(hostname=hostname) -bm.setWarehouse(http_path=http_path) -bm.setConcurrency(concurrency=2) bm.setWarehouseToken(token=access_token) +bm.setWarehouse(http_path=http_path) +bm.setConcurrency(concurrency=1) print("---- Specify query in code ------") query_str = """ SELECT count(*) FROM delta.`/databricks-datasets/nyctaxi/tables/nyctaxi_yellow` - WHERE passenger_count > 2 + WHERE passenger_count > 2; """ bm.setQuery(query=query_str) bm.setCatalog(catalog="hive_metastore") - -beaker_metrics, history_metrics = bm.execute() -print(history_metrics) +bm.setSchema(schema="default") +metrics_pdf = bm.execute() +print(metrics_pdf) print("---- Specify a single query file ------") bm.query_file_format = "semicolon-delimited" bm.setQueryFile("queries/q1.sql") -beaker_metrics, history_metrics = bm.execute() -print(history_metrics) +metrics_pdf = bm.execute() +print(metrics_pdf) -print("---- Specify a query directory ------") +print("---- Specify a query directory semicolon format------") +bm.query_file_format = "semicolon-delimited" bm.setQueryFileDir("queries") -beaker_metrics, history_metrics = bm.execute() -print(history_metrics) +metrics_pdf = bm.execute() +print(metrics_pdf) + + +print("---- Specify a query directory original format------") +bm.query_file_format = "original" +bm.setQueryFileDir("queries_orig") +metrics_pdf = bm.execute() +print(metrics_pdf) + + +print("---- Test prewarm table ------") +bm.setCatalog(catalog_name) +bm.setSchema(schema_name) +tables = ["customer", "lineitem", "nation", "orders", "part", "partsupp", "region", "supplier"] +bm.preWarmTables(tables=tables) \ No newline at end of file diff --git a/examples/getting_started.ipynb b/examples/getting_started.ipynb index c319c3e..62dc0a9 100644 --- a/examples/getting_started.ipynb +++ b/examples/getting_started.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -42,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -62,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -84,7 +84,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -104,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -124,7 +124,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -144,7 +144,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -165,7 +165,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -189,7 +189,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -213,7 +213,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -239,7 +239,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": { @@ -259,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -276,7 +276,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -293,7 +293,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -310,7 +310,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -327,7 +327,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -344,7 +344,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -356,29 +356,21 @@ }, "outputs": [], "source": [ - "beaker_metrics, history_metrics = bm.execute()" + "metrics_pdf = bm.execute()" ] }, { "cell_type": "code", - "execution_count": 0, - "metadata": { - "application/vnd.databricks.v1+cell": { - "cellMetadata": {}, - "inputWidgets": {}, - "nuid": "8356cc87-099f-4d28-902b-4f4b34a1e80e", - "showTitle": false, - "title": "" - } - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "history_metrics" + "metrics_pdf" ] }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -395,7 +387,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -419,7 +411,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, @@ -442,7 +434,7 @@ }, { "cell_type": "code", - "execution_count": 0, + "execution_count": null, "metadata": { "application/vnd.databricks.v1+cell": { "cellMetadata": {}, diff --git a/examples/queries/q1.sql b/examples/queries/q1.sql index e756f3f..3584537 100644 --- a/examples/queries/q1.sql +++ b/examples/queries/q1.sql @@ -1,2 +1,3 @@ -- {"query_id":"q1"} select 'q1', now(); + diff --git a/examples/queries/test.py b/examples/queries/test.py new file mode 100644 index 0000000..cb3b2e0 --- /dev/null +++ b/examples/queries/test.py @@ -0,0 +1,23 @@ +import re + +def parse_sql_file(file_path): + """ + Parses a SQL file and returns a list of tuples with the query_id and the query text. + + Parameters: + file_path (str): The path to the SQL file. + + Returns: + list: A list of tuples, where each tuple contains a query_id and a query text. + """ + with open(file_path, 'r') as file: + content = file.read() + + pattern = r'-- {"query_id":"(.*?)"}\n(.*?);' + matches = re.findall(pattern, content, re.DOTALL) + + return matches + + +queries = parse_sql_file('q1.sql') +print(queries) \ No newline at end of file diff --git a/examples/queries_orig/q1.sql b/examples/queries_orig/q1.sql new file mode 100644 index 0000000..5d501f4 --- /dev/null +++ b/examples/queries_orig/q1.sql @@ -0,0 +1,2 @@ +Q1 +select 'q1', now(); diff --git a/examples/queries_orig/q2.sql b/examples/queries_orig/q2.sql new file mode 100644 index 0000000..44e8a1e --- /dev/null +++ b/examples/queries_orig/q2.sql @@ -0,0 +1,2 @@ +Q2 +select 'q2', now(); diff --git a/examples/requirements.txt b/examples/requirements.txt index 993065b..5a3d0e5 100644 --- a/examples/requirements.txt +++ b/examples/requirements.txt @@ -1,4 +1,5 @@ databricks-sql-connector databricks-sdk pyspark -python-dotenv \ No newline at end of file +python-dotenv +pandas \ No newline at end of file diff --git a/examples/standalone_dist_test.py b/examples/standalone_dist_test.py index 433cfcc..5e6cdcd 100644 --- a/examples/standalone_dist_test.py +++ b/examples/standalone_dist_test.py @@ -14,21 +14,23 @@ logger = logging.getLogger() logger.setLevel(logging.INFO) -bm = benchmark.Benchmark() hostname = os.getenv("DATABRICKS_HOST") http_path = os.getenv("DATABRICKS_HTTP_PATH") # Don't put tokens in plaintext in code access_token = os.getenv("DATABRICKS_ACCESS_TOKEN") +bm = benchmark.Benchmark() +bm.setName(name="standalone_dist_test") bm.setHostname(hostname=hostname) +bm.setWarehouseToken(token=access_token) bm.setWarehouse(http_path=http_path) bm.setConcurrency(concurrency=5) -bm.setWarehouseToken(token=access_token) bm.setQuery("select now(), 'foo';") -bm.setQueryRepeatCount(100) +bm.setCatalog(catalog="hive_metastore") +bm.setQueryRepeatCount(10) -beaker_metrics, history_metrics = bm.execute() -#print(history_metrics) +metrics_pdf = bm.execute() +print(metrics_pdf) diff --git a/src/__init__.py b/src/__init__.py index 0cdff65..262e0b7 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +1 @@ -VERSION = '0.0.6' +VERSION = '0.0.7' diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index 227db43..538b4e6 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -1,4 +1,3 @@ -from databricks.sdk.runtime import * import os import time import re @@ -8,6 +7,8 @@ import threading import datetime import json +import pandas as pd +from pandas import json_normalize from beaker.sqlwarehouseutils import SQLWarehouseUtils from beaker.spark_fixture import get_spark_session, metrics_to_df_view @@ -179,7 +180,6 @@ def setQueryFileDir(self, query_file_dir): def _execute_single_query(self, query, id=None): query = query.strip() - logging.info(query) sql_warehouse = self._get_thread_local_connection() @@ -306,7 +306,7 @@ def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): Returns: -------- - history_df : dataframe of the query history + end_res : query history json """ user_id = self._get_user_id() logging.info("Extracting Query History") @@ -337,7 +337,7 @@ def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): results = response.json()['res'] if all([item['is_final'] for item in results]): break - time.sleep(5) + time.sleep(10) response = requests.get(uri, data=v, headers=headers_auth) if (response.status_code == 200) and ("res" in response.json()): @@ -346,6 +346,16 @@ def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): return end_res else: raise Exception("Failed to retrieve successful query history") + + def clean_query_metrics(self, raw_metrics_pdf): + logging.info("Clean Query Metrics") + metrics_pdf = json_normalize(raw_metrics_pdf['metrics'].apply(str).apply(eval)) + metrics_pdf["query_id"] = raw_metrics_pdf["query_id"] + metrics_pdf["query"] = raw_metrics_pdf["query"] + metrics_pdf["status"] = raw_metrics_pdf["status"] + metrics_pdf["warehouse_name"] = self.warehouse_name + metrics_pdf["id"] = raw_metrics_pdf["id"] + return metrics_pdf def _get_warehouse_info(self): """Gets the warehouse info.""" @@ -355,6 +365,7 @@ def _get_warehouse_info(self): ) warehouse_name = response.json()["name"] return warehouse_name + def execute(self): """Executes the benchmark test.""" @@ -382,10 +393,13 @@ def execute(self): end_ts_ms = int(time.time() * 1000) - logging.info("Getting Query Metrics") history_metrics = self.get_query_history(self.warehouse_id, start_ts_ms, end_ts_ms) - return metrics, history_metrics + history_pdf = pd.DataFrame(history_metrics) + beaker_pdf = pd.DataFrame(metrics) + raw_metrics_pdf = history_pdf.merge(beaker_pdf[['query', 'id']].drop_duplicates(), left_on='query_text', right_on='query', how='inner') + metrics_pdf = self.clean_query_metrics(raw_metrics_pdf) + return metrics_pdf def preWarmTables(self, tables): """Delta caches the table before running a benchmark test.""" @@ -400,7 +414,7 @@ def preWarmTables(self, tables): self._set_default_schema() for table in tables: logging.info(f"Pre-warming table: {table}") - query = f"SELECT * FROM {table}" + query = f"CACHE SELECT * FROM {table}" self._execute_single_query(query) def __str__(self): diff --git a/src/beaker/spark_fixture.py b/src/beaker/spark_fixture.py index bc30cd3..3a3c370 100644 --- a/src/beaker/spark_fixture.py +++ b/src/beaker/spark_fixture.py @@ -17,22 +17,12 @@ def get_spark_session(): return SparkSession.builder.appName("beaker").getOrCreate() -def metrics_to_df_view(beaker_metrics, history_metrics, view_name): - """Convert a list of dicts to a results dataframe. - Create a view and return the dataframe. +def metrics_to_df_view(metrics_pdf, view_name): + """Convert a pandas dataframe to a spark dataframe. + Create a view and return the spark dataframe. """ spark = get_spark_session() - metrics_df = spark.createDataFrame(beaker_metrics) - history_df = spark.createDataFrame(history_metrics) - history_metrics_df = ( - history_df.alias("v1") - .join(metrics_df.select("id", "query", "warehouse_name").distinct().alias("v2"), col("v1.query_text") == col("v2.query"), "inner") - .select("v2.warehouse_name", "v1.warehouse_id", "v2.id", "v1.query_text", - (col("v1.duration") / 1000).alias("duration_sec"), - (col("metrics.execution_time_ms") / 1000).alias("query_execution_time_sec"), - (col("metrics.planning_time_ms") / 1000).alias("planning_time_sec"), - (col("metrics.photon_total_time_ms") / 1000).alias("photon_total_time_sec")) - ) - history_metrics_df.createOrReplaceTempView(view_name) + metrics_df = spark.createDataFrame(metrics_pdf) + metrics_df.createOrReplaceTempView(view_name) print(f"Query metrics at: {view_name}") - return history_metrics_df + return metrics_df From 6184a6fd7f815561a28d12acced6212d7aae97c0 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Mon, 26 Feb 2024 14:33:26 -0800 Subject: [PATCH 16/20] Fix orig file format parsing --- .gitignore | 1 - examples/queries/test.py | 23 ------------ src/beaker/benchmark.py | 67 ++++++++++++++++++++++------------ src/unittest/test_Benchmark.py | 35 ++++++++++++++++++ 4 files changed, 79 insertions(+), 47 deletions(-) delete mode 100644 examples/queries/test.py create mode 100644 src/unittest/test_Benchmark.py diff --git a/.gitignore b/.gitignore index 2051f29..b580ba1 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,3 @@ myvenv/ */.env .env -./examples/queries/test.py diff --git a/examples/queries/test.py b/examples/queries/test.py deleted file mode 100644 index cb3b2e0..0000000 --- a/examples/queries/test.py +++ /dev/null @@ -1,23 +0,0 @@ -import re - -def parse_sql_file(file_path): - """ - Parses a SQL file and returns a list of tuples with the query_id and the query text. - - Parameters: - file_path (str): The path to the SQL file. - - Returns: - list: A list of tuples, where each tuple contains a query_id and a query text. - """ - with open(file_path, 'r') as file: - content = file.read() - - pattern = r'-- {"query_id":"(.*?)"}\n(.*?);' - matches = re.findall(pattern, content, re.DOTALL) - - return matches - - -queries = parse_sql_file('q1.sql') -print(queries) \ No newline at end of file diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index 538b4e6..c6eeb21 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -225,31 +225,52 @@ def _get_queries_from_file_format_orig(self, f): queries = [e for e in zip(file_queries, file_headers)] return queries - def _get_queries_from_file_format_semi(self, f, filter_comment_lines=False): - fc = None - queries = [] - with open(f, "r") as of: - fc = of.read() - for idx, q in enumerate(fc.split(";")): - q = q.strip() - if not q: - continue - # Keep non-empty lines. - # Also keep or remove comments depending on the flag. - rq = [ - l - for l in q.split("\n") - if l.strip() and not (filter_comment_lines and l.startswith("--")) - ] - if rq: - queries.append( - ( - "\n".join(rq), - f"query{idx}", - ) - ) + # def _get_queries_from_file_format_semi(self, f, filter_comment_lines=False): + # fc = None + # queries = [] + # with open(f, "r") as of: + # fc = of.read() + # for idx, q in enumerate(fc.split(";")): + # q = q.strip() + # if not q: + # continue + # # Keep non-empty lines. + # # Also keep or remove comments depending on the flag. + # rq = [ + # l + # for l in q.split("\n") + # if l.strip() and not (filter_comment_lines and l.startswith("--")) + # ] + # if rq: + # queries.append( + # ( + # "\n".join(rq), + # f"query{idx}", + # ) + # ) + # return queries + + def _get_queries_from_file_format_semi(self, file_path): + """ + Parses a SQL file and returns a list of tuples with the query_id and the query text. + + Parameters: + file_path (str): The path to the SQL file. + + Returns: + list: A list of tuples, where each tuple contains a query_id and a query text. + """ + with open(file_path, 'r') as file: + content = file.read() + + pattern = r'-- {"query_id":"(.*?)"}\n(.*?);' + matches = re.findall(pattern, content, re.DOTALL) + + # Swap the order of elements in each tuple + queries = [(query, query_id) for query_id, query in matches] return queries + def _get_queries_from_file(self, query_file): if self.query_file_format == self.QUERY_FILE_FORMAT_SEMICOLON_DELIM: return self._get_queries_from_file_format_semi(query_file) diff --git a/src/unittest/test_Benchmark.py b/src/unittest/test_Benchmark.py new file mode 100644 index 0000000..769938b --- /dev/null +++ b/src/unittest/test_Benchmark.py @@ -0,0 +1,35 @@ +import unittest +import sys +sys.path.append("../") +from beaker import benchmark + +class TestBenchmark(unittest.TestCase): + def setUp(self): + self.bm = benchmark.Benchmark() + + def test_get_queries_from_file_format_semi(self): + # Define a test case + test_file_path = '../../examples/queries/q1.sql' + # replace with the expected output + expected_output = [("select 'q1', now()", 'q1')] + + # Call the function with the test case + actual_output = self.bm._get_queries_from_file_format_semi(test_file_path) + + # Assert that the actual output matches the expected output + self.assertEqual(actual_output, expected_output) + + def test_get_queries_from_file_format_orig(self): + # Define a test case + test_file_path = '../../examples/queries_orig/q1.sql' + # replace with the expected output + expected_output = [("select 'q1', now();", 'Q1')] + + # Call the function with the test case + actual_output = self.bm._get_queries_from_file_format_orig(test_file_path) + + # Assert that the actual output matches the expected output + self.assertEqual(actual_output, expected_output) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From 181887fc46f08525a5536fa5f3a6b69c6d4287d0 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Mon, 26 Feb 2024 18:33:10 -0800 Subject: [PATCH 17/20] Update benchmark - Update benchmark with new connection setting - Add unittest - Add new examples - Update v0.0.6 --- dist/beaker-0.0.6-py3-none-any.whl | Bin 15454 -> 15801 bytes dist/beaker-0.0.6.tar.gz | Bin 13760 -> 15478 bytes dist/beaker-0.0.7-py3-none-any.whl | Bin 15454 -> 0 bytes dist/beaker-0.0.7.tar.gz | Bin 13761 -> 0 bytes examples/beaker_standalone.py | 9 +- examples/beaker_standalone_tpch.py | 40 +++ examples/getting_started.ipynb | 14 +- examples/queries/q10.sql | 2 + examples/tpch/1.sql | 409 +++++++++++++++++++++++++++++ examples/tpch/2.sql | 276 +++++++++++++++++++ src/__init__.py | 2 +- src/beaker/benchmark.py | 23 +- src/beaker/sqlwarehouseutils.py | 13 + src/unittest/test | 112 ++++++++ src/unittest/test_Benchmark.py | 29 +- 15 files changed, 902 insertions(+), 27 deletions(-) delete mode 100644 dist/beaker-0.0.7-py3-none-any.whl delete mode 100644 dist/beaker-0.0.7.tar.gz create mode 100644 examples/beaker_standalone_tpch.py create mode 100644 examples/queries/q10.sql create mode 100644 examples/tpch/1.sql create mode 100644 examples/tpch/2.sql create mode 100644 src/unittest/test diff --git a/dist/beaker-0.0.6-py3-none-any.whl b/dist/beaker-0.0.6-py3-none-any.whl index cfc6bef6ec97c469573f6f2c4abe159e15e0ad9c..e2a577d075774509e214d28e9f8e7df6a53ba645 100644 GIT binary patch delta 7690 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 E07iG$CIA2c delta 7352 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�DdR@7RZwXO3 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 literal 13760 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 diff --git a/dist/beaker-0.0.7.tar.gz b/dist/beaker-0.0.7.tar.gz deleted file mode 100644 index 47b2b4b595e18aba38972819f94ba7e926f17563..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13761 zcmbVSLvt<+vy6=s+qP}nwr$(CZ96%!ZQHg_Y&`c}++Xl5dzRBxGu>TH5Ca7Sgv727 z0=V_FaoHAcJMbNA7zm>wTM`jQ+@8cUOZ7pEif1E{iKnFCxmHs8vzW>V0So~|=A!yb z_vKXcx_+y$@pM4}q}-J9zPCk0jiw?fAYZ`mr|3_ia;U$ESNzXI6Z+S>dWer;}OH{jjh^Nzo3_t5w4{ecX)Ml?9c%1~1U zq6~On_w~olg-?)I_~r`;u{0e18vgvi@UFkQE-?5mw>=nq0r=Lm{T6`2YBm5E9%Q3^ zuOc*varR|Pj(Q7ZExeRI_G>V%(Ha&OJ_BB7pD-A%t^>|DwSNPWBK9nf7e9^=&9Q%^@(rBec65@HyMB2F1D z^;9EseD$Nf(n`CQ?#GV{RwLTq2kY2Dw+Q5t5jpYIPPJ7@eifseWFKqK6~xp?kDXOd zOFWso-IKQ?pP8S~xpC6xZUVc9=o^LK9N>YAI zE?6gGz|I(?L&(e`Le?c9E5<7*N`?m?7Hw*kqpg_dmU*woiRH?r$c#7DXvzDQFu0!~ z3Y1Gz@_%V!%8eNePvTi;f~W*bHhCsllzbpl5~Irq#GRB^_^q9B8D872-C&qPs<7go zywo=hj%ya>^wq)2w{y$$7vBdoP&3@}t(!f9Jc#>%6Z zi_!O{D@1c@_aT|J^kj%GK88UTpNd?QX8*Scej&qw_0pa}veYOiaN^krKsC-`45E}) zkR~(BPCQ0#8K@r4XvU!uArDJ?OPB|0c^fS*7UmU7&<7c z_=UEczv^SmAVlT{s>4|22lvoN%e8t;UB!M4!Ye46g3t%H(DJgaN$i#wC&|4mkQ3p< zchJAseimt+XY~O20lsk7+@f)~SR{3|CRSpQS(MbZ>_`Lum^uS6j$>}5Ll&y@1E5Vjlf)|F3$1+UkX*W7RY^}u= zV>l&`=xM`CV)?P~73#S0A_kpBS55O+k>kV?G)}TGCm<|vC;w%gEjPop z;O_;I1NM?_~ zZLp$NE{oQXb(Dfa;%IM7p%sPNer+HM73-r-zVk`O^mr-+i>y11Rq8VrfE()C$*)&U z!}$tkCYxR*PC;T5NXHqfWjz)N+Zh;@Q8L*mdr8yOq7H?(=raOy(6!6d=t%ZRX*lmp#fRe4>pkAQ461kgpPwpo*AqM#Hb`QWon zv&JJcDOF0UVy%izKOR;BsKl|TM*^kP6J?tr4FUS1d^-Y*=22tws3#9P|163nxw!H| zB$dsxOdgz%KXS_P%223?F8u2iBQd#|LzTe9#EY3fT+L$&#jg@X7egVA=rOL)t3`3< z-y3AH`F@dJL@<<@saD-`I9pzZi9Z&4TH8;Rhf)MX<+^PXTW}qJCxBZ*H7S2li~~qE z3rr#k?ZQEwad}|6W7VVJX5X9NndD+vvx9Cl#3%-P>o?kgc6MP3)hFZGvV+1E5-rI)YF)YdCGi=@_!Rrw!q`Mt#)M)*r)7te{VNlqMFjK0&X2-Bl z8v(3j0&5@PqL~(ShzCd{o!yMsI?9tTwVTFf?Vb5nYkLTgzk|OYzYmv)%9ztI1R>?W z+kLdRqbq^+tj;yyoWET#ZHI$3gV%o0*cbq`#2{q7M+r^kFE-{bve0e8^$qwd??7;U|>-=HylxAMhWP~50a<@uI9HdyJ;3&+On&pUSy z4|-gLh@JturrXpcQ4*c&DsHyBa$g?dJ`_IMZ~Ip5tSb7mZl}1;cmu7`}>jdr*mjNbDVQ zwaQDWf;%WT*(9|R)=AOHZCCUyauc9Mr8>F^27dVN6?K#<&QH=`Ae1=DKZYgHiB!cb zSTruL+l4w$`G8>Mrd6P%-*oA37-nOo{gd-bwCJ zhTXj-W0Z9MH$g;#kXK_lTUP-Wty<+3v;c?A#*~`x!GTb0np z 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 date('1995-03-15') +group by + l_orderkey, + o_orderdate, + o_shippriority +order by + revenue desc, + o_orderdate; + +Q04 +select + o_orderpriority, + count(*) as order_count +from + orders +where + o_orderdate >= date('1993-07-01') + and o_orderdate < add_months('1993-07-01', 3) + and exists ( + select + * + from + lineitem + where + l_orderkey = o_orderkey + and l_commitdate < l_receiptdate + ) +group by + o_orderpriority +order by + o_orderpriority; + +Q05 +select + n_name, + sum(l_extendedprice * (1 - l_discount)) as revenue +from + customer, + orders, + lineitem, + supplier, + nation, + region +where + c_custkey = o_custkey + and l_orderkey = o_orderkey + and l_suppkey = s_suppkey + and c_nationkey = s_nationkey + and s_nationkey = n_nationkey + and n_regionkey = r_regionkey + and r_name = 'ASIA' + and o_orderdate >= date('1993-01-01') + and o_orderdate < date('1994-01-01') +group by + n_name +order by + revenue desc + +Q06 +select + sum(l_extendedprice * l_discount) as revenue +from + lineitem +where + l_shipdate >= date('1993-01-01') + and l_shipdate < date('1994-01-01') + and l_discount between.06 - 0.01 + and.06 + 0.01 + and l_quantity < 24; + +Q07 +select + supp_nation, + cust_nation, + l_year, + sum(volume) as revenue +from + ( + select + n1.n_name as supp_nation, + n2.n_name as cust_nation, + year(l_shipdate) as l_year, + l_extendedprice * (1 - l_discount) as volume + from + supplier, + lineitem, + orders, + customer, + nation n1, + nation n2 + where + s_suppkey = l_suppkey + and o_orderkey = l_orderkey + and c_custkey = o_custkey + and s_nationkey = n1.n_nationkey + and c_nationkey = n2.n_nationkey + and ( + ( + n1.n_name = 'FRANCE' + and n2.n_name = 'GERMANY' + ) + or ( + n1.n_name = 'GERMANY' + and n2.n_name = 'FRANCE' + ) + ) + and l_shipdate between date('1995-01-01') + and date('1996-12-31') + ) as shipping +group by + supp_nation, + cust_nation, + l_year +order by + supp_nation, + cust_nation, + l_year; + +Q08 +select + o_year, + sum( + case + when nation = 'BRAZIL' then volume + else 0 + end + ) / sum(volume) as mkt_share +from + ( + select + year(o_orderdate) as o_year, + l_extendedprice * (1 - l_discount) as volume, + n2.n_name as nation + from + part, + supplier, + lineitem, + orders, + customer, + nation n1, + nation n2, + region + where + p_partkey = l_partkey + and s_suppkey = l_suppkey + and l_orderkey = o_orderkey + and o_custkey = c_custkey + and c_nationkey = n1.n_nationkey + and n1.n_regionkey = r_regionkey + and r_name = 'AMERICA' + and s_nationkey = n2.n_nationkey + and o_orderdate between date('1995-01-01') + and date('1996-12-31') + and p_type = 'ECONOMY ANODIZED STEEL' + ) as all_nations +group by + o_year +order by + o_year; + +Q09 +select + nation, + o_year, + sum(amount) as sum_profit +from + ( + select + n_name as nation, + year(o_orderdate) as o_year, + l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount + from + part, + supplier, + lineitem, + partsupp, + orders, + nation + where + s_suppkey = l_suppkey + and ps_suppkey = l_suppkey + and ps_partkey = l_partkey + and p_partkey = l_partkey + and o_orderkey = l_orderkey + and s_nationkey = n_nationkey + and p_name like '%green%' + ) as profit +group by + nation, + o_year +order by + nation, + o_year desc; + +Q10 +select + c_custkey, + c_name, + sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, + n_name, + c_address, + c_phone, + c_comment +from + customer, + orders, + lineitem, + nation +where + c_custkey = o_custkey + and l_orderkey = o_orderkey + and o_orderdate >= date('1993-10-01') + and o_orderdate < ADD_MONTHS('1993-10-01', 3) + and l_returnflag = 'R' + and c_nationkey = n_nationkey +group by + c_custkey, + c_name, + c_acctbal, + c_phone, + n_name, + c_address, + c_comment +order by + revenue desc; + +Q11 +select + ps_partkey, + sum(ps_supplycost * ps_availqty) as value +from + partsupp, + supplier, + nation +where + ps_suppkey = s_suppkey + and s_nationkey = n_nationkey + and n_name = 'GERMANY' +group by + ps_partkey +having + sum(ps_supplycost * ps_availqty) > ( + select + sum(ps_supplycost * ps_availqty) * 0.0000010000 + from + partsupp, + supplier, + nation + where + ps_suppkey = s_suppkey + and s_nationkey = n_nationkey + and n_name = 'GERMANY' + ) +order by + value desc; + +Q12 +select + l_shipmode, + sum( + case + when o_orderpriority = '1-URGENT' + or o_orderpriority = '2-HIGH' then 1 + else 0 + end + ) as high_line_count, + sum( + case + when o_orderpriority <> '1-URGENT' + and o_orderpriority <> '2-HIGH' then 1 + else 0 + end + ) as low_line_count +from + orders, + lineitem +where + o_orderkey = l_orderkey + and l_shipmode in ('MAIL', 'SHIP') + and l_commitdate < l_receiptdate + and l_shipdate < l_commitdate + and l_receiptdate >= date('1995-01-01') + and l_receiptdate < date('1996-01-01') +group by + l_shipmode +order by + l_shipmode; + +Q13 +select + c_count, + count(*) as custdist +from + ( + select + c_custkey, + count(o_orderkey) + from + customer + left outer join orders on c_custkey = o_custkey + and o_comment not like '%special%requests%' + group by + c_custkey + ) as orders (c_custkey, c_count) +group by + c_count +order by + custdist desc, + c_count desc; + +Q14 +select + 100.00 * sum( + case + when p_type like 'PROMO%' then l_extendedprice * (1 - l_discount) + else 0 + end + ) / sum(l_extendedprice * (1 - l_discount)) as promo_revenue +from + lineitem, + part +where + l_partkey = p_partkey + and l_shipdate >= date('1995-09-01') + and l_shipdate < add_months('1995-09-01', 1); \ No newline at end of file diff --git a/examples/tpch/2.sql b/examples/tpch/2.sql new file mode 100644 index 0000000..fb4faa7 --- /dev/null +++ b/examples/tpch/2.sql @@ -0,0 +1,276 @@ +Q15 +with revenue0 as ( + select + l_suppkey as supplier_no, + sum(l_extendedprice * (1 - l_discount)) as total_revenue + from + lineitem + where + l_shipdate >= date '1996-01-01' + and l_shipdate < date '1996-01-01' + interval '3' month + group by + l_suppkey + ) +select + s_suppkey, + s_name, + s_address, + s_phone, + total_revenue +from + supplier, + revenue0 +where + s_suppkey = supplier_no + and total_revenue = ( + select + max(total_revenue) + from + revenue0 + ) +order by + s_suppkey; + +Q16 +select + p_brand, + p_type, + p_size, + count(distinct ps_suppkey) as supplier_cnt +from + partsupp, + part +where + p_partkey = ps_partkey + and p_brand <> 'Brand#45' + and p_type not like 'MEDIUM POLISHED%' + and p_size in (49, 14, 23, 45, 19, 3, 36, 9) + and ps_suppkey not in ( + select + s_suppkey + from + supplier + where + s_comment like '%Customer%Complaints%' + ) +group by + p_brand, + p_type, + p_size +order by + supplier_cnt desc, + p_brand, + p_type, + p_size; + +Q17 +select + sum(l_extendedprice) / 7.0 as avg_yearly +from + lineitem, + part +where + p_partkey = l_partkey + and p_brand = 'Brand#23' + and p_container = 'MED BOX' + and l_quantity < ( + select + 0.2 * avg(l_quantity) + from + lineitem + where + l_partkey = p_partkey + ); + +Q18 +select + c_name, + c_custkey, + o_orderkey, + o_orderdate, + o_totalprice, + sum(l_quantity) +from + customer, + orders, + lineitem +where + o_orderkey in ( + select + l_orderkey + from + lineitem + group by + l_orderkey + having + sum(l_quantity) > 300 + ) + and c_custkey = o_custkey + and o_orderkey = l_orderkey +group by + c_name, + c_custkey, + o_orderkey, + o_orderdate, + o_totalprice +order by + o_totalprice desc, + o_orderdate; + +Q19 +select + sum(l_extendedprice * (1 - l_discount)) as revenue +from + lineitem, + part +where + ( + p_partkey = l_partkey + and p_brand = 'Brand#12' + and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG') + and l_quantity >= 1 + and l_quantity <= 1 + 10 + and p_size between 1 + and 5 + and l_shipmode in ('AIR', 'AIR REG') + and l_shipinstruct = 'DELIVER IN PERSON' + ) + or ( + p_partkey = l_partkey + and p_brand = 'Brand#23' + and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK') + and l_quantity >= 10 + and l_quantity <= 10 + 10 + and p_size between 1 + and 10 + and l_shipmode in ('AIR', 'AIR REG') + and l_shipinstruct = 'DELIVER IN PERSON' + ) + or ( + p_partkey = l_partkey + and p_brand = 'Brand#34' + and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG') + and l_quantity >= 20 + and l_quantity <= 20 + 10 + and p_size between 1 + and 15 + and l_shipmode in ('AIR', 'AIR REG') + and l_shipinstruct = 'DELIVER IN PERSON' + ); + +Q20 +select + s_name, + s_address +from + supplier, + nation +where + s_suppkey in ( + select + ps_suppkey + from + partsupp + where + ps_partkey in ( + select + p_partkey + from + part + where + p_name like 'forest%' + ) + and ps_availqty > ( + select + 0.5 * sum(l_quantity) + from + lineitem + where + l_partkey = ps_partkey + and l_suppkey = ps_suppkey + and l_shipdate >= date('1993-01-01') + and l_shipdate < date('1994-01-01') + ) + ) + and s_nationkey = n_nationkey + and n_name = 'CANADA' +order by + s_name; + +Q21 +select + s_name, + count(*) as numwait +from + supplier, + lineitem l1, + orders, + nation +where + s_suppkey = l1.l_suppkey + and o_orderkey = l1.l_orderkey + and o_orderstatus = 'F' + and l1.l_receiptdate > l1.l_commitdate + and exists ( + select + * + from + lineitem l2 + where + l2.l_orderkey = l1.l_orderkey + and l2.l_suppkey <> l1.l_suppkey + ) + and not exists ( + select + * + from + lineitem l3 + where + l3.l_orderkey = l1.l_orderkey + and l3.l_suppkey <> l1.l_suppkey + and l3.l_receiptdate > l3.l_commitdate + ) + and s_nationkey = n_nationkey + and n_name = 'SAUDI ARABIA' +group by + s_name +order by + numwait desc, + s_name; + +Q22 +select + cntrycode, + count(*) as numcust, + sum(c_acctbal) as totacctbal +from + ( + select + SUBSTR(c_phone, 1, 2) as cntrycode, + c_acctbal + from + customer + where + SUBSTR(c_phone, 1, 2) in ('13', '31', '23', '29', '30', '18', '17') + and c_acctbal > ( + select + avg(c_acctbal) + from + customer + where + c_acctbal > 0.00 + and SUBSTR(c_phone, 1, 2) in ('13', '31', '23', '29', '30', '18', '17') + ) + and not exists ( + select + * + from + orders + where + o_custkey = c_custkey + ) + ) as custsale +group by + cntrycode +order by + cntrycode; \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index 262e0b7..0cdff65 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +1 @@ -VERSION = '0.0.7' +VERSION = '0.0.6' diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index c6eeb21..2e92a1a 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -56,9 +56,10 @@ def __init__( if new_warehouse_config is not None: self.setWarehouseConfig(new_warehouse_config) self.query_file_format = query_file_format + self.sql_warehouse = None def _create_dbc(self): - sql_warehouse = SQLWarehouseUtils( + self.sql_warehouse = SQLWarehouseUtils( self.hostname, self.http_path, self.token, @@ -67,9 +68,9 @@ def _create_dbc(self): self.results_cache_enabled, ) # establish connection on the existing warehouse - sql_warehouse.setConnection() + self.sql_warehouse.setConnection() - return sql_warehouse + return self.sql_warehouse def _get_thread_local_connection(self): if not hasattr(thread_local, "connection"): @@ -181,11 +182,9 @@ def setQueryFileDir(self, query_file_dir): def _execute_single_query(self, query, id=None): query = query.strip() - sql_warehouse = self._get_thread_local_connection() - ## Instead of using perf counter, we want to get the query duration from /api/2.0/sql/history/queries API start_time = time.perf_counter() - result = sql_warehouse.execute_query(query) + result = self.sql_warehouse.execute_query(query) end_time = time.perf_counter() elapsed_time = f"{end_time - start_time:0.3f}" @@ -392,9 +391,13 @@ def execute(self): """Executes the benchmark test.""" logging.info("Executing benchmark test") logging.info("Set default catalog and schema") + self.sql_warehouse = self._get_thread_local_connection() + + print(self.sql_warehouse) + self._set_default_catalog() self._set_default_schema() - + print(f"Monitor warehouse `{self.warehouse_name}` at: ", f"https://{self.hostname}/sql/warehouses/{self.warehouse_id}/monitoring") start_ts_ms = int(time.time() * 1000) @@ -420,6 +423,7 @@ def execute(self): beaker_pdf = pd.DataFrame(metrics) raw_metrics_pdf = history_pdf.merge(beaker_pdf[['query', 'id']].drop_duplicates(), left_on='query_text', right_on='query', how='inner') metrics_pdf = self.clean_query_metrics(raw_metrics_pdf) + return metrics_pdf def preWarmTables(self, tables): @@ -431,6 +435,9 @@ def preWarmTables(self, tables): assert ( self.catalog is not None ), "No catalog provided. You can add a catalog by calling `.setCatalog()`." + + self.sql_warehouse = self._get_thread_local_connection() + self._set_default_catalog() self._set_default_schema() for table in tables: @@ -438,6 +445,7 @@ def preWarmTables(self, tables): query = f"CACHE SELECT * FROM {table}" self._execute_single_query(query) + def __str__(self): object_str = f""" Benchmark Test: @@ -451,5 +459,6 @@ def __str__(self): query_repeat_count={self.query_repeat_count} hostname={self.hostname} warehouse_http_path={self.http_path} + sql_warehouse={self.sql_warehouse} """ return object_str diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index 6b81658..e1136c4 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -233,3 +233,16 @@ def launch_warehouse(self, config): raise Exception(f"did not get back warehouse_id ({response.json()})") return warehouse_id + + + def __str__(self): + object_str = f""" + SQL Warehouse Utils + ------------------------ + hostname={self.hostname} + catalog={self.catalog} + schema={self.schema} + http_path={self.http_path} + enable_results_caching={self.enable_results_caching} + """ + return object_str \ No newline at end of file diff --git a/src/unittest/test b/src/unittest/test new file mode 100644 index 0000000..e387cc7 --- /dev/null +++ b/src/unittest/test @@ -0,0 +1,112 @@ +/sql/1.0/warehouses/475b94ddc7cd5211 +INFO:root:self.hostname = None +INFO:root:self.hostname = e2-demo-field-eng.cloud.databricks.com +---- Specify query in code ------ +INFO:root:Executing benchmark test +INFO:root:Set default catalog and schema +INFO:databricks.sql.client:Successfully opened session 01eed4fb-6f93-1bb8-9ae2-5e4ed0d4c925 +INFO:root:Created new connection: + + SQL Warehouse Utils + ------------------------ + hostname=e2-demo-field-eng.cloud.databricks.com + catalog=hive_metastore + schema=default + http_path=/sql/1.0/warehouses/475b94ddc7cd5211 + enable_results_caching=False + +Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring +INFO:root:Executing single query. +INFO:root:Getting Query Metrics +INFO:root:Extracting Query History +INFO:root:Await completion of all queries... +INFO:root:Query history extracted successfully +INFO:root:Clean Query Metrics + total_time_ms read_bytes rows_produced_count ... status warehouse_name id +0 481 557980383 1 ... FINISHED Serverless Shared Endpoint query + +[1 rows x 29 columns] +---- Specify a single query file ------ +INFO:root:Executing benchmark test +INFO:root:Set default catalog and schema + + SQL Warehouse Utils + ------------------------ + hostname=e2-demo-field-eng.cloud.databricks.com + catalog=hive_metastore + schema=default + http_path=/sql/1.0/warehouses/475b94ddc7cd5211 + enable_results_caching=False + +Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring +INFO:root:Loading query file. +INFO:root:Getting Query Metrics +INFO:root:Extracting Query History +INFO:root:Await completion of all queries... +INFO:root:Query history extracted successfully +INFO:root:Clean Query Metrics + total_time_ms read_bytes rows_produced_count compilation_time_ms ... query status warehouse_name id +0 71 0 1 14 ... select 'q1', now() FINISHED Serverless Shared Endpoint q1 + +[1 rows x 29 columns] +---- Specify a query directory semicolon format------ +INFO:root:Executing benchmark test +INFO:root:Set default catalog and schema + + SQL Warehouse Utils + ------------------------ + hostname=e2-demo-field-eng.cloud.databricks.com + catalog=hive_metastore + schema=default + http_path=/sql/1.0/warehouses/475b94ddc7cd5211 + enable_results_caching=False + +Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring +INFO:root:Loading query files from directory. +INFO:root:Getting Query Metrics +INFO:root:Extracting Query History +INFO:root:Await completion of all queries... +INFO:root:Query history extracted successfully +INFO:root:Clean Query Metrics + total_time_ms read_bytes rows_produced_count compilation_time_ms ... query status warehouse_name id +0 69 0 1 13 ... select 'q10', now() FINISHED Serverless Shared Endpoint q10 +1 96 0 1 13 ... select 'q2', now() FINISHED Serverless Shared Endpoint q2 +2 77 0 1 13 ... select 'q1', now() FINISHED Serverless Shared Endpoint q1 + +[3 rows x 29 columns] +---- Specify a query directory original format------ +INFO:root:Executing benchmark test +INFO:root:Set default catalog and schema + + SQL Warehouse Utils + ------------------------ + hostname=e2-demo-field-eng.cloud.databricks.com + catalog=hive_metastore + schema=default + http_path=/sql/1.0/warehouses/475b94ddc7cd5211 + enable_results_caching=False + +Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring +INFO:root:Loading query files from directory. +INFO:root:Getting Query Metrics +INFO:root:Extracting Query History +INFO:root:Await completion of all queries... +INFO:root:Query history extracted successfully +INFO:root:Clean Query Metrics + total_time_ms read_bytes rows_produced_count compilation_time_ms ... query status warehouse_name id +0 71 0 1 13 ... select 'q2', now(); FINISHED Serverless Shared Endpoint Q2 +1 66 0 1 16 ... select 'q1', now(); FINISHED Serverless Shared Endpoint Q1 + +[2 rows x 29 columns] +---- Test prewarm table ------ +INFO:root:Pre-warming table: customer +INFO:root:Pre-warming table: lineitem +INFO:root:Pre-warming table: nation +INFO:root:Pre-warming table: orders +INFO:root:Pre-warming table: part +INFO:root:Pre-warming table: partsupp +INFO:root:Pre-warming table: region +INFO:root:Pre-warming table: supplier +INFO:databricks.sql.client:Closing session 01eed4fb-6f93-1bb8-9ae2-5e4ed0d4c925 +INFO:databricks.sql.client:Closing session 01eed4fb-6f93-1bb8-9ae2-5e4ed0d4c925 +INFO:databricks.sql.thrift_backend:Error during request to server: {"method": "CloseSession", "session-id": "b'\\x01\\xee\\xd4\\xfbo\\x93\\x1b\\xb8\\x9a\\xe2^N\\xd0\\xd4\\xc9%'", "query-id": null, "http-code": 200, "error-message": "", "original-exception": "sys.meta_path is None, Python is likely shutting down", "no-retry-reason": "non-retryable error", "bounded-retry-delay": null, "attempt": "1/30", "elapsed-seconds": "0.07865405082702637/900.0"} \ No newline at end of file diff --git a/src/unittest/test_Benchmark.py b/src/unittest/test_Benchmark.py index 769938b..536b669 100644 --- a/src/unittest/test_Benchmark.py +++ b/src/unittest/test_Benchmark.py @@ -9,9 +9,9 @@ def setUp(self): def test_get_queries_from_file_format_semi(self): # Define a test case - test_file_path = '../../examples/queries/q1.sql' + test_file_path = '../../examples/queries/q10.sql' # replace with the expected output - expected_output = [("select 'q1', now()", 'q1')] + expected_output = [("select 'q10', now()", 'q10')] # Call the function with the test case actual_output = self.bm._get_queries_from_file_format_semi(test_file_path) @@ -31,5 +31,30 @@ def test_get_queries_from_file_format_orig(self): # Assert that the actual output matches the expected output self.assertEqual(actual_output, expected_output) + def test_get_queries_from_dir_orig(self): + # Define a test case + test_dir_path = '../../examples/queries_orig/' + # replace with the expected output + expected_output = [("select 'q1', now();", 'Q1'), ("select 'q2', now();", 'Q2')] + + # Call the function with the test case + self.bm.query_file_format = "original" + actual_output = self.bm._get_queries_from_dir(test_dir_path) + + # Assert that the actual output matches the expected output + self.assertEqual(actual_output, expected_output) + + def test_get_queries_from_dir_semi(self): + # Define a test case + test_dir_path = '../../examples/queries/' + # replace with the expected output + expected_output = [("select 'q1', now()", 'q1'), ("select 'q2', now()", 'q2'), ("select 'q10', now()", 'q10')] + + # Call the function with the test case + self.bm.query_file_format = "semicolon-delimited" + actual_output = self.bm._get_queries_from_dir(test_dir_path) + # Assert that the actual output matches the expected output + self.assertEqual(actual_output, expected_output) + if __name__ == '__main__': unittest.main() \ No newline at end of file From 81f3da2750b55052a45fa0e55841807bb80fe184 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Tue, 27 Feb 2024 17:57:28 -0800 Subject: [PATCH 18/20] Add stop warehouse function --- dist/beaker-0.0.7-py3-none-any.whl | Bin 0 -> 15925 bytes dist/beaker-0.0.7.tar.gz | Bin 0 -> 14770 bytes examples/beaker_standalone.py | 5 +- src/__init__.py | 2 +- src/beaker/benchmark.py | 21 +++++- src/beaker/sqlwarehouseutils.py | 1 + src/unittest/test | 112 ----------------------------- src/unittest/test_Benchmark.py | 40 +++++++++++ 8 files changed, 63 insertions(+), 118 deletions(-) create mode 100644 dist/beaker-0.0.7-py3-none-any.whl create mode 100644 dist/beaker-0.0.7.tar.gz delete mode 100644 src/unittest/test diff --git a/dist/beaker-0.0.7-py3-none-any.whl b/dist/beaker-0.0.7-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..25303d3a31d19b4a587c1aba49e968f1aa2d0e34 GIT binary patch literal 15925 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 literal 0 HcmV?d00001 diff --git a/examples/beaker_standalone.py b/examples/beaker_standalone.py index 2146763..29f44c0 100644 --- a/examples/beaker_standalone.py +++ b/examples/beaker_standalone.py @@ -18,7 +18,6 @@ catalog_name = os.getenv("CATALOG") schema_name = os.getenv("SCHEMA") -print(http_path) bm = benchmark.Benchmark() bm.setName(name="simple_test") @@ -62,4 +61,6 @@ print("---- Close connection ------") -bm.sql_warehouse.close_connection() \ No newline at end of file +bm.sql_warehouse.close_connection() +# res = bm.stop_warehouse("c0688d9c9c6d1091") +# print(res) \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index 0cdff65..262e0b7 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +1 @@ -VERSION = '0.0.6' +VERSION = '0.0.7' diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index 2e92a1a..4f4533e 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -85,9 +85,14 @@ def _get_user_id(self): ) return response.json()["id"] + def _validate_warehouse(self, http_path): """Validates the SQL warehouse HTTP path.""" - return True + pattern = r'^/sql/1\.0/warehouses/[a-f0-9]+$' + if re.match(pattern, http_path): + return True + else: + return False def _launch_new_warehouse(self): """Launches a new SQL Warehouse""" @@ -115,17 +120,25 @@ def setWarehouseConfig(self, config): logging.info(f"Creating new warehouse with config: {config}") self.warehouse_id = self._launch_new_warehouse() self.warehouse_name = self._get_warehouse_info() - logging.info(f"The warehouse Id is: {self.warehouse_id}") self.http_path = f"/sql/1.0/warehouses/{self.warehouse_id}" def setWarehouse(self, http_path): """Sets the SQL Warehouse http path to use for the benchmark.""" - assert self._validate_warehouse(id), "Invalid HTTP path for SQL Warehouse." + assert self._validate_warehouse(http_path), "Invalid HTTP path for SQL Warehouse." self.http_path = http_path if self.http_path: self.warehouse_id = self.http_path.split("/")[-1] self.warehouse_name = self._get_warehouse_info() + def stop_warehouse(self, warehouse_id): + """Stops a SQL warehouse.""" + logging.info(f"Stopping warehouse {warehouse_id}") + response = requests.post( + f"https://{self.hostname}/api/2.0/sql/warehouses/{warehouse_id}/stop", + headers={"Authorization": f"Bearer {self.token}"}, + ) + return response.status_code + def setConcurrency(self, concurrency): """Sets the query execution parallelism.""" self.concurrency = concurrency @@ -375,6 +388,8 @@ def clean_query_metrics(self, raw_metrics_pdf): metrics_pdf["status"] = raw_metrics_pdf["status"] metrics_pdf["warehouse_name"] = self.warehouse_name metrics_pdf["id"] = raw_metrics_pdf["id"] + # Set 'id' as the index of the DataFrame + metrics_pdf.set_index('id', inplace=True) return metrics_pdf def _get_warehouse_info(self): diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index e1136c4..6798170 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -111,6 +111,7 @@ def _get_spark_runtimes(self): ) result = list(map(lambda v: v["key"], response.json()["versions"])) return result + def launch_warehouse(self, config): """Creates a new SQL warehouse based upon a config.""" diff --git a/src/unittest/test b/src/unittest/test deleted file mode 100644 index e387cc7..0000000 --- a/src/unittest/test +++ /dev/null @@ -1,112 +0,0 @@ -/sql/1.0/warehouses/475b94ddc7cd5211 -INFO:root:self.hostname = None -INFO:root:self.hostname = e2-demo-field-eng.cloud.databricks.com ----- Specify query in code ------ -INFO:root:Executing benchmark test -INFO:root:Set default catalog and schema -INFO:databricks.sql.client:Successfully opened session 01eed4fb-6f93-1bb8-9ae2-5e4ed0d4c925 -INFO:root:Created new connection: - - SQL Warehouse Utils - ------------------------ - hostname=e2-demo-field-eng.cloud.databricks.com - catalog=hive_metastore - schema=default - http_path=/sql/1.0/warehouses/475b94ddc7cd5211 - enable_results_caching=False - -Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring -INFO:root:Executing single query. -INFO:root:Getting Query Metrics -INFO:root:Extracting Query History -INFO:root:Await completion of all queries... -INFO:root:Query history extracted successfully -INFO:root:Clean Query Metrics - total_time_ms read_bytes rows_produced_count ... status warehouse_name id -0 481 557980383 1 ... FINISHED Serverless Shared Endpoint query - -[1 rows x 29 columns] ----- Specify a single query file ------ -INFO:root:Executing benchmark test -INFO:root:Set default catalog and schema - - SQL Warehouse Utils - ------------------------ - hostname=e2-demo-field-eng.cloud.databricks.com - catalog=hive_metastore - schema=default - http_path=/sql/1.0/warehouses/475b94ddc7cd5211 - enable_results_caching=False - -Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring -INFO:root:Loading query file. -INFO:root:Getting Query Metrics -INFO:root:Extracting Query History -INFO:root:Await completion of all queries... -INFO:root:Query history extracted successfully -INFO:root:Clean Query Metrics - total_time_ms read_bytes rows_produced_count compilation_time_ms ... query status warehouse_name id -0 71 0 1 14 ... select 'q1', now() FINISHED Serverless Shared Endpoint q1 - -[1 rows x 29 columns] ----- Specify a query directory semicolon format------ -INFO:root:Executing benchmark test -INFO:root:Set default catalog and schema - - SQL Warehouse Utils - ------------------------ - hostname=e2-demo-field-eng.cloud.databricks.com - catalog=hive_metastore - schema=default - http_path=/sql/1.0/warehouses/475b94ddc7cd5211 - enable_results_caching=False - -Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring -INFO:root:Loading query files from directory. -INFO:root:Getting Query Metrics -INFO:root:Extracting Query History -INFO:root:Await completion of all queries... -INFO:root:Query history extracted successfully -INFO:root:Clean Query Metrics - total_time_ms read_bytes rows_produced_count compilation_time_ms ... query status warehouse_name id -0 69 0 1 13 ... select 'q10', now() FINISHED Serverless Shared Endpoint q10 -1 96 0 1 13 ... select 'q2', now() FINISHED Serverless Shared Endpoint q2 -2 77 0 1 13 ... select 'q1', now() FINISHED Serverless Shared Endpoint q1 - -[3 rows x 29 columns] ----- Specify a query directory original format------ -INFO:root:Executing benchmark test -INFO:root:Set default catalog and schema - - SQL Warehouse Utils - ------------------------ - hostname=e2-demo-field-eng.cloud.databricks.com - catalog=hive_metastore - schema=default - http_path=/sql/1.0/warehouses/475b94ddc7cd5211 - enable_results_caching=False - -Monitor warehouse `Serverless Shared Endpoint` at: https://e2-demo-field-eng.cloud.databricks.com/sql/warehouses/475b94ddc7cd5211/monitoring -INFO:root:Loading query files from directory. -INFO:root:Getting Query Metrics -INFO:root:Extracting Query History -INFO:root:Await completion of all queries... -INFO:root:Query history extracted successfully -INFO:root:Clean Query Metrics - total_time_ms read_bytes rows_produced_count compilation_time_ms ... query status warehouse_name id -0 71 0 1 13 ... select 'q2', now(); FINISHED Serverless Shared Endpoint Q2 -1 66 0 1 16 ... select 'q1', now(); FINISHED Serverless Shared Endpoint Q1 - -[2 rows x 29 columns] ----- Test prewarm table ------ -INFO:root:Pre-warming table: customer -INFO:root:Pre-warming table: lineitem -INFO:root:Pre-warming table: nation -INFO:root:Pre-warming table: orders -INFO:root:Pre-warming table: part -INFO:root:Pre-warming table: partsupp -INFO:root:Pre-warming table: region -INFO:root:Pre-warming table: supplier -INFO:databricks.sql.client:Closing session 01eed4fb-6f93-1bb8-9ae2-5e4ed0d4c925 -INFO:databricks.sql.client:Closing session 01eed4fb-6f93-1bb8-9ae2-5e4ed0d4c925 -INFO:databricks.sql.thrift_backend:Error during request to server: {"method": "CloseSession", "session-id": "b'\\x01\\xee\\xd4\\xfbo\\x93\\x1b\\xb8\\x9a\\xe2^N\\xd0\\xd4\\xc9%'", "query-id": null, "http-code": 200, "error-message": "", "original-exception": "sys.meta_path is None, Python is likely shutting down", "no-retry-reason": "non-retryable error", "bounded-retry-delay": null, "attempt": "1/30", "elapsed-seconds": "0.07865405082702637/900.0"} \ No newline at end of file diff --git a/src/unittest/test_Benchmark.py b/src/unittest/test_Benchmark.py index 536b669..9bd5b59 100644 --- a/src/unittest/test_Benchmark.py +++ b/src/unittest/test_Benchmark.py @@ -1,11 +1,27 @@ import unittest import sys +from dotenv import load_dotenv +import os + sys.path.append("../") from beaker import benchmark +load_dotenv("../examples/.env") + +hostname = os.getenv("DATABRICKS_HOST") +http_path = os.getenv("DATABRICKS_HTTP_PATH") +# Don't put tokens in plaintext in code +access_token = os.getenv("DATABRICKS_ACCESS_TOKEN") +catalog_name = os.getenv("CATALOG") +schema_name = os.getenv("SCHEMA") + class TestBenchmark(unittest.TestCase): def setUp(self): self.bm = benchmark.Benchmark() + self.bm.setName(name="unittest") + self.bm.setHostname(hostname=hostname) + self.bm.setWarehouseToken(token=access_token) + self.bm.setWarehouse(http_path=http_path) def test_get_queries_from_file_format_semi(self): # Define a test case @@ -56,5 +72,29 @@ def test_get_queries_from_dir_semi(self): # Assert that the actual output matches the expected output self.assertEqual(actual_output, expected_output) + def test_validate_warehouse(self): + # Define a test case + test_http_path = "/sql/1.0/warehouses/632c5da7a7fd6a78" + # replace with the expected output + expected_output = True + + # Call the function with the test case + actual_output = self.bm._validate_warehouse(test_http_path) + + # Assert that the actual output matches the expected output + self.assertEqual(actual_output, expected_output) + + # Define a test case + test_http_path2 = "/sql/1.0/warehouses632c5da7a7fd" + # replace with the expected output + expected_output2 = False + + # Call the function with the test case + actual_output2 = self.bm._validate_warehouse(test_http_path2) + + # Assert that the actual output matches the expected output + self.assertEqual(actual_output2, expected_output2) + + if __name__ == '__main__': unittest.main() \ No newline at end of file From 37aa481724e3410d0729dfc23a8f04358d784d90 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Fri, 1 Mar 2024 11:44:55 -0800 Subject: [PATCH 19/20] Update format of metrics pandas dataframe --- README.md | 2 +- dist/beaker-0.0.6-py3-none-any.whl | Bin 15801 -> 15860 bytes dist/beaker-0.0.6.tar.gz | Bin 15478 -> 14714 bytes dist/beaker-0.0.7-py3-none-any.whl | Bin 15925 -> 0 bytes dist/beaker-0.0.7.tar.gz | Bin 14770 -> 0 bytes src/__init__.py | 2 +- src/beaker/benchmark.py | 16 ++++++---------- src/beaker/sqlwarehouseutils.py | 1 - 8 files changed, 8 insertions(+), 13 deletions(-) delete mode 100644 dist/beaker-0.0.7-py3-none-any.whl delete mode 100644 dist/beaker-0.0.7.tar.gz diff --git a/README.md b/README.md index 70db902..9d88483 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ metrics = benchmark.execute() print(metrics) ``` -`metrics` is a list of dict. Each dict is the result of a single query execution. +`metrics` is a pandas dataframe of the result of a single query execution. If you want to examine the results as a spark DataFrame and your environment has the capability of creating a spark session, you can use spark_fixture. diff --git a/dist/beaker-0.0.6-py3-none-any.whl b/dist/beaker-0.0.6-py3-none-any.whl index e2a577d075774509e214d28e9f8e7df6a53ba645..8d47ac9de21d8ef1d9d621edfd946e38b11c37ff 100644 GIT binary patch delta 10739 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 literal 15478 zcmbVS({>#Uql|6aw$<21W4p0!+qP{xX>6;}j%^$J|6bvo%bEL`wFbm7Fd!hPTn1pk zYd;&0Ey?CR-?4^)A!@18h*0s#gv==C28P9^n~7xdsmVD$9XN_?v@sH4@Itfr_<(7D zfXmC;wbFX^1vgRZSLEpqqLVWL+?kY{n_FLZxA#o22g9ZPyY5fQEPsw|yrc>mW=WEe z;mfbJc?*Hh#VveG+HS9fbG;QX5ZT)=;2%RBVeXDgw=_Iq^uW18C&%L~;EWXkX- zcfKKHd4GShsprxj1<{r#KwBuF*h0?$_%*6&4(?G8l+rDG23ppv={5iz?&VutPd-f3 z3bQeSk% zxGDYYhijjZ)9~taip8n`xHh z-NXzVVeiQh;QqXPC-5sA-FhX4irfqZJSKY3?%(Q7st5jtX+FX1@vWY;iTq#(vTr^$`4 zCwD*OK?eBY=namL^f>Xsns7%fLTAkEGfRCP*Gq;fIq2ApXN`#D+h74a^gQ|J@hMV_ z@|jI6@e=okV$I|jyq%mstZ!{yoxR^4_wRR5T`$VC zAs(?u48%6}_g43RCKo5~&x{;h-{5MFY_SxUcoe!xV@kBu8kJo!o2%%b!?5}WsV(kX zOMYa7akrj%oTcFYC}9^aUJ+Hm()WePL~0*KsNk5FB}5ZYPj4G^DUO}6aF)n)OT#_d z@DS;jd5IWp&eC4s>SK=jav(?7{Ei~?8&76K5kVaw+jy=ow&4P!gLVALV%_s~9{n>| z54{eLNdI;y<%R#UIw zGNs;gBG>bKE;=I^O$SOnHN3_WRHwEGrH2I-rrzxH^d7j&cVF2+nV==pnWNl6J#p&p9?Vn);;$NH(`11Nd}OXI_`S zXytGQ*jv$k=UrhR{4O7y;yv!tVSa^3oU(%xu~RNWMS;@R-u^Bxo1~-hStBAl`%m4R z$Jip#mMo>>jg#k>6M9wOeHTdZKiYqNF0UCuE*L&6gte~44(D;@jZb#0yT8x;YD<`d z1Yuheru1sQ|HX*j0)%%s&)h4?t(Qm$-1XWFY+ZlorcOhda@70yfB9USVD66LfjXx% z%2&sPK+@2Y$K0>X?4V+j_sKU)jzY{Ray%YPSrYbGa;J?wyM$NTI;Dvnx|?HC&ZUN% zD!ff~f9AHd%5$|e4<+I#P8$i*#~?@E=c2K1LTf;*>{y>DxhY5#Q3iWWoBX@Nebkgg zW(EG4E=O6|M6UQHnkNBXVM_#!UI^NVdKbWrS_vHkkud?`+7BoNuSM)V2sdXSI5rZS zIi(1`?^C+fwJX@^uuhLIU>>WR`4j-wK!4dDxm|48*t~(Rj@K9wHwQOh{C;1e{nnt0 z^r5ngQBp>p{X6ZP8$$ZWXjL?O#Hg^vR+ZVHc?s-QD4cq{I0$dxg0m!rHWn@5NT|@Li}!25MO8->%ubhGwXAkqZkYOf=Z}w0?>KMUb@w@~ zvEEexr+Rs9+b+RQ^<8EG*Gn-viW8arLu4jG5F%1AUp-y9F~c_a2ARW8>0?biOA9Ku zI%j>r6SINC0eQr`7>o5oP{D`MxFhZq%LVBW6?VTgizP#7F23NQ&~T%4gM|VWM62V} z#mWP|6RaQ>#HO&49gj$;wXQs*Q42$Bb~)}3g65Vhk>WwZxO7Dbi=;k|SK>SQ&H!R+ z<5I1t{bvt+D3wArMon(o1tbF;84YtOqie0v0J zx=j|ZZjB_ilWCMXx<=)>rSp-kg|)_J@�DdR@7RZwXO3 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 diff --git a/dist/beaker-0.0.7-py3-none-any.whl b/dist/beaker-0.0.7-py3-none-any.whl deleted file mode 100644 index 25303d3a31d19b4a587c1aba49e968f1aa2d0e34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15925 zcmZ|01CS@pw(k9J+qP}nwr$(CZClgUv~AlxZCleerth44zI*rG@A-CBWK>l|sg92AfTuK008oD6IMj|jctJY_m1#yL;l;0&5Uf!oEZ!Ztn95^4GicVy<})6 z=hWt9q-SJi$K_}z)yJpl#u=!U9D|_%0L6b}?TctAtNw+6iU9y9|6&=N*_&9}89Ceh zh4t{-sBB3l@4lg-9pKjDbHL?)H1{lc3>fp8BYXn7aZoZ-!c^r}3)4gK10(kO9L)Jt z5z;^pJ9^+FtfaO69&bNUZB@|KM54W8q8#8h6`y*Td$(Jg?YS#z+I!94o>r=;*-5GH zOKPdJIUdwDo6%~cKzR%_Smg!K#N1y6Q(CF2?6LlUDvbxR+E;WuJGdoP-hg4d97QgUOTWjYG$g!!|I+9l>brQE;^YfK! z8#W{b&&Wn{;YXHlYfYy8X>-q!O>qfF+qy=43l+S_sBq9|&mssnP3TDc%cD>u7zxwv z1kgINFA%`R`^Dz%;p&Uo^Wo{;7=Z7`%lCeKHuQ&y78?~UKy8K+Nnf@X?#j5zSghHD` z4lB*6$(=C!ApC?L$q6MSnKp#2s~AaAD)v+%4sLZK+y1}|uobge!<2vY$iG-U=&pXX zA%wsU?s7pH1tcT-@Jd~Ley^AN%b&hhkt_SSUNKT@Da_5+#S|i!?;D>CD^6&}kaGCD zjJ+apv{ZBXA#$lG|G^+U@K%ye5Vt-kjs#rtkb^+}VVtM?q>!(&Y{rKQs)z_})}2QS z5Q`7h5Y!P^`14S~fQz7hXaxpu%A-|11qZ^BnJ{ELclt=_tG& z4U<3-5(L#4J{xm8PXAa~> z%ci~3>1t17kE(jL!iq}{`_>oq51Wnj8AvtGt-dy*cxDKN_k59{M!6vkv_JccEK@vC zPu)2$iCmlyJ*5Mo#$|haP8sx!77Oy3*T6D54~nC`Z7WNVHgXyLZxEL}xc>C2$Wr=& zz1H2Oni4c{)JtMA!ZOgKmLfD}4a`+G5rX@?2R(4zBbdFMf-qhy<3UcGHP>Zl;u+uTMu+g$}73bHR@1#GsN>QDDfYYssd z(O>v3Kj{H)yOg*_V)!jv{9p?FZ^>6GtaD76Fy$CPG9goRAwC|6TSkc$W+5z2;@n{k zZ*K@t1}^^VtruT!Zxq2QC*+%kfY-QkJ-I&~7{iV)Ga7~>9JM<=ksj(kJOLfPUj!&B zE7aT&ImtC5Q3DDo4eJk8zr2M9tbB^vc{n%|N9cy-lFUH(f?cNvJR>V=TrCo&e_QiV z9~c)LXTu8>Qx_aoh7-RpjPY`pKGf*dn@#MTZGjja2`?SQ$#WjIGO%9lQN9wj1(k2n z;|HpNj=)67l_H?Y)LIG}rk9%+WUhL=xDF26zLVfZLc#6TG@0(DrfcN}!U}c<3tVG~ zQrpFEWD8yt7(E6T&@CTu25#a z-N~_i^#|_tAf-3nj=`aJ?!-6^N%(@3FeJvPzXZ#<~*R}JYd5M zL7_AMvC8a797NJ^ON|)5)S8pPH<=IoT@<_dD9=h;JX+MjHFldq0PCp$dWkG|sY}>Z zmN*mh+iNRYAD8r<@)U8y%<*XD{lPGk;43z;7MD`t=#pm$-d{fh%VyA!BUAsXy8}1p z>r?1L#4@_^R9lWaHwECR3OiM&t?Mp|O_8czD2ZIm_PGE6CtFArw&~H^ zy8D(81X*xd3Vxwfwx0M5lGkZLQYHa$W&jqNjIqMZOm{-FzzW;*UE<&y(rT0%wGj21 zT-pbj4kx4gV)YuAZp)$BgW0fZ-5+ff1(PAGeW9IVBty-#%=V*D%lUXr8raBJn+Qna zn-`HU8x|I&?*sCQtpMs*6LL5as1F>8qZdqamjomK)6*A5c~oUQ0q42)qjP_@HOJ() z5*+j{=voGq<*eh3hF-Qj|RLeaBxfzmGpi32WZR8Oz@b`}%(4x|@-X7LB5;osF~>H$+#_&}PexH6n@ z(tu?0%#OL=q>84`2*v-G@AjDT1)0r?U=ChSj z3Sa_i?yC{Rr4>m@X*%6T9K|&!VUEEmX!kFstAE3IwINvKP)E$Vd|7QT@TLAy@7 z2YHoAt>})MAGgdOLf`v)?=x(^AKn42neRfD$(R7l0hX&jHwQp2I_YnI4=Xrrz;={U zeVA-y&Ia?ymCPZaWbBF96=~HOC}!~TTIt8dLkjV6`Y}cjkQA>X?+IOlC0yM@O?o`0 zpjYb`8^L+!8r#|w@)AMuk<1G8hk`OBuniqSsIKH%t%GOzbw+0*TqGD){zc z_3>%-^NF>dLcd!}m)k|H0(`*@#r}X9^pc2nT-Kz(IxKk|#JVOwph5G~*Gh|o6_R}% z2Syw^ZkS!gC0Do+H*WqllLH4y|F`sLCd4R6-jC2gD11;g#*xcM<6~5OHj%(#U>O6a z3(;cV+IY@CISn-asn0}Ny3dRU!X=l8E+p*Ynoc zmp38xr`@U~5Yj0OAQmR@oMaY@b3O{wm{23bzu35KzbIJ3sn$kD1dqElu)-I69Uq6Z zPODaS#x&Lg!uPnZtj|PPc9|PO`XW+lpDyskK;@oYg=URfs}QP85rSZO%Y*UbKqs^l z{UUfHAy%7zgpN*V!#dGLYwffgQ6`(j7!p{(+7wadCrPpGtAj+?UdF;G=}+u6%N#BQ zWv*)Q@EkEIE`!Dp=6*l!F72J$%=Ue%?dsq8(AbalOZ?Q#AJry?ey@BMB9L^N$6oJFT0lQf#?} z;CrKmPH{JfN9P{*PeE`cam_y@s+Iit1Y{8saQ@ETZ7EFER9wE2mJ>HSA?$qEHmQIEoA zpIeig^O%iM)d8u#0MWz4N*LXEs2-VUxv?nn}7H#LJV^CM}Ip6gIMg;!kwa> zM8Kn0R$GBMsK=wa8_1fBqxSVG?f#t}S=9AXO$cKM45_JS%LvA6auWnmtXwyhRJ#$@ zZC3E}57n&^t*M&^YVD=mUHm;{+zet_Q92usp7@0TZ?=Bc`V~jgO%ulC5WRPp@`l)# ztq)Kk_gXD=Ww%Bvq!xR(;Gu}JXcYN&H|WvYrDyiHWn(k6TOrk2dY>qwN8dn?q@&fZ z;Nt1?pY^&gYbv5xfJpgdpQ!p|%=m=vP5Oy2FZR^TnhN8S4j2$U2XB#4lut(i3 zT4@Z=p>dAj*rXazFJqOOy_!2*C_fi}GN&}oukr@1&&~Px{3t;IUmGEp;?UZ=>Oc8o zF}0;+RAecA!7gQ~SGPg?alI8yqw_|rFGE3h`k91#p*LL*vHNI{O}QzH1L{6&;Mxu4 zL!q`y8DCvkBs&vbKa&lje}xXqoitjEaZLKYkiNi6Y?kd4%vI8G!>6OnEB}{=0V!7lT?Jox!u!3eTe(mC95)OHD%ylZ^2`XKidf7SgF3?!2w914D*7Z2(nq>g)Y^sA1ij-97Y`TpYT;Mc^#uk~T~j$ZZH zfz>8kC~o>!m>P4PsK}DobcD@HewF%q7!G)~!?Z<$^0x@ftExL(05{uKgOASw;doiAC~9 zwu=UbnSB+*3qy3qSQvhcN{>U@ro0rs}o8zQ)GJHYSC$QEVEdUpYK4_Q@jTQ|F{ zi0j_UewLh)7!%{;0({m{whMAnYHxxLj}~zDkpq*^ zdIBRTlS>xKM&9r1*S2kC_XYFsA`}$oWl;d%+KI)J+xcwYxvzzXqfrl{JOxz2_L8CTSnB--#YQL%7Pz386H zD(T*!bt4f71?;@$_Me$nsXr3 zoVrFZwwear1YP5fQfAb$vnj7fA|`RN$U_g22Y{B|`qN_{*+vbc_M$??xn~|^sbXS z6b(pfhf{Y}ssBNfRy5xCRp{6ADf`3myX!j3W`ty*tVvI2kI z|FN1Ax9o?I5^9&vk?U$!Z&cBn7zZtw>@)-ftGoF>xP#E5pKHecbk!0K=12ynR16m( zA(SSc*yW&9L$^TY^e=1}*T*o0=3Ouc0& zKx_ygR{os*+{PPE$fO{JT_Ua>a@+!f$tMGMQ;Y62gpns1wsKZ8*rKSE|4}?KLB+r_NqZtbLa|LsdVTUDN9BIdIK_uddtQ2}y!p+mCV* zV4PJiPxDMW*}R{wPY)Vv5Z95_vXJHH>u(R@YRNO>R}s%#cW zD4+*f%eA(=yJc6(zNTidHDfdbbbBiv;VXHeMm_GL6>I&fBcw?t4rMw5YQN>O$5q7% z>SS9){d4Nao>E>qWty(no|~omm_&XmJFoWde)r`}i@kElvmB;L=~69`wjq>m{Y*H7 zkHlOlJlR9lJ&J`+!rJ7(6z>rx6U+%ZTUSt~9Qi|LWAIt^98`+JV3NchAT^CQ9 zDWDmXP4S}HS4~Mqs0F=1R(fo?*@!`ko+xAkfkhB_n53fdQY&}QP*_X!V#)1Ci_4#6 zXo;>ecJ{`o@(YRN(|An*Q`%kecsqM*6#8L$!A`)=2Z7nRhYja~>q@LQBWW<3=EOYh zx{!HMHMjTALClgBhaHuelRUeMScir7_%=3+Sq|Z~MW(=l8LfnL$ zrY8Qj=e@T~0svd7sWMRU@%gzB##j&h3wjH8#%T!VXb_Xva>D^Yper?+XK;gcfnMX4Xop_e@Y;IUcjYlAkJLFYDOI603LNh%ahYX_YUh7$7K9T8YfoFsAO{4ZjG* z(pRj*bV473FL_@o(@#@-&yoE~JVAK}iTI(FBsW*w>dJWTu^)LK@6w8ILED#r<&~XO zuJb-_aK2rF!tknQ=-?v5GkYCxtL;905WV0xnoX>oMc@3yuhpdsQZX39-oJRr%72s( zCFwhZy;LIZer5QAEYB+hL^Y}1>N>B@c~Mdh#`Wba4@;PeqNa$tdSBrS7Zp?zR-uJ- z7pRyq3di^&GauFgeQS^i9%C|Cg96NL2wo0hedxh3ca+jm#*O(6_n;Sk?i_<;bS5Z) zUj68Mus1UA>5Rpn+)`3=gm5+*%SRz<&~%#`@byLTO}f{Yu-7NxXvjC_*cGlhc=l(* z#=i)lLMm69z9{?=lCy>|5o~k{nH=J;Fufp*20ej%PvOH)tZk$rH#?uEMcd_!b;mZf z3h$I>hVm}IGEtVt3c8)~!xvv3P5P({5UtXQf3v{t4wl)keMyrLsm?-^ z+fUAY%&9H5+@qb=T$FZ0sl>b6NVe%@bS_ga)v`EI%yS-G<9m{(Vdz#vDVhQG*x;@O zBmOm?gdd>K+dvz~a~z9k2P&ujmMZ-EibU)r&vHbbP60U&i;MVx)q&>*8%u6ll7P1j zMjyqO&iscci(m>%30p2PFRHiHG;uOsR#m5YdIZ10;%MrZLPf;L$hosuFXXtFu>KTy zKeQDV?`Wbe8en0rLa)Q~^5Udmg`1YzZhhw-1E=)g$E%%KMb$7W@Jv8l)S6J zW4`@96dY&mCx8BCn%)?U-%j5^0>dWbb4age6#+2|e(d6g1+HKKAmo_(Z3OMf&{+uQwuj}_rVO$6cAH*85UU;$4r|jM^|eC<(u=|PQh4rB zK))9f68u(X0CxP_O#B_iy`%aV-mGHIlovtpiI(}&${ljbBTY+T8$^@MM{vBCG}@q_ z=0Oo;8yQwpNxcoEyUU5&#l&0kgGL>d zSHww&XJI6vJR`#bWB>U4w8_!Q#m&v#>-Q#hfe58JuXKur7Dj#^j@&nCn^y@-UCtJr zOkV`6^V171bI2hB3)?kjAgRC$guZjS#8Rd<*R0|Ax-ezV&yHMF(ATlqh@C#5@w-W1 zi$Y~S!s|X^ZfMyp@C(iM;;=c|+Oby9m4)9vA#nbh(@BRyQ1PvU`5J4YZKhF%GugT( z5iEtGk{O!uwxl<9g&)D-Ytcg6ks#3IFSOpSa7;U%;cNKoh=?XJ8!Hx?b9*;fj6?J`$mabEa} zH+Jp_AanRsoWjoHt4bGRvH!sR`xdU^@}mP9765?82LK5E?-q`Zk)DyBgWlB2#g)#= z-rRvfPE1uuR7h2*R%_e&uobQMRHblZLi1TNHDIwsP2IkymE(E1>r#(u{oIrpSyUL= zIN1<#Ub}S3;@r&Q-PJGD9|9nyl%7JaVlYnX=;(Nx7jPTL$a@n0(uWe3PL0#JbW7?v zrNU(DGC&}Tw9GQL@APWMNWYYdkwet=hxErHHL70m3q}#OzM>BIDc@w9~}${ z^K&wKn9RrhYCAvn9q&y;n{u6JI15bAq!aIezPUYRY;{q2_0G8Eh}fWh)Im^>?6wZ) z*e1Q5BLzv4)j|LrO2x_b^ZonpSMFDF+m)(Fws^h$-7asiW*@lM9;f*IJ?4GwsW4Qq zbRKhCPScywwkzT}m?uhO@4j)bW@OtM^l()5q}KGlDX{^#ev?Bu*Gz8yD|Cx#Fn{JH z;t20_Fa;HD$FU|esHer`54if-vvb;4LVs#ABG+9w`1Q9l*im%^11Y=k8lcj;0O|Ln zN#-*>v@X{-@lBQ+SPW0JjWd9DG;|hDrrWo&*?h&h0y|eA+d&EzVr+x9h0rZ{SPGyTmYTXqhMLTxK9r3gYCMJ4OY&t3KwtREv^Vb zhCL778I(0^MlC4I$YxXZFhtqcETV;=M(>x;vJFAt{0iC7H*!o4hbxh+2C|@nvn55Iw#5pId%j~ge;&?xQ_-Jmk`rk@#w5N; zVKXY!yU?6nmkcWT`Y_iSsp`f^&`d;CgDy7Ps};>zMwNO=Wcdw*;HgH+dYeX|@Zf=0 zf^qKBG$vILS+>MSx03s8R!*pOG+JgQUiV=2&#+q_&8G!ad2k=oT?}F*-57$- zZy&@*nMWf>?7=B0B6sE*#7!T_6#)wa8eyaEV6xGWDPh6Dfjo@d{TnZlgwwBVlU)~A za{@eN%*mW>o(|`~-QC^b; zX(~F}Ycu(cATi#N$Z7w0$f zw z&)um|UKpB!`LT=-%o=NaXxv-C)_tE5GoFy$4&8g(6cSvZ$s8#YJuMI$xQkH=l<<%Z z+$sp&18p7tHDz5sduvGmF)>pVndWoxnTNBZ*ITSIl);A0!Dg}7{M4q}ifz0k7?hSP z@$2u3rsM=;Xg~+K#D#6jX;^>ndFWh{LD%RX9KYQLgryYugtxJ!le?OS5Dn%IsYwo5 z-e~eqDsi-u68?cr^Xf+^t$GT>m8I#zXJftkGp_0+Bv~!ggdc&X?}=OXo6^}~ElGrY z(O?WHCUjN$lSjdB*7xznb&XvnRF(9Wu&|8^mtZOwFGe;2Z390=g5AS6X?^T}VD;NJ z2>^VBu$=oI`<$;VW{=oKC0UtUHakKMq<$RFxj)8ZOlk8j?=02Gma9EM1*cd?2W;eV zKd2Blb1y@ZWLPpMovQoW%bmi6CJ$FLG3KdvP2^H#^BC zC|`2#)H8LE2*zl&v|IQj3ZyHwY zmJY^VZl^Y6JF-2CH20=UzG!Rdkpm7n7!4E6?%b=d0^Z+yh0455p@KemoYQ}rx}u6W z3?sNg{?aZRmpvMDUW|GP-GN`+RtZ-F(aT-8pP!r$4?n;ZTRMxw)nMM#Q)8h9rjM5l90zyAyZ*T)yk79i(i|NmZU)1K-%u;tHKY}Ad{i2{`{2nZ?trxkXhf);r zq4u<$kB=yvEef#vV;*^hA|V`Iwq>}YL6pKu@|)2EK3Q z0t7z0KSRRWyi40?YO8vyE+YvmhQm21@qQeGvTo1LawW-Jc7O94xlt=_`u?Fk9yvaK zS}On5zJo(9|& z0TSd8;T7wjV)?rl(&#!}at+4I{w-bL9M*DOPZh#aNWi3A*u-6x#iZMpYgN#_J57f$ zX{6S2(f7z3oIu1#MB=7N2{jMV%ERby#UwPiB%PERE`_Yq z6gaK8S{XH&Ufmz6^9cEeFA~GA+d!T&OdBetQX(>9m>taKp0l+&nio@%6oRE86khd1 z`?2pxnRQS?ve)h44hA}ePmd;*;QL9x%23#Dm~RrS4rXn4Mq0lPb7+4I!RjRo;=tH2 z8S-jXr{~#RB6UtvS#HK!-azega67q*SW44Zt~8U4rOz%dMp?FRLF=T7(OC#>1MP2- z-i#jdI%I$y>B^ym5oUZElm7l;Iar=KaIScGfID8r*ys@=FqZFCV#x3 z=Hz8H_Mo6x$Lcfo zYT>l0w7$%8U9ul)?z z;tkMw>8eBSH>3AmjxZeuF#D7o(!Qy9ent)L_5FJo0ncNwrS>;`(D>W_%cA<<*3|zI zMrcTiiOIsuNy^PEz{${2&rZ)ZDKjp!>^UpU$k0jCPB1hok4w@@&5ln@%RoqD1|0?8 zKghW9#khe;$0)lnr_`WIM@y@82qQ1mqC!*0xjo!JD7&FNP{&RJhkd%fX&B-&@t=roaW9sg|$ejt- z*`A$5;Y+P3;dw-~)dT$I%ESvEJ=Q682pzwa%*=o>!lY_OBjxqmX$$?xPwONOjw2KKOdfYwyP) z|5H72%s_cy2;Ptav5>6~D<1^=TeKF3Y}uujeS|N_ zx-Y{Zq+!FHv~l3^S5(mz#7f4V{G*l>hwQ8q9s zOt#jOEKqeV!P8v`4nU8vdYAjGFO{bF$?b|R8~nlgn6`Pb*int_n{ZEj2K2sNM_>@V zgXpBVzcd}6qV>DyfV?3&`f1KUH{|+h?QHXJ?HvbScjnbyXFMPvc!q)ca-g+Ut<;jE zmKjYg{0iHYj?B#i&LQUHE0lZ#Q3pmp#!*#Fvo$$o`EZV>f-o4&tD5VI6zs%?PIqwkn>$~i!JJ&_w zQD?oF#i7QQ2|PZRh_aBq5s3xa@5k``0l44mWO4~89RR$2HHPVG`!!8HJ_B6P$0l1? za5)SCj!I84Q~Nj%Rnp8tn_*%X^9=0hHdy6u0YZ#pZ8mU>RJC{@B#vBvGPLzzIIQ8a0&eTaQpLHQ9>cl`lXHQq!;n{Qw~@;!a54;BZk*S?nkQBD5_>+>kY4F=B;n?dtJD-$U_=l?aQMzsAom7f8k7~8GWI0G`%^?V-<7S9md5$}7I>M(vU-~dDyhH;F;Poi z*AA>Y4KWx|zsp1cM7t(UOupQ~M);G4zJUcznQ%#)vEF{loRE?blF9_>h3Pj$RfK?} z5Ti8MS;QKNkUs3LV(4q#lX?9k-*HbY|Mki@s0OE+UMoZ|_z5OOQH2c#jmwG( z1IHf4+v+DPXB6HzZ&mrAzlCv!P8UQRo?A)o_-!;>LMEAp%P&gE6ohmwad^zsTmm^Q z`;Z-NZqXl8)UTJ#7(2m<8(V0pq)@fuV+->s!_FvGD5`e}(>`zmRu0CP{yH~w7=X_} z=#LgFAfR#9Lw(!t($=1djq82h+(4fwRZa#qogr4M^QNe9ov#ZS!%|a8zVK}Qr+sy6hqY-Sdd4kHkHD}tB5{`6kM}62mZEtM zWDLalkq=9kLGgY-7o;x#!gzRlgeV|p&m0eJ#>Q0`^$!ry5w_)%iO;|Sq zx=Y7R+_<^m_KV-S?RiA^2-11E0>=}&ip56IQ?+PrDJZefn7AnO>QaK|gc;Qk-D3&r3NIRPY;&iD*uVCx!qstwL7}@SMC9J3 z*k8T~=rKF#Jb{gCL;n>%%R8#2lA@CheWwL7z=mt}LJ#Xde0L=$}Z?ml?mA zj~lffb`nj_c{SG$vu+ zp7=D)07a9MN^snp!z^6pHfR56YVGGQDpuk?>gBy<*dl8lC{yDn0sayaL$3DrzIqL+ zFJcrVfdGB#7{{SG%~&g@68@PJ?G^W&(31#KCR`9Ne*P4$mWUH&fHLtm`bA7uqp72F zxP=B3zDYR~_=FNrMx{^kVn5Gk-=c&g4;-ke$o~seqUIHQKuO+kB+sEGC6^iN6tNZU zs-ajKZP<~D{driCIm~=nLfVp5Irc3Tql$VK9`lD~&mPTUSa5A{%)lFQr$4_o6WS*u znoOEPc$pI}cGmCAus{g63OjM%N9i;P@_|MqbezDW@r3#xLA&JUM^2m5RG(nvG|Duh zfuyS&R3qv?KnIn3t>LsF|@(V7#@EOQYYorl-?$>?_`tg7%s)b)t1#6CVo5#;!^wzlUS%uyhF zPxI$+2(Lb|HJvRkj~3FD`m-dtgwn6lqM&QbL2)Ldy{A8G4sdHErIAm&voIB`hhe*s zHiYl!+Rcq;Nqo^YoY@l>D9`KjCd(iHB%#(SVh;QefM7G5XEMseb34*M*8jDikvlCR zpFZ~F2_SRL^927}hG5pO@-~WIPC2D`X{JKIi<2u<$sdhMO;`wGY7!)O1zGh4(ocpIHMSQ-_JcdZ z2$>!?e!o8s+AId)sFAua}2Tx2qQ~4lMFUPa#-QN!#8+jNlLPD2=O@8 zsQ4iV8OLQ0Fb*z)AxZ*`ZKG~)b8rQ4PgNw!^3}4Gc##}HhpXb6eSf-c`Mfp-3V@)6 z0}m6?nY+1~MRNJjcQm08f$k7gIK3gqGabR7nm7CysLW_o;9Pnk5Tdvl@_l#(3r@vW z&cWV=tgsST43c9kO_3tH%fZ7}C}t02UdAJ{ozEd=$K$Nz%bE+fgm!;e-;;$lEcwHX z*0!N^85+^r;u-pm;>ac2cYYj(2y9_s6bb&&aFbkxQ9%O_7q7GYX^(3VAM5jWFa>uI z;NM5YTK<_X!cH!Sl&Y^m=~*$Ws3c;lK!x7lU9cOFjTZQRVBP!Lp3C5$=a)}+4Rhz! z+WiLC-2I2~o3-ydPxtKb)1OJ_?h<5Ge>CHg4D)J#=}FnwOVhtYXNGh0-pVM10;Vtk zBF38AtuO`a8hY#+IK8Q?346+A!x3&LtS#}IY;@+Nl-JG`-kNyJzR>1(Jn{7(g z@)sA4oXJDT%944y-%Xv$D=y(k1iw|s3LIYk9Mc0dWxz)Mqal`KWswoZ8DyS2yEPPr z)}EjrKeOepvIRxIw2Q{b^6e4JR2&L{fU_G6UCKS#z6BfVGszCPS(1YeG0ny?4#cfv znz~m+pZG-xc(dRMY&n>ZC_t9_^^rO6&{+8p4bb^9z#D-AZhg-kl9JN)jS>h3GynV` zC>H}86WhYRkR!gDt{}?7e9jNQ zdN?$wk+3O@rfna$Pem!mEfMjX)g`R6R(+U4(5-~1M?@m$%oFxv{YKEg+?}phI~m*< z)&|8D!+iUd3iTJALy~*_{c$n+8p3GIO`WUZ{F>pX`STi-6Acy+2`|flRluXT%%*8M zQNzje7%}VcQ$~^`N?dZU>UoJu>hPJBa%x9V0hGyHiOq=xtY^H(U|IZ{YE`&8KG4$!chO71o#aREue40tqq{#Att9>{Bt1*e)Ss)~-tO--!TsIR9 zPBHyef71xv$uF0>fu1*ne-E`aO|4in|C;8^fB^u!{~X&Yi-{;Gi@MEDCI4Uq2rl>q zz)&-Y=uQWh$3bs^7CEIrMV5uFz-DiP(G|_R}XKI6W4o^Gj2rU8v6=ItpLK$4Kul@c2|Fj+OB=XjJqT+KOy6niNm*WH1zb7nuoXd@Jar!wkmx{o$p}P@g5z$#1@xBE1 ziyuHoB5$$YGXR`CDY3KSV;zDW45vks3V*O)h2IMbS2OHk|7o?^MWGD=)#wqe6KpJ1 zkL6|0t_)$KG^eI}m8_hKJVszeu?wa8-^k*<&cAchg{_0{^0cyjn*T`pr^xhA=s(xexxg=K0>~o!(*9AE;;VwTd_z1_T6^ z(*O*3?Q7$*EtO>CKUO~=x=y+zCW_n-SSj93rR=ID)OL<`ex3Df!4Suwj1dVy3`pXE z1Ezg?puS$+Q0tkm;nOHJZNJQop)4+z1$dd7nVnQOH8E*F+n?Vy*OsYuvlZ{Y*It$_bobt~_k4pb3^bHM z3w&PZ-@n+n35oIuKD&Q-7YDjtcP`(ly_l}9^84S4Z1;Dcfu_xEKlvc=TD3rjd$}l| z%kXptd_%?J!`^&33s2>D=Huv9xc4(XU=&#&2)I_?Prj|trjLpta9ej?^9rcT|EKq? zl-f^yGG%fv^!}=yhn`-YZnnNI>E9Ij3+r6-eGiS6Mrg9*;&52F7!J;?$yz*dV zTmJe7Q8zKe2H1PDI6Cu}?{>EN<6G^NQRRza|K<#L+FcwoNo@nUVvcvdM-Nnm3FCKN zFMP~@y!q+229%Xm9AEF}n(qgUeht;L0WXrt$KY|28l8VuBm8N!wW&PU9?NU!lAL&| z9+dfUcPRd?J+6KE;^>WzkbGJR#;Np&EJ|w595G9NozzK)OF8iB&*PUXYg=RW9KGK` zh_FnIE!O0eFL00yhvU*>^_lP7wZRo;NS^rn@o|4opPw8o8a+K6KRxemo*zHml@A~F zlAm)-L_?f1%LJ!24G&%oeb7qSh)WlFIVL~V=~mVOz-t}kwBDZVVa9>JD%K!duqNS`;X2b)rBk~5<(s(U#O;%$E@_TRHA!CsJiaOd zWo*BmU6yLy)-S`YR2hw4w3G$biXu+E-|!1X!J_|$#7R2V?)SE&xO4Yu-sed0jsh@@A&%D(!H@1G^2S;&(o`UC+K(CsFb1^U(M+_u>vEB>mV^(no z%F75%(-T|is^;;aM~U64hQ?K=+S8LdRkd41_E#Ifx2v_ojiM3-x85(t98NnyN3UZ` z_X5NkT(iWI)mB}6k~ogvBp{AGm@UWeLziQZf?ev|I_p@kNi_FuR1A(}rZ+mkCeMcb zSARWjhL_X`ds&HU1rg*d`mRDm@y^Z*&zZ;3jd2t_{R%yk5>w5`F5xPuzN(0+syfeT z_3|sYg4ECcHxpFIsx=Dsi_-O~p?#$m5hP44CaD97CE{9>A-53>GwO=}B~Z?{U_A;m zLT^s59zBH=eyCfitoEQ%;U>-ar0bEn_fact-(6=IXmiouUig<&5VyoH0kWDK;Ui`oIpc#ptFCVx zAJ@fn;rtLDakIK*Uu+5|#~a*@ZqO5?RB?IykdeH4teDt&L-F^dJF~|sO$!SLpBl6* z%V6vPhn(v_-$Gmg2wZJHaF$A|Q?c&K{!N>}qj%z;@h)i_Nch0=n0meZj7tSzmUK-Zw! z+@|5M;$>JY%-NTq?tG}QdE*l@^!LSfY7MWE0|_LQ|{ zX|UeBa!t~^nGmKzWJlwEZvGt6J*RR0ioY64@~OX!;&# zj$>Ajv)xdp#Ne+b3}+Wn91LX=rIESCAJXXHOX$&7%xOH#M*8dxr|)+Je}20oVfbb! z!!oi}I8_5#EXO66$)u=SRgh-ae}z~1Xw5B^TteWByz2X3`DkB%QmZJ6rq1IPt%ekH zqAL+#hf!)WGOSDC(a$jaUhHp%E$UYD&kT%sQ-g$}T`Uo;?nflJZ&$Ju_O3f65qQYZ z=IF1V)tC)A&c^CGiy|Snz@sZ`u83Gl33L{;Ysv%AZ$cbd*gmAp9Qd|`K{Cj*cgD)j zm!}6{A1_a)WSk&iYcUx0$}eHai|(RDFNYe=u&;Z`6*x%N|HS`L)rf(qwj8?X`oVqS zWQT!0Q=Yec>GC!-6k=cuhL`*~B>DukBu)R#=7)^N$-JA~pzc<~I+d=+3ChCBSk3Fk z6OBwmLNUuHekXiOV-;*>HuVYD*#~BlWRwxssSf3)u0AF5xh5+9Vu9El%e7*&y5_P# zHqiMqNgY+4ccZ=K?K07ienoV)e8Dd}rZ!u{!RqvJmmsZ#$H9ET zEx@cB37@c6PQ{#+^67}-B>vd?xJp>o0m;F1c}cC8nBq4$h^q_}J2#?K0R?{X3DK4W zZ)7BaI6mBSNywjEolkpHeguM0^i_c(irM0gfZ85I)~2r343X&YwUw;DT5lZl^?5iV zBIF9%#e0{g8;{8u1Se2b42LTJ)VqoARY{#5IT0#FsXh=aisN6)UhUZBjVy_vs4rxN$g#AMQ<4?YrZ}z8flXjJBJCTZY zP1A>QyukZ9v-*#H}ZMYW*}{YTb1yG z(_7ofD=y8qMyd;+D7bEKYUy=*D_z(P`80mLbtr7MQcQBn_v{ER1}kudQfO_xLpbAN zHt3ljjZdh!kyON%x{MYKkYy8Zetqq@e|wvIO_=*d0a0FY$7-1cbwf#UK8~ngX%+*{ z{o{sfJN&H~yzULgVesWH3b4CqXX92{1-0e2nkmtY5p4nRM|p3Ino4FhN$C@316 zV75vl&!+JpuNK(xOYpGqFZ$9g!rOf8x@==lnG?5tfu<{DhSVW4%S8kdR2wEZ=`e3{ zW6Os>OxKQ=OMjtHvt0PE{x-}9-QKtjT4+j-IqUqjFCli$U~BDsd5hH{>XDFG6>qD| z&)Y^CVf_XxzhR%iX|z+Yh5#o-=W@#=3C(9txR9@0@TQe}B&TFD9lzv`HybQhLP+C@ z%8@W)Ggi`qqb%ExC^M0bRBrd&f<5G}XNmc2ZpIv#)Gb$z;X!u-$~!A>MKq`}j2}kD zCWU+5_V$wfkm*Xkg0y%MT@h@+jC-qDNIlVn*-U6ieRd!3^CzM+_ys+gI!fbQ_t^S` z!K5!se(92WZ3}~IfU#38K>eQ>rkD8@$*r-u>`r&kgk;*z&i#Br+Y_>k2{JtHb&j)# zD>=+sT)!qb^3$M=221|$Bb%Qn4doP5Its}k0&S3P786H!Sf_bI=Cw$hefn%Z6Ui8U zT!?NXqPgp8zrB8V3XVaA1z6&5U9Pvc^%%de0{42$y{I>wi3#bXQRS>lJBCFQWFexQ zfH)`9s=1##&MZ{HN3v5Uk~FryuS9QJjLr@}Ny~p|6HK)Z@97@#voJ8*oWY^Pb}}lALP4Cuj;E6ee3&NOU9g$<}FM7lwiz3*2n%8v^b--!LIvE!2fC)l+~-e zFc3fo<}BB3Gb;p=7yqMvqW{F4W&axeF&1bdb6hWJr{G&37lbN(rN8YY|ECQ%3V~`T z9JTA(X?&ajUdE6LZWBW9DilGizRq>BiZm<6ilaA%95_73M*q4PUME`J3$jHONz(BA zt2ZL_b+R#hJ=rhUnIjaI!XNp^cJZ%5BRhbcKg$RDG!;g4=!EE9a}senrWbj|+fj97 zgFwHo>iPKyse*;0V;CG4(a2q-;jaO;$aTf znBe+s6Y&OqWHRILK33-6ftvkjmOMoZv++FEVVw+Y*iH!ICJRHCd}uf1ZJI1q$KNK| zeP-#quCK!$et*TBgFe?)S)x4% zu1BDgWj&FG7PN>5mW7MQj0U@O<_CA|#O3RTqn{r?+L*RnZpIvTj zg3>FRBC+Oe4x--lf|Pt5BqtBcL^IhquWaoAR|&pMeR9P$M{s$5umrsVAm+Wzk!89mlE2L#-%FMRVmFO3cL&CU^4hrGZVG zEuaNxKm3QWk9>_!h-V#Yc;<~4sBOy4igWgH1?xec94q>^A~o*5yH%=JhdW(wCf@{v z#uq{29dDDub#A%Weak;lE+c?i<)f>lE!nEJ)gz44I-34Yn>Eg&xl)goz3!{F*d@HZ ztoYB@E9ss%I@+l(is(&fRd_G$7S}-3T5`JGK`1Y!)IUOi#9UY3=pcd*$`++&R+~bT z*^Z<925%?P=AXaLU;e7~rXCV5>QYV+Jhfk2GrV(?fk3k<>AF(68*k8u2J zYlSHa5!`OF4y{F+f`YYio!Ue$V)&u9%gfd3yCHfFdOOZMgJ_Bj_1+A?CxN<~XXD<| zT@tfVT*E4{b3);fYatzK9u)L_IM=8pWbmd838(A;i@K}mgRi=aPr~CkV5&pRPZvu; z_fx+NX@cF_XkY6Z^HRo7j$cJw(LjSuJ(RT-`Hd2gNz_4p@h!I?7MMyq|adJLe1!z3za$5@DU@FU?1Ov>2@D$v6Pl z>qHKfXEtUJxoqBFHYjc&qF5?Q{t5z|70^5sp%a{e37y2mCQA<;vanQ0=(b*~{T*@@ z*1$T z6oiEo;vyTX1yuP3jJJvOvo&k0R9}-BAik-**tV5G^#wxX=mJlG4pt`SyFA)()gxt!a?EGcgEt{3Zj|-l)8|Qh zcj+E;$wdm(B4~zFj&)kYsPtW#k#B&nOdktF-_hP;KXI_VEXdN&?oV}~5CH+=%X|QJ zFTa3i?WK=3LQ>)t$jGIon&#%ibU*0S9ljf*)Vg5Di0rE_k)oMQhiZ712TP_LwGp(3 zC$E#JV|iu|PFAA8K^;|*pjR9NoI8>+y%!f7-QQI%j+wTae{k-M3f=}HgdjDQng+Ua zp?uyak3m>G(PV4g@di8Tv`6-Kt}eMNgyZEXN=&}0x>ZgO{k8CL-%F%Zplks5~}_unlcWNa)z_a$o>hWShykNt1q zFnVroK#0M2gB(ZpB9D4vYuQgGasNLEubPu*A2v`iFatGML_Eb!TgG}E>`6r7pf6-u zbc!d*S}cUml6}um1k@@2&8{AtK9_-5*43?(IoO;~^FPILg`h7!KJ0995}?tkpAd<1 z^C3uku-233>oGof4StjDd}ziL>x~1L3uZ6$@h2bbjGN~{|Vs1$xVoe z3|u#=D2j?Sv<1%pIKlyv4$zSZ>hYKjnz=I-XSpOjV&?42?ya})ZyJww&_8$Hhg~Ya zhbiceDp@4V{SXR5yzrX5moitEX?Yalf8thj^K;4Ri)PywHDz{A#t1L~{w#oysw)U& ze2Xj0(47L6lI!=YiV@^=1f#mMeI3<8%hnnR8ll`5zh-{L7&8>>nWZvP1|K<|aa%iL zVPZdr$(@$dM{x#xCzT`@;TwP~MdTyITA+S$o9p)Ydj|p{5yxElaaa7IRg$vhU=ec` zL{e56qD6-{T@K&<7{r5Pbm^ooo;p>B5tu_~b@iD$7~uoPSxi~hgF~U$X!$mmi>_zb z^jO}@o?2K{S8x>wqW!VLoa(l+D!=)rv49KaHRoEYzJ_xVCGIRYwNBDT%#%=K-st_z zPItf>w+?<|#;j4fAmSXNkfsI})}tv4Ts}W~^jmRa?C4N8J-wDmE=St1bQ+Tfs|!{j z{0bk5&OpaZPSU+HOCX`e0>5rW_`#i8RlLtH_n8t$^+uM!p8CaBMawMI4m|6qafT=_ z6O~85>_%jE2`2(~rGF;#{nc3PYk_zKMjvfdgS7KwXlz~2pG^T=TYQ#x!$+CO0c z+%Kz5ULEx)Md^dPZg$qc*~*2CuUhlD$<4d2)w~CD=T^`F$L-DxiKkSz?j-O1RPJY+1kR;OWHu4gPJsPv^LTAasA0GoV~Eo13O29YX=ltiiK@qLLHiOL z7I1>9#cUW(Ght%9p+}Q1W&mu`xF0&JJ}+tvNKX&IpI6{}{|~(L#L7#eqZ@Eb$xj62 z5rtw%C23O6X>DWe>l@~mBvE@`Z8v9}K^hG4g^wRCw6{RMgw&L>oK9yHZzCSI9srFW z#T8hGyPR~=o_jNHM%Qv48m}Os&*SX9(h#Qu%ErR;nL{?VE&;=tXNtuzK18RXAEj>X zy$*AOG!p2_ldc>+xI~a^DH9jhrBR#=i)+W2U5{z72nA*(*M|iTe<>SIV_^K$ zYSiSmR0@(^S_@CMTECr*%@P4|sNsg)31g>qc?fKihpMG74H0fxe(k7VKB&PmV?uu+ zlgUNF_wrOYhVyiHj8#Rjpj?^^nWz>n-5MO)TyWzZ&*+Y!8#zoY;V{?;72_56?k%>) zX7*>Ksvmj5%q2$3mjsc)3@^*y5A}sqSn?DUabE}z1smV$ggnhJ$|eNDugX_IFJ67B z9uq}%Il4Pd7^Oaa3Su`v2|<1NSA1J<7~+o3(>_n73Sch*p2MyubpJ|Jm3q?a^EK!a z%@{x~t&vZHjj4cv`*2}^9lEYB&UIk5l`>m2c~iHxIu0#M|F=IaEU~~pTI251S#%Hz zaDp_#M(`Mf*1B@n$!<|HLaiZX3I$>lZ^}a#x)7EM&B!oXqTZy(g>rfRWGn?)(%U&l zUl4%S0XMNOdpfO47oZDD#rOqh&s$6&1!0gAN&)OtzTI5?`{nKmktVh%*=<4SYZJ~p)R9E zMz)k&K(pJPRC`Z-F3nrCH};)~YyV-%A$27|1)tmUifP!Vmdb{}LAuEm?fjyB@swv%S1Lc(1*GZYwW7%WQ2? zq_l1IVoD#sR%zt3D414;R5`x-wFUrepdRZ^ix{|gBr+o_R^#$3tXrOT9FK#!ZtCEG zbZP>0v8_o6MrIjH>X3ezJ&Ed3H!R8d&9)nx(!FEJMckj+;eF3wx`<_$4UGw(?!&cg z1s~^?hMh>1O%2)U8HHeYVGl#78HP=Z(-+@-83~8-&G`?fGrbLQ(S-=r{ew%yY#SRjn5hu+Keisf&4@EqNc&|KNJu0A1=SL!bD{0yB)b zFEi$w)dcF+H~tvYRsr^jVyqJ448C@a_`qSZJ_qwDu)(+O?c~(~JUcjFoxDSU%eoh4 zgq)w-joJN|+Z(i05TSZE6N45X08yyt*31EBH6RExO=@mnce}WAxBK&B#7&T!`{n6~ zUx8Ny<@4N*I4kXqUIdv z8No$5AnQ+vXD}`tw~cg4TPDNvOcavF$<6i^De8%*NWf*Y%MdG`$Fb^ z7ILVacJ<%0-Gy}l)}9I|M9t?o)VwEL{7|9Cvie;jr;jk$Q|B6waaA>E}gDxU>z+mO0H7Ht##T^3VSOZq`r! z9bIKoH3Rbo_Vp1FaQ+l<^tHFvTt2Vylkad}^X`E4xvtFmjEoFrkTJsW(DMr@#ByWh z5Vnq=vg*SI+k0okjdwW7^7S?CNbE}yFHyW16pj^7|Tsb(KVE{k>g2o#ug<^>*L1v~*5~hcvj&F=Vs%Xik2$ zrwE#TUrUevsLFiX2W5MMV1aKKuKoj5G4!Geq;2&#{ITi>gI)>cC*^qaoZ&Srxog3d=%gM_|K__2%f|4bk{< zTD3vIU)hB=@IS(b2mBkk_z9N!{?&(D)GO@fz4zbb=G_qH6C#EEOjh>$JNr0#06d%# z{Cl5Xq<_)p-4e}0Qbmqi_H zSM%V-6=}isfcUZOz}5Ca!C5}iZcZLS&(8R|0G*p7H$R_%&ppuHh zK`+rhes0&mL}rkZY9IdbPxnj5li%PCjXHPlc46x*Aor%~DvT`rkwJPDLW^NG z7wV`NUr$*$6d?cLW+Fg;?SO!-c;|uXY7uNig#?k+nw6N(RpJX#nuaYg-9XZ9qEoci$EY<$$ znxhT%c@y5!(JV*(-mcmYVjQ}X`!hI-v}$B`|ptWP1cHI9G#O#O!cw)q>1yogo|;g&2nK; zbMJo(FE5d_l0I>UQAP+>@|J??<}`qL^7`hYjP03VFY`-aO>Ac67!i#~X}b=7{Enp5 z)4{N0))M#{K(gv@C|@%$C1^Q;^m6{b5}Q1H(1-kh9VOxriEo1R9}mVsA=y&TWkZk$ zt2hAzt(uUzi9v_>?XV<8nfc1&RneIzAiOAHmq8OvOUr{CgEHI$CPQkl_e>gMq2t0 zSBM&NCoS4OH(Ch>Z68S|egP;P{R`EhwnzEaqL1A6)$SuAeBFhMoQyt z%1*))Wf$r_I71mn|Fty(K?7MQD8nub5f7IORE3q|bWkf1Zb6!R2B)E4@L4F!wslmBW9t#J zaxkB$u4&~hG(Me=`x%c^LTNtMe;9#zhLZUMM9AP}ok!R!jw2Wd`qIw6P1ADRn(QiV@uq)*`%xJ9a!5IP^+#MXa!qd8Fi+D)_>r04>4A=DzqEy$O%AnDzAl zohAu?xIi{jg9#N#XioE4*hNPM4%AJRIVZ8!eQ*3b0Tbo@-hc%NVa81WPk&BPdt6%B z3f~(eI!tHGx#qq;lb&^Gjv1P}Y-wm^1&LbAcBd4tMwFlFT@~dLkMvDw z^B^S_P)Ru&5!)#jF&r}4O3{;|nvA|vs7WZ(o18)z+~gPx%D1QDDao4Q;#_7dEb3NSESV0n{A$A(HTQez;vRJTw;)M=(ff0s4XH0wEoZQ% zWlpAEyeNW;2sWVvWVUcG!7rr6D-CC}{-sVhhOS|bbwFSFbq;liJi=#xJ}+n~Fp7z% z@J=RE{o5a`jGF;f>7Ttb+YbcX}wNs$DTiccjy3|BbKX13Nun= zD?wysblTRbX6#>J7gDUgBv(ueKP<}T;=5^(7g1iI{Bqu#5Him(dhuI;Qc9?Xl&wTu z%*}HtPf~BvE%a}2^L{fm*ku|}pU0-LeURvth)DfWF7_~G2j#?t%ba~g)TJWh z$Q0kxq1%185UV^^Qq;ijK#8IjuPTlDeOxQUlorUl&Lj(P>aLE_%7msk1*zdLdff^L zg;0)Ks#2LcZkR>PT^~KvWb`m^NqB}*U2IS77g*!3mJ5Ps>K`u8`=#@?9BNFYUuK$m zFcH2JhOK_`Tu3^4PPoD3nFFBAp_R4UxL1?f6ULM88A)YuvySRBW#W}=(k5y(7*>|& zzo^9XR;oH&_o)ZS+>prWN{7PuT9e)|0HOXIr#1W1=lN{Q>=<cFmd5cUTH*%Vj8};>l|%lO|6*d61_M`VV!4iks^C zf+~MghVZFjd-U{hxfRS|^?B^7`aF$0VDZ6!?TmSi`H`^FefDsC9LM3;$`lj+ZqG?j zEf+=udnBDqQ0REJBpQ^&DwoPadpDG9`RDlqVmW@}Y5Szd^5pVbvTK`hXG#bn{yd0F zSdH{ca$(jgNY<1gUQ-EbvRoZ=kPD>UfNFw;#wvl(%PGyZo*^|TRa zTv}s(^IU(%&RSc@PRh{sD+ZLffekAtq`-9 zJcFdlI(v`a5T~P&m5MHHiEseq1T{P!!=WIObKz;2VP^VL8CvuJj6nCP2F^o0RaWdf z)k$FX($pk0X9%Z(vRLCFs!cTa+R(!+ePdvx@51lsmpJJ}33@cwz{2pF5TbEESajpK z$bYncp|I13?`l=GSff&7L)St)xo&w9Flh=1!oe=AiS2NTamhqVGgnXJsLO2*2jYos zbW(Pd76O_e)^W@xbPcGiNa&`nlav*$Iy!Y?!RvJb<7uc4V;l5S)JT?IUYiTGvztYu z7_7Z6*0jprF1ZWqPz8;;X41x`ZjZkDB9dvk654dXWCyYm%1!@8lMcOVd6tgZf3ZcjX8g@~W zINt2E=aM=~k>tU#SLqFM?GTOUTji;mAfd}* zz)J80cmO!gLD%9x!^fEwk>maGdWZ<}pTE|FRrz22+g=av&hP#)i;FTN&&NTF5eYU> zZ+SGk!=b;tSl+JqKfXN8PC5>hGVU?TIa!G0>?v5T2LjAH)Gd?YXY>;1qaapY@a`Zg zqMHoKzpdhI-ef!58yQ5XhYn-_xhW%?(>^&g?3wItjq@_QS}w({Rx{39pX(?;X*8oU zlG3i3B`uzQ5lQRN&(zg0NV`xyGLxIIEJ3Aq9XiJf8lmN)i0L9@bxRN}^{iJfEB5a5 z&L?#9^Sw{I2T@=jPs_(i7`$LNaNnrbd!hhsV+hereY8WdzsqRE=P8M*X;l2IWUnv_ zD-z4+Q!fW5cDQH-!QeDVl6;#5+zd2Iw(lBXbS!_%qw$@KlqU-p&%)BROa{RB*d=Li zv^(W&!kCO*>O5kkyfaMyup#zYdm-@3zK&3;asT5ugYZs0ySGcq>KlF~NqO945M?fu zl2(38rjb5_OqWomE8g`)kvxrq7}N)$FhD2nG0^}!AR$!Yz04w4XerFOQ1(e)pt=wb zaTtI@kxCduEb{CF`@#9}Hj!B!NY+9-8_j!dDd5B!t#|eB?$x`>4wY@+F2UmMn{&B= zq*N?#-Bb|NT-c_Hd6SNJuA8T+r6nGT=@x-})kWE9vyMoo?4L;_omB@l8!x10dtz)IaF9gmlnWqDZ`P;H@1MN2D?Q0*Ix|F}D4lh@>|l zCttNq*{773ye+bfs}uMQg$t9!%%l`}c16`egUyv3$EhzdnroqO>0 z?Cieeysqve^r2ksS?*#U0o}X@A7k>OddIH@sQ3@v7A`XMjJD~a%_02D{;y@vv0hm= zVc8w|xR0gL_#azP39-{|ye^ol9sT>OYR@zptnf+OM18M~@D0BAZGtUw$c{hho%V_}Gq0L=}U5b>u>?ZOf&;U8B!43B2i$I3oh7 z1S&l!oA_2F-_AMnYRbsq)grql8aPN5w)w1!!OlogDJ8dXVS?6x-9+u-I$`2W!zFnk zmDikm_=1yGK#|PmbDJ12WRIz-m7MjIAY>1?2&9!{Kwzcg+}+=NDEpQ3yte{g|;rT1-;60H(DvItpnx zZq8JpG>w^vd5M~b>ywF50p1QWZj#{5R$jD0o5n?aQ75qTR#!JyU%y!jyt4VDwpNsP zE5%BoiWG(Ln*}3D5=xF=5nX>ej`qMRegm7U_Rt4}|G0$XQJ6On2~oWB;P&$MmC{J( zk#z@i5q$6F=v9<-ETtrEy=tR&H`!^DuDhNYo*Vlc|8Xm~n=E%HRGfKmNb_J-I|fNgdSIGdU~m zXEFYZq41Um=hW^R54@{ac*o4hz$8FKY|geYO6vTtGW)8(K(A10`jS4ut!S?>y4G}T z1b@B_NmD$YytCLwPf$S`wjUy;sdwEn<*+?2`mNF_;-2#R3?u~^W}O>uIX(DI+SiJl z%cqu4)md;U1}?EKj7R?7_P?S0f}C_%JJJJ86)QUZX6#F(+M7^?3y|WY8#moaPM$$L z+FFfF|NCReVRId>)xL4n>?k&{3i$goNR`mOQCfvD^>gHf%s`=gazLp-SYo^iN$MEL zEktn~e?1@&imr(byQ`-ru?_7VarUyyOa)%540nr#=O}_*qFL&5R|+8^SgeKY=H<%j zR{_SWShenD~^jDdMKc7L14&J=Tkhq2IziZ`ypz*@0>7U8IdS?ad?ZBHX6}CzU}dQEMKyZ)XIi2UC5Dp(Q!a- z?Of?pcO(zwM0ARp^6GlJ?CF~O4_A;Vc}t=*FHYWKufq0$`T1=s#&=M`OHDPr8$xhj zKI~+bj-XGHJFz+sGf2-RR!#0B_>Yg4`Snpu5)KdAT;GHg)n)65;<#y4Q*b+aLl*LQnz);T^|awM4h1w>r3l#cP;fzxySB zrMmnTgz5)lp6O6DdC_5na5wq3X4reRui)*R9WKm0%met3N^ zCrg8vK3fU-m#bp}G}hj!#21QW@5qXK&PZ)>+82w6{Q8V>8R8nVTZujk5 z`MUFxKUPSMEfmXgZ#1^(q0xC~M|IY;WKTLy{V81y zm?qlyGWD!|r$CSjC8?t<8gvWpk*7J33?iYm@bLwQ5UICzk`;4y#lF%prS)i~aK+HV z6LWS9{v!R}c`US`h>ki7=-NGZRe{O6oIXTHk~;!1+CoO??%B8jTaG=3kF zV9!5d9#@#uTc@HZ7*T%21-TZm9OPXE0#+^5aQ(x#Bj;6aQr)+f*nzv#J^AhYHT70+ zZ1LE$O@f$2NO4e~76qL>|0yPj1+nJuwsXDd#n-d77C-g%Q03sLvyexZHN*&a3Ki?n zZ$QJBwQeCtfeK9hxRsFnXdW>ARtw|mnerG1ISX}p!tCRB2g8OiF_bNu z63rSTr@yyK^u0u*?Uf8*WpYtdekxJu89uV!L(5D`Mny&lQXyeWjLQLzeu|5r=K07@6f`Aa7Y(BMC#A3H*sTmMU!-r(y3zRS(p`N0=Ggyx0OHnEMi=-q za$xQMx%<7h2?m4uT|RUE`ni2+o~>Q|xo!8@MUB6H1m8W&gDDdOE_LtY zCHoZ-({rEUetvimBW9dt5UTqkT&V7Q-a_2xcn=LAa63U7^aOBCX5e8)!WB$v?R|xW z>b~R&d2aLE-3=f@3qx{1>PhEj~x+K{jansf> z;sXYzu5bf}XVTbySYuAcy}V;j4X6hiwc+sG?{{sjruM?q@A?)a+;4g`*?NtcI^40;`C<$AqPhrFnbS>M}GlCGFwE zCHhl^o?tl;b>NWrU_&#SJCj0boj1e6l>E{V3FV1S!ekP5p(1Q9EG?hm+sKSC@#ggE z^hOXNn}Sb06QDoEx*02>LA=u1cPDWY`X#8F5Qi?T8I>^XnV5EFG@*bi&0F#je!~I1 z8~v^hL_nu$I83&-cO;E~ubO(~C<(=iGIP0^99i_xoVN_gq?0IiY^%U5|Anh@PFg?J zFak2-qDUmIDm4V}57SN0(~$%u0q%XhQ^$AWeHBkv% zFTeXn3H|y0KHO0i5FUuXtYDL&IdJD68mAKiWnpb^5iQ!k+sh^S`i|TFetwd~S#cTN z?I>D`IqJvn-EC4wcAJ=sJOfwiP`)-E@!5 zp8i;1{*ru4-W2=Zc<%x#5Iw$>hwfjB*y|e4pJr|9U!Yzg?sO-7{+&n3uIu&4!a>(> zb}Bsv3Q~_BHkBA2W2MF4zJ7;Q{%skcf9`QEp^8}N9N1;ddg0>rLM7{l$TbfVtM4Y% sJ&x)4oiT|z|DWsmOKpK_i|3lW)n+e^|2qhcJpw@|Sz`4;a6m!+2g*tF$p8QV diff --git a/src/__init__.py b/src/__init__.py index 262e0b7..0cdff65 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1 +1 @@ -VERSION = '0.0.7' +VERSION = '0.0.6' diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index 4f4533e..b0f0330 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -341,8 +341,8 @@ def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): -------- end_res : query history json """ + logging.info(f"Extracting query history {self.warehouse_name}") user_id = self._get_user_id() - logging.info("Extracting Query History") ## Put together request request_string = { "filter_by": { @@ -365,7 +365,6 @@ def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): #### Get Query History Results from API response = requests.get(uri, data=v, headers=headers_auth) - logging.info("Await completion of all queries...") while True: results = response.json()['res'] if all([item['is_final'] for item in results]): @@ -374,22 +373,21 @@ def get_query_history(self, warehouse_id, start_ts_ms, end_ts_ms): response = requests.get(uri, data=v, headers=headers_auth) if (response.status_code == 200) and ("res" in response.json()): - logging.info("Query history extracted successfully") end_res = response.json()['res'] return end_res else: raise Exception("Failed to retrieve successful query history") def clean_query_metrics(self, raw_metrics_pdf): - logging.info("Clean Query Metrics") + logging.info(f"Clean Query Metrics {self.warehouse_name}") metrics_pdf = json_normalize(raw_metrics_pdf['metrics'].apply(str).apply(eval)) metrics_pdf["query_id"] = raw_metrics_pdf["query_id"] metrics_pdf["query"] = raw_metrics_pdf["query"] metrics_pdf["status"] = raw_metrics_pdf["status"] metrics_pdf["warehouse_name"] = self.warehouse_name metrics_pdf["id"] = raw_metrics_pdf["id"] - # Set 'id' as the index of the DataFrame - metrics_pdf.set_index('id', inplace=True) + # Reorder the columns + metrics_pdf = metrics_pdf.reindex(columns=['id', 'warehouse_name', 'query', 'query_id', 'status'] + [c for c in metrics_pdf.columns if c not in ['id', 'warehouse_name', 'query', 'query_id', 'status']]) return metrics_pdf def _get_warehouse_info(self): @@ -404,8 +402,7 @@ def _get_warehouse_info(self): def execute(self): """Executes the benchmark test.""" - logging.info("Executing benchmark test") - logging.info("Set default catalog and schema") + logging.info("Executing benchmark") self.sql_warehouse = self._get_thread_local_connection() print(self.sql_warehouse) @@ -432,7 +429,6 @@ def execute(self): end_ts_ms = int(time.time() * 1000) - logging.info("Getting Query Metrics") history_metrics = self.get_query_history(self.warehouse_id, start_ts_ms, end_ts_ms) history_pdf = pd.DataFrame(history_metrics) beaker_pdf = pd.DataFrame(metrics) @@ -455,8 +451,8 @@ def preWarmTables(self, tables): self._set_default_catalog() self._set_default_schema() + logging.info(f"Pre-warming tables on {self.catalog}.{self.schema} in {self.warehouse_name}") for table in tables: - logging.info(f"Pre-warming table: {table}") query = f"CACHE SELECT * FROM {table}" self._execute_single_query(query) diff --git a/src/beaker/sqlwarehouseutils.py b/src/beaker/sqlwarehouseutils.py index 6798170..c9b02eb 100644 --- a/src/beaker/sqlwarehouseutils.py +++ b/src/beaker/sqlwarehouseutils.py @@ -62,7 +62,6 @@ def setConnection(self): schema=self.schema, session_configuration={"use_cached_result": results_caching}, ) - logging.info(f"Created new connection: {connection}") self.connection = connection def close_connection(self): From 2bd7ebe04a8593f8707b728b234cafd0f3940c34 Mon Sep 17 00:00:00 2001 From: anhhchu Date: Mon, 4 Mar 2024 15:54:15 -0800 Subject: [PATCH 20/20] Remove commented out function --- src/beaker/benchmark.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/beaker/benchmark.py b/src/beaker/benchmark.py index b0f0330..cb956f6 100644 --- a/src/beaker/benchmark.py +++ b/src/beaker/benchmark.py @@ -236,31 +236,6 @@ def _get_queries_from_file_format_orig(self, f): file_headers, file_queries = self._parse_queries(raw_queries) queries = [e for e in zip(file_queries, file_headers)] return queries - - # def _get_queries_from_file_format_semi(self, f, filter_comment_lines=False): - # fc = None - # queries = [] - # with open(f, "r") as of: - # fc = of.read() - # for idx, q in enumerate(fc.split(";")): - # q = q.strip() - # if not q: - # continue - # # Keep non-empty lines. - # # Also keep or remove comments depending on the flag. - # rq = [ - # l - # for l in q.split("\n") - # if l.strip() and not (filter_comment_lines and l.startswith("--")) - # ] - # if rq: - # queries.append( - # ( - # "\n".join(rq), - # f"query{idx}", - # ) - # ) - # return queries def _get_queries_from_file_format_semi(self, file_path): """