diff --git a/api/chalicelib/core/sessions_replay.py b/api/chalicelib/core/sessions_replay.py index 48c02f8620..d31d468628 100644 --- a/api/chalicelib/core/sessions_replay.py +++ b/api/chalicelib/core/sessions_replay.py @@ -5,6 +5,10 @@ from chalicelib.utils import pg_client, helper +def __is_mobile_session(platform): + return platform in ('ios', 'android') + + def __group_metadata(session, project_metadata): meta = {} for m in project_metadata.keys(): @@ -47,7 +51,7 @@ def get_by_id2_pg(project_id, session_id, context: schemas.CurrentContext, full_ if data is not None: data = helper.dict_to_camel_case(data) if full_data: - if data["platform"] == 'ios' or data["platform"] == 'android': + if __is_mobile_session(data["platform"]): data['events'] = events_mobile.get_by_sessionId(project_id=project_id, session_id=session_id) for e in data['events']: if e["type"].endswith("_IOS"): @@ -56,7 +60,7 @@ def get_by_id2_pg(project_id, session_id, context: schemas.CurrentContext, full_ e["type"] = e["type"][:-len("_MOBILE")] data['crashes'] = events_mobile.get_crashes_by_session_id(session_id=session_id) data['userEvents'] = events_mobile.get_customs_by_session_id(project_id=project_id, - session_id=session_id) + session_id=session_id) data['mobsUrl'] = [] else: data['events'] = events.get_by_session_id(project_id=project_id, session_id=session_id, @@ -128,10 +132,10 @@ def get_replay(project_id, session_id, context: schemas.CurrentContext, full_dat if data is not None: data = helper.dict_to_camel_case(data) if full_data: - if data["platform"] == 'ios' or data["platform"] == 'android': + if __is_mobile_session(data["platform"]): data['mobsUrl'] = [] data['videoURL'] = sessions_mobs.get_mobile_videos(session_id=session_id, project_id=project_id, - check_existence=False) + check_existence=False) else: data['mobsUrl'] = sessions_mobs.get_urls_depercated(session_id=session_id, check_existence=False) data['devtoolsURL'] = sessions_devtool.get_urls(session_id=session_id, project_id=project_id, @@ -172,7 +176,7 @@ def get_events(project_id, session_id): if s_data is not None: s_data = helper.dict_to_camel_case(s_data) data = {} - if s_data["platform"] == 'ios' or s_data["platform"] == 'android': + if __is_mobile_session(s_data["platform"]): data['events'] = events_mobile.get_by_sessionId(project_id=project_id, session_id=session_id) for e in data['events']: if e["type"].endswith("_IOS"): @@ -181,7 +185,7 @@ def get_events(project_id, session_id): e["type"] = e["type"][:-len("_MOBILE")] data['crashes'] = events_mobile.get_crashes_by_session_id(session_id=session_id) data['userEvents'] = events_mobile.get_customs_by_session_id(project_id=project_id, - session_id=session_id) + session_id=session_id) data['userTesting'] = [] else: data['events'] = events.get_by_session_id(project_id=project_id, session_id=session_id, diff --git a/ee/api/.gitignore b/ee/api/.gitignore index 9fd6db379d..b5b8dc4141 100644 --- a/ee/api/.gitignore +++ b/ee/api/.gitignore @@ -198,7 +198,7 @@ Pipfile.lock /chalicelib/core/custom_metrics_predefined.py /chalicelib/core/dashboards.py /chalicelib/core/errors_favorite.py -/chalicelib/core/events_ios.py +/chalicelib/core/events_mobile.py /chalicelib/core/feature_flags.py /chalicelib/core/funnels.py /chalicelib/core/heatmaps.py diff --git a/ee/api/chalicelib/core/sessions_replay.py b/ee/api/chalicelib/core/sessions_replay.py index ff8a3b0eee..8aa0138b36 100644 --- a/ee/api/chalicelib/core/sessions_replay.py +++ b/ee/api/chalicelib/core/sessions_replay.py @@ -5,6 +5,10 @@ from chalicelib.utils import pg_client, helper +def __is_mobile_session(platform): + return platform in ('ios', 'android') + + def __group_metadata(session, project_metadata): meta = {} for m in project_metadata.keys(): @@ -14,6 +18,7 @@ def __group_metadata(session, project_metadata): return meta +# for EE # for backward compatibility # This function should not use Clickhouse because it doesn't have `file_key` def get_by_id2_pg(project_id, session_id, context: schemas.CurrentContext, full_data=False, @@ -43,22 +48,22 @@ def get_by_id2_pg(project_id, session_id, context: schemas.CurrentContext, full_ AND s.session_id = %(session_id)s;""", {"project_id": project_id, "session_id": session_id, "userId": context.user_id} ) - # print("===============") - # print(query) cur.execute(query=query) data = cur.fetchone() if data is not None: data = helper.dict_to_camel_case(data) if full_data: - if data["platform"] in ('ios', 'android'): + if __is_mobile_session(data["platform"]): data['events'] = events_mobile.get_by_sessionId(project_id=project_id, session_id=session_id) for e in data['events']: if e["type"].endswith("_IOS"): e["type"] = e["type"][:-len("_IOS")] + elif e["type"].endswith("_MOBILE"): + e["type"] = e["type"][:-len("_MOBILE")] data['crashes'] = events_mobile.get_crashes_by_session_id(session_id=session_id) - data['userEvents'] = events_mobile.get_customs_by_sessionId(project_id=project_id, - session_id=session_id) + data['userEvents'] = events_mobile.get_customs_by_session_id(project_id=project_id, + session_id=session_id) data['mobsUrl'] = [] else: data['events'] = events.get_by_session_id(project_id=project_id, session_id=session_id, @@ -74,6 +79,8 @@ def get_by_id2_pg(project_id, session_id, context: schemas.CurrentContext, full_ data['domURL'] = sessions_mobs.get_urls(session_id=session_id, project_id=project_id, check_existence=False) data['mobsUrl'] = sessions_mobs.get_urls_depercated(session_id=session_id, check_existence=False) + # for EE + # context is required to check if the use have the right to access devtools data['devtoolsURL'] = sessions_devtool.get_urls(session_id=session_id, project_id=project_id, context=context, check_existence=False) data['resources'] = resources.get_by_session_id(session_id=session_id, project_id=project_id, @@ -93,6 +100,11 @@ def get_by_id2_pg(project_id, session_id, context: schemas.CurrentContext, full_ return None +def get_pre_replay(project_id, session_id, context: schemas.CurrentContext): + return { + 'domURL': [sessions_mobs.get_first_url(project_id=project_id, session_id=session_id, check_existence=False)]} + + # This function should not use Clickhouse because it doesn't have `file_key` def get_replay(project_id, session_id, context: schemas.CurrentContext, full_data=False, include_fav_viewed=False, group_metadata=False, live=True): @@ -121,20 +133,20 @@ def get_replay(project_id, session_id, context: schemas.CurrentContext, full_dat AND s.session_id = %(session_id)s;""", {"project_id": project_id, "session_id": session_id, "userId": context.user_id} ) - # print("===============") - # print(query) cur.execute(query=query) data = cur.fetchone() if data is not None: data = helper.dict_to_camel_case(data) if full_data: - if data["platform"] == 'ios': + if __is_mobile_session(data["platform"]): data['mobsUrl'] = [] - data['videoURL'] = sessions_mobs.get_ios_videos(session_id=session_id, project_id=project_id, - check_existence=False) + data['videoURL'] = sessions_mobs.get_mobile_videos(session_id=session_id, project_id=project_id, + check_existence=False) else: data['mobsUrl'] = sessions_mobs.get_urls_depercated(session_id=session_id, check_existence=False) + # for EE + # context is required to check if the use have the right to access devtools data['devtoolsURL'] = sessions_devtool.get_urls(session_id=session_id, project_id=project_id, context=context, check_existence=False) data['canvasURL'] = canvas.get_canvas_presigned_urls(session_id=session_id, project_id=project_id) @@ -167,22 +179,23 @@ def get_events(project_id, session_id): AND s.session_id = %(session_id)s;""", {"project_id": project_id, "session_id": session_id} ) - # print("===============") - # print(query) cur.execute(query=query) s_data = cur.fetchone() if s_data is not None: s_data = helper.dict_to_camel_case(s_data) data = {} - if s_data["platform"] == 'ios': + if __is_mobile_session(s_data["platform"]): data['events'] = events_mobile.get_by_sessionId(project_id=project_id, session_id=session_id) for e in data['events']: if e["type"].endswith("_IOS"): e["type"] = e["type"][:-len("_IOS")] + elif e["type"].endswith("_MOBILE"): + e["type"] = e["type"][:-len("_MOBILE")] data['crashes'] = events_mobile.get_crashes_by_session_id(session_id=session_id) data['userEvents'] = events_mobile.get_customs_by_session_id(project_id=project_id, - session_id=session_id) + session_id=session_id) + data['userTesting'] = [] else: data['events'] = events.get_by_session_id(project_id=project_id, session_id=session_id, group_clickrage=True) @@ -196,6 +209,7 @@ def get_events(project_id, session_id): session_id=session_id) data['resources'] = resources.get_by_session_id(session_id=session_id, project_id=project_id, start_ts=s_data["startTs"], duration=s_data["duration"]) + data['userTesting'] = user_testing.get_test_signals(session_id=session_id, project_id=project_id) data['issues'] = issues.get_by_session_id(session_id=session_id, project_id=project_id) data['issues'] = reduce_issues(data['issues']) diff --git a/ee/api/clean-dev.sh b/ee/api/clean-dev.sh index f4da5ecd2a..0497187019 100755 --- a/ee/api/clean-dev.sh +++ b/ee/api/clean-dev.sh @@ -19,7 +19,7 @@ rm -rf ./chalicelib/core/countries.py rm -rf ./chalicelib/core/custom_metrics_predefined.py rm -rf ./chalicelib/core/dashboards.py rm -rf ./chalicelib/core/errors_favorite.py -rm -rf ./chalicelib/core/events_ios.py +rm -rf ./chalicelib/core/events_mobile.py rm -rf ./chalicelib/core/feature_flags.py rm -rf ./chalicelib/core/funnels.py rm -rf ./chalicelib/core/heatmaps.py diff --git a/ee/api/routers/core_dynamic.py b/ee/api/routers/core_dynamic.py index c4ce05da7b..234e99996b 100644 --- a/ee/api/routers/core_dynamic.py +++ b/ee/api/routers/core_dynamic.py @@ -272,6 +272,22 @@ def session_ids_search(projectId: int, data: schemas.SessionsSearchPayloadSchema return {'data': data} +@app.get('/{projectId}/sessions/{sessionId}/first-mob', tags=["sessions", "replay"], + dependencies=[OR_scope(Permissions.session_replay, ServicePermissions.session_replay)]) +def get_first_mob_file(projectId: int, sessionId: Union[int, str], background_tasks: BackgroundTasks, + context: schemas.CurrentContext = Depends(OR_context)): + if not sessionId.isnumeric(): + return {"errors": ["session not found"]} + else: + sessionId = int(sessionId) + data = sessions_replay.get_pre_replay(project_id=projectId, session_id=sessionId, context=context) + if data is None: + return {"errors": ["session not found"]} + return { + 'data': data + } + + @app.get('/{projectId}/sessions/{sessionId}/replay', tags=["sessions", "replay"], dependencies=[OR_scope(Permissions.session_replay, ServicePermissions.session_replay)]) def get_session_events(projectId: int, sessionId: Union[int, str], background_tasks: BackgroundTasks,