Is there a way to log each request / response using Alamofire (something similar to AFNetworkActivityLogger) ?
I am aware of Printable, DebugPrintable and Output (cU
in Alamofire 5 URLRequest is created asynchronously which means
extension Request {
public func debugLog() -> Self {
#if DEBUG
debugPrint(self)
#endif
return self
}
}
is not the best solution anymore. instead, calling cURLDescription
is recommend as below:
let request = AF.request(<Your request>))
request.cURLDescription { (curl) in
print("CURL \(curl)")
}
request.responseJSON { response in
//Do something with your response...
}
or
extension Request {
public func debugLog() -> Self {
#if DEBUG
cURLDescription(calling: { (curl) in
debugPrint("=======================================")
print(curl)
debugPrint("=======================================")
})
#endif
return self
}
}
Timberjack is what you are looking. Timberjack is a simple, unintrusive network activity logger. Log every request your app makes, or limit to only those using a certain NSURLSession if you’d prefer. It also works with Alamofire, if that’s your thing.
https://cocoapods.org/pods/Timberjack
usage:
import Alamofire
import Timberjack
class HTTPManager: Alamofire.Manager {
static let sharedManager: HTTPManager = {
let configuration = Timberjack.defaultSessionConfiguration()
let manager = HTTPManager(configuration: configuration)
return manager
}()
}
In Alamofire 5.0.0 I used the answer based on: https://github.com/Alamofire/Alamofire/issues/2867#issuecomment-509662892 but I had to replace DataResponse by AFDataResponse. For example:
import Alamofire
final class AlamofireLogger: EventMonitor {
func requestDidResume(_ request: Request) {
let allHeaders = request.request.flatMap { $0.allHTTPHeaderFields.map { $0.description } } ?? "None"
let headers = """
⚡️⚡️⚡️⚡️ Request Started: \(request)
⚡️⚡️⚡️⚡️ Headers: \(allHeaders)
"""
NSLog(headers)
let body = request.request.flatMap { $0.httpBody.map { String(decoding: $0, as: UTF8.self) } } ?? "None"
let message = """
⚡️⚡️⚡️⚡️ Request Started: \(request)
⚡️⚡️⚡️⚡️ Body Data: \(body)
"""
NSLog(message)
}
func request<Value>(_ request: DataRequest, didParseResponse response: AFDataResponse<Value>) {
NSLog("⚡️⚡️⚡️⚡️ Response Received: \(response.debugDescription)")
NSLog("⚡️⚡️⚡️⚡️ Response All Headers: \(String(describing: response.response?.allHeaderFields))")
}
}
And then you can use it in the following way:
let session = Session(eventMonitors: [ AlamofireLogger() ])
As it has explained by 0xced in an aforementioned post.
There's a sweet little pod for this: https://github.com/konkab/AlamofireNetworkActivityLogger
Add this to your podfile:
pod 'AlamofireNetworkActivityLogger', '~> 2.0'
In your AppDelegate:
import AlamofireNetworkActivityLogger
Then in your didFinishLaunchingWithOptions
, add this:
NetworkActivityLogger.shared.level = .debug
NetworkActivityLogger.shared.startLogging()
EDIT: I've actually encountered crashes with this in production. To be on the safe side, use "build flags" to only use this in debug, something like this:
#if DEBUG
NetworkActivityLogger.shared.level = .debug
NetworkActivityLogger.shared.startLogging()
#endif
Adding to above answer for Alamofire 4.0+ Swift 3
extension DataRequest {
public func LogRequest() -> Self {
//Your logic for logging
return self
}
}
When Requesting
Alamofire.request(requestUrl, method: .post, parameters: parameter, encoding: JSONEncoding.default)
.LogRequest()
.responseJSON { response in
//Do your thing
}
If you want to cancel the request in any case(which was something I wanted) you can self.cancel()
anywhere before you return self
Something like this might be what you were looking for:
extension Request {
public func debugLog() -> Self {
#if DEBUG
debugPrint(self)
#endif
return self
}
}
Usage:
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.debugLog()
.response {…}
If you want to print all responses, you could write your own response method, similar to the responseObject() method at the top of this tutorial:
http://www.raywenderlich.com/87595/intermediate-alamofire-tutorial
[Update: added below per the request from @trauzti.]
Here's how one might do the responseObject() approach in order to print output on every request.
Caveat lector: I haven't personally tested this code, and would probably make different choices in production. This simply shows how the Wenderlich tutorial code can include debug logging. Also note: since the tutorial is pre-Swift 2.0, I've used the old println() instead of print().
@objc public protocol ResponseObjectSerializable {
init(response: NSHTTPURLResponse, representation: AnyObject)
}
extension Alamofire.Request {
public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
let serializer: Serializer = { (request, response, data) in
#if DEBUG
println("Request: \(request.URL)")
#endif
let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
if response != nil && JSON != nil {
#if DEBUG
println("Response:")
debugPrint(JSON)
#endif
return (T(response: response!, representation: JSON!), nil)
} else {
#if DEBUG
println("Failed Serialization:")
debugPrint(serializationError)
#endif
return (nil, serializationError)
}
}
return response(serializer: serializer, completionHandler: { (request, response, object, error) in
completionHandler(request, response, object as? T, error)
})
}
}