72

有没有办法使用 Alamofire(类似于 AFNetworkActivityLogger)记录每个请求/响应?

我知道 Printable、DebugPrintable 和 Output (cURL),但它们并不是我想要的。

4

9 回答 9

61

有一个可爱的小豆荚:https ://github.com/konkab/AlamofireNetworkActivityLogger

将此添加到您的 podfile 中:

pod 'AlamofireNetworkActivityLogger', '~> 2.0'

在您的 AppDelegate 中:

import AlamofireNetworkActivityLogger

然后在你的didFinishLaunchingWithOptions,添加这个:

NetworkActivityLogger.shared.level = .debug
NetworkActivityLogger.shared.startLogging()

编辑:我实际上在生产中遇到了崩溃。为了安全起见,使用“构建标志”仅在调试中使用它,如下所示:

#if DEBUG
    NetworkActivityLogger.shared.level = .debug
    NetworkActivityLogger.shared.startLogging()
#endif
于 2017-05-11T13:04:59.203 回答
48

像这样的东西可能是您正在寻找的东西:

extension Request {
   public func debugLog() -> Self {
      #if DEBUG
         debugPrint(self)
      #endif
      return self
   }
}

用法:

Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
         .debugLog()
         .response {…}

如果要打印所有响应,可以编写自己的响应方法,类似于本教程顶部的 responseObject() 方法:

http://www.raywenderlich.com/87595/intermediate-alamofire-tutorial

[更新:根据@trauzti 的要求在下面添加。]

以下是如何使用 responseObject() 方法来打印每个请求的输出。

警告讲师:我没有亲自测试过这段代码,并且可能会在生产中做出不同的选择。这只是显示了 Wenderlich 教程代码如何包含调试日志记录。另请注意:由于本教程是 Swift 2.0 之前的版本,因此我使用了旧的 println() 而不是 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)
    })
  }
}
于 2015-05-20T16:40:10.600 回答
16

从 Alamofire 5 开始,最简单的方法是定义一个EventMonitor子类:

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)")
    }
}

然后在您的会话中使用它:

let session = Session(eventMonitors: [ AlamofireLogger() ])

此示例代码改编自https://github.com/Alamofire/Alamofire/issues/2867#issuecomment-509662892

于 2019-09-09T22:42:07.863 回答
11

Timberjack 就是您正在寻找的东西。Timberjack 是一个简单的、非侵入式的网络活动记录器。记录您的应用程序发出的每个请求,或者如果您愿意,则仅限于使用特定 NSURLSession 的请求。如果这是你的事,它也适用于 Alamofire。

https://cocoapods.org/pods/Timberjack

用法:

import Alamofire
import Timberjack

class HTTPManager: Alamofire.Manager {
static let sharedManager: HTTPManager = {
    let configuration = Timberjack.defaultSessionConfiguration()
    let manager = HTTPManager(configuration: configuration)
    return manager
}()
}
于 2016-01-15T12:39:00.710 回答
6

添加到 Alamofire 4.0+ Swift 3 的上述答案

extension DataRequest {        
        public func LogRequest() -> Self {
        //Your logic for logging
        return self
    }
}

请求时

Alamofire.request(requestUrl, method: .post, parameters: parameter, encoding: JSONEncoding.default)
            .LogRequest()
            .responseJSON { response in
            //Do your thing
            }

如果您想在任何情况下取消请求(这是我想要的),您可以self.cancel()在返回之前的任何地方

于 2017-01-20T17:01:21.770 回答
4

在 Alamofire 5 中,URLRequest 是异步创建的,这意味着

extension Request {
 public func debugLog() -> Self {
  #if DEBUG
     debugPrint(self)
  #endif
  return self
  }
}

不再是最好的解决方案。相反,cURLDescription建议如下调用:

let request = AF.request(<Your request>))
request.cURLDescription { (curl) in
   print("CURL \(curl)")
}
request.responseJSON { response in
   //Do something with your response...
}

或者

extension Request {
public func debugLog() -> Self {
    #if DEBUG
    cURLDescription(calling: { (curl) in
        debugPrint("=======================================")
        print(curl)
        debugPrint("=======================================")
    })
    #endif
    return self
  }
 }
于 2020-06-24T18:14:21.663 回答
1

在 Alamofire 5.0.0 中,我使用了基于: https ://github.com/Alamofire/Alamofire/issues/2867#issuecomment-509662892 的答案, 但我不得不用 AFDataResponse 替换 DataResponse。例如:

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))")
    }
}

然后您可以通过以下方式使用它:

let session = Session(eventMonitors: [ AlamofireLogger() ])

正如 0xced 在上述帖子中所解释的那样。

于 2020-03-01T12:20:04.937 回答
1

斯威夫特 3.0+ 的解决方案

对于打印请求参数和标头:

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()

用于打印响应。使用下面的扩展名。

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
    }
}

给你的小要点: https ://gist.github.com/manishpathak99/348f2eb0167c0ff6e12ecd667612bc9b/edit

于 2017-06-06T13:46:55.910 回答
0

在 Alamofire 5 及更高版本中,您可以curl通过以下代码获取请求详细信息:

request.cURLDescription(calling: { (curl) in
    print(curl)
})

和响应/错误数据:

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
            }
            
        }
于 2022-01-21T16:32:50.143 回答