+10
-5
src/logger/metrics.ts
+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
+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
}