mirror of
https://github.com/PostHog/posthog.git
synced 2024-11-28 18:26:15 +01:00
2550fb26c6
* test(funnel-people): add tests for converted/dropped people urls As per https://github.com/PostHog/posthog/issues/6935 we are adding urls to responses to attempt to improve consistency between insight responses and the people we display in the UI. This simply adds tests for these urls, just for funnel step response shape. The other two types of response will be handled separately. * feat(funnel-people): return converted/dropped people url in funnel Here I have simply added converted / dropped urls in the base funnel. This touches both clickhouse and postgres functionality, so I will probably add in tests for postgres also, or just disable to postgres. It doesn't pass yet as there is an issue in that the order appears to be ignored by the people endpoint. * fix(funnels): actually use strict/unordered persons querying Previously we were always using the standard `ClickhouseFunnelPersons` class for retrieving people from the `/api/persons/funnel/` endpoint. This change selects from the unordered and strict variants based on the `funnel_order_type` setting. Refers to https://github.com/PostHog/posthog/issues/7058 although there is a frontend component to add that will truely resolve the issue. * feat(funnel-people): add people urls for funnels with breakdown In this I have also removed any changes from the non-clickhouse code. Note that there are two places I've added the url generation code, one in the `ClickhouseFunnelBase` and another in the `ClickhouseFunnel` I think the former covers the unordered and strict cases, and the later for the breakdown case. I think there are further test that I'll need to add to validate e.g. if breakdown + strict work as expected. * Fix people urls for unordered funnels + breakdown * test: add test for strict breakdown with people urls * make funnel response assertions not check people url equality * fix typing * fix tests * remove new line in postgres funnel.py * clear cache on insight test start * no really, clear the cache * remove flakiness from strict funnel test * correct the unordered test * use absolute uris * use step.index not step.order * remove out of date comment * use step.index, not step.order * use step.index, remove unordered funnels comment * use journeys_for instead of create_events
150 lines
5.9 KiB
Python
150 lines
5.9 KiB
Python
import json
|
||
from typing import Any, Dict, Type
|
||
|
||
from rest_framework.decorators import action
|
||
from rest_framework.request import Request
|
||
from rest_framework.response import Response
|
||
|
||
from ee.clickhouse.queries import ClickhousePaths
|
||
from ee.clickhouse.queries.clickhouse_retention import ClickhouseRetention
|
||
from ee.clickhouse.queries.clickhouse_stickiness import ClickhouseStickiness
|
||
from ee.clickhouse.queries.funnels import (
|
||
ClickhouseFunnel,
|
||
ClickhouseFunnelBase,
|
||
ClickhouseFunnelStrict,
|
||
ClickhouseFunnelTimeToConvert,
|
||
ClickhouseFunnelTrends,
|
||
ClickhouseFunnelUnordered,
|
||
)
|
||
from ee.clickhouse.queries.funnels.funnel_correlation import FunnelCorrelation
|
||
from ee.clickhouse.queries.sessions.clickhouse_sessions import ClickhouseSessions
|
||
from ee.clickhouse.queries.trends.clickhouse_trends import ClickhouseTrends
|
||
from ee.clickhouse.queries.util import get_earliest_timestamp
|
||
from posthog.api.insight import InsightViewSet
|
||
from posthog.constants import (
|
||
INSIGHT_FUNNELS,
|
||
INSIGHT_PATHS,
|
||
INSIGHT_SESSIONS,
|
||
INSIGHT_STICKINESS,
|
||
PATHS_INCLUDE_EVENT_TYPES,
|
||
TRENDS_STICKINESS,
|
||
FunnelOrderType,
|
||
FunnelVizType,
|
||
)
|
||
from posthog.decorators import cached_function
|
||
from posthog.models.filters import Filter
|
||
from posthog.models.filters.path_filter import PathFilter
|
||
from posthog.models.filters.retention_filter import RetentionFilter
|
||
from posthog.models.filters.sessions_filter import SessionsFilter
|
||
from posthog.models.filters.stickiness_filter import StickinessFilter
|
||
|
||
|
||
class ClickhouseInsightsViewSet(InsightViewSet):
|
||
@cached_function
|
||
def calculate_trends(self, request: Request) -> Dict[str, Any]:
|
||
team = self.team
|
||
filter = Filter(request=request, team=self.team)
|
||
|
||
if filter.insight == INSIGHT_STICKINESS or filter.shown_as == TRENDS_STICKINESS:
|
||
stickiness_filter = StickinessFilter(
|
||
request=request, team=team, get_earliest_timestamp=get_earliest_timestamp
|
||
)
|
||
result = ClickhouseStickiness().run(stickiness_filter, team)
|
||
else:
|
||
trends_query = ClickhouseTrends()
|
||
result = trends_query.run(filter, team)
|
||
|
||
self._refresh_dashboard(request=request)
|
||
return {"result": result}
|
||
|
||
@cached_function
|
||
def calculate_session(self, request: Request) -> Dict[str, Any]:
|
||
return {
|
||
"result": ClickhouseSessions().run(
|
||
team=self.team,
|
||
filter=SessionsFilter(request=request, data={"insight": INSIGHT_SESSIONS}, team=self.team),
|
||
)
|
||
}
|
||
|
||
@cached_function
|
||
def calculate_path(self, request: Request) -> Dict[str, Any]:
|
||
team = self.team
|
||
filter = PathFilter(request=request, data={"insight": INSIGHT_PATHS}, team=self.team)
|
||
|
||
funnel_filter = None
|
||
funnel_filter_data = request.GET.get("funnel_filter") or request.data.get("funnel_filter")
|
||
if funnel_filter_data:
|
||
if isinstance(funnel_filter_data, str):
|
||
funnel_filter_data = json.loads(funnel_filter_data)
|
||
funnel_filter = Filter(data={"insight": INSIGHT_FUNNELS, **funnel_filter_data}, team=self.team)
|
||
|
||
# backwards compatibility
|
||
if filter.path_type:
|
||
filter = filter.with_data({PATHS_INCLUDE_EVENT_TYPES: [filter.path_type]})
|
||
resp = ClickhousePaths(filter=filter, team=team, funnel_filter=funnel_filter).run()
|
||
|
||
return {"result": resp}
|
||
|
||
@cached_function
|
||
def calculate_funnel(self, request: Request) -> Dict[str, Any]:
|
||
team = self.team
|
||
filter = Filter(request=request, data={"insight": INSIGHT_FUNNELS}, team=self.team)
|
||
|
||
funnel_order_class: Type[ClickhouseFunnelBase] = ClickhouseFunnel
|
||
if filter.funnel_order_type == FunnelOrderType.UNORDERED:
|
||
funnel_order_class = ClickhouseFunnelUnordered
|
||
elif filter.funnel_order_type == FunnelOrderType.STRICT:
|
||
funnel_order_class = ClickhouseFunnelStrict
|
||
|
||
if filter.funnel_viz_type == FunnelVizType.TRENDS:
|
||
return {
|
||
"result": ClickhouseFunnelTrends(team=team, filter=filter, funnel_order_class=funnel_order_class).run()
|
||
}
|
||
elif filter.funnel_viz_type == FunnelVizType.TIME_TO_CONVERT:
|
||
return {
|
||
"result": ClickhouseFunnelTimeToConvert(
|
||
team=team, filter=filter, funnel_order_class=funnel_order_class
|
||
).run()
|
||
}
|
||
else:
|
||
base_uri = request.build_absolute_uri("/")
|
||
return {"result": funnel_order_class(team=team, filter=filter, base_uri=base_uri).run()}
|
||
|
||
# ******************************************
|
||
# /projects/:id/insights/funnel/correlation
|
||
#
|
||
# params:
|
||
# - params are the same as for funnel
|
||
#
|
||
# Returns significant events, i.e. those that are correlated with a person
|
||
# making it through a funnel
|
||
# ******************************************
|
||
@action(methods=["GET", "POST"], url_path="funnel/correlation", detail=False)
|
||
def funnel_correlation(self, request: Request, *args: Any, **kwargs: Any) -> Response:
|
||
result = self.calculate_funnel_correlation(request)
|
||
return Response(result)
|
||
|
||
@cached_function
|
||
def calculate_funnel_correlation(self, request: Request) -> Dict[str, Any]:
|
||
team = self.team
|
||
filter = Filter(request=request)
|
||
|
||
base_uri = request.build_absolute_uri("/")
|
||
result = FunnelCorrelation(filter=filter, team=team, base_uri=base_uri).run()
|
||
|
||
return {"result": result}
|
||
|
||
@cached_function
|
||
def calculate_retention(self, request: Request) -> Dict[str, Any]:
|
||
team = self.team
|
||
data = {}
|
||
if not request.GET.get("date_from"):
|
||
data.update({"date_from": "-11d"})
|
||
filter = RetentionFilter(data=data, request=request, team=self.team)
|
||
result = ClickhouseRetention().run(filter, team)
|
||
return {"result": result}
|
||
|
||
|
||
class LegacyClickhouseInsightsViewSet(ClickhouseInsightsViewSet):
|
||
legacy_team_compatibility = True
|