diff options
author | Eric Bailey <git@esb.lol> | 2025-02-28 17:13:49 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-28 17:13:49 -0600 |
commit | 96f4f6359add6a4f2a37df8f17cf3f2f59f0a2a6 (patch) | |
tree | afabc0fe9628a66f1db69f9e07b824db725aa6e1 /src/lib/statsig | |
parent | 9e59a2eef2f82511a9a9a056dbdb0c62fe2f61c6 (diff) | |
download | voidsky-96f4f6359add6a4f2a37df8f17cf3f2f59f0a2a6.tar.zst |
Logger metrics (#7867)
* Adjust datalake abstraction (cherry picked from commit 8ba6a8d45b1bd5698afbd06d9e858a91789f0ea6) * Just be really really specific (cherry picked from commit 920198959659329a7f7f7282a1293aaad198d8e3) * Add metric method to logger, replace datalake calls with new method (cherry picked from commit 7a026bbeae75514b64f928d7ff59707c518fd5e5) * Clarify types (cherry picked from commit 422b150deb158a70ef37e8a456d91bf26cd0b1bc)
Diffstat (limited to 'src/lib/statsig')
-rw-r--r-- | src/lib/statsig/events.ts | 308 | ||||
-rw-r--r-- | src/lib/statsig/statsig.tsx | 35 |
2 files changed, 27 insertions, 316 deletions
diff --git a/src/lib/statsig/events.ts b/src/lib/statsig/events.ts deleted file mode 100644 index 519e3997e..000000000 --- a/src/lib/statsig/events.ts +++ /dev/null @@ -1,308 +0,0 @@ -export type LogEvents = { - // App events - init: { - initMs: number - } - 'account:loggedIn': { - logContext: - | 'LoginForm' - | 'SwitchAccount' - | 'ChooseAccountForm' - | 'Settings' - | 'Notification' - withPassword: boolean - } - 'account:loggedOut': { - logContext: - | 'SwitchAccount' - | 'Settings' - | 'SignupQueued' - | 'Deactivated' - | 'Takendown' - scope: 'current' | 'every' - } - 'notifications:openApp': {} - 'notifications:request': { - context: 'StartOnboarding' | 'AfterOnboarding' | 'Login' | 'Home' - status: 'granted' | 'denied' | 'undetermined' - } - 'state:background': { - secondsActive: number - } - 'state:foreground': {} - 'lake:router:navigate': { - from?: string - } - 'deepLink:referrerReceived': { - to: string - referrer: string - hostname: string - } - - // Screen events - 'splash:signInPressed': {} - 'splash:createAccountPressed': {} - 'signup:nextPressed': { - activeStep: number - phoneVerificationRequired?: boolean - } - 'signup:backPressed': { - activeStep: number - } - 'signup:captchaSuccess': {} - 'signup:captchaFailure': {} - 'signin:hostingProviderPressed': { - hostingProviderDidChange: boolean - } - 'signin:hostingProviderFailedResolution': {} - 'signin:success': { - failedAttemptsCount: number - isUsingCustomProvider: boolean - timeTakenSeconds: number - } - 'signin:backPressed': { - failedAttemptsCount: number - } - 'signin:forgotPasswordPressed': {} - 'signin:passwordReset': {} - 'signin:passwordResetSuccess': {} - 'signin:passwordResetFailure': {} - 'onboarding:interests:nextPressed': { - selectedInterests: string[] - selectedInterestsLength: number - } - 'onboarding:suggestedAccounts:nextPressed': { - selectedAccountsLength: number - skipped: boolean - } - 'onboarding:followingFeed:nextPressed': {} - 'onboarding:algoFeeds:nextPressed': { - selectedPrimaryFeeds: string[] - selectedPrimaryFeedsLength: number - selectedSecondaryFeeds: string[] - selectedSecondaryFeedsLength: number - } - 'onboarding:topicalFeeds:nextPressed': { - selectedFeeds: string[] - selectedFeedsLength: number - } - 'onboarding:moderation:nextPressed': {} - 'onboarding:profile:nextPressed': {} - 'onboarding:finished:nextPressed': { - usedStarterPack: boolean - starterPackName?: string - starterPackCreator?: string - starterPackUri?: string - profilesFollowed: number - feedsPinned: number - } - 'onboarding:finished:avatarResult': { - avatarResult: 'default' | 'created' | 'uploaded' - } - 'home:feedDisplayed': { - feedUrl: string - feedType: string - index: number - } - 'feed:endReached': { - feedUrl: string - feedType: string - itemCount: number - } - 'feed:refresh': { - feedUrl: string - feedType: string - reason: 'pull-to-refresh' | 'soft-reset' | 'load-latest' - } - 'discover:showMore': { - feedContext: string - } - 'discover:showLess': { - feedContext: string - } - 'discover:clickthrough': { - count: number - } - 'discover:engaged': { - count: number - } - 'discover:seen': { - count: number - } - - 'composer:gif:open': {} - 'composer:gif:select': {} - - // Data events - 'account:create:begin': {} - 'account:create:success': {} - 'post:create': { - imageCount: number - isReply: boolean - isPartOfThread: boolean - hasLink: boolean - hasQuote: boolean - langs: string - logContext: 'Composer' - } - 'thread:create': { - postCount: number - isReply: boolean - } - 'post:like': { - doesLikerFollowPoster: boolean | undefined - doesPosterFollowLiker: boolean | undefined - likerClout: number | undefined - postClout: number | undefined - logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' - } - 'post:repost': { - logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' - } - 'post:unlike': { - logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' - } - 'post:unrepost': { - logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' - } - 'post:mute': {} - 'post:unmute': {} - 'post:pin': {} - 'post:unpin': {} - 'profile:follow': { - didBecomeMutual: boolean | undefined - followeeClout: number | undefined - followerClout: number | undefined - logContext: - | 'RecommendedFollowsItem' - | 'PostThreadItem' - | 'ProfileCard' - | 'ProfileHeader' - | 'ProfileHeaderSuggestedFollows' - | 'ProfileMenu' - | 'ProfileHoverCard' - | 'AvatarButton' - | 'StarterPackProfilesList' - | 'FeedInterstitial' - | 'ProfileHeaderSuggestedFollows' - | 'PostOnboardingFindFollows' - | 'ImmersiveVideo' - } - 'suggestedUser:follow': { - logContext: - | 'Explore' - | 'InterstitialDiscover' - | 'InterstitialProfile' - | 'Profile' - location: 'Card' | 'Profile' - recId?: number - position: number - } - 'suggestedUser:press': { - logContext: 'Explore' | 'InterstitialDiscover' | 'InterstitialProfile' - recId?: number - position: number - } - 'suggestedUser:seen': { - logContext: 'Explore' | 'InterstitialDiscover' | 'InterstitialProfile' - recId?: number - position: number - } - 'profile:unfollow': { - logContext: - | 'RecommendedFollowsItem' - | 'PostThreadItem' - | 'ProfileCard' - | 'ProfileHeader' - | 'ProfileHeaderSuggestedFollows' - | 'ProfileMenu' - | 'ProfileHoverCard' - | 'Chat' - | 'AvatarButton' - | 'StarterPackProfilesList' - | 'FeedInterstitial' - | 'ProfileHeaderSuggestedFollows' - | 'PostOnboardingFindFollows' - | 'ImmersiveVideo' - } - 'chat:create': { - logContext: 'ProfileHeader' | 'NewChatDialog' | 'SendViaChatDialog' - } - 'chat:open': { - logContext: - | 'ProfileHeader' - | 'NewChatDialog' - | 'ChatsList' - | 'SendViaChatDialog' - } - 'starterPack:share': { - starterPack: string - shareType: 'link' | 'qrcode' - qrShareType?: 'save' | 'copy' | 'share' - } - 'starterPack:followAll': { - logContext: 'StarterPackProfilesList' | 'Onboarding' - starterPack: string - count: number - } - 'starterPack:delete': {} - 'starterPack:create': { - setName: boolean - setDescription: boolean - profilesCount: number - feedsCount: number - } - 'starterPack:ctaPress': { - starterPack: string - } - 'starterPack:opened': { - starterPack: string - } - 'link:clicked': { - url: string - domain: string - } - - 'feed:interstitial:feedCard:press': {} - - 'profile:header:suggestedFollowsCard:press': {} - - 'test:all:always': {} - 'test:all:sometimes': {} - 'test:all:boosted_by_gate1': {reason: 'base' | 'gate1'} - 'test:all:boosted_by_gate2': {reason: 'base' | 'gate2'} - 'test:all:boosted_by_both': {reason: 'base' | 'gate1' | 'gate2'} - 'test:gate1:always': {} - 'test:gate1:sometimes': {} - 'test:gate2:always': {} - 'test:gate2:sometimes': {} - - 'tmd:share': {} - 'tmd:download': {} - 'tmd:post': {} - - 'trendingTopics:show': { - context: 'settings' - } - 'trendingTopics:hide': { - context: 'settings' | 'sidebar' | 'interstitial' | 'explore:trending' - } - 'trendingTopic:click': { - context: 'sidebar' | 'interstitial' | 'explore' - } - 'recommendedTopic:click': { - context: 'explore' - } - 'trendingVideos:show': { - context: 'settings' - } - 'trendingVideos:hide': { - context: 'settings' | 'interstitial:discover' | 'interstitial:explore' - } - 'videoCard:click': { - context: 'interstitial:discover' | 'interstitial:explore' | 'feed' - } - - 'progressGuide:hide': {} - 'progressGuide:followDialog:open': {} -} diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx index a64c710ea..7f04da126 100644 --- a/src/lib/statsig/statsig.tsx +++ b/src/lib/statsig/statsig.tsx @@ -5,12 +5,12 @@ import {Statsig, StatsigProvider} from 'statsig-react-native-expo' import {BUNDLE_DATE, BUNDLE_IDENTIFIER, IS_TESTFLIGHT} from '#/lib/app-info' import {logger} from '#/logger' +import {MetricEvents} from '#/logger/metrics' import {isWeb} from '#/platform/detection' import * as persisted from '#/state/persisted' import {useSession} from '../../state/session' import {timeout} from '../async/timeout' import {useNonReactiveCallback} from '../hooks/useNonReactiveCallback' -import {LogEvents} from './events' import {Gate} from './gates' const SDK_KEY = 'client-SXJakO39w9vIhl3D44u8UupyzFl4oZ2qPIkjwcvuPsV' @@ -42,7 +42,7 @@ if (isWeb && typeof window !== 'undefined') { refUrl = decodeURIComponent(params.get('ref_url') ?? '') } -export type {LogEvents} +export type {MetricEvents as LogEvents} function createStatsigOptions(prefetchUsers: StatsigUser[]) { return { @@ -91,25 +91,44 @@ export function toClout(n: number | null | undefined): number | undefined { } } -export function logEvent<E extends keyof LogEvents>( +/** + * @deprecated use `logger.metric()` instead + */ +export function logEvent<E extends keyof MetricEvents>( eventName: E & string, - rawMetadata: LogEvents[E] & FlatJSONRecord, + rawMetadata: MetricEvents[E] & FlatJSONRecord, + options: { + /** + * Send to our data lake only, not to StatSig + */ + lake?: boolean + } = {lake: false}, ) { try { const fullMetadata = toStringRecord(rawMetadata) fullMetadata.routeName = getCurrentRouteName() ?? '(Uninitialized)' if (Statsig.initializeCalled()) { - Statsig.logEvent(eventName, null, fullMetadata) + let ev: string = eventName + if (options.lake) { + ev = `lake:${ev}` + } + Statsig.logEvent(ev, null, fullMetadata) + } + /** + * All datalake events should be sent using `logger.metric`, and we don't + * want to double-emit logs to other transports. + */ + if (!options.lake) { + logger.info(eventName, fullMetadata) } - logger.info(eventName, fullMetadata) } catch (e) { // A log should never interrupt the calling code, whatever happens. logger.error('Failed to log an event', {message: e}) } } -function toStringRecord<E extends keyof LogEvents>( - metadata: LogEvents[E] & FlatJSONRecord, +function toStringRecord<E extends keyof MetricEvents>( + metadata: MetricEvents[E] & FlatJSONRecord, ): Record<string, string> { const record: Record<string, string> = {} for (let key in metadata) { |