def test_return_cached_results_dashboard_has_filters(self): # Regression test, we were dashboard = Dashboard.objects.create(team=self.team, name="dashboard") filter_dict = { "events": [{"id": "$pageview"}], "properties": [{"key": "$browser", "value": "Mac OS X"}], "date_from": "-7d", } filter = Filter(data=filter_dict) item = Insight.objects.create(dashboard=dashboard, filters=filter_dict, team=self.team,) Insight.objects.create( dashboard=dashboard, filters=filter.to_dict(), team=self.team, ) self.client.get( f"/api/projects/{self.team.id}/insights/trend/?events=%s&properties=%s&date_from=-7d" % (json.dumps(filter_dict["events"]), json.dumps(filter_dict["properties"])) ) patch_response = self.client.patch( f"/api/projects/{self.team.id}/dashboards/%s/" % dashboard.pk, {"filters": {"date_from": "-24h"}}, format="json", ).json() self.assertEqual(patch_response["items"][0]["result"], None) # cache results response = self.client.get( f"/api/projects/{self.team.id}/insights/trend/?events=%s&properties=%s&date_from=-24h" % (json.dumps(filter_dict["events"]), json.dumps(filter_dict["properties"])) ) self.assertEqual(response.status_code, 200) item = Insight.objects.get(pk=item.pk) # Expecting this to only have one day as per the dashboard filter response = self.client.get(f"/api/projects/{self.team.id}/dashboards/%s/" % dashboard.pk).json() self.assertEqual(len(response["items"][0]["result"][0]["days"]), 2) # type: ignore
def _calculate_funnel(filter: Filter, team_id: int) -> List[Dict[str, Any]]: dashboard_items = DashboardItem.objects.filter(team_id=team_id, filters=filter.to_dict()) dashboard_items.update(refreshing=True) result = Funnel(filter=filter, team=Team(pk=team_id)).run() dashboard_items.update(last_refresh=timezone.now(), refreshing=False) return result
def test_return_cached_results(self): dashboard = Dashboard.objects.create(team=self.team, name="dashboard") filter_dict = { "events": [{"id": "$pageview"}], "properties": [{"key": "$browser", "value": "Mac OS X"}], } filter = Filter(data=filter_dict) item = Insight.objects.create(dashboard=dashboard, filters=filter_dict, team=self.team,) Insight.objects.create( dashboard=dashboard, filters=filter.to_dict(), team=self.team, ) response = self.client.get(f"/api/projects/{self.team.id}/dashboards/%s/" % dashboard.pk).json() self.assertEqual(response["items"][0]["result"], None) # cache results response = self.client.get( f"/api/projects/{self.team.id}/insights/trend/?events=%s&properties=%s" % (json.dumps(filter_dict["events"]), json.dumps(filter_dict["properties"])) ) self.assertEqual(response.status_code, 200) item = Insight.objects.get(pk=item.pk) self.assertAlmostEqual(item.last_refresh, now(), delta=timezone.timedelta(seconds=5)) self.assertEqual(item.filters_hash, generate_cache_key(f"{filter.toJSON()}_{self.team.pk}")) with self.assertNumQueries(13): # Django session, PostHog user, PostHog team, PostHog org membership, PostHog dashboard, # PostHog dashboard item, PostHog team, PostHog dashboard item UPDATE, PostHog team, # PostHog dashboard item UPDATE, PostHog dashboard UPDATE, PostHog dashboard item, Posthog org tags response = self.client.get(f"/api/projects/{self.team.id}/dashboards/%s/" % dashboard.pk).json() self.assertAlmostEqual(Dashboard.objects.get().last_accessed_at, now(), delta=timezone.timedelta(seconds=5)) self.assertEqual(response["items"][0]["result"][0]["count"], 0)
def test_return_cached_results(self): dashboard = Dashboard.objects.create(team=self.team, name="dashboard") filter_dict = { "events": [{"id": "$pageview"}], "properties": [{"key": "$browser", "value": "Mac OS X"}], } filter = Filter(data=filter_dict) item = DashboardItem.objects.create(dashboard=dashboard, filters=filter_dict, team=self.team,) DashboardItem.objects.create( dashboard=dashboard, filters=filter.to_dict(), team=self.team, ) response = self.client.get("/api/dashboard/%s/" % dashboard.pk).json() self.assertEqual(response["items"][0]["result"], None) # cache results response = self.client.get( "/api/insight/trend/?events=%s&properties=%s" % (json.dumps(filter_dict["events"]), json.dumps(filter_dict["properties"])) ) self.assertEqual(response.status_code, 200) item = DashboardItem.objects.get(pk=item.pk) self.assertAlmostEqual(item.last_refresh, now(), delta=timezone.timedelta(seconds=5)) self.assertEqual(item.filters_hash, generate_cache_key("{}_{}".format(filter.toJSON(), self.team.pk))) with self.assertNumQueries(11): response = self.client.get("/api/dashboard/%s/" % dashboard.pk).json() self.assertAlmostEqual(Dashboard.objects.get().last_accessed_at, now(), delta=timezone.timedelta(seconds=5)) self.assertEqual(response["items"][0]["result"][0]["count"], 0)
def test_refresh_dashboard_cache(self, patch_update_cache_item: MagicMock, patch_apply_async: MagicMock) -> None: # There's two things we want to refresh # Any shared dashboard, as we only use cached items to show those # Any dashboard accessed in the last 7 days filter_dict = { "events": [{"id": "$pageview"}], "properties": [{"key": "$browser", "value": "Mac OS X"}], } filter = Filter(data=filter_dict) shared_dashboard = Dashboard.objects.create(team=self.team, is_shared=True) funnel_filter = Filter(data={"events": [{"id": "user signed up", "type": "events", "order": 0},],}) item = DashboardItem.objects.create(dashboard=shared_dashboard, filters=filter.to_dict(), team=self.team) funnel_item = DashboardItem.objects.create( dashboard=shared_dashboard, filters=funnel_filter.to_dict(), team=self.team ) dashboard_to_cache = Dashboard.objects.create(team=self.team, is_shared=True, last_accessed_at=now()) item_to_cache = DashboardItem.objects.create( dashboard=dashboard_to_cache, filters=Filter(data={"events": [{"id": "cache this"}]}).to_dict(), team=self.team, ) dashboard_do_not_cache = Dashboard.objects.create( team=self.team, is_shared=True, last_accessed_at="2020-01-01T12:00:00Z" ) item_do_not_cache = DashboardItem.objects.create( dashboard=dashboard_do_not_cache, filters=Filter(data={"events": [{"id": "do not cache this"}]}).to_dict(), team=self.team, ) item_key = generate_cache_key(filter.toJSON() + "_" + str(self.team.pk)) funnel_key = generate_cache_key(filter.toJSON() + "_" + str(self.team.pk)) update_cached_items() # pass the caught calls straight to the function # we do this to skip Redis for call_item in patch_update_cache_item.call_args_list: update_cache_item(*call_item[0]) self.assertIsNotNone(DashboardItem.objects.get(pk=item.pk).last_refresh) self.assertIsNotNone(DashboardItem.objects.get(pk=item_to_cache.pk).last_refresh) self.assertIsNotNone(DashboardItem.objects.get(pk=item_do_not_cache.pk).last_refresh) self.assertEqual(get_safe_cache(item_key)["result"][0]["count"], 0) self.assertEqual(get_safe_cache(funnel_key)["result"][0]["count"], 0)
def _calculate_trends(filter: Filter, team_id: int) -> List[Dict[str, Any]]: actions = Action.objects.filter(team_id=team_id) actions = actions.prefetch_related( Prefetch("steps", queryset=ActionStep.objects.order_by("id"))) dashboard_items = DashboardItem.objects.filter(team_id=team_id, filters=filter.to_dict()) dashboard_items.update(refreshing=True) result = Trends().run(filter, Team(pk=team_id)) dashboard_items.update(last_refresh=timezone.now(), refreshing=False) return result
def test_to_dict(self): filter = Filter( data={ "events": [{"id": "$pageview"}], "display": "ActionsLineGraph", "compare": True, "interval": "", "actions": [], "date_from": "2020-01-01T20:00:00Z", } ) self.assertCountEqual(list(filter.to_dict().keys()), ["events", "display", "compare", "insight", "date_from"])
def test_stickiness_regression(self, patch_update_cache_item: MagicMock, patch_apply_async: MagicMock) -> None: # We moved Stickiness from being a "shown_as" item to its own insight # This move caused issues hence a regression test filter_stickiness = StickinessFilter( data={ "events": [{"id": "$pageview"}], "properties": [{"key": "$browser", "value": "Mac OS X"}], "date_from": "2012-01-10", "date_to": "2012-01-15", "insight": INSIGHT_STICKINESS, "shown_as": "Stickiness", }, team=self.team, get_earliest_timestamp=Event.objects.earliest_timestamp, ) filter = Filter( data={ "events": [{"id": "$pageview"}], "properties": [{"key": "$browser", "value": "Mac OS X"}], "date_from": "2012-01-10", "date_to": "2012-01-15", } ) shared_dashboard = Dashboard.objects.create(team=self.team, is_shared=True) DashboardItem.objects.create(dashboard=shared_dashboard, filters=filter_stickiness.to_dict(), team=self.team) DashboardItem.objects.create(dashboard=shared_dashboard, filters=filter.to_dict(), team=self.team) item_stickiness_key = generate_cache_key(filter_stickiness.toJSON() + "_" + str(self.team.pk)) item_key = generate_cache_key(filter.toJSON() + "_" + str(self.team.pk)) update_cached_items() for call_item in patch_update_cache_item.call_args_list: update_cache_item(*call_item[0]) self.assertEqual( get_safe_cache(item_stickiness_key)["result"][0]["labels"], ["1 day", "2 days", "3 days", "4 days", "5 days", "6 days"], ) self.assertEqual( get_safe_cache(item_key)["result"][0]["labels"], [ "Tue. 10 January", "Wed. 11 January", "Thu. 12 January", "Fri. 13 January", "Sat. 14 January", "Sun. 15 January", ], )
def create(self, validated_data: Dict, *args: Any, **kwargs: Any) -> DashboardItem: request = self.context["request"] team = request.user.team_set.get() validated_data.pop("last_refresh", None) # last_refresh sometimes gets sent if dashboard_item is duplicated if not validated_data.get("dashboard", None): dashboard_item = DashboardItem.objects.create(team=team, created_by=request.user, **validated_data) return dashboard_item elif validated_data["dashboard"].team == team: filter_data = validated_data.pop("filters", None) filters = Filter(data=filter_data) if filter_data else None dashboard_item = DashboardItem.objects.create( team=team, last_refresh=now(), filters=filters.to_dict() if filters else {}, **validated_data ) return dashboard_item else: raise serializers.ValidationError("Dashboard not found")