diff options
author | Hailey <me@haileyok.com> | 2024-11-15 11:40:43 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-15 11:40:43 -0800 |
commit | 3bd14371330abf902690dff9b3f0f2036ef472e5 (patch) | |
tree | 641df6c63773a7784d435add9f7ee80fd9bc97c9 | |
parent | 400c4322833d9cd4a6fb1e322c9ba844d85eff10 (diff) | |
download | voidsky-3bd14371330abf902690dff9b3f0f2036ef472e5.tar.zst |
[Statsig] Remove client downsampling (#6153)
-rw-r--r-- | src/Navigation.tsx | 2 | ||||
-rw-r--r-- | src/components/ProfileCard.tsx | 4 | ||||
-rw-r--r-- | src/components/hooks/useFollowMethods.ts | 4 | ||||
-rw-r--r-- | src/lib/statsig/events.ts | 30 | ||||
-rw-r--r-- | src/lib/statsig/statsig.tsx | 42 | ||||
-rw-r--r-- | src/state/feed-feedback.tsx | 6 | ||||
-rw-r--r-- | src/state/queries/post.ts | 24 | ||||
-rw-r--r-- | src/state/queries/profile.ts | 12 | ||||
-rw-r--r-- | src/view/com/feeds/FeedPage.tsx | 4 | ||||
-rw-r--r-- | src/view/com/pager/Pager.tsx | 6 | ||||
-rw-r--r-- | src/view/com/pager/Pager.web.tsx | 9 | ||||
-rw-r--r-- | src/view/com/posts/Feed.tsx | 4 | ||||
-rw-r--r-- | src/view/screens/Home.tsx | 9 |
13 files changed, 57 insertions, 99 deletions
diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 0ab4bb613..1806df92e 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -696,7 +696,7 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) { onStateChange={() => { const routeName = getCurrentRouteName() if (routeName === 'Notifications') { - logEvent('router:navigate:notifications:sampled', {}) + logEvent('router:navigate:notifications', {}) } }} onReady={() => { diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx index 50b34ba99..668bd0f3c 100644 --- a/src/components/ProfileCard.tsx +++ b/src/components/ProfileCard.tsx @@ -283,8 +283,8 @@ export function DescriptionPlaceholder({ export type FollowButtonProps = { profile: AppBskyActorDefs.ProfileViewBasic moderationOpts: ModerationOpts - logContext: LogEvents['profile:follow:sampled']['logContext'] & - LogEvents['profile:unfollow:sampled']['logContext'] + logContext: LogEvents['profile:follow']['logContext'] & + LogEvents['profile:unfollow']['logContext'] } & Partial<ButtonProps> export function FollowButton(props: FollowButtonProps) { diff --git a/src/components/hooks/useFollowMethods.ts b/src/components/hooks/useFollowMethods.ts index 31a1e43da..d67c3690f 100644 --- a/src/components/hooks/useFollowMethods.ts +++ b/src/components/hooks/useFollowMethods.ts @@ -15,8 +15,8 @@ export function useFollowMethods({ logContext, }: { profile: Shadow<AppBskyActorDefs.ProfileViewBasic> - logContext: LogEvents['profile:follow:sampled']['logContext'] & - LogEvents['profile:unfollow:sampled']['logContext'] + logContext: LogEvents['profile:follow']['logContext'] & + LogEvents['profile:unfollow']['logContext'] }) { const {_} = useLingui() const requireAuth = useRequireAuth() diff --git a/src/lib/statsig/events.ts b/src/lib/statsig/events.ts index 8f8504021..f8c6d181c 100644 --- a/src/lib/statsig/events.ts +++ b/src/lib/statsig/events.ts @@ -21,11 +21,11 @@ export type LogEvents = { context: 'StartOnboarding' | 'AfterOnboarding' | 'Login' | 'Home' status: 'granted' | 'denied' | 'undetermined' } - 'state:background:sampled': { + 'state:background': { secondsActive: number } - 'state:foreground:sampled': {} - 'router:navigate:notifications:sampled': {} + 'state:foreground': {} + 'router:navigate:notifications': {} 'deepLink:referrerReceived': { to: string referrer: string @@ -76,7 +76,7 @@ export type LogEvents = { 'onboarding:finished:avatarResult': { avatarResult: 'default' | 'created' | 'uploaded' } - 'home:feedDisplayed:sampled': { + 'home:feedDisplayed': { feedUrl: string feedType: string index: number @@ -87,12 +87,12 @@ export type LogEvents = { | 'desktop-sidebar-click' | 'starter-pack-initial-feed' } - 'feed:endReached:sampled': { + 'feed:endReached': { feedUrl: string feedType: string itemCount: number } - 'feed:refresh:sampled': { + 'feed:refresh': { feedUrl: string feedType: string reason: 'pull-to-refresh' | 'soft-reset' | 'load-latest' @@ -103,13 +103,13 @@ export type LogEvents = { 'discover:showLess': { feedContext: string } - 'discover:clickthrough:sampled': { + 'discover:clickthrough': { count: number } - 'discover:engaged:sampled': { + 'discover:engaged': { count: number } - 'discover:seen:sampled': { + 'discover:seen': { count: number } @@ -132,27 +132,27 @@ export type LogEvents = { postCount: number isReply: boolean } - 'post:like:sampled': { + 'post:like': { doesLikerFollowPoster: boolean | undefined doesPosterFollowLiker: boolean | undefined likerClout: number | undefined postClout: number | undefined logContext: 'FeedItem' | 'PostThreadItem' | 'Post' } - 'post:repost:sampled': { + 'post:repost': { logContext: 'FeedItem' | 'PostThreadItem' | 'Post' } - 'post:unlike:sampled': { + 'post:unlike': { logContext: 'FeedItem' | 'PostThreadItem' | 'Post' } - 'post:unrepost:sampled': { + 'post:unrepost': { logContext: 'FeedItem' | 'PostThreadItem' | 'Post' } 'post:mute': {} 'post:unmute': {} 'post:pin': {} 'post:unpin': {} - 'profile:follow:sampled': { + 'profile:follow': { didBecomeMutual: boolean | undefined followeeClout: number | undefined followerClout: number | undefined @@ -169,7 +169,7 @@ export type LogEvents = { | 'FeedInterstitial' | 'ProfileHeaderSuggestedFollows' } - 'profile:unfollow:sampled': { + 'profile:unfollow': { logContext: | 'RecommendedFollowsItem' | 'PostThreadItem' diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx index 36bd54e2a..51d7eb98e 100644 --- a/src/lib/statsig/statsig.tsx +++ b/src/lib/statsig/statsig.tsx @@ -59,6 +59,7 @@ function createStatsigOptions(prefetchUsers: StatsigUser[]) { initTimeoutMs: 1, // Get fresh flags for other accounts as well, if any. prefetchUsers, + api: 'https://events.bsky.app/v2', } } @@ -89,51 +90,14 @@ export function toClout(n: number | null | undefined): number | undefined { } } -const DOWNSAMPLE_RATE = 0.99 // 99% likely -const DOWNSAMPLED_EVENTS: Set<keyof LogEvents> = new Set([ - 'router:navigate:notifications:sampled', - 'state:background:sampled', - 'state:foreground:sampled', - 'home:feedDisplayed:sampled', - 'feed:endReached:sampled', - 'feed:refresh:sampled', - 'discover:clickthrough:sampled', - 'discover:engaged:sampled', - 'discover:seen:sampled', - 'post:like:sampled', - 'post:unlike:sampled', - 'post:repost:sampled', - 'post:unrepost:sampled', - 'profile:follow:sampled', - 'profile:unfollow:sampled', -]) -const isDownsampledSession = Math.random() < DOWNSAMPLE_RATE - export function logEvent<E extends keyof LogEvents>( eventName: E & string, rawMetadata: LogEvents[E] & FlatJSONRecord, ) { try { - if ( - process.env.NODE_ENV === 'development' && - eventName.endsWith(':sampled') && - !DOWNSAMPLED_EVENTS.has(eventName) - ) { - logger.error( - 'Did you forget to add ' + eventName + ' to DOWNSAMPLED_EVENTS?', - ) - } - - const isDownsampledEvent = DOWNSAMPLED_EVENTS.has(eventName) - if (isDownsampledSession && isDownsampledEvent) { - return - } const fullMetadata = { ...rawMetadata, } as Record<string, string> // Statsig typings are unnecessarily strict here. - if (isDownsampledEvent) { - fullMetadata.downsampleRate = DOWNSAMPLE_RATE.toString() - } fullMetadata.routeName = getCurrentRouteName() ?? '(Uninitialized)' if (Statsig.initializeCalled()) { Statsig.logEvent(eventName, null, fullMetadata) @@ -232,13 +196,13 @@ AppState.addEventListener('change', (state: AppStateStatus) => { lastState = state if (state === 'active') { lastActive = performance.now() - logEvent('state:foreground:sampled', {}) + logEvent('state:foreground', {}) } else { let secondsActive = 0 if (lastActive != null) { secondsActive = Math.round((performance.now() - lastActive) / 1e3) lastActive = null - logEvent('state:background:sampled', { + logEvent('state:background', { secondsActive, }) } diff --git a/src/state/feed-feedback.tsx b/src/state/feed-feedback.tsx index 41579edc1..eaf6529f3 100644 --- a/src/state/feed-feedback.tsx +++ b/src/state/feed-feedback.tsx @@ -234,21 +234,21 @@ function flushToStatsig(stats: AggregatedStats | null) { } if (stats.clickthroughCount > 0) { - logEvent('discover:clickthrough:sampled', { + logEvent('discover:clickthrough', { count: stats.clickthroughCount, }) stats.clickthroughCount = 0 } if (stats.engagedCount > 0) { - logEvent('discover:engaged:sampled', { + logEvent('discover:engaged', { count: stats.engagedCount, }) stats.engagedCount = 0 } if (stats.seenCount > 0) { - logEvent('discover:seen:sampled', { + logEvent('discover:seen', { count: stats.seenCount, }) stats.seenCount = 0 diff --git a/src/state/queries/post.ts b/src/state/queries/post.ts index 7023580bb..7052590ca 100644 --- a/src/state/queries/post.ts +++ b/src/state/queries/post.ts @@ -98,8 +98,8 @@ export function useGetPosts() { export function usePostLikeMutationQueue( post: Shadow<AppBskyFeedDefs.PostView>, - logContext: LogEvents['post:like:sampled']['logContext'] & - LogEvents['post:unlike:sampled']['logContext'], + logContext: LogEvents['post:like']['logContext'] & + LogEvents['post:unlike']['logContext'], ) { const queryClient = useQueryClient() const postUri = post.uri @@ -157,7 +157,7 @@ export function usePostLikeMutationQueue( } function usePostLikeMutation( - logContext: LogEvents['post:like:sampled']['logContext'], + logContext: LogEvents['post:like']['logContext'], post: Shadow<AppBskyFeedDefs.PostView>, ) { const {currentAccount} = useSession() @@ -174,7 +174,7 @@ function usePostLikeMutation( if (currentAccount) { ownProfile = findProfileQueryData(queryClient, currentAccount.did) } - logEvent('post:like:sampled', { + logEvent('post:like', { logContext, doesPosterFollowLiker: postAuthor.viewer ? Boolean(postAuthor.viewer.followedBy) @@ -196,12 +196,12 @@ function usePostLikeMutation( } function usePostUnlikeMutation( - logContext: LogEvents['post:unlike:sampled']['logContext'], + logContext: LogEvents['post:unlike']['logContext'], ) { const agent = useAgent() return useMutation<void, Error, {postUri: string; likeUri: string}>({ mutationFn: ({likeUri}) => { - logEvent('post:unlike:sampled', {logContext}) + logEvent('post:unlike', {logContext}) return agent.deleteLike(likeUri) }, }) @@ -209,8 +209,8 @@ function usePostUnlikeMutation( export function usePostRepostMutationQueue( post: Shadow<AppBskyFeedDefs.PostView>, - logContext: LogEvents['post:repost:sampled']['logContext'] & - LogEvents['post:unrepost:sampled']['logContext'], + logContext: LogEvents['post:repost']['logContext'] & + LogEvents['post:unrepost']['logContext'], ) { const queryClient = useQueryClient() const postUri = post.uri @@ -266,7 +266,7 @@ export function usePostRepostMutationQueue( } function usePostRepostMutation( - logContext: LogEvents['post:repost:sampled']['logContext'], + logContext: LogEvents['post:repost']['logContext'], ) { const agent = useAgent() return useMutation< @@ -275,19 +275,19 @@ function usePostRepostMutation( {uri: string; cid: string} // the post's uri and cid >({ mutationFn: post => { - logEvent('post:repost:sampled', {logContext}) + logEvent('post:repost', {logContext}) return agent.repost(post.uri, post.cid) }, }) } function usePostUnrepostMutation( - logContext: LogEvents['post:unrepost:sampled']['logContext'], + logContext: LogEvents['post:unrepost']['logContext'], ) { const agent = useAgent() return useMutation<void, Error, {postUri: string; repostUri: string}>({ mutationFn: ({repostUri}) => { - logEvent('post:unrepost:sampled', {logContext}) + logEvent('post:unrepost', {logContext}) return agent.deleteRepost(repostUri) }, }) diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts index 3059d9efe..84f209d95 100644 --- a/src/state/queries/profile.ts +++ b/src/state/queries/profile.ts @@ -221,8 +221,8 @@ export function useProfileUpdateMutation() { export function useProfileFollowMutationQueue( profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>, - logContext: LogEvents['profile:follow:sampled']['logContext'] & - LogEvents['profile:follow:sampled']['logContext'], + logContext: LogEvents['profile:follow']['logContext'] & + LogEvents['profile:follow']['logContext'], ) { const agent = useAgent() const queryClient = useQueryClient() @@ -293,7 +293,7 @@ export function useProfileFollowMutationQueue( } function useProfileFollowMutation( - logContext: LogEvents['profile:follow:sampled']['logContext'], + logContext: LogEvents['profile:follow']['logContext'], profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>, ) { const {currentAccount} = useSession() @@ -308,7 +308,7 @@ function useProfileFollowMutation( ownProfile = findProfileQueryData(queryClient, currentAccount.did) } captureAction(ProgressGuideAction.Follow) - logEvent('profile:follow:sampled', { + logEvent('profile:follow', { logContext, didBecomeMutual: profile.viewer ? Boolean(profile.viewer.followedBy) @@ -322,12 +322,12 @@ function useProfileFollowMutation( } function useProfileUnfollowMutation( - logContext: LogEvents['profile:unfollow:sampled']['logContext'], + logContext: LogEvents['profile:unfollow']['logContext'], ) { const agent = useAgent() return useMutation<void, Error, {did: string; followUri: string}>({ mutationFn: async ({followUri}) => { - logEvent('profile:unfollow:sampled', {logContext}) + logEvent('profile:unfollow', {logContext}) return await agent.deleteFollow(followUri) }, }) diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx index d61a81498..1028d7e64 100644 --- a/src/view/com/feeds/FeedPage.tsx +++ b/src/view/com/feeds/FeedPage.tsx @@ -74,7 +74,7 @@ export function FeedPage({ scrollToTop() truncateAndInvalidate(queryClient, FEED_RQKEY(feed)) setHasNew(false) - logEvent('feed:refresh:sampled', { + logEvent('feed:refresh', { feedType: feed.split('|')[0], feedUrl: feed, reason: 'soft-reset', @@ -98,7 +98,7 @@ export function FeedPage({ scrollToTop() truncateAndInvalidate(queryClient, FEED_RQKEY(feed)) setHasNew(false) - logEvent('feed:refresh:sampled', { + logEvent('feed:refresh', { feedType: feed.split('|')[0], feedUrl: feed, reason: 'load-latest', diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index 4d5da960c..aca3245a7 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -15,7 +15,7 @@ const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) export interface PagerRef { setPage: ( index: number, - reason: LogEvents['home:feedDisplayed:sampled']['reason'], + reason: LogEvents['home:feedDisplayed']['reason'], ) => void } @@ -32,7 +32,7 @@ interface Props { onPageSelected?: (index: number) => void onPageSelecting?: ( index: number, - reason: LogEvents['home:feedDisplayed:sampled']['reason'], + reason: LogEvents['home:feedDisplayed']['reason'], ) => void onPageScrollStateChanged?: ( scrollState: 'idle' | 'dragging' | 'settling', @@ -61,7 +61,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>( React.useImperativeHandle(ref, () => ({ setPage: ( index: number, - reason: LogEvents['home:feedDisplayed:sampled']['reason'], + reason: LogEvents['home:feedDisplayed']['reason'], ) => { pagerView.current?.setPage(index) onPageSelecting?.(index, reason) diff --git a/src/view/com/pager/Pager.web.tsx b/src/view/com/pager/Pager.web.tsx index 2cce727c0..e6909fe10 100644 --- a/src/view/com/pager/Pager.web.tsx +++ b/src/view/com/pager/Pager.web.tsx @@ -18,7 +18,7 @@ interface Props { onPageSelected?: (index: number) => void onPageSelecting?: ( index: number, - reason: LogEvents['home:feedDisplayed:sampled']['reason'], + reason: LogEvents['home:feedDisplayed']['reason'], ) => void } export const Pager = React.forwardRef(function PagerImpl( @@ -38,17 +38,14 @@ export const Pager = React.forwardRef(function PagerImpl( React.useImperativeHandle(ref, () => ({ setPage: ( index: number, - reason: LogEvents['home:feedDisplayed:sampled']['reason'], + reason: LogEvents['home:feedDisplayed']['reason'], ) => { onTabBarSelect(index, reason) }, })) const onTabBarSelect = React.useCallback( - ( - index: number, - reason: LogEvents['home:feedDisplayed:sampled']['reason'], - ) => { + (index: number, reason: LogEvents['home:feedDisplayed']['reason']) => { const scrollY = window.scrollY // We want to determine if the tabbar is already "sticking" at the top (in which // case we should preserve and restore scroll), or if it is somewhere below in the diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index 905c1e0e0..d6cf6dac5 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -403,7 +403,7 @@ let Feed = ({ // = const onRefresh = React.useCallback(async () => { - logEvent('feed:refresh:sampled', { + logEvent('feed:refresh', { feedType: feedType, feedUrl: feed, reason: 'pull-to-refresh', @@ -421,7 +421,7 @@ let Feed = ({ const onEndReached = React.useCallback(async () => { if (isFetching || !hasNextPage || isError) return - logEvent('feed:endReached:sampled', { + logEvent('feed:endReached', { feedType: feedType, feedUrl: feed, itemCount: feedItems.length, diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 237449383..cadfb4890 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -141,7 +141,7 @@ function HomeScreenReady({ useFocusEffect( useNonReactiveCallback(() => { if (selectedFeed) { - logEvent('home:feedDisplayed:sampled', { + logEvent('home:feedDisplayed', { index: selectedIndex, feedType: selectedFeed.split('|')[0], feedUrl: selectedFeed, @@ -163,12 +163,9 @@ function HomeScreenReady({ ) const onPageSelecting = React.useCallback( - ( - index: number, - reason: LogEvents['home:feedDisplayed:sampled']['reason'], - ) => { + (index: number, reason: LogEvents['home:feedDisplayed']['reason']) => { const feed = allFeeds[index] - logEvent('home:feedDisplayed:sampled', { + logEvent('home:feedDisplayed', { index, feedType: feed.split('|')[0], feedUrl: feed, |