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 | |
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')
-rw-r--r-- | src/Navigation.tsx | 5 | ||||
-rw-r--r-- | src/lib/statsig/statsig.tsx | 35 | ||||
-rw-r--r-- | src/logger/index.ts | 21 | ||||
-rw-r--r-- | src/logger/metrics.ts (renamed from src/lib/statsig/events.ts) | 4 | ||||
-rw-r--r-- | src/logger/transports/bitdrift.ts | 3 | ||||
-rw-r--r-- | src/logger/transports/sentry.ts | 3 | ||||
-rw-r--r-- | src/logger/types.ts | 10 |
7 files changed, 63 insertions, 18 deletions
diff --git a/src/Navigation.tsx b/src/Navigation.tsx index cf09406a6..baf99f110 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -32,6 +32,7 @@ import { import {RouteParams, State} from '#/lib/routes/types' import {attachRouteToLogEvents, logEvent} from '#/lib/statsig/statsig' import {bskyTitle} from '#/lib/strings/headings' +import {logger} from '#/logger' import {isNative, isWeb} from '#/platform/detection' import {useModalControls} from '#/state/modals' import {useUnreadNotifications} from '#/state/queries/notifications/unread' @@ -729,7 +730,7 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) { linking={LINKING} theme={theme} onStateChange={() => { - logEvent('lake:router:navigate', { + logger.metric('router:navigate', { from: prevLoggedRouteName.current, }) prevLoggedRouteName.current = getCurrentRouteName() @@ -738,7 +739,7 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) { attachRouteToLogEvents(getCurrentRouteName) logModuleInitTime() onReady() - logEvent('lake:router:navigate', {}) + logger.metric('router:navigate', {}) }}> {children} </NavigationContainer> 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) { diff --git a/src/logger/index.ts b/src/logger/index.ts index 410d29bb3..0a50a9d21 100644 --- a/src/logger/index.ts +++ b/src/logger/index.ts @@ -1,6 +1,8 @@ import {nanoid} from 'nanoid/non-secure' +import {logEvent} from '#/lib/statsig/statsig' import {add} from '#/logger/logDump' +import {MetricEvents} from '#/logger/metrics' import {bitdriftTransport} from '#/logger/transports/bitdrift' import {consoleTransport} from '#/logger/transports/console' import {sentryTransport} from '#/logger/transports/sentry' @@ -89,6 +91,25 @@ export class Logger { this.transport({level: LogLevel.Error, message: error, metadata}) } + metric<E extends keyof MetricEvents>( + event: E & string, + metadata: MetricEvents[E], + options: { + /** + * Optionally also send to StatSig + */ + statsig?: boolean + } = {statsig: false}, + ) { + logEvent(event, metadata, { + lake: !options.statsig, + }) + + for (const transport of this.transports) { + transport(LogLevel.Info, LogContext.Metric, event, metadata, Date.now()) + } + } + addTransport(transport: Transport) { this.transports.push(transport) return () => { diff --git a/src/lib/statsig/events.ts b/src/logger/metrics.ts index 519e3997e..e3bd93314 100644 --- a/src/lib/statsig/events.ts +++ b/src/logger/metrics.ts @@ -1,4 +1,4 @@ -export type LogEvents = { +export type MetricEvents = { // App events init: { initMs: number @@ -30,7 +30,7 @@ export type LogEvents = { secondsActive: number } 'state:foreground': {} - 'lake:router:navigate': { + 'router:navigate': { from?: string } 'deepLink:referrerReceived': { diff --git a/src/logger/transports/bitdrift.ts b/src/logger/transports/bitdrift.ts index cf125c6e2..a407f9485 100644 --- a/src/logger/transports/bitdrift.ts +++ b/src/logger/transports/bitdrift.ts @@ -18,8 +18,7 @@ export const bitdriftTransport: Transport = ( ) => { const log = logFunctions[level] log(message.toString(), { - // match Sentry payload - context, + __context__: context, ...prepareMetadata(metadata), }) } diff --git a/src/logger/transports/sentry.ts b/src/logger/transports/sentry.ts index 890918d67..33dd78ec2 100644 --- a/src/logger/transports/sentry.ts +++ b/src/logger/transports/sentry.ts @@ -11,8 +11,7 @@ export const sentryTransport: Transport = ( timestamp, ) => { const meta = { - // match Bitdrift payload - context, + __context__: context, ...prepareMetadata(metadata), } let _tags = tags || {} diff --git a/src/logger/types.ts b/src/logger/types.ts index 517893d29..9110a8c6f 100644 --- a/src/logger/types.ts +++ b/src/logger/types.ts @@ -9,6 +9,12 @@ export enum LogContext { Notifications = 'notifications', ConversationAgent = 'conversation-agent', DMsAgent = 'dms-agent', + + /** + * METRIC IS FOR INTERNAL USE ONLY, don't create any other loggers using this + * context + */ + Metric = 'metric', } export enum LogLevel { @@ -33,9 +39,9 @@ export type Transport = ( */ export type Metadata = { /** - * Reserved for appending `LogContext` to logging payloads + * Reserved for appending `LogContext` in logging payloads */ - context?: undefined + __context__?: undefined /** * Applied as Sentry breadcrumb types. Defaults to `default`. |