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

1k views Asked by At

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.

1

There are 1 answers

3
Andreas Oetjen On BEST ANSWER

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.