How can I log each request/response using Alamofire?

前端 未结 8 1398
迷失自我
迷失自我 2020-12-23 16:20

Is there a way to log each request / response using Alamofire (something similar to AFNetworkActivityLogger) ?

I am aware of Printable, DebugPrintable and Output (cU

相关标签:
8条回答
  • 2020-12-23 16:24

    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
      }
     }
    
    0 讨论(0)
  • 2020-12-23 16:25

    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
    }()
    }
    
    0 讨论(0)
  • 2020-12-23 16:27

    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.

    0 讨论(0)
  • 2020-12-23 16:28

    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
    
    0 讨论(0)
  • 2020-12-23 16:28

    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

    0 讨论(0)
  • 2020-12-23 16:30

    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)
        })
      }
    }
    
    0 讨论(0)
提交回复
热议问题