There are multiple options for logging network requests using Pulse.
Manual Logging #
The recommended option it to log the request manually using a NetworkLogger
instance.
URLSession #
Add the following calls to your URLSessionDelegate
.
let logger = NetworkLogger()
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
logger.logDataTask(dataTask, didReceive: response)
// ... make sure to call a completionHandler
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
logger.logTask(task, didCompleteWithError: error)
// ...
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
logger.logDataTask(dataTask, didReceive: data)
// ...
}
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
logger.logTask(task, didFinishCollecting: metrics)
// ...
}
The initial version only supports
URLSessionDataTask
.
NetworkLogger
has a couple of cutomization options. For example, withwillLogTask
, you can filter out sensitive information from the requests.
Alamofire and Moya #
If you are using Alamofire or Moya, you can use any of the approaches outlined in this guide. For manual logging, you can use Alamofire.EventMonitor
. It also works for Moya which uses on Alamofire.
import Alamofire
// Don't forget to bootstrap the logging system first.
let session = Alamofire.Session(eventMonitors: [NetworkLoggerEventMonitor(logger: logger)])
struct NetworkLoggerEventMonitor: EventMonitor {
let logger: NetworkLogger
func request(_ request: Request, didCreateTask task: URLSessionTask) {
logger.logTaskCreated(task)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
logger.logDataTask(dataTask, didReceive: data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
logger.logTask(task, didFinishCollecting: metrics)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
logger.logTask(task, didCompleteWithError: error)
}
}
Other #
NetworkLogger
allows you to track the status of the request incrementally. But if you just want to store the response or you are using an API that doesn’t provide access to URLSessionTask
instances, you can just store the response directly:
LoggerStore.default.storeRequest(request, response: response, error: error, data: data, metrics: nil)
Automatic Logging #
Manual logging is a simple and powerful option, but if you want to automate things a little bit or get access to URLSession
instances you don’t have control over, you have options.
You can use URLSessionProxyDelegate
to automatically capture all of the important URLSession
events, including task metrics. You can either enable it for all session:
// Call it anywhere in your code prior to instantiating a `URLSession`
URLSessionProxyDelegate.enableAutomaticRegistration()
// Instantiate `URLSession` as usual
let session = URLSession(configuration: .default, delegate: YourURLSessionDelegate(), delegateQueue: nil)
URLSessionProxyDelegate
uses Objective-C runtime to proxy the URLSessionDelegate calls and swizzling for automatic registration for all session.
If you want to enable logging just for your session, use URLSessionProxyDelegate
directly.
let originalDelegate = YourURLSessionDelegate()
let proxyDelegate = URLSessionProxyDelegate(delegate: originalDelegate)
let session = URLSession(configuration: .default, delegate: proxyDelegate, delegateQueue: nil)
If you are using a default URLSession
with completion closure, the best option is to just store the responses manually in the completion closure using LoggerStore
. But you can also give Experimental.URLSessionProxy
a try. It’s not battle-tested yet, and it will affect your networking, so please use it at your own risk.
Experimental.URLSessionProxy.shared.isEnabled = true
The way it works is by registering a custom URLProtocol and using a secondary
URLSession
instance in it. This will affect your networking and should only be used for evaluating Pulse.