| // Copyright 2016 The Tulsi Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| import Foundation |
| import TulsiGenerator |
| |
| |
| /// Writes events to the console. |
| final class EventLogger { |
| private let verboseLevel: TulsiMessageLevel |
| private var observer: NSObjectProtocol? = nil |
| |
| private let logFile: FileHandle? = nil |
| |
| init(verboseLevel: TulsiMessageLevel, logToFile: Bool=false) { |
| self.verboseLevel = verboseLevel |
| |
| if logToFile, let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String { |
| self.logFile = EventLogger.createLogFile(appName) |
| } else { |
| self.logFile = nil |
| } |
| } |
| |
| deinit { |
| if let observer = self.observer { |
| NotificationCenter.default.removeObserver(observer) |
| } |
| } |
| |
| func startLogging() { |
| observer = NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: TulsiMessageNotification), |
| object: nil, |
| queue: nil) { |
| [weak self] (notification: Notification) in |
| guard let item = LogMessage(notification: notification) else { |
| return |
| } |
| self?.logItem(item) |
| } |
| } |
| |
| // MARK: - Private methods |
| |
| private static func createLogFile(_ appName: String) -> FileHandle? { |
| let fileManager = FileManager.default |
| guard let folder = fileManager.urls(for: .applicationSupportDirectory, |
| in: .userDomainMask).first else { |
| return |
| } |
| |
| let tulsiFolder = folder.appendingPathComponent(appName) |
| var isDirectory: ObjCBool = false |
| let fileExists = fileManager.fileExists(atPath: tulsiFolder.path, isDirectory: &isDirectory) |
| |
| if !fileExists || !isDirectory.boolValue { |
| do { |
| try fileManager.createDirectory(at: tulsiFolder, |
| withIntermediateDirectories: true, |
| attributes: nil) |
| } catch { |
| print("failed to create logging folder at \"\(tulsiFolder)\".") |
| return |
| } |
| } |
| |
| let dateFormatter = DateFormatter() |
| dateFormatter.dateFormat = "yyyyMMdd_HHmmss" |
| let date = Date() |
| let dateString = dateFormatter.string(from: date) |
| |
| let logFileUrl = tulsiFolder.appendingPathComponent("log_\(dateString).txt") |
| do { |
| fileManager.createFile(atPath: logFileUrl.path, contents: nil, attributes: nil) |
| try self.logFile = FileHandle(forWritingTo: logFileUrl) |
| } catch { |
| print("error creating log file at \"\(logFileUrl.path)\".") |
| return |
| } |
| } |
| |
| private func logItem(_ item: LogMessage) { |
| let level: String = item.level.rawValue |
| |
| let logString = "[\(level)] \(item.message)\n" |
| if let logFile = self.logFile, let logData = logString.data(using: .utf8) { |
| logFile.seekToEndOfFile() |
| logFile.write(logData) |
| } |
| |
| guard self.verboseLevel.logRank.rawValue >= item.level.logRank.rawValue else { |
| return |
| } |
| |
| let details: String |
| if let itemDetails = item.details { |
| details = " \(itemDetails)" |
| } else { |
| details = "" |
| } |
| print("[\(level)] \(item.message)\(details)") |
| } |
| } |