Skip to content

Commit 8c0232b

Browse files
performance enhancements with cacheing, split out session metrics to a separate page
1 parent 88ec175 commit 8c0232b

File tree

7 files changed

+174
-81
lines changed

7 files changed

+174
-81
lines changed

.streamlit/pages.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,10 @@ icon = ":small_orange_diamond:"
6161
[[pages]]
6262
path = "app_pages/engagement_over_time.py"
6363
name = "Engagement Over Time"
64-
icon = ":small_orange_diamond:"
64+
icon = ":small_orange_diamond:"
65+
66+
[[pages]]
67+
path = "app_pages/unity_cr_engagement_metrics.py"
68+
name = "Unity and CR Session Metrics"
69+
icon = ":small_orange_diamond:"
70+

app_pages/Unity_vs_CR.py

Lines changed: 37 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
import ui_widgets as ui
77
import users
88
import metrics
9-
from pyinstrument import Profiler
10-
from pyinstrument.renderers.console import ConsoleRenderer
9+
from settings import get_logger
1110

1211
settings.initialize()
1312
settings.init_user_list()
@@ -17,6 +16,7 @@
1716

1817
ui.colorize_multiselect_options()
1918

19+
logger = settings.get_logger()
2020

2121
# --- Filter Row ---
2222
col_date, col_lang, col_country = st.columns((1, 1, 1), gap="large")
@@ -53,72 +53,43 @@
5353
with col_cr_head:
5454
st.markdown("<strong><div style='text-align: center;'>Curious Reader</div></strong>", unsafe_allow_html=True)
5555

56-
# --- Metrics + Funnels ---
57-
p = Profiler(async_mode="disabled")
58-
with p:
59-
if len(daterange) == 2 and countries_list:
6056

61-
# --- Get user cohorts ---
62-
user_cohort_list_unity = metrics.get_user_cohort_list(
63-
daterange=daterange,
64-
languages=language,
57+
if len(daterange) == 2 and countries_list:
58+
59+
# --- Get user cohorts ---
60+
user_cohort_list_unity = metrics.get_user_cohort_list(
61+
daterange=daterange,
62+
languages=language,
63+
countries_list=countries_list,
64+
app="Unity"
65+
)
66+
user_cohort_list_cr = metrics.get_user_cohort_list(
67+
daterange=daterange,
68+
languages=language,
69+
countries_list=countries_list,
70+
app="CR"
71+
)
72+
73+
col1, col2 = st.columns((1, 1), gap="large")
74+
75+
# --- Funnel Charts ---
76+
with col1:
77+
uic.create_funnels(
6578
countries_list=countries_list,
66-
app="Unity"
67-
)
68-
user_cohort_list_cr = metrics.get_user_cohort_list(
6979
daterange=daterange,
70-
languages=language,
71-
countries_list=countries_list,
72-
app="CR"
80+
app="Unity",
81+
key_prefix="u-1",
82+
languages=languages,
83+
user_list=user_cohort_list_unity
7384
)
7485

75-
# --- Calculate metrics ---
76-
metrics_unity = {
77-
"Avg # Sessions / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="engagement_event_count"),
78-
"Avg Total Play Time / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="total_time_minutes"),
79-
"Avg Session Length / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="avg_session_length_minutes"),
80-
"Active Span / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="active_span"),
81-
}
82-
83-
metrics_cr = {
84-
"Avg # Sessions / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="engagement_event_count"),
85-
"Avg Total Play Time / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="total_time_minutes"),
86-
"Avg Session Length / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="avg_session_length_minutes"),
87-
"Active Span / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="active_span"),
88-
}
89-
90-
# --- Metric Display Columns ---
91-
col_unity_metrics, col_cr_metrics = st.columns((1, 1), gap="large")
92-
93-
with col_unity_metrics:
94-
for label, value in metrics_unity.items():
95-
unit = " days" if "Span" in label else " min" if "Time" in label or "Length" in label else ""
96-
st.metric(label=label, value=f"{value:.2f}{unit}")
97-
98-
with col_cr_metrics:
99-
for label, value in metrics_cr.items():
100-
unit = " days" if "Span" in label else " min" if "Time" in label or "Length" in label else ""
101-
st.metric(label=label, value=f"{value:.2f}{unit}")
102-
103-
# --- Funnel Charts ---
104-
with col_unity_metrics:
105-
uic.create_funnels(
106-
countries_list=countries_list,
107-
daterange=daterange,
108-
app="Unity",
109-
key_prefix="u-1",
110-
languages=languages,
111-
user_list=user_cohort_list_unity
112-
)
113-
114-
with col_cr_metrics:
115-
uic.create_funnels(
116-
countries_list=countries_list,
117-
daterange=daterange,
118-
app="CR",
119-
funnel_size="compact",
120-
key_prefix="u-2",
121-
languages=languages,
122-
user_list=user_cohort_list_cr)
123-
124-
print(p.output(ConsoleRenderer(show_all=False,timeline=True,color=True,unicode=True,short_mode=False)))
86+
with col2:
87+
uic.create_funnels(
88+
countries_list=countries_list,
89+
daterange=daterange,
90+
app="CR",
91+
funnel_size="compact",
92+
key_prefix="u-2",
93+
languages=languages,
94+
user_list=user_cohort_list_cr)
95+
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import streamlit as st
2+
import settings
3+
from rich import print as rprint
4+
from millify import prettify
5+
import ui_components as uic
6+
import ui_widgets as ui
7+
import users
8+
import metrics
9+
from settings import get_logger
10+
11+
settings.initialize()
12+
settings.init_user_list()
13+
14+
ui.display_definitions_table("Data Notes",ui.data_notes)
15+
countries_list = users.get_country_list()
16+
17+
ui.colorize_multiselect_options()
18+
19+
logger = settings.get_logger()
20+
21+
# --- Filter Row ---
22+
col_date, col_lang, col_country = st.columns((1, 1, 1), gap="large")
23+
24+
with col_date:
25+
st.caption("Select a Date")
26+
selected_date, option = ui.calendar_selector(placement="middle")
27+
daterange = ui.convert_date_to_range(selected_date, option)
28+
29+
with col_lang:
30+
languages = users.get_language_list()
31+
language = ui.single_selector(
32+
languages, placement="middle", title="Select a language", key="acq-1"
33+
)
34+
35+
with col_country:
36+
countries_list = ui.multi_select_all(
37+
countries_list,
38+
title="Country Selection",
39+
key="acq-2",
40+
placement="middle"
41+
)
42+
43+
# --- Date Display ---
44+
if len(daterange) == 2:
45+
start = daterange[0].strftime("%b %d, %Y")
46+
end = daterange[1].strftime("%b %d, %Y")
47+
st.write(f"{start} to {end}")
48+
49+
# --- Header Row ---
50+
col_unity_head, col_cr_head = st.columns((1, 1), gap="large")
51+
with col_unity_head:
52+
st.markdown("<strong><div style='text-align: center;'>Unity</div></strong>", unsafe_allow_html=True)
53+
with col_cr_head:
54+
st.markdown("<strong><div style='text-align: center;'>Curious Reader</div></strong>", unsafe_allow_html=True)
55+
56+
57+
if len(daterange) == 2 and countries_list:
58+
59+
# --- Get user cohorts ---
60+
user_cohort_list_unity = metrics.get_user_cohort_list(
61+
daterange=daterange,
62+
languages=language,
63+
countries_list=countries_list,
64+
app="Unity"
65+
)
66+
user_cohort_list_cr = metrics.get_user_cohort_list(
67+
daterange=daterange,
68+
languages=language,
69+
countries_list=countries_list,
70+
app="CR"
71+
)
72+
73+
# --- Calculate metrics ---
74+
metrics_unity = {
75+
"Avg # Sessions / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="engagement_event_count"),
76+
"Avg Total Play Time / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="total_time_minutes"),
77+
"Avg Session Length / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="avg_session_length_minutes"),
78+
"Active Span / User": metrics.calculate_average_metric_per_user(user_cohort_list_unity, app="Unity", column_name="active_span"),
79+
}
80+
81+
metrics_cr = {
82+
"Avg # Sessions / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="engagement_event_count"),
83+
"Avg Total Play Time / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="total_time_minutes"),
84+
"Avg Session Length / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="avg_session_length_minutes"),
85+
"Active Span / User": metrics.calculate_average_metric_per_user(user_cohort_list_cr, app="CR", column_name="active_span"),
86+
}
87+
88+
# --- Metric Display Columns ---
89+
col_unity_metrics, col_cr_metrics = st.columns((1, 1), gap="large")
90+
91+
with col_unity_metrics:
92+
for label, value in metrics_unity.items():
93+
unit = " days" if "Span" in label else " min" if "Time" in label or "Length" in label else ""
94+
st.metric(label=label, value=f"{value:.2f}{unit}")
95+
96+
with col_cr_metrics:
97+
for label, value in metrics_cr.items():
98+
unit = " days" if "Span" in label else " min" if "Time" in label or "Length" in label else ""
99+
st.metric(label=label, value=f"{value:.2f}{unit}")
100+
101+

metrics.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def weeks_since(daterange):
180180

181181

182182
# Returns a DataFrame list of counts by language or counts by country
183-
#@st.cache_data(ttl="1d", show_spinner=False)
183+
@st.cache_data(ttl="1d", show_spinner=False)
184184
def get_counts(
185185
type="app_language",
186186
daterange=default_daterange,
@@ -266,7 +266,7 @@ def get_counts(
266266

267267
#Added new parameter user_list. If passed, only return the funnel based on that set of users
268268

269-
#@st.cache_data(ttl="1d", show_spinner=False)
269+
@st.cache_data(ttl="1d", show_spinner=False)
270270
def build_funnel_dataframe(
271271
index_col="language",
272272
daterange=default_daterange,
@@ -469,7 +469,7 @@ def add_level_percents(df):
469469

470470

471471
# Get the campaign data and filter by date, language, and country selections
472-
#@st.cache_data(ttl="1d", show_spinner=False)
472+
@st.cache_data(ttl="1d", show_spinner=False)
473473
def filter_campaigns(df_campaigns_all,daterange,selected_languages,countries_list):
474474

475475
# Drop the campaigns that don't meet the naming convention
@@ -514,7 +514,6 @@ def get_month_ranges(start_date, end_date):
514514
return month_ranges
515515

516516
#Returns a dataframe of the totals of a stat for each month
517-
#@st.cache_data(ttl="1d", show_spinner=False)
518517
def get_totals_per_month(daterange, stat, countries_list, language):
519518
# First, get all campaign data
520519
df_campaigns_all = st.session_state["df_campaigns_all"]
@@ -560,7 +559,7 @@ def get_totals_per_month(daterange, stat, countries_list, language):
560559
# Display the DataFrame
561560
return df_totals
562561

563-
#@st.cache_data(ttl="1d", show_spinner=False)
562+
@st.cache_data(ttl="1d", show_spinner=False)
564563
def get_date_cohort_dataframe(
565564
daterange=default_daterange,
566565
languages=["All"],
@@ -618,7 +617,7 @@ def get_user_cohort_list(
618617
return user_cohort_df
619618

620619

621-
#@st.cache_data(ttl="1d", show_spinner=False)
620+
622621
def calculate_average_metric_per_user(user_cohort_list, app, column_name):
623622
df_cr_app_launch = st.session_state["df_cr_app_launch"]
624623
df_unity_users = st.session_state["df_unity_users"]
@@ -633,7 +632,9 @@ def calculate_average_metric_per_user(user_cohort_list, app, column_name):
633632
df_filtered = df_unity_users[df_unity_users["user_pseudo_id"].isin(user_cohort_list)]
634633

635634
# Sum the selected column and calculate the average
636-
total = df_filtered[column_name].sum()
635+
import numpy as np
636+
637+
total = np.sum(df_filtered[column_name].values)
637638

638639
average = total / len(user_cohort_list)
639640

settings.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@
1212

1313
default_daterange = [dt.datetime(2021, 1, 1).date(), dt.date.today()]
1414

15+
import logging
16+
17+
def get_logger(name="dashboard_logger"):
18+
logger = logging.getLogger(name)
19+
if not logger.handlers:
20+
logger.setLevel(logging.DEBUG)
21+
22+
# Console handler or file handler
23+
handler = logging.StreamHandler() # or logging.FileHandler("logs/app.log")
24+
25+
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
26+
handler.setFormatter(formatter)
27+
28+
logger.addHandler(handler)
29+
logger.propagate = False # Prevent double logging
30+
return logger
1531

1632
def get_gcp_credentials():
1733
# first get credentials to secret manager

ui_components.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ def lrc_scatter_chart(option,display_category,df_campaigns,daterange):
359359
st.write("No data for selected period")
360360

361361

362-
#@st.cache_data(ttl="1d", show_spinner=False)
362+
@st.cache_data(ttl="1d", show_spinner=False)
363363
def spend_by_country_map(df_campaigns,source):
364364

365365
if source == 'Both':
@@ -402,7 +402,6 @@ def spend_by_country_map(df_campaigns,source):
402402
st.plotly_chart(country_fig)
403403

404404

405-
@st.cache_data(ttl="1d", show_spinner=False)
406405
def campaign_funnel_chart():
407406
df_campaigns = st.session_state.df_campaigns
408407
impressions = df_campaigns["impressions"].sum()
@@ -603,8 +602,6 @@ def funnel_change_line_chart(df, graph_type='sum'):
603602
st.plotly_chart(fig, use_container_width=True)
604603

605604

606-
607-
@st.cache_data(ttl="1d", show_spinner=False)
608605
def top_campaigns_by_downloads_barchart(n):
609606
df_campaigns = st.session_state.df_campaigns
610607
df = df_campaigns.filter(["campaign_name", "mobile_app_install"], axis=1)
@@ -942,7 +939,7 @@ def top_and_bottom_languages_per_level(selection, min_LR):
942939

943940

944941
#Added user_list which is a list of cr_user_id to filter with
945-
#@st.cache_data(ttl="1d", show_spinner=False)
942+
946943
def create_funnels(countries_list=["All"],
947944
daterange=default_daterange,
948945
languages=["All"],

users.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pyinstrument import Profiler
66
from pyinstrument.renderers.console import ConsoleRenderer
77
import asyncio
8+
import settings
89

910

1011
# How far back to obtain user data. Currently the queries pull back to 01/01/2021
@@ -103,8 +104,8 @@ async def run_query(query):
103104
max_level_indices_unity = df_unity_users.groupby('user_pseudo_id')['max_user_level'].idxmax()
104105
df_unity_users = df_unity_users.loc[max_level_indices_unity].reset_index()
105106

106-
107-
print(p.output(ConsoleRenderer(show_all=False,timeline=True,color=True,unicode=True,short_mode=True)))
107+
logger = settings.get_logger()
108+
logger.debug(p.output(ConsoleRenderer(show_all=False,timeline=True,color=True,unicode=True,short_mode=False)))
108109

109110
return df_cr_users, df_unity_users, df_cr_app_launch
110111

0 commit comments

Comments
 (0)