diff --git a/posthog/tasks/test/__snapshots__/test_usage_report.ambr b/posthog/tasks/test/__snapshots__/test_usage_report.ambr index 490b07d3fd0..5310c571bde 100644 --- a/posthog/tasks/test/__snapshots__/test_usage_report.ambr +++ b/posthog/tasks/test/__snapshots__/test_usage_report.ambr @@ -37,7 +37,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['hogql_query', 'HogQLQuery']) + AND (NULL IS NULL + OR query_type IN (NULL)) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = '' GROUP BY team_id @@ -54,7 +55,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['hogql_query', 'HogQLQuery']) + AND (NULL IS NULL + OR query_type IN (NULL)) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = 'personal_api_key' GROUP BY team_id @@ -71,7 +73,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['hogql_query', 'HogQLQuery']) + AND (NULL IS NULL + OR query_type IN (NULL)) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = 'personal_api_key' GROUP BY team_id @@ -88,7 +91,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['hogql_query', 'HogQLQuery']) + AND (NULL IS NULL + OR query_type IN (NULL)) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = 'personal_api_key' GROUP BY team_id @@ -105,7 +109,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['EventsQuery']) + AND (['EventsQuery'] IS NULL + OR query_type IN (['EventsQuery'])) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = '' GROUP BY team_id @@ -122,7 +127,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['EventsQuery']) + AND (['EventsQuery'] IS NULL + OR query_type IN (['EventsQuery'])) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = '' GROUP BY team_id @@ -139,7 +145,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['EventsQuery']) + AND (['EventsQuery'] IS NULL + OR query_type IN (['EventsQuery'])) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = '' GROUP BY team_id @@ -156,7 +163,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['EventsQuery']) + AND (['EventsQuery'] IS NULL + OR query_type IN (['EventsQuery'])) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = 'personal_api_key' GROUP BY team_id @@ -173,7 +181,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['EventsQuery']) + AND (['EventsQuery'] IS NULL + OR query_type IN (['EventsQuery'])) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = 'personal_api_key' GROUP BY team_id @@ -190,7 +199,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['EventsQuery']) + AND (['EventsQuery'] IS NULL + OR query_type IN (['EventsQuery'])) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = 'personal_api_key' GROUP BY team_id @@ -342,7 +352,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['hogql_query', 'HogQLQuery']) + AND (NULL IS NULL + OR query_type IN (NULL)) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = '' GROUP BY team_id @@ -359,7 +370,8 @@ WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (['hogql_query', 'HogQLQuery']) + AND (NULL IS NULL + OR query_type IN (NULL)) AND query_start_time between '2022-01-10 00:00:00' AND '2022-01-10 23:59:59' AND access_method = '' GROUP BY team_id diff --git a/posthog/tasks/test/test_usage_report.py b/posthog/tasks/test/test_usage_report.py index 41795a3bc37..832d8a6be82 100644 --- a/posthog/tasks/test/test_usage_report.py +++ b/posthog/tasks/test/test_usage_report.py @@ -16,6 +16,7 @@ from ee.billing.billing_manager import build_billing_token from ee.models.license import License from ee.settings import BILLING_SERVICE_URL from posthog.clickhouse.client import sync_execute +from posthog.clickhouse.query_tagging import tag_queries from posthog.cloud_utils import TEST_clear_instance_license_cache from posthog.hogql.query import execute_hogql_query from posthog.hogql_queries.events_query_runner import EventsQueryRunner @@ -529,12 +530,12 @@ class UsageReport(APIBaseTest, ClickhouseTestMixin, ClickhouseDestroyTablesMixin "local_evaluation_requests_count_in_period": 0, "billable_feature_flag_requests_count_in_period": 0, "survey_responses_count_in_period": 1, - "hogql_app_bytes_read": 0, - "hogql_app_rows_read": 0, - "hogql_app_duration_ms": 0, - "hogql_api_bytes_read": 0, - "hogql_api_rows_read": 0, - "hogql_api_duration_ms": 0, + "query_app_bytes_read": 0, + "query_app_rows_read": 0, + "query_app_duration_ms": 0, + "query_api_bytes_read": 0, + "query_api_rows_read": 0, + "query_api_duration_ms": 0, "event_explorer_app_bytes_read": 0, "event_explorer_app_rows_read": 0, "event_explorer_app_duration_ms": 0, @@ -583,12 +584,12 @@ class UsageReport(APIBaseTest, ClickhouseTestMixin, ClickhouseDestroyTablesMixin "local_evaluation_requests_count_in_period": 0, "billable_feature_flag_requests_count_in_period": 0, "survey_responses_count_in_period": 1, - "hogql_app_bytes_read": 0, - "hogql_app_rows_read": 0, - "hogql_app_duration_ms": 0, - "hogql_api_bytes_read": 0, - "hogql_api_rows_read": 0, - "hogql_api_duration_ms": 0, + "query_app_bytes_read": 0, + "query_app_rows_read": 0, + "query_app_duration_ms": 0, + "query_api_bytes_read": 0, + "query_api_rows_read": 0, + "query_api_duration_ms": 0, "event_explorer_app_bytes_read": 0, "event_explorer_app_rows_read": 0, "event_explorer_app_duration_ms": 0, @@ -631,12 +632,12 @@ class UsageReport(APIBaseTest, ClickhouseTestMixin, ClickhouseDestroyTablesMixin "local_evaluation_requests_count_in_period": 0, "billable_feature_flag_requests_count_in_period": 0, "survey_responses_count_in_period": 0, - "hogql_app_bytes_read": 0, - "hogql_app_rows_read": 0, - "hogql_app_duration_ms": 0, - "hogql_api_bytes_read": 0, - "hogql_api_rows_read": 0, - "hogql_api_duration_ms": 0, + "query_app_bytes_read": 0, + "query_app_rows_read": 0, + "query_app_duration_ms": 0, + "query_api_bytes_read": 0, + "query_api_rows_read": 0, + "query_api_duration_ms": 0, "event_explorer_app_bytes_read": 0, "event_explorer_app_rows_read": 0, "event_explorer_app_duration_ms": 0, @@ -702,12 +703,12 @@ class UsageReport(APIBaseTest, ClickhouseTestMixin, ClickhouseDestroyTablesMixin "local_evaluation_requests_count_in_period": 0, "billable_feature_flag_requests_count_in_period": 0, "survey_responses_count_in_period": 0, - "hogql_app_bytes_read": 0, - "hogql_app_rows_read": 0, - "hogql_app_duration_ms": 0, - "hogql_api_bytes_read": 0, - "hogql_api_rows_read": 0, - "hogql_api_duration_ms": 0, + "query_app_bytes_read": 0, + "query_app_rows_read": 0, + "query_app_duration_ms": 0, + "query_api_bytes_read": 0, + "query_api_rows_read": 0, + "query_api_duration_ms": 0, "event_explorer_app_bytes_read": 0, "event_explorer_app_rows_read": 0, "event_explorer_app_duration_ms": 0, @@ -756,12 +757,12 @@ class UsageReport(APIBaseTest, ClickhouseTestMixin, ClickhouseDestroyTablesMixin "local_evaluation_requests_count_in_period": 0, "billable_feature_flag_requests_count_in_period": 0, "survey_responses_count_in_period": 0, - "hogql_app_bytes_read": 0, - "hogql_app_rows_read": 0, - "hogql_app_duration_ms": 0, - "hogql_api_bytes_read": 0, - "hogql_api_rows_read": 0, - "hogql_api_duration_ms": 0, + "query_app_bytes_read": 0, + "query_app_rows_read": 0, + "query_app_duration_ms": 0, + "query_api_bytes_read": 0, + "query_api_rows_read": 0, + "query_api_duration_ms": 0, "event_explorer_app_bytes_read": 0, "event_explorer_app_rows_read": 0, "event_explorer_app_duration_ms": 0, @@ -893,7 +894,7 @@ class HogQLUsageReport(APIBaseTest, ClickhouseTestMixin, ClickhouseDestroyTables sync_execute("TRUNCATE TABLE system.query_log") execute_hogql_query( - query="select * from events limit 200", + query="select * from events limit 400", team=self.team, query_type="HogQLQuery", ) @@ -906,16 +907,56 @@ class HogQLUsageReport(APIBaseTest, ClickhouseTestMixin, ClickhouseDestroyTables report = _get_team_report(all_reports, self.team) - # We selected 200 or 50 rows, but still read 100 rows to return the query - assert report.hogql_app_rows_read == 100 - assert report.hogql_app_bytes_read > 0 + # We selected 400 rows, but still read 200 rows to return the query + assert report.query_app_rows_read == 200 + assert report.query_app_bytes_read > 0 + # We selected 50 rows, but still read 100 rows to return the query assert report.event_explorer_app_rows_read == 100 assert report.event_explorer_app_bytes_read > 0 # Nothing was read via the API - assert report.hogql_api_rows_read == 0 + assert report.query_api_rows_read == 0 assert report.event_explorer_api_rows_read == 0 + @also_test_with_materialized_columns(event_properties=["$lib"], verify_no_jsonextract=False) + def test_usage_report_api_queries(self) -> None: + for _ in range(0, 100): + _create_event( + distinct_id="hello", + event="$event1", + properties={"$lib": "web"}, + timestamp=now() - relativedelta(hours=12), + team=self.team, + ) + flush_persons_and_events() + sync_execute("SYSTEM FLUSH LOGS") + sync_execute("TRUNCATE TABLE system.query_log") + tag_queries(kind="request", id="1", access_method="personal_api_key") + + execute_hogql_query( + query="select * from events limit 400", + team=self.team, + query_type="HogQLQuery", + ) + EventsQueryRunner(query=EventsQuery(select=["event"], limit=50), team=self.team).calculate() + sync_execute("SYSTEM FLUSH LOGS") + + period = get_previous_day(at=now() + relativedelta(days=1)) + period_start, period_end = period + all_reports = _get_all_usage_data_as_team_rows(period_start, period_end) + + report = _get_team_report(all_reports, self.team) + + # No queries were read via the app + assert report.query_app_rows_read == 0 + assert report.query_app_bytes_read == 0 + assert report.event_explorer_app_rows_read == 0 + assert report.event_explorer_app_bytes_read == 0 + + # Queries were read via the API + assert report.query_api_rows_read == 200 + assert report.event_explorer_api_rows_read == 100 + @freeze_time("2022-01-10T00:01:00Z") class TestFeatureFlagsUsageReport(ClickhouseDestroyTablesMixin, TestCase, ClickhouseTestMixin): diff --git a/posthog/tasks/usage_report.py b/posthog/tasks/usage_report.py index f9e3982409d..8485aed175c 100644 --- a/posthog/tasks/usage_report.py +++ b/posthog/tasks/usage_report.py @@ -97,13 +97,13 @@ class UsageReportCounters: decide_requests_count_in_period: int local_evaluation_requests_count_in_period: int billable_feature_flag_requests_count_in_period: int - # HogQL - hogql_app_bytes_read: int - hogql_app_rows_read: int - hogql_app_duration_ms: int - hogql_api_bytes_read: int - hogql_api_rows_read: int - hogql_api_duration_ms: int + # Queries + query_app_bytes_read: int + query_app_rows_read: int + query_app_duration_ms: int + query_api_bytes_read: int + query_api_rows_read: int + query_api_duration_ms: int # Event Explorer event_explorer_app_bytes_read: int event_explorer_app_rows_read: int @@ -561,10 +561,10 @@ def get_teams_with_recording_count_in_period( @timed_log() @retry(tries=QUERY_RETRIES, delay=QUERY_RETRY_DELAY, backoff=QUERY_RETRY_BACKOFF) -def get_teams_with_hogql_metric( +def get_teams_with_query_metric( begin: datetime, end: datetime, - query_types: list[str], + query_types: Optional[list[str]] = None, access_method: str = "", metric: Literal["read_bytes", "read_rows", "query_duration_ms"] = "read_bytes", ) -> list[tuple[int, int]]: @@ -580,7 +580,7 @@ def get_teams_with_hogql_metric( FROM clusterAllReplicas({CLICKHOUSE_CLUSTER}, system.query_log) WHERE (type = 'QueryFinish' OR type = 'ExceptionWhileProcessing') AND is_initial_query = 1 - AND query_type IN (%(query_types)s) + AND (%(query_types)s IS NULL OR query_type IN (%(query_types)s)) AND query_start_time between %(begin)s AND %(end)s AND access_method = %(access_method)s GROUP BY team_id @@ -823,84 +823,78 @@ def _get_all_usage_data(period_start: datetime, period_end: datetime) -> dict[st "teams_with_ff_active_count": list( FeatureFlag.objects.filter(active=True).values("team_id").annotate(total=Count("id")).order_by("team_id") ), - "teams_with_hogql_app_bytes_read": get_teams_with_hogql_metric( + "teams_with_query_app_bytes_read": get_teams_with_query_metric( period_start, period_end, metric="read_bytes", - query_types=["hogql_query", "HogQLQuery"], access_method="", ), - "teams_with_hogql_app_rows_read": get_teams_with_hogql_metric( + "teams_with_query_app_rows_read": get_teams_with_query_metric( period_start, period_end, metric="read_rows", - query_types=["hogql_query", "HogQLQuery"], access_method="", ), - "teams_with_hogql_app_duration_ms": get_teams_with_hogql_metric( + "teams_with_query_app_duration_ms": get_teams_with_query_metric( period_start, period_end, metric="query_duration_ms", - query_types=["hogql_query", "HogQLQuery"], access_method="", ), - "teams_with_hogql_api_bytes_read": get_teams_with_hogql_metric( + "teams_with_query_api_bytes_read": get_teams_with_query_metric( period_start, period_end, metric="read_bytes", - query_types=["hogql_query", "HogQLQuery"], access_method="personal_api_key", ), - "teams_with_hogql_api_rows_read": get_teams_with_hogql_metric( + "teams_with_query_api_rows_read": get_teams_with_query_metric( period_start, period_end, metric="read_rows", - query_types=["hogql_query", "HogQLQuery"], access_method="personal_api_key", ), - "teams_with_hogql_api_duration_ms": get_teams_with_hogql_metric( + "teams_with_query_api_duration_ms": get_teams_with_query_metric( period_start, period_end, metric="query_duration_ms", - query_types=["hogql_query", "HogQLQuery"], access_method="personal_api_key", ), - "teams_with_event_explorer_app_bytes_read": get_teams_with_hogql_metric( + "teams_with_event_explorer_app_bytes_read": get_teams_with_query_metric( period_start, period_end, metric="read_bytes", query_types=["EventsQuery"], access_method="", ), - "teams_with_event_explorer_app_rows_read": get_teams_with_hogql_metric( + "teams_with_event_explorer_app_rows_read": get_teams_with_query_metric( period_start, period_end, metric="read_rows", query_types=["EventsQuery"], access_method="", ), - "teams_with_event_explorer_app_duration_ms": get_teams_with_hogql_metric( + "teams_with_event_explorer_app_duration_ms": get_teams_with_query_metric( period_start, period_end, metric="query_duration_ms", query_types=["EventsQuery"], access_method="", ), - "teams_with_event_explorer_api_bytes_read": get_teams_with_hogql_metric( + "teams_with_event_explorer_api_bytes_read": get_teams_with_query_metric( period_start, period_end, metric="read_bytes", query_types=["EventsQuery"], access_method="personal_api_key", ), - "teams_with_event_explorer_api_rows_read": get_teams_with_hogql_metric( + "teams_with_event_explorer_api_rows_read": get_teams_with_query_metric( period_start, period_end, metric="read_rows", query_types=["EventsQuery"], access_method="personal_api_key", ), - "teams_with_event_explorer_api_duration_ms": get_teams_with_hogql_metric( + "teams_with_event_explorer_api_duration_ms": get_teams_with_query_metric( period_start, period_end, metric="query_duration_ms", @@ -972,12 +966,12 @@ def _get_team_report(all_data: dict[str, Any], team: Team) -> UsageReportCounter dashboard_tagged_count=all_data["teams_with_dashboard_tagged_count"].get(team.id, 0), ff_count=all_data["teams_with_ff_count"].get(team.id, 0), ff_active_count=all_data["teams_with_ff_active_count"].get(team.id, 0), - hogql_app_bytes_read=all_data["teams_with_hogql_app_bytes_read"].get(team.id, 0), - hogql_app_rows_read=all_data["teams_with_hogql_app_rows_read"].get(team.id, 0), - hogql_app_duration_ms=all_data["teams_with_hogql_app_duration_ms"].get(team.id, 0), - hogql_api_bytes_read=all_data["teams_with_hogql_api_bytes_read"].get(team.id, 0), - hogql_api_rows_read=all_data["teams_with_hogql_api_rows_read"].get(team.id, 0), - hogql_api_duration_ms=all_data["teams_with_hogql_api_duration_ms"].get(team.id, 0), + query_app_bytes_read=all_data["teams_with_query_app_bytes_read"].get(team.id, 0), + query_app_rows_read=all_data["teams_with_query_app_rows_read"].get(team.id, 0), + query_app_duration_ms=all_data["teams_with_query_app_duration_ms"].get(team.id, 0), + query_api_bytes_read=all_data["teams_with_query_api_bytes_read"].get(team.id, 0), + query_api_rows_read=all_data["teams_with_query_api_rows_read"].get(team.id, 0), + query_api_duration_ms=all_data["teams_with_query_api_duration_ms"].get(team.id, 0), event_explorer_app_bytes_read=all_data["teams_with_event_explorer_app_bytes_read"].get(team.id, 0), event_explorer_app_rows_read=all_data["teams_with_event_explorer_app_rows_read"].get(team.id, 0), event_explorer_app_duration_ms=all_data["teams_with_event_explorer_app_duration_ms"].get(team.id, 0),