@@ -130,173 +130,290 @@ public struct LogSubsystem: OptionSet, CustomStringConvertible, Sendable {
130130}
131131
132132public enum LogConfig {
133+ private struct State {
134+ var identifier : String = " "
135+ var level : LogLevel = . error
136+ var dateFormatter : DateFormatter = {
137+ let df = DateFormatter ( )
138+ df. dateFormat = " yyyy-MM-dd HH:mm:ss.SSS "
139+ return df
140+ } ( )
141+
142+ var formatters : [ LogFormatter ] = [ ]
143+ var showDate : Bool = true
144+ var showLevel : Bool = true
145+ var showIdentifier : Bool = false
146+ var showThreadName : Bool = true
147+ var showFileName : Bool = true
148+ var showLineNumber : Bool = true
149+ var showFunctionName : Bool = true
150+ var subsystems : LogSubsystem = . all
151+
152+ var destinationTypes : [ LogDestination . Type ] = if #available( iOS 14 . 0 , * ) {
153+ [ OSLogDestination . self]
154+ } else {
155+ [ ConsoleLogDestination . self]
156+ }
157+
158+ private var _destinations : [ LogDestination ] ?
159+
160+ var destinations : [ LogDestination ] {
161+ mutating get {
162+ if let _destinations {
163+ return _destinations
164+ }
165+ let newDestinations = destinationTypes. map {
166+ $0. init (
167+ identifier: identifier,
168+ level: level,
169+ subsystems: subsystems,
170+ showDate: showDate,
171+ dateFormatter: dateFormatter,
172+ formatters: formatters,
173+ showLevel: showLevel,
174+ showIdentifier: showIdentifier,
175+ showThreadName: showThreadName,
176+ showFileName: showFileName,
177+ showLineNumber: showLineNumber,
178+ showFunctionName: showFunctionName
179+ )
180+ }
181+ _destinations = newDestinations
182+ return newDestinations
183+ }
184+ set {
185+ _destinations = newValue
186+ }
187+ }
188+
189+ private var _logger : Logger ?
190+
191+ var logger : Logger {
192+ mutating get {
193+ if let _logger {
194+ return _logger
195+ }
196+ let logger = Logger ( identifier: identifier, destinations: destinations)
197+ _logger = logger
198+ return logger
199+ }
200+ set {
201+ _logger = newValue
202+ }
203+ }
204+
205+ mutating func invalidateLogger( ) {
206+ _destinations = nil
207+ _logger = nil
208+ }
209+ }
210+
211+ private static let _state = AllocatedUnfairLock < State > ( State ( ) )
212+
133213 /// Identifier for the logger. Defaults to empty.
134- public nonisolated ( unsafe) static var identifier = " " {
135- didSet {
136- invalidateLogger ( )
214+ public static var identifier : String {
215+ get {
216+ _state. withLock { $0. identifier }
217+ }
218+ set {
219+ _state. withLock {
220+ $0. identifier = newValue
221+ $0. invalidateLogger ( )
222+ }
137223 }
138224 }
139225
140226 /// Output level for the logger.
141- public nonisolated ( unsafe) static var level : LogLevel = . error {
142- didSet {
143- invalidateLogger ( )
227+ public static var level : LogLevel {
228+ get {
229+ _state. withLock { $0. level }
230+ }
231+ set {
232+ _state. withLock {
233+ $0. level = newValue
234+ $0. invalidateLogger ( )
235+ }
144236 }
145237 }
146238
147239 /// Date formatter for the logger. Defaults to ISO8601
148- public nonisolated ( unsafe) static var dateFormatter : DateFormatter = {
149- let df = DateFormatter ( )
150- df. dateFormat = " yyyy-MM-dd HH:mm:ss.SSS "
151- return df
152- } ( ) {
153- didSet {
154- invalidateLogger ( )
240+ public static var dateFormatter : DateFormatter {
241+ get {
242+ _state. withLock { $0. dateFormatter }
243+ }
244+ set {
245+ _state. withLock {
246+ $0. dateFormatter = newValue
247+ $0. invalidateLogger ( )
248+ }
155249 }
156250 }
157251
158252 /// Log formatters to be applied in order before logs are outputted. Defaults to empty (no formatters).
159253 /// Please see `LogFormatter` for more info.
160- public nonisolated ( unsafe) static var formatters = [ LogFormatter] ( ) {
161- didSet {
162- invalidateLogger ( )
254+ public static var formatters : [ LogFormatter ] {
255+ get {
256+ _state. withLock { $0. formatters }
257+ }
258+ set {
259+ _state. withLock {
260+ $0. formatters = newValue
261+ $0. invalidateLogger ( )
262+ }
163263 }
164264 }
165265
166266 /// Toggle for showing date in logs
167- public nonisolated ( unsafe) static var showDate = true {
168- didSet {
169- invalidateLogger ( )
267+ public static var showDate : Bool {
268+ get {
269+ _state. withLock { $0. showDate }
270+ }
271+ set {
272+ _state. withLock {
273+ $0. showDate = newValue
274+ $0. invalidateLogger ( )
275+ }
170276 }
171277 }
172278
173279 /// Toggle for showing log level in logs
174- public nonisolated ( unsafe) static var showLevel = true {
175- didSet {
176- invalidateLogger ( )
280+ public static var showLevel : Bool {
281+ get {
282+ _state. withLock { $0. showLevel }
283+ }
284+ set {
285+ _state. withLock {
286+ $0. showLevel = newValue
287+ $0. invalidateLogger ( )
288+ }
177289 }
178290 }
179291
180292 /// Toggle for showing identifier in logs
181- public nonisolated ( unsafe) static var showIdentifier = false {
182- didSet {
183- invalidateLogger ( )
293+ public static var showIdentifier : Bool {
294+ get {
295+ _state. withLock { $0. showIdentifier }
296+ }
297+ set {
298+ _state. withLock {
299+ $0. showIdentifier = newValue
300+ $0. invalidateLogger ( )
301+ }
184302 }
185303 }
186304
187305 /// Toggle for showing thread name in logs
188- public nonisolated ( unsafe) static var showThreadName = true {
189- didSet {
190- invalidateLogger ( )
306+ public static var showThreadName : Bool {
307+ get {
308+ _state. withLock { $0. showThreadName }
309+ }
310+ set {
311+ _state. withLock {
312+ $0. showThreadName = newValue
313+ $0. invalidateLogger ( )
314+ }
191315 }
192316 }
193317
194318 /// Toggle for showing file name in logs
195- public nonisolated ( unsafe) static var showFileName = true {
196- didSet {
197- invalidateLogger ( )
319+ public static var showFileName : Bool {
320+ get {
321+ _state. withLock { $0. showFileName }
322+ }
323+ set {
324+ _state. withLock {
325+ $0. showFileName = newValue
326+ $0. invalidateLogger ( )
327+ }
198328 }
199329 }
200330
201331 /// Toggle for showing line number in logs
202- public nonisolated ( unsafe) static var showLineNumber = true {
203- didSet {
204- invalidateLogger ( )
332+ public static var showLineNumber : Bool {
333+ get {
334+ _state. withLock { $0. showLineNumber }
335+ }
336+ set {
337+ _state. withLock {
338+ $0. showLineNumber = newValue
339+ $0. invalidateLogger ( )
340+ }
205341 }
206342 }
207343
208344 /// Toggle for showing function name in logs
209- public nonisolated ( unsafe) static var showFunctionName = true {
210- didSet {
211- invalidateLogger ( )
345+ public static var showFunctionName : Bool {
346+ get {
347+ _state. withLock { $0. showFunctionName }
348+ }
349+ set {
350+ _state. withLock {
351+ $0. showFunctionName = newValue
352+ $0. invalidateLogger ( )
353+ }
212354 }
213355 }
214356
215357 /// Subsystems for the logger
216- public nonisolated ( unsafe) static var subsystems : LogSubsystem = . all {
217- didSet {
218- invalidateLogger ( )
358+ public static var subsystems : LogSubsystem {
359+ get {
360+ _state. withLock { $0. subsystems }
361+ }
362+ set {
363+ _state. withLock {
364+ $0. subsystems = newValue
365+ $0. invalidateLogger ( )
366+ }
219367 }
220368 }
221369
222370 /// Destination types this logger will use.
223371 ///
224372 /// Logger will initialize the destinations with its own parameters. If you want full control on the parameters, use `destinations` directly,
225373 /// where you can pass parameters to destination initializers yourself.
226- public nonisolated ( unsafe ) static var destinationTypes : [ LogDestination . Type ] = Self . defaultDestinations {
227- didSet {
228- invalidateLogger ( )
374+ public static var destinationTypes : [ LogDestination . Type ] {
375+ get {
376+ _state . withLock { $0 . destinationTypes }
229377 }
230- }
231-
232- static var defaultDestinations : [ LogDestination . Type ] {
233- if #available( iOS 14 . 0 , * ) {
234- [ OSLogDestination . self]
235- } else {
236- [ ConsoleLogDestination . self]
378+ set {
379+ _state. withLock {
380+ $0. destinationTypes = newValue
381+ $0. invalidateLogger ( )
382+ }
237383 }
238384 }
239-
240- private nonisolated ( unsafe) static var _destinations : [ LogDestination ] ?
241385
242386 /// Destinations for the default logger. Please see `LogDestination`.
243387 /// Defaults to only `ConsoleLogDestination`, which only prints the messages.
244388 ///
245389 /// - Important: Other options in `ChatClientConfig.Logging` will not take affect if this is changed.
246390 public static var destinations : [ LogDestination ] {
247391 get {
248- if let destinations = _destinations {
249- return destinations
250- } else {
251- _destinations = destinationTypes. map {
252- $0. init (
253- identifier: identifier,
254- level: level,
255- subsystems: subsystems,
256- showDate: showDate,
257- dateFormatter: dateFormatter,
258- formatters: formatters,
259- showLevel: showLevel,
260- showIdentifier: showIdentifier,
261- showThreadName: showThreadName,
262- showFileName: showFileName,
263- showLineNumber: showLineNumber,
264- showFunctionName: showFunctionName
265- )
266- }
267- return _destinations!
268- }
392+ _state. withLock { $0. destinations }
269393 }
270394 set {
271- invalidateLogger ( )
272- _destinations = newValue
395+ _state. withLock {
396+ // Order is important
397+ $0. invalidateLogger ( )
398+ $0. destinations = newValue
399+ }
273400 }
274401 }
275-
276- /// Underlying logger instance to control singleton.
277- private nonisolated ( unsafe) static var _logger : Logger ?
278402
279403 /// Logger instance to be used by StreamChat.
280404 ///
281405 /// - Important: Other options in `LogConfig` will not take affect if this is changed.
282406 public static var logger : Logger {
283407 get {
284- if let logger = _logger {
285- return logger
286- } else {
287- _logger = Logger ( identifier: identifier, destinations: destinations)
288- return _logger!
289- }
408+ _state. withLock { $0. logger }
290409 }
291410 set {
292- _logger = newValue
411+ _state . withLock { $0 . logger = newValue }
293412 }
294413 }
295414
296- /// Invalidates the current logger instance so it can be recreated.
297- private static func invalidateLogger( ) {
298- _logger = nil
299- _destinations = nil
415+ static func reset( ) {
416+ _state. withLock { $0 = State ( ) }
300417 }
301418}
302419
0 commit comments