def test_people_arent_returned_multiple_times(self):

        people = journeys_for(
            {
                "user_1": [
                    {
                        "event": "user signed up",
                        "timestamp": datetime(2020, 1, 2, 14)
                    },
                    {
                        "event": "positively_related",
                        "timestamp": datetime(2020, 1, 3, 14)
                    },
                    # duplicate event
                    {
                        "event": "positively_related",
                        "timestamp": datetime(2020, 1, 3, 14)
                    },
                    {
                        "event": "paid",
                        "timestamp": datetime(2020, 1, 4, 14)
                    },
                ]
            },
            self.team,
        )

        filter = Filter(
            data={
                "events": [
                    {
                        "id": "user signed up",
                        "type": "events",
                        "order": 0
                    },
                    {
                        "id": "paid",
                        "type": "events",
                        "order": 1
                    },
                ],
                "insight":
                INSIGHT_FUNNELS,
                "date_from":
                "2020-01-01",
                "date_to":
                "2020-01-14",
                "funnel_correlation_type":
                "events",
                "funnel_correlation_person_entity": {
                    "id": "positively_related",
                    "type": "events"
                },
                "funnel_correlation_person_converted":
                "TrUe",
            })
        _, serialized_actors = FunnelCorrelationActors(filter,
                                                       self.team).get_actors()

        self.assertCountEqual([str(val["id"]) for val in serialized_actors],
                              [str(people["user_1"].uuid)])
Example #2
0
        def test_retention_period_weekly(self):
            Person.objects.create(
                team=self.team,
                distinct_ids=["person1", "alias1"],
                properties={"email": "*****@*****.**"},
            )
            Person.objects.create(
                team=self.team,
                distinct_ids=["person2"],
                properties={"email": "*****@*****.**"},
            )

            self._create_events([
                ("person1", self._date(0)),
                ("person2", self._date(0)),
                ("person1", self._date(1)),
                ("person2", self._date(1)),
                ("person1", self._date(7)),
                ("person2", self._date(7)),
                ("person1", self._date(14)),
                ("person1", self._date(month=1, day=-6)),
                ("person2", self._date(month=1, day=-6)),
                ("person2", self._date(month=1, day=1)),
                ("person1", self._date(month=1, day=1)),
                ("person2", self._date(month=1, day=15)),
            ])

            result = retention().run(
                Filter(data={
                    "date_to": self._date(10, month=1, hour=0),
                    "period": "Week"
                }),
                self.team,
                total_intervals=7,
            )

            self.assertEqual(
                self.pluck(result, "label"),
                [
                    "Week 0", "Week 1", "Week 2", "Week 3", "Week 4", "Week 5",
                    "Week 6"
                ],
            )

            self.assertEqual(
                self.pluck(result, "values", "count"),
                [
                    [2, 2, 1, 2, 2, 0, 1],
                    [2, 1, 2, 2, 0, 1],
                    [1, 1, 1, 0, 0],
                    [2, 2, 0, 1],
                    [2, 0, 1],
                    [0, 0],
                    [1],
                ],
            )

            self.assertEqual(
                self.pluck(result, "date"),
                [
                    datetime(2020, 6, 7, 0, tzinfo=pytz.UTC),
                    datetime(2020, 6, 14, 0, tzinfo=pytz.UTC),
                    datetime(2020, 6, 21, 0, tzinfo=pytz.UTC),
                    datetime(2020, 6, 28, 0, tzinfo=pytz.UTC),
                    datetime(2020, 7, 5, 0, tzinfo=pytz.UTC),
                    datetime(2020, 7, 12, 0, tzinfo=pytz.UTC),
                    datetime(2020, 7, 19, 0, tzinfo=pytz.UTC),
                ],
            )
Example #3
0
    def list(self, request):
        team = request.user.team_set.get()
        resp = []
        date_query = request_to_date_query(request.GET)
        event, path_type, event_filter, start_comparator = self._determine_path_type(request)
        properties = request.GET.get('properties')
        start_point = request.GET.get('start')

        sessions = Event.objects.add_person_id(team.pk).filter(
                team=team,
                **(event_filter),
                **date_query
            )\
            .filter(~Q(event__in=['$autocapture', '$pageview', '$identify', '$pageleave']) if event is None else Q())\
            .filter(Filter(data={'properties': json.loads(properties)}).properties_to_Q(team_id=team.pk) if properties else Q())\
            .annotate(previous_timestamp=Window(
                expression=Lag('timestamp', default=None),
                partition_by=F('distinct_id'),
                order_by=F('timestamp').asc()
            ))

        sessions_sql, sessions_sql_params = sessions.query.sql_with_params()

        if event == "$autocapture":
            sessions_sql = self._add_elements(query_string=sessions_sql)

        events_notated = '\
        SELECT *, CASE WHEN EXTRACT(\'EPOCH\' FROM (timestamp - previous_timestamp)) >= (60 * 30) OR previous_timestamp IS NULL THEN 1 ELSE 0 END AS new_session\
        FROM ({}) AS inner_sessions\
        '.format(sessions_sql)

        sessionified = '\
        SELECT events_notated.*, SUM(new_session) OVER (\
            ORDER BY distinct_id\
                    ,timestamp\
            ) AS session\
        FROM ({}) as events_notated\
        '.format(events_notated)

        if start_point:
            sessionified = self._apply_start_point(start_comparator=start_comparator, query_string=sessionified, start_point=start_point)

        final = '\
        SELECT {} as path_type, id, sessionified.session\
            ,ROW_NUMBER() OVER (\
                    PARTITION BY distinct_id\
                    ,session ORDER BY timestamp\
                    ) AS event_number\
        FROM ({}) as sessionified\
        '.format(path_type, sessionified)

        counts = '\
        SELECT event_number || \'_\' || path_type as target_event, id as target_id, LAG(event_number || \'_\' || path_type, 1) OVER (\
            PARTITION BY session\
            ) AS source_event , LAG(id, 1) OVER (\
            PARTITION BY session\
            ) AS source_id from \
        ({}) as final\
        where event_number <= 4\
        '.format(final)

        cursor = connection.cursor()
        cursor.execute('\
        SELECT source_event, target_event, MAX(target_id), MAX(source_id), count(*) from ({}) as counts\
        where source_event is not null and target_event is not null\
        group by source_event, target_event order by count desc limit 20\
        '.format(counts), sessions_sql_params)
        rows = cursor.fetchall()

        for row in rows:
            resp.append({
                'source': row[0],
                'target': row[1],
                'target_id': row[2],
                'source_id': row[3],
                'value': row[4]
            })

        
        resp = sorted(resp, key=lambda x: x['value'], reverse=True)
        return Response(resp)
Example #4
0
        def test_first_user_retention(self):
            person_factory(team_id=self.team.pk,
                           distinct_ids=["person1", "alias1"])
            person_factory(team_id=self.team.pk, distinct_ids=["person2"])
            person_factory(team_id=self.team.pk, distinct_ids=["person3"])
            person_factory(team_id=self.team.pk, distinct_ids=["person4"])
            person_factory(team_id=self.team.pk,
                           distinct_ids=["shouldnt_include"])

            self._create_events(
                [
                    ("shouldnt_include", self._date(-5)),
                    ("shouldnt_include", self._date(-1)),
                    ("person1", self._date(-1)),
                    ("person1", self._date(1)),
                    ("person1", self._date(2)),
                    ("person1", self._date(3)),
                    ("person2", self._date(-1)),
                ],
                "$user_signed_up",
            )

            self._create_events([
                ("person1", self._date(0)),
                ("person1", self._date(1)),
                ("person1", self._date(2)),
                ("person1", self._date(5)),
                ("alias1", self._date(5, 9)),
                ("person1", self._date(6)),
                ("person2", self._date(1)),
                ("person2", self._date(2)),
                ("person2", self._date(3)),
                ("person2", self._date(6)),
            ])

            self._create_events([("person3", self._date(0))],
                                "$user_signed_up")

            self._create_events([
                ("person3", self._date(1)),
                ("person3", self._date(3)),
                ("person3", self._date(4)),
                ("person3", self._date(5)),
            ])

            self._create_events([("person4", self._date(2))],
                                "$user_signed_up")

            self._create_events([
                ("person4", self._date(3)),
                ("person4", self._date(5)),
            ])

            target_entity = json.dumps({
                "id": "$user_signed_up",
                "type": TREND_FILTER_TYPE_EVENTS
            })
            result = retention().run(
                Filter(
                    data={
                        "date_to": self._date(5, hour=6),
                        RETENTION_TYPE: RETENTION_FIRST_TIME,
                        "target_entity": target_entity,
                        "events": [
                            {
                                "id": "$pageview",
                                "type": "events"
                            },
                        ],
                    }),
                self.team,
                total_intervals=7,
            )

            self.assertEqual(len(result), 7)
            self.assertEqual(
                self.pluck(result, "label"),
                [
                    "Day 0", "Day 1", "Day 2", "Day 3", "Day 4", "Day 5",
                    "Day 6"
                ],
            )

            self.assertEqual(
                self.pluck(result, "values", "count"),
                [[2, 1, 2, 2, 1, 0, 1], [1, 1, 0, 1, 1, 1], [0, 0, 0, 0, 0],
                 [1, 1, 0, 1], [0, 0, 0], [0, 0], [0]],
            )
Example #5
0
        def test_retention_with_user_properties(self):
            person1 = person_factory(
                team_id=self.team.pk,
                distinct_ids=["person1", "alias1"],
                properties={"email": "*****@*****.**"},
            )
            person2 = person_factory(
                team_id=self.team.pk,
                distinct_ids=["person2"],
                properties={"email": "*****@*****.**"},
            )

            self._create_events([
                ("person1", self._date(0)),
                ("person1", self._date(1)),
                ("person1", self._date(2)),
                ("person1", self._date(5)),
                ("alias1", self._date(5, 9)),
                ("person1", self._date(6)),
                ("person2", self._date(1)),
                ("person2", self._date(2)),
                ("person2", self._date(3)),
                ("person2", self._date(6)),
            ])

            result = retention().run(
                Filter(
                    data={
                        "properties": [{
                            "key": "email",
                            "value": "*****@*****.**",
                            "type": "person",
                        }],
                        "date_to":
                        self._date(6, hour=0),
                    }),
                self.team,
                total_intervals=7,
            )

            self.assertEqual(len(result), 7)
            self.assertEqual(
                self.pluck(result, "label"),
                [
                    "Day 0", "Day 1", "Day 2", "Day 3", "Day 4", "Day 5",
                    "Day 6"
                ],
            )
            self.assertEqual(result[0]["date"],
                             datetime(2020, 6, 10, 0, tzinfo=pytz.UTC))
            self.assertEqual(
                self.pluck(result, "values", "count"),
                [
                    [1, 1, 1, 0, 0, 1, 1],
                    [1, 1, 0, 0, 1, 1],
                    [1, 0, 0, 1, 1],
                    [0, 0, 0, 0],
                    [0, 0, 0],
                    [1, 1],
                    [1],
                ],
            )
Example #6
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(cache.get(item_key)["result"][0]["count"], 0)
        self.assertEqual(cache.get(funnel_key)["result"][0]["count"], 0)
Example #7
0
    def people(self, request: request.Request, *args: Any, **kwargs: Any) -> Response:
        team = request.user.team_set.get()
        filter = Filter(request=request)
        offset = int(request.GET.get("offset", 0))

        def _calculate_people(events: QuerySet, offset: int):
            shown_as = request.GET.get("shown_as")
            if shown_as is not None and shown_as == "Stickiness":
                stickiness_days = int(request.GET["stickiness_days"])
                events = (
                    events.values("person_id")
                    .annotate(day_count=Count(functions.TruncDay("timestamp"), distinct=True))
                    .filter(day_count=stickiness_days)
                )
            else:
                events = events.values("person_id").distinct()

            if request.GET.get("breakdown_type") == "cohort" and request.GET.get("breakdown_value") != "all":
                events = events.filter(
                    Exists(
                        CohortPeople.objects.filter(
                            cohort_id=int(request.GET["breakdown_value"]), person_id=OuterRef("person_id"),
                        ).only("id")
                    )
                )
            if request.GET.get("breakdown_type") == "person":
                events = events.filter(
                    Exists(
                        Person.objects.filter(
                            **{
                                "id": OuterRef("person_id"),
                                "properties__{}".format(request.GET["breakdown"]): request.GET["breakdown_value"],
                            }
                        ).only("id")
                    )
                )

            people = Person.objects.filter(team=team, id__in=[p["person_id"] for p in events[offset : offset + 100]],)

            people = people.prefetch_related(Prefetch("persondistinctid_set", to_attr="distinct_ids_cache"))

            return serialize_people(people=people, request=request)

        filtered_events: QuerySet = QuerySet()
        if request.GET.get("session"):
            filtered_events = (
                Event.objects.filter(team=team).filter(base.filter_events(team.pk, filter)).add_person_id(team.pk)
            )
        else:
            if len(filter.entities) >= 1:
                entity = filter.entities[0]
            else:
                entity = Entity({"id": request.GET["entityId"], "type": request.GET["type"]})

            if entity.type == TREND_FILTER_TYPE_EVENTS:
                filtered_events = base.process_entity_for_events(entity, team_id=team.pk, order_by=None).filter(
                    base.filter_events(team.pk, filter, entity)
                )
            elif entity.type == TREND_FILTER_TYPE_ACTIONS:
                actions = super().get_queryset()
                actions = actions.filter(deleted=False)
                try:
                    action = actions.get(pk=entity.id)
                except Action.DoesNotExist:
                    return Response([])
                filtered_events = base.process_entity_for_events(entity, team_id=team.pk, order_by=None).filter(
                    base.filter_events(team.pk, filter, entity)
                )

        people = _calculate_people(events=filtered_events, offset=offset)

        current_url = request.get_full_path()
        next_url: Optional[str] = request.get_full_path()
        if people["count"] > 99 and next_url:
            if "offset" in next_url:
                next_url = next_url[1:]
                next_url = next_url.replace("offset=" + str(offset), "offset=" + str(offset + 100))
            else:
                next_url = request.build_absolute_uri(
                    "{}{}offset={}".format(next_url, "&" if "?" in next_url else "?", offset + 100)
                )
        else:
            next_url = None

        return Response({"results": [people], "next": next_url, "previous": current_url[1:]})
Example #8
0
 def test_response_empty_if_no_events(self):
     self._create_events()
     response = trends().run(Filter(data={"date_from": "2012-12-12"}),
                             self.team)
     self.assertEqual(response, [])
Example #9
0
        def test_interval_filtering(self):
            self._create_events(use_time=True)

            # test minute
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2020-01-01",
                            "interval": "minute",
                            "events": [{
                                "id": "sign up"
                            }]
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][6], "Wed. 1 January, 00:06")
            self.assertEqual(response[0]["data"][6], 3.0)

            # test hour
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2019-12-24",
                            "interval": "hour",
                            "events": [{
                                "id": "sign up"
                            }]
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][3],
                             "Tue. 24 December, 03:00")
            self.assertEqual(response[0]["data"][3], 1.0)
            # 217 - 24 - 1
            self.assertEqual(response[0]["data"][192], 3.0)

            # test week
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2019-11-24",
                            "interval": "week",
                            "events": [{
                                "id": "sign up"
                            }]
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][4], "Sun. 22 December")
            self.assertEqual(response[0]["data"][4], 1.0)
            self.assertEqual(response[0]["labels"][5], "Sun. 29 December")
            self.assertEqual(response[0]["data"][5], 4.0)

            # test month
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2019-9-24",
                            "interval": "month",
                            "events": [{
                                "id": "sign up"
                            }]
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][2], "Sat. 30 November")
            self.assertEqual(response[0]["data"][2], 1.0)
            self.assertEqual(response[0]["labels"][3], "Tue. 31 December")
            self.assertEqual(response[0]["data"][3], 4.0)

            with freeze_time("2020-01-02 23:30"):
                event_factory(team=self.team,
                              event="sign up",
                              distinct_id="blabla")

            # test today + hourly
            with freeze_time("2020-01-02T23:31:00Z"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "dStart",
                            "interval": "hour",
                            "events": [{
                                "id": "sign up"
                            }]
                        }), self.team)
            self.assertEqual(response[0]["labels"][23],
                             "Thu. 2 January, 23:00")
            self.assertEqual(response[0]["data"][23], 1.0)
Example #10
0
        def test_interval_filtering_breakdown(self):
            self._create_events(use_time=True)
            cohort = cohort_factory(name="cohort1",
                                    team=self.team,
                                    groups=[{
                                        "properties": {
                                            "$some_prop": "some_val"
                                        }
                                    }])

            # test minute
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2020-01-01",
                            "interval": "minute",
                            "events": [{
                                "id": "sign up"
                            }],
                            "breakdown": json.dumps([cohort.pk]),
                            "breakdown_type": "cohort",
                        }),
                    self.team,
                )

            self.assertEqual(response[0]["labels"][6], "Wed. 1 January, 00:06")
            self.assertEqual(response[0]["data"][6], 3.0)

            # test hour
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2019-12-24",
                            "interval": "hour",
                            "events": [{
                                "id": "sign up"
                            }],
                            "breakdown": json.dumps([cohort.pk]),
                            "breakdown_type": "cohort",
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][3],
                             "Tue. 24 December, 03:00")
            self.assertEqual(response[0]["data"][3], 1.0)
            # 217 - 24 - 1
            self.assertEqual(response[0]["data"][192], 3.0)

            # test week
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2019-11-24",
                            "interval": "week",
                            "events": [{
                                "id": "sign up"
                            }],
                            "breakdown": json.dumps([cohort.pk]),
                            "breakdown_type": "cohort",
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][4], "Sun. 22 December")
            self.assertEqual(response[0]["data"][4], 1.0)
            self.assertEqual(response[0]["labels"][5], "Sun. 29 December")
            self.assertEqual(response[0]["data"][5], 4.0)

            # test month
            with freeze_time("2020-01-02"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "2019-9-24",
                            "interval": "month",
                            "events": [{
                                "id": "sign up"
                            }],
                            "breakdown": json.dumps([cohort.pk]),
                            "breakdown_type": "cohort",
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][2], "Sat. 30 November")
            self.assertEqual(response[0]["data"][2], 1.0)
            self.assertEqual(response[0]["labels"][3], "Tue. 31 December")
            self.assertEqual(response[0]["data"][3], 4.0)

            with freeze_time("2020-01-02 23:30"):
                event_factory(team=self.team,
                              event="sign up",
                              distinct_id="blabla")

            # test today + hourly
            with freeze_time("2020-01-02T23:31:00Z"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from": "dStart",
                            "interval": "hour",
                            "events": [{
                                "id": "sign up"
                            }],
                            "breakdown": json.dumps([cohort.pk]),
                            "breakdown_type": "cohort",
                        }),
                    self.team,
                )
            self.assertEqual(response[0]["labels"][23],
                             "Thu. 2 January, 23:00")
            self.assertEqual(response[0]["data"][23], 1.0)
Example #11
0
        def test_breakdown_by_person_property(self):
            person1, person2, person3, person4 = self._create_multiple_people()
            action = action_factory(name="watched movie", team=self.team)

            with freeze_time("2020-01-04T13:01:01Z"):
                action_response = trends().run(
                    Filter(
                        data={
                            "date_from":
                            "-14d",
                            "breakdown":
                            "name",
                            "breakdown_type":
                            "person",
                            "actions": [{
                                "id": action.pk,
                                "type": "actions",
                                "order": 0
                            }],
                        }),
                    self.team,
                )
                event_response = trends().run(
                    Filter(
                        data={
                            "date_from":
                            "-14d",
                            "breakdown":
                            "name",
                            "breakdown_type":
                            "person",
                            "events": [{
                                "id": "watched movie",
                                "name": "watched movie",
                                "type": "events",
                                "order": 0,
                            }],
                        }),
                    self.team,
                )

            self.assertListEqual(
                sorted([res["breakdown_value"] for res in event_response]),
                ["person1", "person2", "person3", "person4"])

            for response in event_response:
                if response["breakdown_value"] == "person1":
                    self.assertEqual(response["count"], 1)
                    self.assertEqual(response["label"],
                                     "watched movie - person1")
                if response["breakdown_value"] == "person2":
                    self.assertEqual(response["count"], 3)
                if response["breakdown_value"] == "person3":
                    self.assertEqual(response["count"], 3)
                if response["breakdown_value"] == "person4":
                    self.assertEqual(response["count"], 0)

            self.assertTrue(
                self._compare_entity_response(
                    event_response,
                    action_response,
                ))
    def test_strict_funnel_correlation_with_recordings(self):

        # First use that successfully completes the strict funnel
        p1 = _create_person(distinct_ids=["user_1"],
                            team=self.team,
                            properties={"foo": "bar"})
        _create_event(
            event="$pageview",
            distinct_id="user_1",
            team=self.team,
            timestamp=timezone.now(),
            properties={
                "$session_id": "s2",
                "$window_id": "w1"
            },
            event_uuid="11111111-1111-1111-1111-111111111111",
        )
        _create_event(
            event="insight analyzed",
            distinct_id="user_1",
            team=self.team,
            timestamp=(timezone.now() + timedelta(minutes=3)),
            properties={
                "$session_id": "s2",
                "$window_id": "w2"
            },
            event_uuid="31111111-1111-1111-1111-111111111111",
        )
        _create_event(
            event="insight analyzed",  # Second event should not be returned
            distinct_id="user_1",
            team=self.team,
            timestamp=(timezone.now() + timedelta(minutes=4)),
            properties={
                "$session_id": "s2",
                "$window_id": "w2"
            },
            event_uuid="41111111-1111-1111-1111-111111111111",
        )
        _create_session_recording_event(self.team.pk, "user_1", "s2",
                                        datetime(2021, 1, 2, 0, 0, 0))

        # Second user with strict funnel drop off, but completed the step events for a normal funnel
        p2 = _create_person(distinct_ids=["user_2"],
                            team=self.team,
                            properties={"foo": "bar"})
        _create_event(
            event="$pageview",
            distinct_id="user_2",
            team=self.team,
            timestamp=timezone.now(),
            properties={
                "$session_id": "s3",
                "$window_id": "w1"
            },
            event_uuid="51111111-1111-1111-1111-111111111111",
        )
        _create_event(
            event="insight loaded",  # Interupting event
            distinct_id="user_2",
            team=self.team,
            timestamp=(timezone.now() + timedelta(minutes=3)),
            properties={
                "$session_id": "s3",
                "$window_id": "w2"
            },
            event_uuid="61111111-1111-1111-1111-111111111111",
        )
        _create_event(
            event="insight analyzed",
            distinct_id="user_2",
            team=self.team,
            timestamp=(timezone.now() + timedelta(minutes=4)),
            properties={
                "$session_id": "s3",
                "$window_id": "w2"
            },
            event_uuid="71111111-1111-1111-1111-111111111111",
        )
        _create_session_recording_event(self.team.pk, "user_2", "s3",
                                        datetime(2021, 1, 2, 0, 0, 0))

        # Success filter
        filter = Filter(
            data={
                "insight":
                INSIGHT_FUNNELS,
                "date_from":
                "2021-01-01",
                "date_to":
                "2021-01-08",
                "funnel_order_type":
                "strict",
                "funnel_correlation_type":
                "properties",
                "events": [{
                    "id": "$pageview",
                    "order": 0
                }, {
                    "id": "insight analyzed",
                    "order": 1
                }],
                "include_recordings":
                "true",
                "funnel_correlation_property_values": [{
                    "key": "foo",
                    "value": "bar",
                    "operator": "exact",
                    "type": "person"
                }],
                "funnel_correlation_person_converted":
                "True",
            })
        _, results = FunnelCorrelationActors(filter, self.team).get_actors()

        self.assertEqual(len(results), 1)
        self.assertEqual(results[0]["id"], p1.uuid)
        self.assertEqual(
            results[0]["matched_recordings"],
            [{
                "events": [{
                    "timestamp": timezone.now() + timedelta(minutes=3),
                    "uuid": UUID("31111111-1111-1111-1111-111111111111"),
                    "window_id": "w2",
                }],
                "session_id":
                "s2",
            }],
        )

        # Drop off filter
        filter = Filter(
            data={
                "insight":
                INSIGHT_FUNNELS,
                "date_from":
                "2021-01-01",
                "date_to":
                "2021-01-08",
                "funnel_order_type":
                "strict",
                "funnel_correlation_type":
                "properties",
                "events": [{
                    "id": "$pageview",
                    "order": 0
                }, {
                    "id": "insight analyzed",
                    "order": 1
                }],
                "include_recordings":
                "true",
                "funnel_correlation_property_values": [{
                    "key": "foo",
                    "value": "bar",
                    "operator": "exact",
                    "type": "person"
                }],
                "funnel_correlation_person_converted":
                "False",
            })
        _, results = FunnelCorrelationActors(filter, self.team).get_actors()

        self.assertEqual(results[0]["id"], p2.uuid)
        self.assertEqual(
            results[0]["matched_recordings"],
            [{
                "events": [{
                    "timestamp": timezone.now(),
                    "uuid": UUID("51111111-1111-1111-1111-111111111111"),
                    "window_id": "w1",
                }],
                "session_id":
                "s3",
            }],
        )
    def _setup_basic_test(self):
        filters = {
            "events": [
                {
                    "id": "user signed up",
                    "type": "events",
                    "order": 0
                },
                {
                    "id": "paid",
                    "type": "events",
                    "order": 1
                },
            ],
            "insight":
            INSIGHT_FUNNELS,
            "date_from":
            "2020-01-01",
            "date_to":
            "2020-01-14",
            "funnel_correlation_type":
            "events",
        }

        filter = Filter(data=filters)

        success_target_persons = []
        failure_target_persons = []
        events_by_person = {}
        for i in range(10):
            person_id = f"user_{i}"
            person = _create_person(distinct_ids=[person_id],
                                    team_id=self.team.pk)
            events_by_person[person_id] = [{
                "event":
                "user signed up",
                "timestamp":
                datetime(2020, 1, 2, 14)
            }]

            if i % 2 == 0:
                events_by_person[person_id].append({
                    "event":
                    "positively_related",
                    "timestamp":
                    datetime(2020, 1, 3, 14)
                })

                success_target_persons.append(str(person.uuid))

            events_by_person[person_id].append({
                "event":
                "paid",
                "timestamp":
                datetime(2020, 1, 4, 14)
            })

        for i in range(10, 20):
            person_id = f"user_{i}"
            person = _create_person(distinct_ids=[person_id],
                                    team_id=self.team.pk)
            events_by_person[person_id] = [{
                "event":
                "user signed up",
                "timestamp":
                datetime(2020, 1, 2, 14)
            }]
            if i % 2 == 0:
                events_by_person[person_id].append({
                    "event":
                    "negatively_related",
                    "timestamp":
                    datetime(2020, 1, 3, 14)
                })
                failure_target_persons.append(str(person.uuid))

        # One positively_related as failure
        person_fail_id = f"user_fail"
        person_fail = _create_person(distinct_ids=[person_fail_id],
                                     team_id=self.team.pk)
        events_by_person[person_fail_id] = [
            {
                "event": "user signed up",
                "timestamp": datetime(2020, 1, 2, 14)
            },
            {
                "event": "positively_related",
                "timestamp": datetime(2020, 1, 3, 14)
            },
        ]

        # One negatively_related as success
        person_success_id = f"user_succ"
        person_succ = _create_person(distinct_ids=[person_success_id],
                                     team_id=self.team.pk)
        events_by_person[person_success_id] = [
            {
                "event": "user signed up",
                "timestamp": datetime(2020, 1, 2, 14)
            },
            {
                "event": "negatively_related",
                "timestamp": datetime(2020, 1, 3, 14)
            },
            {
                "event": "paid",
                "timestamp": datetime(2020, 1, 4, 14)
            },
        ]
        journeys_for(events_by_person, self.team)

        return filter, success_target_persons, failure_target_persons, person_fail, person_succ
    def test_funnel_correlation_on_properties_with_recordings(self):
        p1 = _create_person(distinct_ids=["user_1"],
                            team=self.team,
                            properties={"foo": "bar"})
        _create_event(
            event="$pageview",
            distinct_id="user_1",
            team=self.team,
            timestamp=timezone.now(),
            properties={
                "$session_id": "s2",
                "$window_id": "w1"
            },
            event_uuid="11111111-1111-1111-1111-111111111111",
        )
        _create_event(
            event="insight analyzed",
            distinct_id="user_1",
            team=self.team,
            timestamp=(timezone.now() + timedelta(minutes=3)),
            properties={
                "$session_id": "s2",
                "$window_id": "w2"
            },
            event_uuid="21111111-1111-1111-1111-111111111111",
        )

        _create_session_recording_event(self.team.pk, "user_1", "s2",
                                        datetime(2021, 1, 2, 0, 0, 0))

        # Success filter
        filter = Filter(
            data={
                "insight":
                INSIGHT_FUNNELS,
                "date_from":
                "2021-01-01",
                "date_to":
                "2021-01-08",
                "funnel_correlation_type":
                "properties",
                "events": [{
                    "id": "$pageview",
                    "order": 0
                }, {
                    "id": "insight analyzed",
                    "order": 1
                }],
                "include_recordings":
                "true",
                "funnel_correlation_property_values": [{
                    "key": "foo",
                    "value": "bar",
                    "operator": "exact",
                    "type": "person"
                }],
                "funnel_correlation_person_converted":
                "True",
            })
        _, results = FunnelCorrelationActors(filter, self.team).get_actors()

        self.assertEqual(results[0]["id"], p1.uuid)
        self.assertEqual(
            results[0]["matched_recordings"],
            [{
                "events": [{
                    "timestamp": timezone.now() + timedelta(minutes=3),
                    "uuid": UUID("21111111-1111-1111-1111-111111111111"),
                    "window_id": "w2",
                }],
                "session_id":
                "s2",
            }],
        )
Example #15
0
    def test_refresh_cache(self):
        dashboard = Dashboard.objects.create(team=self.team, name="dashboard")

        with freeze_time("2020-01-04T13:00:01Z"):
            # Pretend we cached something a while ago, but we won't have anything in the redis cache
            item_default: Insight = Insight.objects.create(
                dashboard=dashboard,
                filters=Filter(
                    data={
                        "events": [{
                            "id": "$pageview"
                        }],
                        "properties": [{
                            "key": "$browser",
                            "value": "Mac OS X"
                        }],
                    }).to_dict(),
                team=self.team,
                last_refresh=now(),
            )
            item_sessions: Insight = Insight.objects.create(
                dashboard=dashboard,
                filters=Filter(
                    data={
                        "display":
                        "ActionsLineGraph",
                        "events": [{
                            "id": "$pageview",
                            "type": "events",
                            "order": 0,
                            "properties": []
                        }],
                        "filters": [],
                        "insight":
                        "SESSIONS",
                        "interval":
                        "day",
                        "pagination": {},
                        "session":
                        "avg",
                    }).to_dict(),
                team=self.team,
                last_refresh=now(),
            )

        with freeze_time("2020-01-20T13:00:01Z"):
            response = self.client.get(
                f"/api/projects/{self.team.id}/dashboards/%s?refresh=true" %
                dashboard.pk)

            self.assertEqual(response.status_code, 200)

            response_data = response.json()
            self.assertIsNotNone(response_data["items"][0]["result"])
            self.assertIsNotNone(response_data["items"][0]["last_refresh"])
            self.assertEqual(response_data["items"][0]["result"][0]["count"],
                             0)

            item_default.refresh_from_db()
            item_sessions.refresh_from_db()

            self.assertEqual(
                parser.isoparse(response_data["items"][0]["last_refresh"]),
                item_default.last_refresh)
            self.assertEqual(
                parser.isoparse(response_data["items"][1]["last_refresh"]),
                item_sessions.last_refresh)

            self.assertAlmostEqual(item_default.last_refresh,
                                   now(),
                                   delta=timezone.timedelta(seconds=5))
            self.assertAlmostEqual(item_sessions.last_refresh,
                                   now(),
                                   delta=timezone.timedelta(seconds=5))
Example #16
0
        def test_breakdown_filtering(self):
            self._create_events()
            # test breakdown filtering
            with freeze_time("2020-01-04T13:01:01Z"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from":
                            "-14d",
                            "breakdown":
                            "$some_property",
                            "events": [
                                {
                                    "id": "sign up",
                                    "name": "sign up",
                                    "type": "events",
                                    "order": 0,
                                },
                                {
                                    "id": "no events"
                                },
                            ],
                        }),
                    self.team,
                )

            self.assertEqual(response[0]["label"], "sign up - Other")
            self.assertEqual(response[1]["label"], "sign up - other_value")
            self.assertEqual(response[2]["label"], "sign up - value")
            self.assertEqual(response[3]["label"], "no events - Other")

            self.assertEqual(sum(response[0]["data"]), 2)
            self.assertEqual(response[0]["data"][4 + 7], 2)
            self.assertEqual(response[0]["breakdown_value"], "nan")

            self.assertEqual(sum(response[1]["data"]), 1)
            self.assertEqual(response[1]["data"][5 + 7], 1)
            self.assertEqual(response[1]["breakdown_value"], "other_value")

            # check numerical breakdown
            with freeze_time("2020-01-04T13:01:01Z"):
                response = trends().run(
                    Filter(
                        data={
                            "date_from":
                            "-14d",
                            "breakdown":
                            "$some_numerical_prop",
                            "events": [
                                {
                                    "id": "sign up",
                                    "name": "sign up",
                                    "type": "events",
                                    "order": 0,
                                },
                                {
                                    "id": "no events"
                                },
                            ],
                        }),
                    self.team,
                )

            self.assertEqual(response[0]["label"], "sign up - Other")
            self.assertEqual(response[0]["count"], 4.0)
            self.assertEqual(response[1]["label"], "sign up - 80.0")
            self.assertEqual(response[1]["count"], 1.0)
Example #17
0
        def test_user_properties(self):
            person1 = person_factory(team_id=self.team.pk,
                                     distinct_ids=["person1"],
                                     properties={"group": "some group"})
            person2 = person_factory(team_id=self.team.pk,
                                     distinct_ids=["person2"],
                                     properties={"group": "another group"})
            event2 = event_factory(
                team=self.team,
                distinct_id="person1",
                event="$pageview",
                properties={
                    "$current_url": "https://something.com",
                    "another_key": "value",
                },
            )
            event_p2 = event_factory(
                team=self.team,
                distinct_id="person2",
                event="$pageview",
                properties={"$current_url": "https://something.com"},
            )

            # test for leakage
            team2 = Team.objects.create()
            person_team2 = person_factory(
                team_id=team2.pk,
                distinct_ids=["person_team_2"],
                properties={"group": "another group"})
            event_team2 = event_factory(
                team=team2,
                distinct_id="person_team_2",
                event="$pageview",
                properties={
                    "$current_url": "https://something.com",
                    "another_key": "value",
                },
            )

            filter = Filter(
                data={
                    "properties": [{
                        "key": "group",
                        "value": "some group",
                        "type": "person"
                    }]
                })
            events = filter_events(filter=filter,
                                   team=self.team,
                                   person_query=True,
                                   order_by=None)
            self.assertEqual(len(events), 1)
            self.assertEqual(events[0]["id"], event2.pk)

            filter = Filter(
                data={
                    "properties": [{
                        "key": "group",
                        "operator": "is_not",
                        "value": "some group",
                        "type": "person"
                    }]
                })
            events = filter_events(filter=filter,
                                   team=self.team,
                                   person_query=True,
                                   order_by=None)
            self.assertEqual(events[0]["id"], event_p2.pk)
            self.assertEqual(len(events), 1)
Example #18
0
        def test_breakdown_by_cohort(self):
            person1, person2, person3, person4 = self._create_multiple_people()
            cohort = cohort_factory(name="cohort1",
                                    team=self.team,
                                    groups=[{
                                        "properties": {
                                            "name": "person1"
                                        }
                                    }])
            cohort2 = cohort_factory(name="cohort2",
                                     team=self.team,
                                     groups=[{
                                         "properties": {
                                             "name": "person2"
                                         }
                                     }])
            cohort3 = cohort_factory(
                name="cohort3",
                team=self.team,
                groups=[
                    {
                        "properties": {
                            "name": "person1"
                        }
                    },
                    {
                        "properties": {
                            "name": "person2"
                        }
                    },
                ],
            )
            action = action_factory(name="watched movie", team=self.team)
            action.calculate_events()

            with freeze_time("2020-01-04T13:01:01Z"):
                action_response = trends().run(
                    Filter(
                        data={
                            "date_from":
                            "-14d",
                            "breakdown":
                            json.dumps(
                                [cohort.pk, cohort2.pk, cohort3.pk, "all"]),
                            "breakdown_type":
                            "cohort",
                            "actions": [{
                                "id": action.pk,
                                "type": "actions",
                                "order": 0
                            }],
                        }),
                    self.team,
                )
                event_response = trends().run(
                    Filter(
                        data={
                            "date_from":
                            "-14d",
                            "breakdown":
                            json.dumps(
                                [cohort.pk, cohort2.pk, cohort3.pk, "all"]),
                            "breakdown_type":
                            "cohort",
                            "events": [{
                                "id": "watched movie",
                                "name": "watched movie",
                                "type": "events",
                                "order": 0,
                            }],
                        }),
                    self.team,
                )

            self.assertTrue(
                self._compare_entity_response(
                    event_response,
                    action_response,
                ))
            self.assertEqual(event_response[1]["label"],
                             "watched movie - cohort2")
            self.assertEqual(event_response[2]["label"],
                             "watched movie - cohort3")
            self.assertEqual(event_response[3]["label"],
                             "watched movie - all users")

            self.assertEqual(sum(event_response[0]["data"]), 1)
            self.assertEqual(event_response[0]["breakdown_value"], cohort.pk)

            self.assertEqual(sum(event_response[1]["data"]), 3)
            self.assertEqual(event_response[1]["breakdown_value"], cohort2.pk)

            self.assertEqual(sum(event_response[2]["data"]), 4)
            self.assertEqual(event_response[2]["breakdown_value"], cohort3.pk)

            self.assertEqual(sum(event_response[3]["data"]), 7)
            self.assertEqual(event_response[3]["breakdown_value"], "all")
Example #19
0
    def session_recording(self, request: Request, *args: Any, **kwargs: Any) -> Response:
        session_recording = SessionRecording().run(
            team=self.team, filter=Filter(request=request), session_recording_id=request.GET["session_recording_id"]
        )

        return Response({"result": session_recording})
Example #20
0
 def trend(self, request: request.Request, *args: Any, **kwargs: Any) -> Response:
     result = self.calculate_trends(request)
     filter = Filter(request=request)
     next = format_next_url(request, filter.offset, 20) if len(result["result"]) > 20 else None
     return Response({**result, "next": next})
Example #21
0
        def test_retention_multiple_events(self):
            person_factory(team_id=self.team.pk,
                           distinct_ids=["person1", "alias1"])
            person_factory(team_id=self.team.pk, distinct_ids=["person2"])
            person_factory(team_id=self.team.pk, distinct_ids=["person3"])
            person_factory(team_id=self.team.pk, distinct_ids=["person4"])

            first_event = "$some_event"
            self._create_events(
                [
                    ("person1", self._date(0)),
                    ("person1", self._date(1)),
                    ("person1", self._date(2)),
                    ("person1", self._date(3)),
                    ("person2", self._date(0)),
                    ("person2", self._date(1)),
                    ("person2", self._date(2)),
                    ("person2", self._date(3)),
                ],
                first_event,
            )

            self._create_events(
                [
                    ("person1", self._date(5)),
                    ("person1", self._date(6)),
                    ("person2", self._date(5)),
                ],
                "$pageview",
            )

            target_entity = json.dumps({
                "id": first_event,
                "type": TREND_FILTER_TYPE_EVENTS
            })
            result = retention().run(
                Filter(
                    data={
                        "date_to": self._date(6, hour=6),
                        "target_entity": target_entity,
                        "events": [
                            {
                                "id": "$pageview",
                                "type": "events"
                            },
                        ],
                    }),
                self.team,
                total_intervals=7,
            )
            self.assertEqual(len(result), 7)
            self.assertEqual(
                self.pluck(result, "label"),
                [
                    "Day 0", "Day 1", "Day 2", "Day 3", "Day 4", "Day 5",
                    "Day 6"
                ],
            )

            self.assertEqual(
                self.pluck(result, "values", "count"),
                [[2, 2, 2, 2, 0, 2, 1], [2, 2, 2, 0, 2, 1], [2, 2, 0, 2, 1],
                 [2, 0, 2, 1], [0, 0, 0], [2, 1], [1]],
            )
Example #22
0
import pytest

from posthog.models import Filter


@pytest.mark.parametrize(
    "filter,expected_interval",
    [
        (Filter(data={"interval": "hour"}), "hour"),
        (Filter(data={"interval": "day"}), "day"),
        (Filter(data={"interval": "week"}), "week"),
        (Filter(data={"interval": "month"}), "month"),
        # Downcasing
        (Filter(data={"interval": "HoUR"}), "hour"),
        # Blank filter
        (Filter(data={"events": []}), "day"),
        # Legacy support - translate minutes to hours!
        (Filter(data={"interval": "minute"}), "hour"),
    ],
)
def test_filter_interval_success(filter, expected_interval):
    assert filter.interval == expected_interval
    assert filter.interval_to_dict() == {"interval": expected_interval}


@pytest.mark.parametrize(
    "filter,expected_error_message",
    [
        (Filter(data={"interval": "foo"}),
         "Interval foo does not belong to SUPPORTED_INTERVAL_TYPES!"),
        (Filter(data={"interval": 123}), "Interval must be a string!"),
Example #23
0
        def test_retention_with_properties(self):

            person1 = person_factory(team_id=self.team.pk,
                                     distinct_ids=["person1", "alias1"])
            person2 = person_factory(team_id=self.team.pk,
                                     distinct_ids=["person2"])

            self._create_events([
                ("person1", self._date(0)),
                ("person1", self._date(1)),
                ("person1", self._date(2)),
                ("person1", self._date(5)),
                ("alias1", self._date(5, 9)),
                ("person1", self._date(6)),
                ("person2", self._date(1)),
                ("person2", self._date(2)),
                ("person2", self._date(3)),
                ("person2", self._date(6)),
            ])

            result = retention().run(
                Filter(
                    data={
                        "properties": [{
                            "key": "$some_property",
                            "value": "value"
                        }],
                        "date_to": self._date(10, hour=0),
                    }),
                self.team,
            )
            self.assertEqual(len(result), 11)
            self.assertEqual(
                self.pluck(result, "label"),
                [
                    "Day 0",
                    "Day 1",
                    "Day 2",
                    "Day 3",
                    "Day 4",
                    "Day 5",
                    "Day 6",
                    "Day 7",
                    "Day 8",
                    "Day 9",
                    "Day 10",
                ],
            )
            self.assertEqual(result[0]["date"],
                             datetime(2020, 6, 10, 0, tzinfo=pytz.UTC))

            self.assertEqual(
                self.pluck(result, "values", "count"),
                [
                    [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
                    [1, 0, 1, 0, 0, 0, 0, 0, 0, 0],
                    [1, 0, 0, 1, 0, 0, 0, 0, 0],
                    [1, 0, 0, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0, 0, 0],
                    [1, 0, 0, 0, 0, 0],
                    [0, 0, 0, 0, 0],
                    [0, 0, 0, 0],
                    [0, 0, 0],
                    [0, 0],
                    [0],
                ],
            )
Example #24
0
        def test_lifecycle_trend_people(self):

            people = self._create_events(data=[
                (
                    "p1",
                    [
                        "2020-01-11T12:00:00Z",
                        "2020-01-12T12:00:00Z",
                        "2020-01-13T12:00:00Z",
                        "2020-01-15T12:00:00Z",
                        "2020-01-17T12:00:00Z",
                        "2020-01-19T12:00:00Z",
                    ],
                ),
                ("p2", ["2020-01-09T12:00:00Z", "2020-01-12T12:00:00Z"]),
                ("p3", ["2020-01-12T12:00:00Z"]),
                ("p4", ["2020-01-15T12:00:00Z"]),
            ])

            p1 = people[0]

            result = trends().get_people(
                Filter(
                    data={
                        "date_from":
                        "2020-01-12T00:00:00Z",
                        "date_to":
                        "2020-01-19T00:00:00Z",
                        "events": [{
                            "id": "$pageview",
                            "type": "events",
                            "order": 0
                        }],
                        "shown_as":
                        TRENDS_LIFECYCLE,
                    }),
                self.team.pk,
                relative_date_parse("2020-01-13T00:00:00Z"),
                "returning",
            )

            self.assertEqual(len(result), 1)
            self.assertEqual(result[0]["id"], p1.pk)

            dormant_result = trends().get_people(
                Filter(
                    data={
                        "date_from":
                        "2020-01-12T00:00:00Z",
                        "date_to":
                        "2020-01-19T00:00:00Z",
                        "events": [{
                            "id": "$pageview",
                            "type": "events",
                            "order": 0
                        }],
                        "shown_as":
                        TRENDS_LIFECYCLE,
                    }),
                self.team.pk,
                relative_date_parse("2020-01-13T00:00:00Z"),
                "dormant",
            )

            self.assertEqual(len(dormant_result), 2)

            dormant_result = trends().get_people(
                Filter(
                    data={
                        "date_from":
                        "2020-01-12T00:00:00Z",
                        "date_to":
                        "2020-01-19T00:00:00Z",
                        "events": [{
                            "id": "$pageview",
                            "type": "events",
                            "order": 0
                        }],
                        "shown_as":
                        TRENDS_LIFECYCLE,
                    }),
                self.team.pk,
                relative_date_parse("2020-01-14T00:00:00Z"),
                "dormant",
            )

            self.assertEqual(len(dormant_result), 1)
Example #25
0
        def test_retention_period_monthly(self):
            Person.objects.create(
                team=self.team,
                distinct_ids=["person1", "alias1"],
                properties={"email": "*****@*****.**"},
            )
            Person.objects.create(
                team=self.team,
                distinct_ids=["person2"],
                properties={"email": "*****@*****.**"},
            )

            self._create_events([
                ("person1", self._date(day=0, month=-5)),
                ("person2", self._date(day=0, month=-5)),
                ("person1", self._date(day=0, month=-4)),
                ("person2", self._date(day=0, month=-4)),
                ("person1", self._date(day=0, month=-3)),
                ("person2", self._date(day=0, month=-3)),
                ("person1", self._date(day=0, month=-1)),
                ("person1", self._date(day=0, month=0)),
                ("person2", self._date(day=0, month=0)),
                ("person2", self._date(day=0, month=1)),
                ("person1", self._date(day=0, month=3)),
                ("person2", self._date(day=0, month=5)),
            ])

            filter = Filter(data={
                "date_to": self._date(0, month=5, hour=0),
                "period": "Month"
            })

            result = retention().run(filter, self.team, total_intervals=11)

            self.assertEqual(
                self.pluck(result, "label"),
                [
                    "Month 0",
                    "Month 1",
                    "Month 2",
                    "Month 3",
                    "Month 4",
                    "Month 5",
                    "Month 6",
                    "Month 7",
                    "Month 8",
                    "Month 9",
                    "Month 10",
                ],
            )

            self.assertEqual(
                self.pluck(result, "values", "count"),
                [
                    [2, 2, 2, 0, 1, 2, 1, 0, 1, 0, 1],
                    [2, 2, 0, 1, 2, 1, 0, 1, 0, 1],
                    [2, 0, 1, 2, 1, 0, 1, 0, 1],
                    [0, 0, 0, 0, 0, 0, 0, 0],
                    [1, 1, 0, 0, 1, 0, 0],
                    [2, 1, 0, 1, 0, 1],
                    [1, 0, 0, 0, 1],
                    [0, 0, 0, 0],
                    [1, 0, 0],
                    [0, 0],
                    [1],
                ],
            )

            self.assertEqual(
                self.pluck(result, "date"),
                [
                    datetime(2020, 1, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 2, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 3, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 4, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 5, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 7, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 8, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 9, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 10, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 11, 10, 0, tzinfo=pytz.UTC),
                ],
            )
Example #26
0
        def test_lifecycle_trend_weeks(self):
            # lifecycle weeks rounds the date to the nearest following week  2/5 -> 2/10
            p1 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p1"],
                                properties={"name": "p1"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-02-01T12:00:00Z",
            )
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-02-05T12:00:00Z",
            )
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-02-10T12:00:00Z",
            )

            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-02-15T12:00:00Z",
            )

            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-02-27T12:00:00Z",
            )

            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-03-02T12:00:00Z",
            )

            p2 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p2"],
                                properties={"name": "p2"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p2",
                timestamp="2020-02-11T12:00:00Z",
            )
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p2",
                timestamp="2020-02-18T12:00:00Z",
            )

            p3 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p3"],
                                properties={"name": "p3"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p3",
                timestamp="2020-02-12T12:00:00Z",
            )

            p4 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p4"],
                                properties={"name": "p4"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p4",
                timestamp="2020-02-27T12:00:00Z",
            )

            result = trends().run(
                Filter(
                    data={
                        "date_from":
                        "2020-02-05T00:00:00Z",
                        "date_to":
                        "2020-03-09T00:00:00Z",
                        "events": [{
                            "id": "$pageview",
                            "type": "events",
                            "order": 0
                        }],
                        "shown_as":
                        TRENDS_LIFECYCLE,
                        "interval":
                        "week",
                    }),
                self.team,
            )

            self.assertEqual(len(result), 4)
            self.assertEqual(sorted([res["status"] for res in result]),
                             ["dormant", "new", "resurrecting", "returning"])
            self.assertTrue(result[0]["days"] == [
                "2020-02-09", "2020-02-16", "2020-02-23", "2020-03-01",
                "2020-03-08"
            ] or result[0]["days"] == [
                "2020-02-10", "2020-02-17", "2020-02-24", "2020-03-02",
                "2020-03-09"
            ])
            for res in result:
                if res["status"] == "dormant":
                    self.assertEqual(res["data"], [0, -2, -1, -1, -1])
                elif res["status"] == "returning":
                    self.assertEqual(res["data"], [1, 1, 0, 1, 0])
                elif res["status"] == "resurrecting":
                    self.assertEqual(res["data"], [0, 0, 1, 0, 0])
                elif res["status"] == "new":
                    self.assertEqual(res["data"], [2, 0, 1, 0, 0])
Example #27
0
        def test_retention_period_hourly(self):
            Person.objects.create(
                team=self.team,
                distinct_ids=["person1", "alias1"],
                properties={"email": "*****@*****.**"},
            )
            Person.objects.create(
                team=self.team,
                distinct_ids=["person2"],
                properties={"email": "*****@*****.**"},
            )

            self._create_events([
                ("person1", self._date(day=0, hour=0)),
                ("person2", self._date(day=0, hour=0)),
                ("person1", self._date(day=0, hour=1)),
                ("person2", self._date(day=0, hour=1)),
                ("person1", self._date(day=0, hour=2)),
                ("person2", self._date(day=0, hour=2)),
                ("person1", self._date(day=0, hour=4)),
                ("person1", self._date(day=0, hour=5)),
                ("person2", self._date(day=0, hour=5)),
                ("person2", self._date(day=0, hour=6)),
                ("person1", self._date(day=0, hour=8)),
                ("person2", self._date(day=0, hour=10)),
            ])

            filter = Filter(data={
                "date_to": self._date(0, hour=10),
                "period": "Hour"
            })

            result = retention().run(filter, self.team, total_intervals=11)

            self.assertEqual(
                self.pluck(result, "label"),
                [
                    "Hour 0",
                    "Hour 1",
                    "Hour 2",
                    "Hour 3",
                    "Hour 4",
                    "Hour 5",
                    "Hour 6",
                    "Hour 7",
                    "Hour 8",
                    "Hour 9",
                    "Hour 10",
                ],
            )

            self.assertEqual(
                self.pluck(result, "values", "count"),
                [
                    [2, 2, 2, 0, 1, 2, 1, 0, 1, 0, 1],
                    [2, 2, 0, 1, 2, 1, 0, 1, 0, 1],
                    [2, 0, 1, 2, 1, 0, 1, 0, 1],
                    [0, 0, 0, 0, 0, 0, 0, 0],
                    [1, 1, 0, 0, 1, 0, 0],
                    [2, 1, 0, 1, 0, 1],
                    [1, 0, 0, 0, 1],
                    [0, 0, 0, 0],
                    [1, 0, 0],
                    [0, 0],
                    [1],
                ],
            )

            self.assertEqual(
                self.pluck(result, "date"),
                [
                    datetime(2020, 6, 10, 0, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 1, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 2, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 3, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 4, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 5, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 6, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 7, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 8, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 9, tzinfo=pytz.UTC),
                    datetime(2020, 6, 10, 10, tzinfo=pytz.UTC),
                ],
            )
Example #28
0
        def test_lifecycle_trend_prop_filtering(self):

            p1 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p1"],
                                properties={"name": "p1"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-01-11T12:00:00Z",
                properties={"$number": 1},
            )
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-01-12T12:00:00Z",
                properties={"$number": 1},
            )
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-01-13T12:00:00Z",
                properties={"$number": 1},
            )

            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-01-15T12:00:00Z",
                properties={"$number": 1},
            )

            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-01-17T12:00:00Z",
                properties={"$number": 1},
            )

            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p1",
                timestamp="2020-01-19T12:00:00Z",
                properties={"$number": 1},
            )

            p2 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p2"],
                                properties={"name": "p2"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p2",
                timestamp="2020-01-09T12:00:00Z",
            )
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p2",
                timestamp="2020-01-12T12:00:00Z",
            )

            p3 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p3"],
                                properties={"name": "p3"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p3",
                timestamp="2020-01-12T12:00:00Z",
            )

            p4 = person_factory(team_id=self.team.pk,
                                distinct_ids=["p4"],
                                properties={"name": "p4"})
            event_factory(
                team=self.team,
                event="$pageview",
                distinct_id="p4",
                timestamp="2020-01-15T12:00:00Z",
            )

            result = trends().run(
                Filter(
                    data={
                        "date_from":
                        "2020-01-12T00:00:00Z",
                        "date_to":
                        "2020-01-19T00:00:00Z",
                        "events": [{
                            "id": "$pageview",
                            "type": "events",
                            "order": 0
                        }],
                        "shown_as":
                        TRENDS_LIFECYCLE,
                        "properties": [{
                            "key": "$number",
                            "value": 1
                        }],
                    }),
                self.team,
            )

            self.assertEqual(len(result), 4)
            self.assertEqual(sorted([res["status"] for res in result]),
                             ["dormant", "new", "resurrecting", "returning"])
            for res in result:
                if res["status"] == "dormant":
                    self.assertEqual(res["data"], [0, 0, -1, 0, -1, 0, -1, 0])
                elif res["status"] == "returning":
                    self.assertEqual(res["data"], [1, 1, 0, 0, 0, 0, 0, 0])
                elif res["status"] == "resurrecting":
                    self.assertEqual(res["data"], [0, 0, 0, 1, 0, 1, 0, 1])
                elif res["status"] == "new":
                    self.assertEqual(res["data"], [0, 0, 0, 0, 0, 0, 0, 0])
Example #29
0
    def list(self, request: Request, *args: Any, **kwargs: Any) -> Response:
        team = self.team
        filter = Filter(request=request)
        if request.GET.get("after"):
            filter._date_from = request.GET["after"]
        if request.GET.get("before"):
            filter._date_to = request.GET["before"]
        limit = "LIMIT 101"
        conditions, condition_params = determine_event_conditions(
            request.GET.dict())
        prop_filters, prop_filter_params = parse_prop_clauses(
            filter.properties, team.pk)
        if request.GET.get("action_id"):
            action = Action.objects.get(pk=request.GET["action_id"])
            if action.steps.count() == 0:
                return Response({"next": False, "results": []})
            action_query, params = format_action_filter(action)
            prop_filters += " AND {}".format(action_query)
            prop_filter_params = {**prop_filter_params, **params}

        if prop_filters != "":
            query_result = sync_execute(
                SELECT_EVENT_WITH_PROP_SQL.format(conditions=conditions,
                                                  limit=limit,
                                                  filters=prop_filters),
                {
                    "team_id": team.pk,
                    **condition_params,
                    **prop_filter_params
                },
            )
        else:
            query_result = sync_execute(
                SELECT_EVENT_WITH_ARRAY_PROPS_SQL.format(conditions=conditions,
                                                         limit=limit),
                {
                    "team_id": team.pk,
                    **condition_params
                },
            )

        result = ClickhouseEventSerializer(
            query_result[0:100],
            many=True,
            context={
                "people": self._get_people(query_result, team),
            },
        ).data

        if len(query_result) > 100:
            path = request.get_full_path()
            reverse = request.GET.get("orderBy", "-timestamp") != "-timestamp"
            next_url: Optional[str] = request.build_absolute_uri(
                "{}{}{}={}".format(
                    path,
                    "&" if "?" in path else "?",
                    "after" if reverse else "before",
                    query_result[99][3].strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
                ))
        else:
            next_url = None

        return Response({"next": next_url, "results": result})
Example #30
0
        def test_sessions_avg_length_interval(self):
            with freeze_time("2012-01-14T03:21:34.000Z"):
                event_factory(team=self.team, event="1st action", distinct_id="1")
                event_factory(team=self.team, event="1st action", distinct_id="2")
            with freeze_time("2012-01-14T03:25:34.000Z"):
                event_factory(team=self.team, event="2nd action", distinct_id="1")
                event_factory(team=self.team, event="2nd action", distinct_id="2")
            with freeze_time("2012-01-25T03:59:34.000Z"):
                event_factory(team=self.team, event="3rd action", distinct_id="1")
                event_factory(team=self.team, event="3rd action", distinct_id="2")
            with freeze_time("2012-01-25T04:01:34.000Z"):
                event_factory(team=self.team, event="4th action", distinct_id="1")
                event_factory(team=self.team, event="4th action", distinct_id="2")

            with freeze_time("2012-03-14T03:21:34.000Z"):
                event_factory(team=self.team, event="1st action", distinct_id="2")
            with freeze_time("2012-03-14T03:25:34.000Z"):
                event_factory(team=self.team, event="2nd action", distinct_id="2")
            with freeze_time("2012-03-15T03:59:34.000Z"):
                event_factory(team=self.team, event="3rd action", distinct_id="2")
            with freeze_time("2012-03-15T04:01:34.000Z"):
                event_factory(team=self.team, event="4th action", distinct_id="2")

            # month
            month_response = sessions().run(
                Filter(
                    data={"date_from": "2012-01-01", "date_to": "2012-04-01", "interval": "month", "session": "avg"}
                ),
                self.team,
            )

            self.assertEqual(month_response[0]["data"][0], 180)
            self.assertEqual(month_response[0]["data"][2], 180)
            self.assertEqual(month_response[0]["labels"][0], "Tue. 31 January")
            self.assertEqual(month_response[0]["labels"][1], "Wed. 29 February")
            self.assertEqual(month_response[0]["days"][0], "2012-01-31")
            self.assertEqual(month_response[0]["days"][1], "2012-02-29")

            # # week
            week_response = sessions().run(
                Filter(data={"date_from": "2012-01-01", "date_to": "2012-02-01", "interval": "week", "session": "avg"}),
                self.team,
            )
            self.assertEqual(week_response[0]["data"][1], 240.0)
            self.assertEqual(week_response[0]["data"][3], 120.0)
            self.assertEqual(week_response[0]["labels"][0], "Sun. 1 January")
            self.assertEqual(week_response[0]["labels"][1], "Sun. 8 January")
            self.assertEqual(week_response[0]["days"][0], "2012-01-01")
            self.assertEqual(week_response[0]["days"][1], "2012-01-08")

            # # # hour
            hour_response = sessions().run(
                Filter(data={"date_from": "2012-03-14", "date_to": "2012-03-16", "interval": "hour", "session": "avg"}),
                self.team,
            )
            self.assertEqual(hour_response[0]["data"][3], 240.0)
            self.assertEqual(hour_response[0]["data"][27], 120.0)
            self.assertEqual(hour_response[0]["labels"][0], "Wed. 14 March, 00:00")
            self.assertEqual(hour_response[0]["labels"][1], "Wed. 14 March, 01:00")
            self.assertEqual(hour_response[0]["days"][0], "2012-03-14 00:00:00")
            self.assertEqual(hour_response[0]["days"][1], "2012-03-14 01:00:00")