@@ -13,11 +13,17 @@ class FileLoggerManager {
1313 /// The class is used as a Singleton, thus should be accesed via instance property !!!
1414 static let shared = FileLoggerManager ( )
1515
16- let logDirUrl : URL ? = {
16+ lazy var logDirUrl : URL ? = {
1717 do {
1818 let fileManager = FileManager . default
19- let documentDirUrl = try fileManager. url ( for: . documentDirectory, in: . userDomainMask, appropriateFor: nil , create: true )
20- let _logDirUrl = documentDirUrl. appendingPathComponent ( " logs " )
19+ var dirUrl : URL
20+ if let suiteName = suiteName,
21+ let url = fileManager. containerURL ( forSecurityApplicationGroupIdentifier: suiteName) {
22+ dirUrl = url
23+ } else {
24+ dirUrl = try fileManager. url ( for: . documentDirectory, in: . userDomainMask, appropriateFor: nil , create: true )
25+ }
26+ let _logDirUrl = dirUrl. appendingPathComponent ( " logs " )
2127 if !fileManager. fileExists ( atPath: _logDirUrl. path) {
2228 try fileManager. createDirectory ( at: _logDirUrl, withIntermediateDirectories: true , attributes: nil )
2329 }
@@ -30,6 +36,8 @@ class FileLoggerManager {
3036 }
3137 } ( )
3238
39+ private let suiteName : String ?
40+
3341 private( set) var currentLogFileNumber : Int = 0 {
3442 didSet {
3543 // Check if currentLogFileNumber got updated, if not - do nothing, thus keep the currentWritableFileHandle opened
@@ -56,7 +64,9 @@ class FileLoggerManager {
5664 }
5765
5866 var currentLogFileUrl : URL ? {
59- return logDirUrl? . appendingPathComponent ( " \( currentLogFileNumber) " ) . appendingPathExtension ( " log " )
67+ suiteName == nil ?
68+ logDirUrl? . appendingPathComponent ( " \( currentLogFileNumber) " ) . appendingPathExtension ( " log " ) :
69+ logDirUrl? . appendingPathComponent ( " extension- \( currentLogFileNumber) " ) . appendingPathExtension ( " log " )
6070 }
6171
6272 private var currentWritableFileHandle : FileHandle ? {
@@ -86,21 +96,42 @@ class FileLoggerManager {
8696 }
8797 }
8898
89- // Url of the zip file containing all log files.
90- var archivedLogFilesUrl : URL ? {
91- return archivedLogFiles? . url
99+ init ( suiteName: String ? = nil ) {
100+ self . suiteName = suiteName
101+ if let _dateOfLastLog = UserDefaults . standard. object ( forKey: QuantiLoggerConstants . UserDefaultsKeys. dateOfLastLog) as? Date {
102+ dateOfLastLog = _dateOfLastLog
103+ } else {
104+ UserDefaults . standard. set ( dateOfLastLog, forKey: QuantiLoggerConstants . UserDefaultsKeys. dateOfLastLog)
105+ }
106+
107+ if let _currentLogFileNumber = UserDefaults . standard. object ( forKey: QuantiLoggerConstants . UserDefaultsKeys. currentLogFileNumber) as? Int {
108+ currentLogFileNumber = _currentLogFileNumber
109+ } else {
110+ UserDefaults . standard. set ( currentLogFileNumber, forKey: QuantiLoggerConstants . UserDefaultsKeys. currentLogFileNumber)
111+ }
112+
113+ if let _numOfLogFiles = UserDefaults . standard. object ( forKey: QuantiLoggerConstants . UserDefaultsKeys. numOfLogFiles) as? Int {
114+ numOfLogFiles = _numOfLogFiles
115+ } else {
116+ UserDefaults . standard. set ( numOfLogFiles, forKey: QuantiLoggerConstants . UserDefaultsKeys. numOfLogFiles)
117+ }
92118 }
93119
94- // Zip file containing log files
95- var archivedLogFiles : Archive ? {
120+ /// Get archive that contains logs
121+ ///
122+ /// - Parameters:
123+ /// - subsystem: suit name of the application. Must be passed to add logs from app extensions to archive.
124+ ///
125+ /// - Returns: compressed archive with logs
126+ func getArchivedLogFiles( suiteName: String ? ) -> Archive ? {
96127 guard let _logDirUrl = logDirUrl else {
97128 print ( " \( #function) - logDirUrl is nil. " )
98129 return nil
99130 }
100131
101132 let archiveUrl = _logDirUrl. appendingPathComponent ( " log_files_archive.zip " )
102133
103- guard let allLogFiles = gettingAllLogFiles ( ) , allLogFiles. count > 0 else {
134+ guard let allLogFiles = gettingAllLogFiles ( suiteName : suiteName ) , allLogFiles. count > 0 else {
104135 print ( " \( #function) - no log files. " )
105136 return nil
106137 }
@@ -139,26 +170,6 @@ class FileLoggerManager {
139170 return archive
140171 }
141172
142- private init ( ) {
143- if let _dateOfLastLog = UserDefaults . standard. object ( forKey: QuantiLoggerConstants . UserDefaultsKeys. dateOfLastLog) as? Date {
144- dateOfLastLog = _dateOfLastLog
145- } else {
146- UserDefaults . standard. set ( dateOfLastLog, forKey: QuantiLoggerConstants . UserDefaultsKeys. dateOfLastLog)
147- }
148-
149- if let _currentLogFileNumber = UserDefaults . standard. object ( forKey: QuantiLoggerConstants . UserDefaultsKeys. currentLogFileNumber) as? Int {
150- currentLogFileNumber = _currentLogFileNumber
151- } else {
152- UserDefaults . standard. set ( currentLogFileNumber, forKey: QuantiLoggerConstants . UserDefaultsKeys. currentLogFileNumber)
153- }
154-
155- if let _numOfLogFiles = UserDefaults . standard. object ( forKey: QuantiLoggerConstants . UserDefaultsKeys. numOfLogFiles) as? Int {
156- numOfLogFiles = _numOfLogFiles
157- } else {
158- UserDefaults . standard. set ( numOfLogFiles, forKey: QuantiLoggerConstants . UserDefaultsKeys. numOfLogFiles)
159- }
160- }
161-
162173 /// Method to reset properties that control the correct flow of storing log files.
163174 /// - "currentLogFileNumber" represents the current logging file number
164175 /// - "dateTimeOfLastLog" represents the last date the logger was used
@@ -171,8 +182,8 @@ class FileLoggerManager {
171182 }
172183
173184 /// Method to remove all log files from dedicated log folder. These files are detected by its ".log" suffix.
174- func deleteAllLogFiles( ) {
175- guard let aLogFiles = gettingAllLogFiles ( ) else { return }
185+ func deleteAllLogFiles( suiteName : String ? = nil ) {
186+ guard let aLogFiles = gettingAllLogFiles ( suiteName : suiteName ) else { return }
176187
177188 aLogFiles. forEach { ( aLogFileUrl) in
178189 deleteLogFile ( at: aLogFileUrl)
@@ -231,12 +242,22 @@ class FileLoggerManager {
231242
232243 /// Method to get all log file names from dedicated log folder. These files are detected by its ".log" suffix.
233244 ///
245+ /// - Parameters:
246+ /// - subsystem: suit name of the application. Must be passed to also get logs from app extensions.
247+ ///
234248 /// - Returns: Array of log file names
235- func gettingAllLogFiles( ) -> [ URL ] ? {
236- guard let _logDirUrl = logDirUrl else { return nil }
237-
249+ func gettingAllLogFiles( suiteName: String ? = nil ) -> [ URL ] ? {
250+ var logDirectories = [ logDirUrl]
251+ if let suiteName = suiteName,
252+ let extensionDirectory = FileManager . default. containerURL ( forSecurityApplicationGroupIdentifier: suiteName) ? . appendingPathComponent ( " logs " ) , FileManager . default. fileExists ( atPath: extensionDirectory. path) {
253+ logDirectories. append ( extensionDirectory)
254+ }
238255 do {
239- let directoryContent = try FileManager . default. contentsOfDirectory ( at: _logDirUrl, includingPropertiesForKeys: nil , options: [ ] )
256+ let directoryContent = try logDirectories
257+ . compactMap { $0 }
258+ . flatMap {
259+ try FileManager . default. contentsOfDirectory ( at: $0, includingPropertiesForKeys: nil , options: [ ] )
260+ }
240261 let logFiles = directoryContent. filter ( { ( file) -> Bool in
241262 file. pathExtension == " log "
242263 } )
0 commit comments