IOS-1540 Back out 0b9e5083075e: Cleaning out Logger. IOS-1540_GOOD
authorDirk Zimmermann <dz@pep.security>
Tue, 11 Jun 2019 16:28:31 +0200
branchIOS-1540_GOOD
changeset 897922913a3226eb
parent 8978 2ba8db059a3e
child 8980 352ea3d0c911
IOS-1540 Back out 0b9e5083075e: Cleaning out Logger.
Submodules/pEpIOSToolbox/pEpIOSToolbox/Other/Logger.swift
     1.1 --- a/Submodules/pEpIOSToolbox/pEpIOSToolbox/Other/Logger.swift	Tue Jun 11 16:28:31 2019 +0200
     1.2 +++ b/Submodules/pEpIOSToolbox/pEpIOSToolbox/Other/Logger.swift	Tue Jun 11 16:28:31 2019 +0200
     1.3 @@ -9,13 +9,158 @@
     1.4  import Foundation
     1.5  import os.log
     1.6  
     1.7 +/**
     1.8 + Thin layer over `os_log` where not available.
     1.9 + */
    1.10 +@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)
    1.11  public class Logger {
    1.12 +    /**
    1.13 +     Map `os_log` levels.
    1.14 +     */
    1.15 +    public enum Severity {
    1.16 +        /**
    1.17 +         - Note: Not persisted by default, but will be written in case of errors.
    1.18 +         */
    1.19 +        case info
    1.20 +
    1.21 +        /**
    1.22 +         - Note: Not persisted by default, but will be written in case of errors.
    1.23 +         */
    1.24 +        case debug
    1.25 +
    1.26 +        /**
    1.27 +         This is the lowest priority that gets written to disk by default.
    1.28 +         Used like WARN in this logger.
    1.29 +         */
    1.30 +        case `default`
    1.31 +
    1.32 +        case error
    1.33 +
    1.34 +        /**
    1.35 +         - Note: As this is referring to inter-process problems, I don't see a use-case
    1.36 +         for iOS.
    1.37 +         */
    1.38 +        case fault
    1.39 +
    1.40 +        public func osLogType() -> OSLogType {
    1.41 +            switch self {
    1.42 +            case .info:
    1.43 +                return .info
    1.44 +            case .debug:
    1.45 +                return .debug
    1.46 +            case .default:
    1.47 +                return .default
    1.48 +            case .error:
    1.49 +                return .error
    1.50 +            case .fault:
    1.51 +                return .fault
    1.52 +            }
    1.53 +        }
    1.54 +    }
    1.55 +
    1.56      public init(subsystem: String = "security.pEp.app.iOS", category: String) {
    1.57          self.subsystem = subsystem
    1.58          self.category = category
    1.59          osLogger = OSLog(subsystem: subsystem, category: category)
    1.60      }
    1.61  
    1.62 +    /**
    1.63 +     Logs to default.
    1.64 +     */
    1.65 +    public func log(function: String = #function,
    1.66 +                    filePath: String = #file,
    1.67 +                    fileLine: Int = #line,
    1.68 +                    _ message: StaticString,
    1.69 +                    _ args: CVarArg...) {
    1.70 +        saveLog(message: message,
    1.71 +                severity: .default,
    1.72 +                function: function,
    1.73 +                filePath: filePath,
    1.74 +                fileLine: fileLine,
    1.75 +                args: args)
    1.76 +    }
    1.77 +
    1.78 +    /**
    1.79 +     os_log doesn't have a warn per se, but default is coming close.
    1.80 +     This is the same as log.
    1.81 +     */
    1.82 +    public func warn(function: String = #function,
    1.83 +                     filePath: String = #file,
    1.84 +                     fileLine: Int = #line,
    1.85 +                     _ message: StaticString,
    1.86 +                     _ args: CVarArg...) {
    1.87 +        saveLog(message: message,
    1.88 +                severity: .default,
    1.89 +                function: function,
    1.90 +                filePath: filePath,
    1.91 +                fileLine: fileLine,
    1.92 +                args: args)
    1.93 +    }
    1.94 +
    1.95 +    /**
    1.96 +     Logs to info.
    1.97 +     */
    1.98 +    public func info(function: String = #function,
    1.99 +                     filePath: String = #file,
   1.100 +                     fileLine: Int = #line,
   1.101 +                     _ message: StaticString,
   1.102 +                     _ args: CVarArg...) {
   1.103 +        saveLog(message: message,
   1.104 +                severity: .info,
   1.105 +                function: function,
   1.106 +                filePath: filePath,
   1.107 +                fileLine: fileLine,
   1.108 +                args: args)
   1.109 +    }
   1.110 +
   1.111 +    /**
   1.112 +     Logs to debug.
   1.113 +     */
   1.114 +    public func debug(function: String = #function,
   1.115 +                      filePath: String = #file,
   1.116 +                      fileLine: Int = #line,
   1.117 +                      _ message: StaticString,
   1.118 +                      _ args: CVarArg...) {
   1.119 +        saveLog(message: message,
   1.120 +                severity: .debug,
   1.121 +                function: function,
   1.122 +                filePath: filePath,
   1.123 +                fileLine: fileLine,
   1.124 +                args: args)
   1.125 +    }
   1.126 +
   1.127 +    /**
   1.128 +     Logs to error.
   1.129 +     */
   1.130 +    public func error(function: String = #function,
   1.131 +                      filePath: String = #file,
   1.132 +                      fileLine: Int = #line,
   1.133 +                      _ message: StaticString,
   1.134 +                      _ args: CVarArg...) {
   1.135 +        saveLog(message: message,
   1.136 +                severity: .error,
   1.137 +                function: function,
   1.138 +                filePath: filePath,
   1.139 +                fileLine: fileLine,
   1.140 +                args: args)
   1.141 +    }
   1.142 +
   1.143 +    /**
   1.144 +     Logs to fault.
   1.145 +     */
   1.146 +    public func fault(function: String = #function,
   1.147 +                      filePath: String = #file,
   1.148 +                      fileLine: Int = #line,
   1.149 +                      _ message: StaticString,
   1.150 +                      _ args: CVarArg...) {
   1.151 +        saveLog(message: message,
   1.152 +                severity: .fault,
   1.153 +                function: function,
   1.154 +                filePath: filePath,
   1.155 +                fileLine: fileLine,
   1.156 +                args: args)
   1.157 +    }
   1.158 +
   1.159      public func errorAndCrash(function: String = #function,
   1.160                                filePath: String = #file,
   1.161                                fileLine: Int = #line,
   1.162 @@ -30,6 +175,9 @@
   1.163          SystemUtils.crash("\(filePath):\(function):\(fileLine) - \(error)")
   1.164      }
   1.165  
   1.166 +    /**
   1.167 +     Logs an error.
   1.168 +     */
   1.169      public func log(function: String = #function,
   1.170                      filePath: String = #file,
   1.171                      fileLine: Int = #line,
   1.172 @@ -41,12 +189,13 @@
   1.173          // log messages.
   1.174          // So we wrap it into an NSError which does suppord CVArg.
   1.175          let nsErr = NSError(domain: subsystem, code: 0, userInfo: [NSUnderlyingErrorKey: error])
   1.176 -        os_log("Error (%{public}@ %{public}@:%d) %{public}@",
   1.177 -               type: .error,
   1.178 -               function,
   1.179 -               filePath,
   1.180 -               fileLine,
   1.181 -               nsErr)
   1.182 +
   1.183 +        saveLog(message: "%{public}@",
   1.184 +                severity: .default,
   1.185 +                function: function,
   1.186 +                filePath: filePath,
   1.187 +                fileLine: fileLine,
   1.188 +                args: [nsErr])
   1.189      }
   1.190  
   1.191      /**
   1.192 @@ -60,5 +209,113 @@
   1.193      private let subsystem: String
   1.194      private let category: String
   1.195  
   1.196 -    private let osLogger: OSLog
   1.197 +    private let osLogger: Any?
   1.198 +
   1.199 +    private func saveLog(message: StaticString,
   1.200 +                         severity: Severity,
   1.201 +                         function: String = #function,
   1.202 +                         filePath: String = #file,
   1.203 +                         fileLine: Int = #line,
   1.204 +                         args: [CVarArg]) {
   1.205 +        osLog(message: message,
   1.206 +              severity: severity,
   1.207 +              function: function,
   1.208 +              filePath: filePath,
   1.209 +              fileLine: fileLine,
   1.210 +              args: args)
   1.211 +    }
   1.212 +
   1.213 +    /**
   1.214 +     - Note: If the number of arguments to the format string exceeds 10,
   1.215 +     the logging doesn't work correctly. Can be easily fixed though, if really needed.
   1.216 +     */
   1.217 +    private func osLog(message: StaticString,
   1.218 +                       severity: Severity,
   1.219 +                       function: String = #function,
   1.220 +                       filePath: String = #file,
   1.221 +                       fileLine: Int = #line,
   1.222 +                       args: [CVarArg]) {
   1.223 +        let theLog = osLogger as! OSLog
   1.224 +        let theType = severity.osLogType()
   1.225 +
   1.226 +        // I haven't found a way of injecting `function` etc. into the original message for
   1.227 +        // just one call to `os_log`, so the 'position' is logged on a separate line.
   1.228 +        os_log("%@:%d %@:",
   1.229 +               log: theLog,
   1.230 +               type: theType,
   1.231 +               filePath,
   1.232 +               fileLine,
   1.233 +               function)
   1.234 +
   1.235 +        // We have to expand the array of arguments into positional ones.
   1.236 +        // There is no attempt of trying to format the string on our side
   1.237 +        // in order to make use of `os_log`'s fast 'offline' formatting
   1.238 +        // (that is, the work is delayed until actual log display).
   1.239 +        switch args.count {
   1.240 +        case 0:
   1.241 +            os_log(message,
   1.242 +                   log: theLog,
   1.243 +                   type: theType)
   1.244 +        case 1:
   1.245 +            os_log(message,
   1.246 +                   log: theLog,
   1.247 +                   type: theType,
   1.248 +                   args[0])
   1.249 +        case 2:
   1.250 +            os_log(message,
   1.251 +                   log: theLog,
   1.252 +                   type: theType,
   1.253 +                   args[0], args[1])
   1.254 +        case 3:
   1.255 +            os_log(message,
   1.256 +                   log: theLog,
   1.257 +                   type: theType,
   1.258 +                   args[0], args[1], args[2])
   1.259 +        case 4:
   1.260 +            os_log(message,
   1.261 +                   log: theLog,
   1.262 +                   type: theType,
   1.263 +                   args[0], args[1], args[2], args[3])
   1.264 +        case 5:
   1.265 +            os_log(message,
   1.266 +                   log: theLog,
   1.267 +                   type: theType,
   1.268 +                   args[0], args[1], args[2], args[3], args[4])
   1.269 +        case 6:
   1.270 +            os_log(message,
   1.271 +                   log: theLog,
   1.272 +                   type: theType,
   1.273 +                   args[0], args[1], args[2], args[3], args[4], args[5])
   1.274 +        case 7:
   1.275 +            os_log(message,
   1.276 +                   log: theLog,
   1.277 +                   type: theType,
   1.278 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6])
   1.279 +        case 8:
   1.280 +            os_log(message,
   1.281 +                   log: theLog,
   1.282 +                   type: theType,
   1.283 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7])
   1.284 +        case 9:
   1.285 +            os_log(message,
   1.286 +                   log: theLog,
   1.287 +                   type: theType,
   1.288 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
   1.289 +                   args[8])
   1.290 +        case 10:
   1.291 +            os_log(message,
   1.292 +                   log: theLog,
   1.293 +                   type: theType,
   1.294 +                   args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
   1.295 +                   args[8], args[9])
   1.296 +        default:
   1.297 +            os_log("Using more than 10 parameters",
   1.298 +                   log: theLog,
   1.299 +                   type: .error)
   1.300 +            os_log(message,
   1.301 +                   log: theLog,
   1.302 +                   type: theType,
   1.303 +                   args)
   1.304 +        }
   1.305 +    }
   1.306  }