Bluesky app fork with some witchin' additions 馃挮
at main 104 lines 2.6 kB view raw
1import {isNetworkError} from '#/lib/strings/errors' 2import {Sentry} from '#/logger/sentry/lib' 3import {LogLevel, type Transport} from '#/logger/types' 4import {prepareMetadata} from '#/logger/util' 5 6export const sentryTransport: Transport = ( 7 level, 8 context, 9 message, 10 {type, tags, ...metadata}, 11 timestamp, 12) => { 13 // Skip debug messages entirely for now - esb 14 if (level === LogLevel.Debug) return 15 16 const meta = { 17 __context__: context, 18 ...prepareMetadata(metadata), 19 } 20 let _tags = tags || {} 21 _tags = { 22 // use `category` to match breadcrumbs 23 category: context, 24 ...tags, 25 } 26 27 /** 28 * If a string, report a breadcrumb 29 */ 30 if (typeof message === 'string') { 31 const severity = ( 32 { 33 [LogLevel.Debug]: 'debug', 34 [LogLevel.Info]: 'info', 35 [LogLevel.Log]: 'log', // Sentry value here is undefined 36 [LogLevel.Warn]: 'warning', 37 [LogLevel.Error]: 'error', 38 } as const 39 )[level] 40 41 Sentry.addBreadcrumb({ 42 category: context, 43 message, 44 data: meta, 45 type: type || 'default', 46 level: severity, 47 timestamp: timestamp / 1000, // Sentry expects seconds 48 }) 49 50 // We don't want to send any network errors to sentry 51 if (isNetworkError(message)) { 52 return 53 } 54 55 /** 56 * Send all higher levels with `captureMessage`, with appropriate severity 57 * level 58 */ 59 if (level === 'error' || level === 'warn' || level === 'log') { 60 // Defer non-critical messages so they're sent in a batch 61 queueMessageForSentry(message, { 62 level: severity, 63 tags: _tags, 64 extra: meta, 65 }) 66 } 67 } else { 68 /** 69 * It's otherwise an Error and should be reported with captureException 70 */ 71 Sentry.captureException(message, { 72 tags: _tags, 73 extra: meta, 74 }) 75 } 76} 77 78const queuedMessages: [string, Parameters<typeof Sentry.captureMessage>[1]][] = 79 [] 80let sentrySendTimeout: ReturnType<typeof setTimeout> | null = null 81 82function queueMessageForSentry( 83 message: string, 84 captureContext: Parameters<typeof Sentry.captureMessage>[1], 85) { 86 queuedMessages.push([message, captureContext]) 87 if (!sentrySendTimeout) { 88 // Throttle sending messages with a leading delay 89 // so that we can get Sentry out of the critical path. 90 sentrySendTimeout = setTimeout(() => { 91 sentrySendTimeout = null 92 sendQueuedMessages() 93 }, 7000) 94 } 95} 96 97function sendQueuedMessages() { 98 while (queuedMessages.length > 0) { 99 const record = queuedMessages.shift() 100 if (record) { 101 Sentry.captureMessage(record[0], record[1]) 102 } 103 } 104}