[APP-1782] Analytics migration (#9734)
* WIP * Clean up growthbook code, integrate into init and sessions * Move everything out of React * Add metrics client * Move to separate file * Shared metadata cache * Ensure we update metadata when session ID changes * Ensure userMetadata is cleared when logging out * WIP revamp * Integrate feature gates into analytics context * Clean up old code * Fix useMeta util * Some comments and cleanup * Add logger to base analytics context * Refactor current route handling * Rip out LogEvent from navigation * Update tracking endpoint * Migrate toClout * Clear out statsig client * Add todo, reset logger readme * Ope fix statsig noop * Refactor logging in feed-feedback, add debug logging to metrics client * Remove LogEvents alias for Metrics * Prefer root package export * Remove Metrics alias from logger * [APP-1782] Migrate to new analytics APIs (#9735) * Migrate logEvent to useAnalytics * Migrate logger.metric to useAnalytics * Migrate tricky spot, fix types * Migrate remaining tricky spot * Missed one * Remove metric() from logger * Migrate useGate to useAnalytics * Remove all other StatSig mentions * Update event payload * Update logger tests * Mock expo method * Fix session ID bug * Add session ID test * Add test for metrics client * Clarify intent * Clean up core analytics file * Clean up the call once utils * Fix TODO * Fix TODO * Fix TODO * Fix TODO * Fix TODO * Remove debug code * Fix navigation context * OK nav context is not working, todo * Checkpoint: works but feels hacky * Fix navigation context issue * Improve feature API * Improve metric logging * Update logger tests
This commit is contained in:
@@ -13,8 +13,6 @@ import * as bcp47Match from 'bcp-47-match'
|
||||
import {popularInterests, useInterestsDisplayNames} from '#/lib/interests'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {logger} from '#/logger'
|
||||
import {type MetricEvents} from '#/logger/metrics'
|
||||
import {useLanguagePrefs} from '#/state/preferences/languages'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {RQKEY_ROOT as useActorSearchQueryKeyRoot} from '#/state/queries/actor-search'
|
||||
@@ -68,6 +66,7 @@ import {Loader} from '#/components/Loader'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {SubtleHover} from '#/components/SubtleHover'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {type Metrics, useAnalytics} from '#/analytics'
|
||||
import {ExploreScreenLiveEventFeedsBanner} from '#/features/liveEvents/components/ExploreScreenLiveEventFeedsBanner'
|
||||
import * as ModuleHeader from './components/ModuleHeader'
|
||||
import {
|
||||
@@ -124,7 +123,7 @@ type ExploreScreenItems =
|
||||
bottomBorder?: boolean
|
||||
searchButton?: {
|
||||
label: string
|
||||
metricsTag: MetricEvents['explore:module:searchButtonPress']['module']
|
||||
metricsTag: Metrics['explore:module:searchButtonPress']['module']
|
||||
tab: 'user' | 'profile' | 'feed'
|
||||
}
|
||||
}
|
||||
@@ -135,7 +134,7 @@ type ExploreScreenItems =
|
||||
icon: React.ComponentType<SVGIconProps>
|
||||
searchButton?: {
|
||||
label: string
|
||||
metricsTag: MetricEvents['explore:module:searchButtonPress']['module']
|
||||
metricsTag: Metrics['explore:module:searchButtonPress']['module']
|
||||
tab: 'user' | 'profile' | 'feed'
|
||||
}
|
||||
hideDefaultTab?: boolean
|
||||
@@ -213,6 +212,7 @@ export function Explore({
|
||||
focusSearchInput: (tab: 'user' | 'profile' | 'feed') => void
|
||||
headerHeight: number
|
||||
}) {
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const {data: preferences, error: preferencesError} = usePreferencesQuery()
|
||||
@@ -273,9 +273,10 @@ export function Explore({
|
||||
try {
|
||||
await fetchNextFeedsPage()
|
||||
} catch (err) {
|
||||
logger.error('Failed to load more suggested follows', {message: err})
|
||||
ax.logger.error('Failed to load more suggested follows', {message: err})
|
||||
}
|
||||
}, [
|
||||
ax,
|
||||
isFetchingNextFeedsPage,
|
||||
hasNextFeedsPage,
|
||||
feedsError,
|
||||
@@ -333,9 +334,10 @@ export function Explore({
|
||||
try {
|
||||
await fetchNextPageFeedPreviews()
|
||||
} catch (err) {
|
||||
logger.error('Failed to load more feed previews', {message: err})
|
||||
ax.logger.error('Failed to load more feed previews', {message: err})
|
||||
}
|
||||
}, [
|
||||
ax,
|
||||
isPendingFeedPreviews,
|
||||
isFetchingNextPageFeedPreviews,
|
||||
hasNextPageFeedPreviews,
|
||||
@@ -492,11 +494,7 @@ export function Explore({
|
||||
if (hasPressedLoadMoreFeeds && index < 6) {
|
||||
continue
|
||||
}
|
||||
logger.metric(
|
||||
'feed:suggestion:seen',
|
||||
{feedUrl: item.feed.uri},
|
||||
{statsig: false},
|
||||
)
|
||||
ax.metric('feed:suggestion:seen', {feedUrl: item.feed.uri})
|
||||
}
|
||||
}
|
||||
if (!hasPressedLoadMoreFeeds) {
|
||||
@@ -609,6 +607,7 @@ export function Explore({
|
||||
return i
|
||||
}, [
|
||||
_,
|
||||
ax,
|
||||
useFullExperience,
|
||||
suggestedFeeds,
|
||||
preferences,
|
||||
@@ -729,12 +728,7 @@ export function Explore({
|
||||
<ModuleHeader.SearchButton
|
||||
{...item.searchButton}
|
||||
onPress={() =>
|
||||
focusSearchInput(
|
||||
(item.searchButton?.tab || 'user') as
|
||||
| 'user'
|
||||
| 'profile'
|
||||
| 'feed',
|
||||
)
|
||||
focusSearchInput(item.searchButton?.tab || 'user')
|
||||
}
|
||||
/>
|
||||
)}
|
||||
@@ -751,12 +745,7 @@ export function Explore({
|
||||
<ModuleHeader.SearchButton
|
||||
{...item.searchButton}
|
||||
onPress={() =>
|
||||
focusSearchInput(
|
||||
(item.searchButton?.tab || 'user') as
|
||||
| 'user'
|
||||
| 'profile'
|
||||
| 'feed',
|
||||
)
|
||||
focusSearchInput(item.searchButton?.tab || 'user')
|
||||
}
|
||||
/>
|
||||
)}
|
||||
@@ -822,7 +811,7 @@ export function Explore({
|
||||
if (!useFullExperience) {
|
||||
return
|
||||
}
|
||||
logger.metric('feed:suggestion:press', {
|
||||
ax.metric('feed:suggestion:press', {
|
||||
feedUrl: item.feed.uri,
|
||||
})
|
||||
}}
|
||||
@@ -1011,6 +1000,7 @@ export function Explore({
|
||||
}
|
||||
},
|
||||
[
|
||||
ax,
|
||||
t.atoms.border_contrast_low,
|
||||
t.atoms.bg_contrast_25,
|
||||
t.atoms.text_contrast_medium,
|
||||
@@ -1043,7 +1033,7 @@ export function Explore({
|
||||
const seenProfilesRef = useRef<Set<string>>(new Set())
|
||||
const onItemSeen = useCallback(
|
||||
(item: ExploreScreenItems) => {
|
||||
let module: MetricEvents['explore:module:seen']['module']
|
||||
let module: Metrics['explore:module:seen']['module']
|
||||
if (item.type === 'trendingTopics' || item.type === 'trendingVideos') {
|
||||
module = item.type
|
||||
} else if (item.type === 'profile') {
|
||||
@@ -1054,17 +1044,13 @@ export function Explore({
|
||||
const position = suggestedFollowsModule.findIndex(
|
||||
i => i.type === 'profile' && i.profile.did === item.profile.did,
|
||||
)
|
||||
logger.metric(
|
||||
'suggestedUser:seen',
|
||||
{
|
||||
logContext: 'Explore',
|
||||
recId: item.recId,
|
||||
position: position !== -1 ? position - 1 : 0, // -1 to account for header
|
||||
suggestedDid: item.profile.did,
|
||||
category: null,
|
||||
},
|
||||
{statsig: true},
|
||||
)
|
||||
ax.metric('suggestedUser:seen', {
|
||||
logContext: 'Explore',
|
||||
recId: item.recId,
|
||||
position: position !== -1 ? position - 1 : 0, // -1 to account for header
|
||||
suggestedDid: item.profile.did,
|
||||
category: null,
|
||||
})
|
||||
}
|
||||
} else if (item.type === 'feed') {
|
||||
module = 'suggestedFeeds'
|
||||
@@ -1077,10 +1063,10 @@ export function Explore({
|
||||
}
|
||||
if (!alreadyReportedRef.current.has(module)) {
|
||||
alreadyReportedRef.current.set(module, module)
|
||||
logger.metric('explore:module:seen', {module}, {statsig: false})
|
||||
ax.metric('explore:module:seen', {module})
|
||||
}
|
||||
},
|
||||
[suggestedFollowsModule],
|
||||
[ax, suggestedFollowsModule],
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user