fix(chalice): cards drilldown returns valid sessions

This commit is contained in:
Taha Yassine Kraiem 2025-05-26 16:56:37 +02:00 committed by Kraiem Taha Yassine
parent ce4f03f049
commit bb13cb1911
6 changed files with 78 additions and 13 deletions

View file

@ -172,7 +172,8 @@ def get_sessions_by_card_id(project: schemas.ProjectContext, user_id, metric_id,
results = []
for s in data.series:
results.append({"seriesId": s.series_id, "seriesName": s.name,
**sessions_search.search_sessions(data=s.filter, project=project, user_id=user_id)})
**sessions_search.search_sessions(data=s.filter, project=project, user_id=user_id,
metric_of=data.metric_of)})
return results
@ -187,7 +188,8 @@ def get_sessions(project: schemas.ProjectContext, user_id, data: schemas.CardSes
s.filter = schemas.SessionsSearchPayloadSchema(**s.filter.model_dump(by_alias=True))
results.append({"seriesId": None, "seriesName": s.name,
**sessions_search.search_sessions(data=s.filter, project=project, user_id=user_id)})
**sessions_search.search_sessions(data=s.filter, project=project, user_id=user_id,
metric_of=data.metric_of)})
return results

View file

@ -150,7 +150,7 @@ def search2_table(data: schemas.SessionsSearchPayloadSchema, project_id: int, de
for e in data.events:
if e.type == schemas.EventType.LOCATION:
if e.operator not in extra_conditions:
extra_conditions[e.operator] = schemas.SessionSearchEventSchema.model_validate({
extra_conditions[e.operator] = schemas.SessionSearchEventSchema(**{
"type": e.type,
"isEvent": True,
"value": [],
@ -175,7 +175,7 @@ def search2_table(data: schemas.SessionsSearchPayloadSchema, project_id: int, de
for e in data.events:
if e.type == schemas.EventType.REQUEST_DETAILS:
if e.operator not in extra_conditions:
extra_conditions[e.operator] = schemas.SessionSearchEventSchema.model_validate({
extra_conditions[e.operator] = schemas.SessionSearchEventSchema(**{
"type": e.type,
"isEvent": True,
"value": [],

View file

@ -64,8 +64,7 @@ def __parse_metadata(metadata_map):
# This function executes the query and return result
def search_sessions(data: schemas.SessionsSearchPayloadSchema, project: schemas.ProjectContext,
user_id, errors_only=False, error_status=schemas.ErrorStatus.ALL,
count_only=False, issue=None, ids_only=False):
platform = project.platform
count_only=False, issue=None, ids_only=False, metric_of: schemas.MetricOfTable = None):
if data.bookmarked:
data.startTimestamp, data.endTimestamp = sessions_favorite.get_start_end_timestamp(project.project_id, user_id)
if data.startTimestamp is None:
@ -75,18 +74,78 @@ def search_sessions(data: schemas.SessionsSearchPayloadSchema, project: schemas.
'sessions': [],
'_src': 2
}
# ---------------------- extra filter in order to only select sessions that has been used in the card-table
extra_event = None
# extra_deduplication = []
extra_conditions = None
if metric_of == schemas.MetricOfTable.VISITED_URL:
extra_event = f"""SELECT DISTINCT ev.session_id,
JSONExtractString(toString(ev.`$properties`), 'url_path') AS url_path
FROM {exp_ch_helper.get_main_events_table(data.startTimestamp)} AS ev
WHERE ev.created_at >= toDateTime(%(startDate)s / 1000)
AND ev.created_at <= toDateTime(%(endDate)s / 1000)
AND ev.project_id = %(project_id)s
AND ev.`$event_name` = 'LOCATION'"""
# extra_deduplication.append("url_path")
extra_conditions = {}
for e in data.events:
if e.type == schemas.EventType.LOCATION:
if e.operator not in extra_conditions:
extra_conditions[e.operator] = schemas.SessionSearchEventSchema(**{
"type": e.type,
"isEvent": True,
"value": [],
"operator": e.operator,
"filters": e.filters
})
for v in e.value:
if v not in extra_conditions[e.operator].value:
extra_conditions[e.operator].value.append(v)
extra_conditions = list(extra_conditions.values())
elif metric_of == schemas.MetricOfTable.FETCH:
extra_event = f"""SELECT DISTINCT ev.session_id
FROM {exp_ch_helper.get_main_events_table(data.startTimestamp)} AS ev
WHERE ev.created_at >= toDateTime(%(startDate)s / 1000)
AND ev.created_at <= toDateTime(%(endDate)s / 1000)
AND ev.project_id = %(project_id)s
AND ev.`$event_name` = 'REQUEST'"""
# extra_deduplication.append("url_path")
extra_conditions = {}
for e in data.events:
if e.type == schemas.EventType.REQUEST_DETAILS:
if e.operator not in extra_conditions:
extra_conditions[e.operator] = schemas.SessionSearchEventSchema(**{
"type": e.type,
"isEvent": True,
"value": [],
"operator": e.operator,
"filters": e.filters
})
for v in e.value:
if v not in extra_conditions[e.operator].value:
extra_conditions[e.operator].value.append(v)
extra_conditions = list(extra_conditions.values())
# elif metric_of == schemas.MetricOfTable.ISSUES and len(metric_value) > 0:
# data.filters.append(schemas.SessionSearchFilterSchema(value=metric_value, type=schemas.FilterType.ISSUE,
# operator=schemas.SearchEventOperator.IS))
# ----------------------
if project.platform == "web":
full_args, query_part = sessions.search_query_parts_ch(data=data, error_status=error_status,
errors_only=errors_only,
favorite_only=data.bookmarked, issue=issue,
project_id=project.project_id,
user_id=user_id, platform=platform)
user_id=user_id, platform=project.platform,
extra_event=extra_event,
# extra_deduplication=extra_deduplication,
extra_conditions=extra_conditions)
else:
full_args, query_part = sessions_legacy_mobil.search_query_parts_ch(data=data, error_status=error_status,
errors_only=errors_only,
favorite_only=data.bookmarked, issue=issue,
project_id=project.project_id,
user_id=user_id, platform=platform)
user_id=user_id, platform=project.platform)
if data.sort == "startTs":
data.sort = "datetime"
if data.limit is not None and data.page is not None:

View file

@ -40,7 +40,7 @@ COALESCE((SELECT TRUE
# This function executes the query and return result
def search_sessions(data: schemas.SessionsSearchPayloadSchema, project: schemas.ProjectContext,
user_id, errors_only=False, error_status=schemas.ErrorStatus.ALL,
count_only=False, issue=None, ids_only=False):
count_only=False, issue=None, ids_only=False, metric_of: schemas.MetricOfTable = None):
platform = project.platform
if data.bookmarked:
data.startTimestamp, data.endTimestamp = sessions_favorite.get_start_end_timestamp(project.project_id, user_id)

View file

@ -22,7 +22,8 @@ class BaseModel(_BaseModel):
model_config = ConfigDict(alias_generator=attribute_to_camel_case,
use_enum_values=True,
json_schema_extra=schema_extra,
extra='forbid')
# extra='forbid'
)
class Enum(_Enum):

View file

@ -1043,11 +1043,16 @@ class MetricOfPathAnalysis(str, Enum):
session_count = MetricOfTimeseries.SESSION_COUNT.value
# class CardSessionsSchema(SessionsSearchPayloadSchema):
class CardSessionsSchema(_TimedSchema, _PaginatedSchema):
startTimestamp: int = Field(default=TimeUTC.now(-7))
endTimestamp: int = Field(default=TimeUTC.now())
density: int = Field(default=7, ge=1, le=200)
# we need metric_type&metric_of in the payload of sessions search
# because the API will retrun all sessions if the card is not identified
# example: table of requests contains only sessions that have a request,
# but drill-down doesn't take that into consideration
metric_type: MetricType = Field(...)
metric_of: Any
series: List[CardSeriesSchema] = Field(default_factory=list)
# events: List[SessionSearchEventSchema2] = Field(default_factory=list, doc_hidden=True)
@ -1125,8 +1130,6 @@ class __CardSchema(CardSessionsSchema):
thumbnail: Optional[str] = Field(default=None)
metric_format: Optional[MetricFormatType] = Field(default=None)
view_type: Any
metric_type: MetricType = Field(...)
metric_of: Any
metric_value: List[IssueType] = Field(default_factory=list)
# This is used to save the selected session for heatmaps
session_id: Optional[int] = Field(default=None)