Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
at main 158 lines 3.9 kB view raw
1import {nanoid} from 'nanoid/non-secure' 2 3import {add} from '#/logger/logDump' 4import {consoleTransport} from '#/logger/transports/console' 5import { 6 LogContext, 7 LogLevel, 8 type Metadata, 9 type Transport, 10} from '#/logger/types' 11import {enabledLogLevels} from '#/logger/util' 12import {ENV} from '#/env' 13import {sentryTransport} from './transports/sentry' 14 15const TRANSPORTS: Transport[] = (function configureTransports() { 16 switch (ENV) { 17 case 'production': { 18 return [sentryTransport].filter(Boolean) 19 } 20 case 'test': { 21 return [] 22 } 23 default: { 24 return [consoleTransport] 25 } 26 } 27})() 28 29export class Logger { 30 static Level = LogLevel 31 static Context = LogContext 32 33 level: LogLevel 34 context: LogContext | undefined = undefined 35 contextFilter: string = '' 36 ambientMetadata: Record<string, unknown> = {} 37 38 protected debugContextRegexes: RegExp[] = [] 39 protected transports: Transport[] = [] 40 41 static create(context?: LogContext, metadata: Record<string, unknown> = {}) { 42 const logger = new Logger({ 43 level: process.env.EXPO_PUBLIC_LOG_LEVEL as LogLevel, 44 context, 45 contextFilter: process.env.EXPO_PUBLIC_LOG_DEBUG || '', 46 metadata, 47 }) 48 for (const transport of TRANSPORTS) { 49 logger.addTransport(transport) 50 } 51 return logger 52 } 53 54 constructor({ 55 level, 56 context, 57 contextFilter, 58 metadata: ambientMetadata = {}, 59 }: { 60 level?: LogLevel 61 context?: LogContext 62 contextFilter?: string 63 metadata?: Record<string, unknown> 64 } = {}) { 65 this.context = context 66 this.level = level || LogLevel.Info 67 this.contextFilter = contextFilter || '' 68 this.ambientMetadata = ambientMetadata 69 if (this.contextFilter) { 70 this.level = LogLevel.Debug 71 } 72 this.debugContextRegexes = (this.contextFilter || '') 73 .split(',') 74 .map(filter => { 75 return new RegExp(filter.replace(/[^\w:*-]/, '').replace(/\*/g, '.*')) 76 }) 77 } 78 79 debug(message: string, metadata: Metadata = {}) { 80 this.transport({level: LogLevel.Debug, message, metadata}) 81 } 82 83 info(message: string, metadata: Metadata = {}) { 84 this.transport({level: LogLevel.Info, message, metadata}) 85 } 86 87 log(message: string, metadata: Metadata = {}) { 88 this.transport({level: LogLevel.Log, message, metadata}) 89 } 90 91 warn(message: string, metadata: Metadata = {}) { 92 this.transport({level: LogLevel.Warn, message, metadata}) 93 } 94 95 error(error: Error | string, metadata: Metadata = {}) { 96 this.transport({level: LogLevel.Error, message: error, metadata}) 97 } 98 99 addTransport(transport: Transport) { 100 this.transports.push(transport) 101 return () => { 102 this.transports.splice(this.transports.indexOf(transport), 1) 103 } 104 } 105 106 protected transport({ 107 level, 108 message, 109 metadata = {}, 110 }: { 111 level: LogLevel 112 message: string | Error 113 metadata: Metadata 114 }) { 115 if ( 116 level === LogLevel.Debug && 117 !!this.contextFilter && 118 !!this.context && 119 !this.debugContextRegexes.find(reg => reg.test(this.context!)) 120 ) 121 return 122 123 const timestamp = Date.now() 124 const meta: Metadata = { 125 __metadata__: this.ambientMetadata, 126 ...metadata, 127 } 128 129 // send every log to syslog 130 add({ 131 id: nanoid(), 132 timestamp, 133 level, 134 context: this.context, 135 message, 136 metadata: meta, 137 }) 138 139 if (!enabledLogLevels[this.level].includes(level)) return 140 141 for (const transport of this.transports) { 142 transport(level, this.context, message, meta, timestamp) 143 } 144 } 145} 146 147/** 148 * Default logger instance. See `@/logger/README` for docs. 149 * 150 * Basic usage: 151 * 152 * `logger.debug(message[, metadata])` 153 * `logger.info(message[, metadata])` 154 * `logger.log(message[, metadata])` 155 * `logger.warn(message[, metadata])` 156 * `logger.error(error[, metadata])` 157 */ 158export const logger = Logger.create(Logger.Context.Default)