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