@@ -130,173 +130,290 @@ public struct LogSubsystem: OptionSet, CustomStringConvertible, Sendable {
130
130
}
131
131
132
132
public 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
+
133
213
/// 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
+ }
137
223
}
138
224
}
139
225
140
226
/// 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
+ }
144
236
}
145
237
}
146
238
147
239
/// 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
+ }
155
249
}
156
250
}
157
251
158
252
/// Log formatters to be applied in order before logs are outputted. Defaults to empty (no formatters).
159
253
/// 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
+ }
163
263
}
164
264
}
165
265
166
266
/// 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
+ }
170
276
}
171
277
}
172
278
173
279
/// 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
+ }
177
289
}
178
290
}
179
291
180
292
/// 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
+ }
184
302
}
185
303
}
186
304
187
305
/// 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
+ }
191
315
}
192
316
}
193
317
194
318
/// 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
+ }
198
328
}
199
329
}
200
330
201
331
/// 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
+ }
205
341
}
206
342
}
207
343
208
344
/// 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
+ }
212
354
}
213
355
}
214
356
215
357
/// 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
+ }
219
367
}
220
368
}
221
369
222
370
/// Destination types this logger will use.
223
371
///
224
372
/// Logger will initialize the destinations with its own parameters. If you want full control on the parameters, use `destinations` directly,
225
373
/// 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 }
229
377
}
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
+ }
237
383
}
238
384
}
239
-
240
- private nonisolated ( unsafe) static var _destinations : [ LogDestination ] ?
241
385
242
386
/// Destinations for the default logger. Please see `LogDestination`.
243
387
/// Defaults to only `ConsoleLogDestination`, which only prints the messages.
244
388
///
245
389
/// - Important: Other options in `ChatClientConfig.Logging` will not take affect if this is changed.
246
390
public static var destinations : [ LogDestination ] {
247
391
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 }
269
393
}
270
394
set {
271
- invalidateLogger ( )
272
- _destinations = newValue
395
+ _state. withLock {
396
+ // Order is important
397
+ $0. invalidateLogger ( )
398
+ $0. destinations = newValue
399
+ }
273
400
}
274
401
}
275
-
276
- /// Underlying logger instance to control singleton.
277
- private nonisolated ( unsafe) static var _logger : Logger ?
278
402
279
403
/// Logger instance to be used by StreamChat.
280
404
///
281
405
/// - Important: Other options in `LogConfig` will not take affect if this is changed.
282
406
public static var logger : Logger {
283
407
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 }
290
409
}
291
410
set {
292
- _logger = newValue
411
+ _state . withLock { $0 . logger = newValue }
293
412
}
294
413
}
295
414
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 ( ) }
300
417
}
301
418
}
302
419
0 commit comments