mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at samuel/exp-cli 159 lines 3.8 kB view raw
1import {AtpSessionData, AtpSessionEvent} from '@atproto/api' 2import {sha256} from 'js-sha256' 3import {Statsig} from 'statsig-react-native-expo' 4 5import {IS_INTERNAL} from '#/lib/app-info' 6import {Schema} from '../persisted' 7import {Action, State} from './reducer' 8import {SessionAccount} from './types' 9 10type Reducer = (state: State, action: Action) => State 11 12type Log = 13 | { 14 type: 'reducer:init' 15 state: State 16 } 17 | { 18 type: 'reducer:call' 19 action: Action 20 prevState: State 21 nextState: State 22 } 23 | { 24 type: 'method:start' 25 method: 26 | 'createAccount' 27 | 'login' 28 | 'logout' 29 | 'resumeSession' 30 | 'removeAccount' 31 account?: SessionAccount 32 } 33 | { 34 type: 'method:end' 35 method: 36 | 'createAccount' 37 | 'login' 38 | 'logout' 39 | 'resumeSession' 40 | 'removeAccount' 41 account?: SessionAccount 42 } 43 | { 44 type: 'persisted:broadcast' 45 data: Schema['session'] 46 } 47 | { 48 type: 'persisted:receive' 49 data: Schema['session'] 50 } 51 | { 52 type: 'agent:switch' 53 prevAgent: object 54 nextAgent: object 55 } 56 | { 57 type: 'agent:patch' 58 agent: object 59 prevSession: AtpSessionData | undefined 60 nextSession: AtpSessionData | undefined 61 } 62 63export function wrapSessionReducerForLogging(reducer: Reducer): Reducer { 64 return function loggingWrapper(prevState: State, action: Action): State { 65 const nextState = reducer(prevState, action) 66 addSessionDebugLog({type: 'reducer:call', prevState, action, nextState}) 67 return nextState 68 } 69} 70 71let nextMessageIndex = 0 72const MAX_SLICE_LENGTH = 1000 73 74// Not gated. 75export function addSessionErrorLog(did: string, event: AtpSessionEvent) { 76 try { 77 if (!Statsig.initializeCalled() || !Statsig.getStableID()) { 78 return 79 } 80 const stack = (new Error().stack ?? '').slice(0, MAX_SLICE_LENGTH) 81 Statsig.logEvent('session:error', null, { 82 did, 83 event, 84 stack, 85 }) 86 } catch (e) { 87 console.error(e) 88 } 89} 90 91export function addSessionDebugLog(log: Log) { 92 try { 93 if (!Statsig.initializeCalled() || !Statsig.getStableID()) { 94 // Drop these logs for now. 95 return 96 } 97 // DISABLING THIS GATE DUE TO EME @TODO EME-GATE 98 if (!IS_INTERNAL) { 99 return 100 } 101 // if (!Statsig.checkGate('debug_session')) { 102 // return 103 // } 104 const messageIndex = nextMessageIndex++ 105 const {type, ...content} = log 106 let payload = JSON.stringify(content, replacer) 107 108 let nextSliceIndex = 0 109 while (payload.length > 0) { 110 const sliceIndex = nextSliceIndex++ 111 const slice = payload.slice(0, MAX_SLICE_LENGTH) 112 payload = payload.slice(MAX_SLICE_LENGTH) 113 Statsig.logEvent('session:debug', null, { 114 realmId, 115 messageIndex: String(messageIndex), 116 messageType: type, 117 sliceIndex: String(sliceIndex), 118 slice, 119 }) 120 } 121 } catch (e) { 122 console.error(e) 123 } 124} 125 126let agentIds = new WeakMap<object, string>() 127let realmId = Math.random().toString(36).slice(2) 128let nextAgentId = 1 129 130function getAgentId(agent: object) { 131 let id = agentIds.get(agent) 132 if (id === undefined) { 133 id = realmId + '::' + nextAgentId++ 134 agentIds.set(agent, id) 135 } 136 return id 137} 138 139function replacer(key: string, value: unknown) { 140 if (typeof value === 'object' && value != null && 'api' in value) { 141 return getAgentId(value) 142 } 143 if ( 144 key === 'service' || 145 key === 'email' || 146 key === 'emailConfirmed' || 147 key === 'emailAuthFactor' || 148 key === 'pdsUrl' 149 ) { 150 return undefined 151 } 152 if ( 153 typeof value === 'string' && 154 (key === 'refreshJwt' || key === 'accessJwt') 155 ) { 156 return sha256(value) 157 } 158 return value 159}