An ATproto social media client -- with an independent Appview.

Fix feedfeedback metrics not distinguishing which feed it's from (#9099)

* fix feedfeedback metrics being sent for all feeds

* remove `discover:` metrics

authored by samuel.fm and committed by GitHub 1e6a44f2 144d61ef

Changed files
+36 -17
src
+10 -5
src/logger/metrics.ts
··· 175 'feed:suggestion:press': { 176 feedUrl: string 177 } 178 - 'discover:showMore': { 179 feedContext: string 180 } 181 - 'discover:showLess': { 182 feedContext: string 183 } 184 - 'discover:clickthrough': { 185 count: number 186 } 187 - 'discover:engaged': { 188 count: number 189 } 190 - 'discover:seen': { 191 count: number 192 } 193
··· 175 'feed:suggestion:press': { 176 feedUrl: string 177 } 178 + 'feed:showMore': { 179 + feed: string 180 feedContext: string 181 } 182 + 'feed:showLess': { 183 + feed: string 184 feedContext: string 185 } 186 + 'feed:clickthrough': { 187 + feed: string 188 count: number 189 } 190 + 'feed:engaged': { 191 + feed: string 192 count: number 193 } 194 + 'feed:seen': { 195 + feed: string 196 count: number 197 } 198
+26 -12
src/state/feed-feedback.tsx
··· 12 13 import {PROD_FEEDS, STAGING_FEEDS} from '#/lib/constants' 14 import {isNetworkError} from '#/lib/hooks/useCleanError' 15 - import {logEvent} from '#/lib/statsig/statsig' 16 import {Logger} from '#/logger' 17 import { 18 type FeedSourceFeedInfo, ··· 90 const aggregatedStats = useRef<AggregatedStats | null>(null) 91 const throttledFlushAggregatedStats = useMemo( 92 () => 93 - throttle(() => flushToStatsig(aggregatedStats.current), 45e3, { 94 - leading: true, // The outer call is already throttled somewhat. 95 - trailing: true, 96 - }), 97 - [], 98 ) 99 100 const sendToFeedNoDelay = useCallback(() => { ··· 135 sendOrAggregateInteractionsForStats( 136 aggregatedStats.current, 137 interactionsToSend, 138 ) 139 throttledFlushAggregatedStats() 140 logger.debug('flushed') ··· 271 function sendOrAggregateInteractionsForStats( 272 stats: AggregatedStats, 273 interactions: AppBskyFeedDefs.Interaction[], 274 ) { 275 for (let interaction of interactions) { 276 switch (interaction.event) { 277 // Pressing "Show more" / "Show less" is relatively uncommon so we won't aggregate them. 278 // This lets us send the feed context together with them. 279 case 'app.bsky.feed.defs#requestLess': { 280 - logEvent('discover:showLess', { 281 feedContext: interaction.feedContext ?? '', 282 }) 283 break 284 } 285 case 'app.bsky.feed.defs#requestMore': { 286 - logEvent('discover:showMore', { 287 feedContext: interaction.feedContext ?? '', 288 }) 289 break ··· 313 } 314 } 315 316 - function flushToStatsig(stats: AggregatedStats | null) { 317 if (stats === null) { 318 return 319 } 320 321 if (stats.clickthroughCount > 0) { 322 - logEvent('discover:clickthrough', { 323 count: stats.clickthroughCount, 324 }) 325 stats.clickthroughCount = 0 326 } 327 328 if (stats.engagedCount > 0) { 329 - logEvent('discover:engaged', { 330 count: stats.engagedCount, 331 }) 332 stats.engagedCount = 0 333 } 334 335 if (stats.seenCount > 0) { 336 - logEvent('discover:seen', { 337 count: stats.seenCount, 338 }) 339 stats.seenCount = 0 340 }
··· 12 13 import {PROD_FEEDS, STAGING_FEEDS} from '#/lib/constants' 14 import {isNetworkError} from '#/lib/hooks/useCleanError' 15 import {Logger} from '#/logger' 16 import { 17 type FeedSourceFeedInfo, ··· 89 const aggregatedStats = useRef<AggregatedStats | null>(null) 90 const throttledFlushAggregatedStats = useMemo( 91 () => 92 + throttle( 93 + () => 94 + flushToStatsig( 95 + aggregatedStats.current, 96 + feed?.feedDescriptor ?? 'unknown', 97 + ), 98 + 45e3, 99 + { 100 + leading: true, // The outer call is already throttled somewhat. 101 + trailing: true, 102 + }, 103 + ), 104 + [feed?.feedDescriptor], 105 ) 106 107 const sendToFeedNoDelay = useCallback(() => { ··· 142 sendOrAggregateInteractionsForStats( 143 aggregatedStats.current, 144 interactionsToSend, 145 + feed?.feedDescriptor ?? 'unknown', 146 ) 147 throttledFlushAggregatedStats() 148 logger.debug('flushed') ··· 279 function sendOrAggregateInteractionsForStats( 280 stats: AggregatedStats, 281 interactions: AppBskyFeedDefs.Interaction[], 282 + feed: string, 283 ) { 284 for (let interaction of interactions) { 285 switch (interaction.event) { 286 // Pressing "Show more" / "Show less" is relatively uncommon so we won't aggregate them. 287 // This lets us send the feed context together with them. 288 case 'app.bsky.feed.defs#requestLess': { 289 + logger.metric('feed:showLess', { 290 + feed, 291 feedContext: interaction.feedContext ?? '', 292 }) 293 break 294 } 295 case 'app.bsky.feed.defs#requestMore': { 296 + logger.metric('feed:showMore', { 297 + feed, 298 feedContext: interaction.feedContext ?? '', 299 }) 300 break ··· 324 } 325 } 326 327 + function flushToStatsig(stats: AggregatedStats | null, feedDescriptor: string) { 328 if (stats === null) { 329 return 330 } 331 332 if (stats.clickthroughCount > 0) { 333 + logger.metric('feed:clickthrough', { 334 count: stats.clickthroughCount, 335 + feed: feedDescriptor, 336 }) 337 stats.clickthroughCount = 0 338 } 339 340 if (stats.engagedCount > 0) { 341 + logger.metric('feed:engaged', { 342 count: stats.engagedCount, 343 + feed: feedDescriptor, 344 }) 345 stats.engagedCount = 0 346 } 347 348 if (stats.seenCount > 0) { 349 + logger.metric('feed:seen', { 350 count: stats.seenCount, 351 + feed: feedDescriptor, 352 }) 353 stats.seenCount = 0 354 }