diff --git a/api/chalicelib/core/errors/errors.py b/api/chalicelib/core/errors/errors.py index 18166aa3a..8679471ea 100644 --- a/api/chalicelib/core/errors/errors.py +++ b/api/chalicelib/core/errors/errors.py @@ -149,11 +149,7 @@ def search(data: schemas.SearchErrorsSchema, project: schemas.ProjectContext, us params["error_query"] = helper.values_for_operator(value=data.query, op=schemas.SearchEventOperator.CONTAINS) - main_pg_query = f"""WITH raw_data AS (SELECT DISTINCT session_id - FROM events.errors - {"INNER JOIN public.sessions USING(session_id)" if platform else ""} - WHERE {" AND ".join(pg_sub_query_chart)}) - SELECT full_count, + main_pg_query = f"""SELECT full_count, error_id, name, message, @@ -187,11 +183,11 @@ def search(data: schemas.SearchErrorsSchema, project: schemas.ProjectContext, us FROM (SELECT generated_timestamp AS timestamp, COUNT(session_id) AS count FROM generate_series(%(startDate)s, %(endDate)s, %(step_size)s) AS generated_timestamp - LEFT JOIN LATERAL (SELECT * - FROM raw_data - UNION ALL - SELECT NULL AS session_id - WHERE NOT EXISTS(SELECT 1 FROM raw_data)) AS sessions ON (TRUE) + LEFT JOIN LATERAL (SELECT DISTINCT session_id + FROM events.errors + {"INNER JOIN public.sessions USING(session_id)" if platform else ""} + WHERE {" AND ".join(pg_sub_query_chart)} + ) AS sessions ON (TRUE) GROUP BY timestamp ORDER BY timestamp) AS chart_details) AS chart_details ON (TRUE);""" diff --git a/api/chalicelib/core/errors/errors_ch.py b/api/chalicelib/core/errors/errors_ch.py index 178b33701..83954fc16 100644 --- a/api/chalicelib/core/errors/errors_ch.py +++ b/api/chalicelib/core/errors/errors_ch.py @@ -148,7 +148,7 @@ def search(data: schemas.SearchErrorsSchema, project: schemas.ProjectContext, us if len(data.events) > errors_condition_count: subquery_part_args, subquery_part = sessions.search_query_parts_ch(data=data, error_status=data.status, errors_only=True, - project_id=project_id, user_id=user_id, + project_id=project.project_id, user_id=user_id, issue=None, favorite_only=False) subquery_part = f"INNER JOIN {subquery_part} USING(session_id)" diff --git a/api/chalicelib/core/sessions/sessions_ch.py b/api/chalicelib/core/sessions/sessions_ch.py index 0df98e004..6a987a2d3 100644 --- a/api/chalicelib/core/sessions/sessions_ch.py +++ b/api/chalicelib/core/sessions/sessions_ch.py @@ -34,40 +34,27 @@ def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, d with ch_client.ClickHouseClient() as cur: if metric_type == schemas.MetricType.TIMESERIES: if metric_of == schemas.MetricOfTimeseries.SESSION_COUNT: - query = f"""WITH raw_data AS (SELECT s.session_id AS session_id, - s.datetime AS datetime - {query_part}) - SELECT gs.generate_series AS timestamp, + query = f"""SELECT gs.generate_series AS timestamp, COALESCE(COUNT(DISTINCT processed_sessions.session_id),0) AS count FROM generate_series(%(startDate)s, %(endDate)s, %(step_size)s) AS gs - LEFT JOIN (SELECT * - FROM raw_data - UNION ALL - SELECT NULL AS session_id, - NULL AS datetime - WHERE NOT EXISTS(SELECT 1 FROM raw_data)) AS processed_sessions ON(TRUE) + LEFT JOIN (SELECT s.session_id AS session_id, + s.datetime AS datetime + {query_part}) AS processed_sessions ON(TRUE) WHERE processed_sessions.datetime >= toDateTime(timestamp / 1000) AND processed_sessions.datetime < toDateTime((timestamp + %(step_size)s) / 1000) GROUP BY timestamp ORDER BY timestamp;""" elif metric_of == schemas.MetricOfTimeseries.USER_COUNT: - query = f"""WITH raw_data AS (SELECT s.user_id AS user_id, - s.datetime AS datetime - {query_part} - WHERE isNotNull(s.user_id) - AND s.user_id != '') - SELECT gs.generate_series AS timestamp, + query = f"""SELECT gs.generate_series AS timestamp, COALESCE(COUNT(DISTINCT processed_sessions.user_id),0) AS count FROM generate_series(%(startDate)s, %(endDate)s, %(step_size)s) AS gs - LEFT JOIN (SELECT * - FROM raw_data - UNION ALL - SELECT NULL AS user_id, - NULL AS datatime - WHERE NOT EXISTS(SELECT 1 FROM raw_data)) AS processed_sessions ON(TRUE) - WHERE processed_sessions.user_id IS NULL - OR processed_sessions.datetime >= toDateTime(timestamp / 1000) - AND processed_sessions.datetime < toDateTime((timestamp + %(step_size)s) / 1000) + LEFT JOIN (SELECT multiIf(s.user_id IS NOT NULL AND s.user_id != '', s.user_id, + s.user_anonymous_id IS NOT NULL AND s.user_anonymous_id != '', + s.user_anonymous_id, toString(s.user_uuid)) AS user_id, + s.datetime AS datetime + {query_part}) AS processed_sessions ON(TRUE) + WHERE processed_sessions.datetime >= toDateTime(timestamp / 1000) + AND processed_sessions.datetime < toDateTime((timestamp + %(step_size)s) / 1000) GROUP BY timestamp ORDER BY timestamp;""" else: @@ -134,7 +121,8 @@ def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, d s.pop("main_count") sessions = {"count": count, "values": helper.list_to_camel_case(sessions)} - return sessions + return helper.complete_missing_steps(rows=sessions, start_timestamp=data.startTimestamp, + end_timestamp=data.endTimestamp, step=step_size, neutral={"count": 0}) def search2_table(data: schemas.SessionsSearchPayloadSchema, project_id: int, density: int, diff --git a/api/chalicelib/utils/helper.py b/api/chalicelib/utils/helper.py index ba89a8529..6710100ba 100644 --- a/api/chalicelib/utils/helper.py +++ b/api/chalicelib/utils/helper.py @@ -334,3 +334,21 @@ def cast_session_id_to_string(data): for key in keys: data[key] = cast_session_id_to_string(data[key]) return data + + +from typing import List + + +def complete_missing_steps(rows: List[dict], start_timestamp: int, end_timestamp: int, step: int, neutral: dict, + time_key: str = "timestamp") -> List[dict]: + result = [] + i = 0 + for t in range(start_timestamp, end_timestamp, step): + if i >= len(rows) or rows[i][time_key] > t: + neutral[time_key] = t + result.append(neutral.copy()) + elif i < len(rows) and rows[i][time_key] == t: + result.append(rows[i]) + i += 1 + + return result