Refactor logging in feed-feedback, add debug logging to metrics client
This commit is contained in:
@@ -131,6 +131,8 @@ export function AnalyticsContext({
|
||||
combinedMetadata.base.sessionId = sessionId
|
||||
combinedMetadata.geolocation = geolocation
|
||||
const context: AnalyticsBaseContextType = {
|
||||
...parentContext,
|
||||
// TODO trim down metadata
|
||||
logger: createLogger(Logger.Context.Default, combinedMetadata),
|
||||
metadata: combinedMetadata,
|
||||
metric: (event, payload, extraMetadata) => {
|
||||
@@ -196,6 +198,7 @@ export function useAnalyticsBase() {
|
||||
export function useAnalytics() {
|
||||
const ctx = useContext(Context)
|
||||
if (!('feature' in ctx) || !('Features' in ctx)) {
|
||||
console.log(ctx)
|
||||
throw new Error(
|
||||
'useAnalytics must be used within an AnalyticsFeaturesContext',
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {onAppStateChange} from '#/lib/appState'
|
||||
import {isNetworkError} from '#/lib/strings/errors'
|
||||
import {Logger} from '#/logger'
|
||||
import {Sentry} from '#/logger/sentry/lib'
|
||||
import * as env from '#/env'
|
||||
|
||||
@@ -13,6 +14,7 @@ type Event<M extends Record<string, any>> = {
|
||||
}
|
||||
|
||||
const TRACKING_ENDPOINT = env.METRICS_API_HOST + '/t'
|
||||
const logger = Logger.create(Logger.Context.Metric, {})
|
||||
|
||||
export class MetricsClient<M extends Record<string, any>> {
|
||||
private started: boolean = false
|
||||
@@ -49,6 +51,11 @@ export class MetricsClient<M extends Record<string, any>> {
|
||||
metadata,
|
||||
})
|
||||
|
||||
logger.debug(`event: ${event as string}`, {
|
||||
payload,
|
||||
metadata,
|
||||
})
|
||||
|
||||
if (this.queue.length > 100) {
|
||||
this.flush()
|
||||
}
|
||||
@@ -62,6 +69,10 @@ export class MetricsClient<M extends Record<string, any>> {
|
||||
}
|
||||
|
||||
private async sendBatch(events: Event<M>[], isRetry: boolean = false) {
|
||||
logger.debug(`sendBatch: ${events.length}`, {
|
||||
isRetry,
|
||||
})
|
||||
|
||||
try {
|
||||
const body = JSON.stringify(events)
|
||||
if (env.IS_WEB && 'navigator' in globalThis && navigator.sendBeacon) {
|
||||
|
||||
+39
-40
@@ -11,7 +11,6 @@ import {type AppBskyFeedDefs} from '@atproto/api'
|
||||
import throttle from 'lodash.throttle'
|
||||
|
||||
import {PROD_FEEDS, STAGING_FEEDS} from '#/lib/constants'
|
||||
import {Logger} from '#/logger'
|
||||
import {
|
||||
type FeedSourceFeedInfo,
|
||||
type FeedSourceInfo,
|
||||
@@ -22,6 +21,7 @@ import {
|
||||
type FeedPostSliceItem,
|
||||
} from '#/state/queries/post-feed'
|
||||
import {getItemsForFeedback} from '#/view/com/posts/PostFeed'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {useAgent} from './session'
|
||||
|
||||
export const FEEDBACK_FEEDS = [...PROD_FEEDS, ...STAGING_FEEDS]
|
||||
@@ -42,8 +42,6 @@ export const THIRD_PARTY_ALLOWED_INTERACTIONS = new Set<
|
||||
'app.bsky.feed.defs#interactionSeen',
|
||||
])
|
||||
|
||||
const logger = Logger.create(Logger.Context.FeedFeedback)
|
||||
|
||||
export type StateContext = {
|
||||
enabled: boolean
|
||||
onItemSeen: (item: any) => void
|
||||
@@ -65,6 +63,8 @@ export function useFeedFeedback(
|
||||
feedSourceInfo: FeedSourceInfo | undefined,
|
||||
hasSession: boolean,
|
||||
) {
|
||||
const ax = useAnalytics()
|
||||
const logger = ax.logger.useContext(ax.logger.Context.FeedFeedback)
|
||||
const agent = useAgent()
|
||||
|
||||
const feed =
|
||||
@@ -85,22 +85,55 @@ export function useFeedFeedback(
|
||||
WeakSet<FeedPostSliceItem | AppBskyFeedDefs.Interaction>
|
||||
>(new WeakSet())
|
||||
|
||||
const flushEvents = useCallback(
|
||||
(stats: AggregatedStats | null, feedDescriptor: string) => {
|
||||
if (stats === null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (stats.clickthroughCount > 0) {
|
||||
ax.metric('feed:clickthrough', {
|
||||
count: stats.clickthroughCount,
|
||||
feed: feedDescriptor,
|
||||
})
|
||||
stats.clickthroughCount = 0
|
||||
}
|
||||
|
||||
if (stats.engagedCount > 0) {
|
||||
ax.metric('feed:engaged', {
|
||||
count: stats.engagedCount,
|
||||
feed: feedDescriptor,
|
||||
})
|
||||
stats.engagedCount = 0
|
||||
}
|
||||
|
||||
if (stats.seenCount > 0) {
|
||||
ax.metric('feed:seen', {
|
||||
count: stats.seenCount,
|
||||
feed: feedDescriptor,
|
||||
})
|
||||
stats.seenCount = 0
|
||||
}
|
||||
},
|
||||
[ax],
|
||||
)
|
||||
|
||||
const aggregatedStats = useRef<AggregatedStats | null>(null)
|
||||
const throttledFlushAggregatedStats = useMemo(
|
||||
() =>
|
||||
throttle(
|
||||
() =>
|
||||
flushToStatsig(
|
||||
flushEvents(
|
||||
aggregatedStats.current,
|
||||
feed?.feedDescriptor ?? 'unknown',
|
||||
),
|
||||
45e3,
|
||||
5e3,
|
||||
{
|
||||
leading: true, // The outer call is already throttled somewhat.
|
||||
trailing: true,
|
||||
},
|
||||
),
|
||||
[feed?.feedDescriptor],
|
||||
[feed?.feedDescriptor, flushEvents],
|
||||
)
|
||||
|
||||
const sendToFeedNoDelay = useCallback(() => {
|
||||
@@ -299,37 +332,3 @@ function sendOrAggregateInteractionsForStats(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function flushToStatsig(stats: AggregatedStats | null, feedDescriptor: string) {
|
||||
if (stats === null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (stats.clickthroughCount > 0) {
|
||||
logger.metric('feed:clickthrough', {
|
||||
count: stats.clickthroughCount,
|
||||
feed: feedDescriptor,
|
||||
})
|
||||
stats.clickthroughCount = 0
|
||||
}
|
||||
|
||||
if (stats.engagedCount > 0) {
|
||||
logger.metric('feed:engaged', {
|
||||
count: stats.engagedCount,
|
||||
feed: feedDescriptor,
|
||||
})
|
||||
stats.engagedCount = 0
|
||||
}
|
||||
|
||||
if (stats.seenCount > 0) {
|
||||
logger.metric(
|
||||
'feed:seen',
|
||||
{
|
||||
count: stats.seenCount,
|
||||
feed: feedDescriptor,
|
||||
},
|
||||
{statsig: false},
|
||||
)
|
||||
stats.seenCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user