iosloggingnsdocumentdirectory

How to capture Device Logs in iOS during Runtime into a file in Documents Directory from iPhone?


My requirement is to capture all the Debug Logs into a file during the runtime of the Application in iOS. The basic reason to have this is to understand the behaviour of VOIP Calls in my Application in different Networks. We want to understand the behaviour of calls in 5G Network as we don't have a provision to test the behaviour in 5G Network. Our SDK can Log the behaviour. I am aware of capturing the Logs for the Development devices by connecting it to Xcode and but I need to do the same for the devices that are in Production. I want to provide an option to mail those Logs to a mail ID. Is there a way to do it? Any help would be appreciated.


Solution

  • There a a few options to get the log information from a production device, but they all have there drawbacks.

    1. sysdiagnosis

    The user has to manually trigger the sysdiagnose, then navigate in the settings to the analysis data, find the corresponding file and somehow send it to you. It's quite large (hundreds of MB), but you'll find the corresponding logarchive inside and can open it in the console app or use the log command

    2. Wait for iOS 14 (maybe)

    On macOS, the OSLog framework contains means to collect the log information by OSLogStore; in iOS 13 betas this was also available, but finally has been removed from the final version. Maybe Apple will put it in the next iOS

    3. Use 3rd party tools

    There are several 3rd party logging tools available, just take a look at SwiftyBeaver, SwiftLog, CocoaLumberjack or others.

    4. Bring your own

    You could also implement some basic logging in your app, write the information to a file, and let the user e-mail this to you (or transfer via https, but I'd rather inform the user about this). Fun fact is that I'm just about to write some little helper classes, because I don't want all this 3rd-party-cloud-logging. Something like this:

     
    @IBAction func doAction(_ sender: Any) {
        pEnter(); defer { pLeave() }       
        // ...
        let dateString = " ... "
        traceError("Illegal init date: \(dateString)")
    }
    
    /* ... */
    
     
    #if DEBUG
    func pEnter(file: String = #file, line: Int = #line, function: String = #function) {
        FunctionCallTracker.instance.enter(file: file, line: line, function: function) 
    }
    func pLeave(file: String = #file, line: Int = #line, function: String = #function) {
        FunctionCallTracker.instance.leave(file: file, line: line, function: function) 
    }
     
    func traceError(_ text: @autoclosure @escaping()->String, 
                     error:Error? = nil, 
                     file: String = #file, 
                     function: String = #function,
                     line: Int = #line) {
        /* ... */
    }
    #else
    @inline(__always) func traceFile(_ text: @autoclosure @escaping()->String) {}
    @inline(__always) func pEnter() {}
    @inline(__always) func pLeave() {}
    #endif
    

    If you are interested, I could update you in a few weeks when it's finished.