From 73681fcb7ab84c814d50797a22a165160d47352a Mon Sep 17 00:00:00 2001 From: Josh Temple <8672171+joshtemple@users.noreply.github.com> Date: Tue, 18 Apr 2023 14:52:19 -0400 Subject: [PATCH 1/4] Save runtime to Query object Closes #653 --- spectacles/validators/sql.py | 1 + 1 file changed, 1 insertion(+) diff --git a/spectacles/validators/sql.py b/spectacles/validators/sql.py index 177201b3..5fe7655f 100644 --- a/spectacles/validators/sql.py +++ b/spectacles/validators/sql.py @@ -315,6 +315,7 @@ async def _get_query_results( Union[CompletedQueryResult, ErrorQueryResult], query_result ) query = self._task_to_query[task_id] + query.runtime = query_result.runtime if query_result.runtime > self.runtime_threshold: self._long_running_queries.append(query) if query_result.status == "complete": From dca854437acec5576ba916c70928946bb12d1cca Mon Sep 17 00:00:00 2001 From: Josh Temple <8672171+joshtemple@users.noreply.github.com> Date: Tue, 18 Apr 2023 14:56:50 -0400 Subject: [PATCH 2/4] Add smoke test for profiler --- tests/integration/test_runner.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/integration/test_runner.py b/tests/integration/test_runner.py index 46e42630..3bc937e8 100644 --- a/tests/integration/test_runner.py +++ b/tests/integration/test_runner.py @@ -191,3 +191,11 @@ async def test_incremental_sql_with_diff_explores_and_invalid_existing_sql_shoul assert result["tested"][1]["explore"] == "users__fail" assert result["tested"][1]["status"] == "passed" assert len(result["errors"]) == 0 + + +async def test_validate_sql_with_query_profiler_should_work( + looker_client: LookerClient, caplog: pytest.LogCaptureFixture +): + runner = Runner(looker_client, "eye_exam") + await runner.validate_sql(fail_fast=True, profile=True, runtime_threshold=0) + assert "Query profiler results" in caplog.text From c098715a58f8e177eea6500f3d05b50c619a5c33 Mon Sep 17 00:00:00 2001 From: Josh Temple <8672171+joshtemple@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:16:52 -0400 Subject: [PATCH 3/4] Allow profiling for non-fail fast, return dimensions in result --- spectacles/runner.py | 4 +--- spectacles/validators/sql.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/spectacles/runner.py b/spectacles/runner.py index d2087f85..ec3264be 100644 --- a/spectacles/runner.py +++ b/spectacles/runner.py @@ -399,9 +399,7 @@ async def validate_sql( ) async with self.branch_manager(ref=ref): - await validator.search( - explores, fail_fast, chunk_size, profile=profile if fail_fast else False - ) + await validator.search(explores, fail_fast, chunk_size, profile=profile) # Create dimension tests for the desired ref when explores errored if not fail_fast and incremental: diff --git a/spectacles/validators/sql.py b/spectacles/validators/sql.py index 5fe7655f..b0d6a2db 100644 --- a/spectacles/validators/sql.py +++ b/spectacles/validators/sql.py @@ -16,7 +16,7 @@ DEFAULT_CHUNK_SIZE = 500 DEFAULT_QUERY_CONCURRENCY = 10 DEFAULT_RUNTIME_THRESHOLD = 5 -ProfilerTableRow = Tuple[str, float, str, str] +ProfilerTableRow = Tuple[str, str, float, str, str] @dataclass @@ -62,7 +62,13 @@ def to_profiler_format(self) -> ProfilerTableRow: "Query.explore_url cannot be None, " "run Query.create to get an explore URL" ) - return (self.explore.name, self.runtime, self.query_id, self.explore_url) + return ( + self.explore.name, + self.dimensions[0].name if len(self.dimensions) == 1 else "*", + self.runtime, + self.query_id, + self.explore_url, + ) def print_profile_results(queries: List[Query], runtime_threshold: int) -> None: @@ -79,6 +85,7 @@ def print_profile_results(queries: List[Query], runtime_threshold: int) -> None: [query.to_profiler_format() for query in queries_by_runtime], headers=[ "Explore", + "Dimension(s)", "Runtime (s)", "Query ID", "Explore From Here", From 925649e2d864f0a0e6cf48e477fbada6e9088ef2 Mon Sep 17 00:00:00 2001 From: Josh Temple <8672171+joshtemple@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:22:04 -0400 Subject: [PATCH 4/4] Update query profiler format test --- tests/unit/test_query.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_query.py b/tests/unit/test_query.py index 93079ca1..2ab2a0df 100644 --- a/tests/unit/test_query.py +++ b/tests/unit/test_query.py @@ -70,4 +70,25 @@ def test_query_should_convert_to_profiler_format( query_id=query_id, explore_url=explore_url, ) - assert query.to_profiler_format() == (explore.name, runtime, query_id, explore_url) + assert query.to_profiler_format() == ( + explore.name, + "*", + runtime, + query_id, + explore_url, + ) + + query = Query( + explore=explore, + dimensions=(dimension,), + runtime=runtime, + query_id=query_id, + explore_url=explore_url, + ) + assert query.to_profiler_format() == ( + explore.name, + dimension.name, + runtime, + query_id, + explore_url, + )