'How can I log each request/response using Alamofire?
Is there a way to log each request / response using Alamofire (something similar to AFNetworkActivityLogger) ?
I am aware of Printable, DebugPrintable and Output (cURL) but they are not quite what I am looking for.
Solution 1:[1]
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
Solution 2:[2]
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)
})
}
}
Solution 3:[3]
Since Alamofire 5, the easiest way is to define an EventMonitor
subclass:
final class AlamofireLogger: EventMonitor {
func requestDidResume(_ request: Request) {
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: DataResponse<Value>) {
NSLog("?? Response Received: \(response.debugDescription)")
}
}
Then use it on your session:
let session = Session(eventMonitors: [ AlamofireLogger() ])
This sample code was adapted from https://github.com/Alamofire/Alamofire/issues/2867#issuecomment-509662892
Solution 4:[4]
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
}()
}
Solution 5:[5]
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
Solution 6:[6]
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
}
}
Solution 7:[7]
SOLUTION FOR SWIFT 3.0+
For Printing Request parameter and headers:
Alamofire.request(url, method: .get, parameters: parameters, headers: headers)
.validate()
.responseObject { (response: DataResponse<T>) in
self.pendingRequests.removeValue(forKey: endPoint)
completion!(response)
if(NetworkConfig.loggingEnable) {
debugPrint("************* printing REQUEST parameter and Headers *************")
debugPrint("RESPONSE : \(response.debugDescription)")
}
}.responseDebugPrint()
For Printing Response . use below extension .
import Foundation
import Alamofire
extension Alamofire.DataRequest {
func responseDebugPrint() -> Self {
if NetworkConfig.loggingEnable {
return responseJSON() {
response in
if let JSON = response.result.value,
let JSONData = try? JSONSerialization.data(withJSONObject: JSON, options: .prettyPrinted),
let prettyString = NSString(data: JSONData, encoding: String.Encoding.utf8.rawValue) {
print(prettyString)
} else if let error = response.result.error {
print("Error Debug Print: \(error.localizedDescription)")
}
}
}
return self
}
}
Small gist for you : https://gist.github.com/manishpathak99/348f2eb0167c0ff6e12ecd667612bc9b/edit
Solution 8:[8]
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.
Solution 9:[9]
In Alamofire 5 and above you can get curl
request details by the below code:
request.cURLDescription(calling: { (curl) in
print(curl)
})
And response/error data:
request.responseDecodable { (response:AFDataResponse<T>) in
switch response.result {
case .success(let value):
var responseMessage : String?
if let data = response.data {
let json = String(data: data, encoding: String.Encoding.utf8)
responseMessage = String(describing: json)
}
print(responseMessage)
break;
case .failure(let error):
var message : String?
if let data = response.data {
let json = String(data: data, encoding: String.Encoding.utf8)
message = String(describing: json)
}
print(message)
break
}
}
Solution 10:[10]
Alamofire provides a powerful way to gain insight into all the internal events via the EventMonitor
protocol. EventMonitor
includes several Alamofire events such as URLSessionDelegate
request events. This makes EventMonitor
ideal for logging events.
import Alamofire
class NetworkLogger: EventMonitor {
let queue = DispatchQueue(label: "com.company.project.networklogger")
func requestDidFinish(_ request: Request) {
print(request.description)
}
func request<Value>(
_ request: DataRequest,
didParseResponse response: DataResponse<Value, AFError>
) {
guard let data = response.data else {
return
}
if let json = try? JSONSerialization
.jsonObject(with: data, options: .mutableContainers) {
print(json)
}
}
}
Reference: https://www.raywenderlich.com/11668143-alamofire-tutorial-for-ios-advanced-usage#toc-anchor-004
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | 0xced |
Solution 4 | ali |
Solution 5 | vinbhai4u |
Solution 6 | |
Solution 7 | |
Solution 8 | Genar |
Solution 9 | AaoIi |
Solution 10 | andy0570 |