Skip to content

Commit

Permalink
merge masteR
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasheriques committed Mar 1, 2025
2 parents d61f2f9 + e6cdfed commit d24ce77
Show file tree
Hide file tree
Showing 71 changed files with 789 additions and 867 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime
import json
from typing import Any
import posthoganalytics
Expand Down Expand Up @@ -39,6 +40,11 @@
"when a count task for a playlist is unknown",
)

REPLAY_TEAM_PLAYLIST_COUNT_SKIPPED = Counter(
"replay_playlist_count_skipped",
"when a count task for a playlist is skipped because the cooldown period has not passed",
)

REPLAY_PLAYLIST_COUNT_TIMER = Histogram(
"replay_playlist_with_filters_count_timer_seconds",
"Time spent loading session recordings that match filters in a playlist in seconds",
Expand Down Expand Up @@ -141,14 +147,34 @@ def count_recordings_that_match_playlist_filters(playlist_id: int) -> None:
try:
with REPLAY_PLAYLIST_COUNT_TIMER.time():
playlist = SessionRecordingPlaylist.objects.get(id=playlist_id)
redis_client = get_client()

existing_value = redis_client.get(f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}")
if existing_value:
existing_value = json.loads(existing_value)
else:
existing_value = {}

if existing_value.get("refreshed_at"):
last_refreshed_at = datetime.fromisoformat(existing_value["refreshed_at"])
seconds_since_refresh = int((datetime.now() - last_refreshed_at).total_seconds())

if seconds_since_refresh <= settings.PLAYLIST_COUNTER_PROCESSING_COOLDOWN_SECONDS:
REPLAY_TEAM_PLAYLIST_COUNT_SKIPPED.inc()
return

query = convert_universal_filters_to_recordings_query(playlist.filters)
(recordings, more_recordings_available, _) = list_recordings_from_query(
query, user=None, team=playlist.team
)

redis_client = get_client()
value_to_set = json.dumps(
{"session_ids": [r.session_id for r in recordings], "has_more": more_recordings_available}
{
"session_ids": [r.session_id for r in recordings],
"has_more": more_recordings_available,
"previous_ids": existing_value.get("session_ids", None),
"refreshed_at": datetime.now().isoformat(),
}
)
redis_client.setex(
f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}", THIRTY_SIX_HOURS_IN_SECONDS, value_to_set
Expand All @@ -159,17 +185,27 @@ def count_recordings_that_match_playlist_filters(playlist_id: int) -> None:
logger.info("Playlist does not exist", playlist_id=playlist_id)
REPLAY_TEAM_PLAYLIST_COUNT_UNKNOWN.inc()
except Exception as e:
posthoganalytics.capture_exception(e)
posthoganalytics.capture_exception(
e, properties={"playlist_id": playlist_id, "posthog_feature": "session_replay_playlist_counters"}
)
logger.exception("Failed to count recordings that match playlist filters", playlist_id=playlist_id, error=e)
REPLAY_TEAM_PLAYLIST_COUNT_FAILED.inc()


def enqueue_recordings_that_match_playlist_filters() -> None:
teams_with_counter_processing = settings.PLAYLIST_COUNTER_PROCESSING_ALLOWED_TEAMS
if not settings.PLAYLIST_COUNTER_PROCESSING_MAX_ALLOWED_TEAM_ID or not isinstance(
settings.PLAYLIST_COUNTER_PROCESSING_MAX_ALLOWED_TEAM_ID, int
):
raise Exception("PLAYLIST_COUNTER_PROCESSING_MAX_ALLOWED_TEAM_ID is not set")

for team in teams_with_counter_processing:
all_playlists = SessionRecordingPlaylist.objects.filter(team_id=int(team), deleted=False, filters__isnull=False)
REPLAY_TEAM_PLAYLISTS_IN_TEAM_COUNT.inc(all_playlists.count())
if settings.PLAYLIST_COUNTER_PROCESSING_MAX_ALLOWED_TEAM_ID == 0:
# If we're not processing any teams, we don't need to enqueue anything
return

all_playlists = SessionRecordingPlaylist.objects.filter(
team_id__lte=int(settings.PLAYLIST_COUNTER_PROCESSING_MAX_ALLOWED_TEAM_ID), deleted=False, filters__isnull=False
)
REPLAY_TEAM_PLAYLISTS_IN_TEAM_COUNT.inc(all_playlists.count())

for playlist in all_playlists:
count_recordings_that_match_playlist_filters.delay(playlist.id)
for playlist in all_playlists:
count_recordings_that_match_playlist_filters.delay(playlist.id)
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from datetime import datetime, timedelta
import json
from unittest import mock
from unittest.mock import MagicMock, patch
from ee.session_recordings.playlist_counters.recordings_that_match_playlist_filters import (
count_recordings_that_match_playlist_filters,
Expand Down Expand Up @@ -38,7 +40,9 @@ def test_count_recordings_that_match_no_recordings(

assert json.loads(self.redis_client.get(f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}")) == {
"session_ids": [],
"previous_ids": None,
"has_more": False,
"refreshed_at": mock.ANY,
}

@patch("posthoganalytics.capture_exception")
Expand Down Expand Up @@ -66,5 +70,64 @@ def test_count_recordings_that_match_recordings(

assert json.loads(self.redis_client.get(f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}")) == {
"session_ids": ["123"],
"previous_ids": None,
"has_more": True,
"refreshed_at": mock.ANY,
}

@patch("posthoganalytics.capture_exception")
@patch("ee.session_recordings.playlist_counters.recordings_that_match_playlist_filters.list_recordings_from_query")
def test_count_recordings_that_match_recordings_records_previous_ids(
self, mock_list_recordings_from_query: MagicMock, mock_capture_exception: MagicMock
):
mock_list_recordings_from_query.return_value = (
[
SessionRecording.objects.create(
team=self.team,
session_id="123",
)
],
True,
None,
)
playlist = SessionRecordingPlaylist.objects.create(
team=self.team,
name="test",
filters={},
)
self.redis_client.set(
f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}", json.dumps({"session_ids": ["245"], "has_more": True})
)
count_recordings_that_match_playlist_filters(playlist.id)
mock_capture_exception.assert_not_called()

assert json.loads(self.redis_client.get(f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}")) == {
"session_ids": ["123"],
"has_more": True,
"previous_ids": ["245"],
"refreshed_at": mock.ANY,
}

@patch("posthoganalytics.capture_exception")
@patch("ee.session_recordings.playlist_counters.recordings_that_match_playlist_filters.list_recordings_from_query")
def test_count_recordings_that_match_recordings_skips_cooldown(
self, mock_list_recordings_from_query: MagicMock, mock_capture_exception: MagicMock
):
mock_list_recordings_from_query.return_value = ([], False, None)

playlist = SessionRecordingPlaylist.objects.create(
team=self.team,
name="test",
filters={},
)
existing_value = {"refreshed_at": (datetime.now() - timedelta(seconds=3600)).isoformat()}
self.redis_client.set(f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}", json.dumps(existing_value))

count_recordings_that_match_playlist_filters(playlist.id)

mock_list_recordings_from_query.assert_not_called()
mock_capture_exception.assert_not_called()

assert self.redis_client.get(f"{PLAYLIST_COUNT_REDIS_PREFIX}{playlist.short_id}").decode("utf-8") == json.dumps(
existing_value
)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/exporter-exporter--dashboard--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-insights--retention--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/scenes-app-insights--retention--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions frontend/src/exporter/Exporter.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,6 @@ FunnelTimeToConvertInsight.args = {
export const RetentionInsight: Story = Template.bind({})
RetentionInsight.args = { insight: require('../mocks/fixtures/api/projects/team_id/insights/retention.json') }

export const RetentionBreakdownInsight: Story = Template.bind({})
RetentionBreakdownInsight.args = {
insight: require('../mocks/fixtures/api/projects/team_id/insights/retentionBreakdown.json'),
}

export const LifecycleInsight: Story = Template.bind({})
LifecycleInsight.args = { insight: require('../mocks/fixtures/api/projects/team_id/insights/lifecycle.json') }
LifecycleInsight.tags = ['test-skip'] // doesn't produce a helpful reference image, as canvas can't be captured
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export const FEATURE_FLAGS = {
SURVEYS_CUSTOM_FONTS: 'surveys-custom-fonts', // owner: #team-surveys
YEAR_IN_HOG: 'year-in-hog', // owner: #team-replay
SESSION_REPLAY_EXPORT_MOBILE_DATA: 'session-replay-export-mobile-data', // owner: #team-replay
DISCUSSIONS: 'discussions', // owner: #team-replay
DISCUSSIONS: 'discussions', // owner: @daibhin @benjackwhite
REDIRECT_INSIGHT_CREATION_PRODUCT_ANALYTICS_ONBOARDING: 'redirect-insight-creation-product-analytics-onboarding', // owner: @biancayang
AI_SESSION_SUMMARY: 'ai-session-summary', // owner: #team-replay
AI_SESSION_PERMISSIONS: 'ai-session-permissions', // owner: #team-replay
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
}
],
"label": "Day 0",
"date": "2022-03-04T00:00:00Z",
"date": "2022-03-01T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B0%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand Down Expand Up @@ -127,7 +127,7 @@
}
],
"label": "Day 1",
"date": "2022-03-05T00:00:00Z",
"date": "2022-03-02T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B1%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand Down Expand Up @@ -170,7 +170,7 @@
}
],
"label": "Day 2",
"date": "2022-03-06T00:00:00Z",
"date": "2022-03-03T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B2%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand Down Expand Up @@ -213,7 +213,7 @@
}
],
"label": "Day 3",
"date": "2022-03-07T00:00:00Z",
"date": "2022-03-04T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B3%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand Down Expand Up @@ -252,7 +252,7 @@
}
],
"label": "Day 4",
"date": "2022-03-08T00:00:00Z",
"date": "2022-03-05T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B4%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand Down Expand Up @@ -285,7 +285,7 @@
}
],
"label": "Day 5",
"date": "2022-03-09T00:00:00Z",
"date": "2022-03-06T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B5%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand Down Expand Up @@ -314,7 +314,7 @@
}
],
"label": "Day 6",
"date": "2022-03-10T00:00:00Z",
"date": "2022-03-07T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B6%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand All @@ -339,7 +339,7 @@
}
],
"label": "Day 7",
"date": "2022-03-11T00:00:00Z",
"date": "2022-03-08T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B7%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand All @@ -358,7 +358,7 @@
}
],
"label": "Day 8",
"date": "2022-03-12T00:00:00Z",
"date": "2022-03-09T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B8%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand All @@ -373,7 +373,7 @@
}
],
"label": "Day 9",
"date": "2022-03-13T00:00:00Z",
"date": "2022-03-10T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B9%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
},
{
Expand All @@ -385,7 +385,7 @@
}
],
"label": "Day 10",
"date": "2022-03-14T00:00:00Z",
"date": "2022-03-11T00:00:00Z",
"people_url": "/api/person/retention/?breakdown_values=%5B10%5D&display=ActionsTable&insight=RETENTION&period=Day&retention_type=retention_first_time&returning_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&target_entity=%7B%22id%22%3A+%22%24pageview%22%2C+%22type%22%3A+%22events%22%2C+%22order%22%3A+null%2C+%22name%22%3A+%22%24pageview%22%2C+%22custom_name%22%3A+null%2C+%22math%22%3A+null%2C+%22math_property%22%3A+null%2C+%22math_group_type_index%22%3A+null%2C+%22properties%22%3A+%7B%7D%7D&total_intervals=11"
}
],
Expand Down
Loading

0 comments on commit d24ce77

Please sign in to comment.