Repository: Moya/Moya
File: Sources/Moya/Plugins/NetworkLoggerPlugin.swift (Swift)

Code before:
            || configuration.successResponseLoggingOptions.contains(.body) {

            let stringOutput = configuration.responseDataFormatter(response.data)
            output.append(newEntry(identifier: "Response Body", message: stringOutput))
        }

        return output
    }


    func logNetworkError(_ error: MoyaError, target: TargetType) -> [String] {
        //Some errors will still have a response, like errors due to Alamofire's HTTP code validation.
        if let moyaResponse = error.response {
            return logNetworkResponse(moyaResponse, target: target, isFromError: true)
        }

        //Errors without an HTTPURLResponse are those due to connectivity, time-out and such.
        return [newEntry(identifier: "Error", message: "Error calling \(target) : \(error)")]
    }
}

//MARK: - Configuration
public extension NetworkLoggerPlugin {
    struct Configuration {

        public typealias OutputType = (_ target: TargetType, _ items: [Any]) -> Void
        public typealias DataFormatterType = (Data) -> (String)

        fileprivate let loggerId: String
        fileprivate let dateFormatter: DateFormatter
        fileprivate let output: OutputType
        fileprivate let requestDataFormatter: DataFormatterType
        //fileprivate let responseDataFormatter: ((Data) -> (Data))?
        fileprivate let responseDataFormatter: DataFormatterType
        fileprivate let requestLoggingOptions: RequestLogOptions
        fileprivate let successResponseLoggingOptions: ResponseLogOptions
        fileprivate let errorResponseLoggingOptions: ResponseLogOptions

        public init(loggerId: String = "Moya_Logger",
                    dateFormatter: DateFormatter = defaultDateFormatter,
                    output: @escaping OutputType = defaultOutput,
                    requestDataFormatter: @escaping DataFormatterType = defaultDataFormatter,
                    responseDataFormatter: @escaping DataFormatterType = defaultDataFormatter,
                    requestLoggingOptions: RequestLogOptions = .default,
                    successResponseLoggingOptions: ResponseLogOptions = .default,
                    errorResponseLoggingOptions: ResponseLogOptions = .default) {
            self.loggerId = loggerId
            self.dateFormatter = dateFormatter
            self.output = output
            self.requestDataFormatter = requestDataFormatter
            self.responseDataFormatter = responseDataFormatter

Review comment (suggestion):
`[Any]` was previously `Any...`
Some questions here:
- the previous logger actually sent strings wrapped in an array. I do not understand why. Feel free to enlight me.
- why `Any` and not simply `String`? Entries sent by the logger are always `String`.

Code after:

            let stringOutput = configuration.responseDataFormatter(response.data)
            output.append(newEntry(identifier: "Response Body", message: stringOutput))
        }

        return output
    }

    func logNetworkError(_ error: MoyaError, target: TargetType) -> [String] {
        //Some errors will still have a response, like errors due to Alamofire's HTTP code validation.
        if let moyaResponse = error.response {
            return logNetworkResponse(moyaResponse, target: target, isFromError: true)
        }

        //Errors without an HTTPURLResponse are those due to connectivity, time-out and such.
        return [newEntry(identifier: "Error", message: "Error calling \(target) : \(error)")]
    }
}

// MARK: - Configuration
public extension NetworkLoggerPlugin {
    struct Configuration {

        public typealias OutputType = (_ target: TargetType, _ items: [String]) -> Void
        public typealias DataFormatterType = (Data) -> (String)

        fileprivate let loggerId: String
        fileprivate let dateFormatter: DateFormatter
        fileprivate let output: OutputType
        fileprivate let requestDataFormatter: DataFormatterType
        fileprivate let responseDataFormatter: DataFormatterType
        fileprivate let logOptions: LogOptions

        /// The designated way to instanciate a Configuration.
        ///
        /// - Parameters:
        ///   - loggerId: An identifier that prefixes every log entry.
        ///   - dateFormatter: The dateFormatter to be used to display the date of every log entry.
        ///                    The default formatter sets both `timeStyle` and `dateStyle` to `short`
        ///   - output: A closure responsible of writing the given log entries into your log system.
        ///                    The default value writes entries to the debug console.
        ///   - requestDataFormatter: A closure converting HTTP request's body into a String.
        ///                    The default value assumes the body's data is an utf8 String.
        ///   - responseDataFormatter: A closure converting HTTP response's body into a String.
        ///                    The default value assumes the body's data is an utf8 String.
        ///   - logOptions: A set of options you can use to customize which request component is logged.
        public init(loggerId: String = "Moya_Logger",
                    dateFormatter: DateFormatter = defaultDateFormatter,
                    output: @escaping OutputType = defaultOutput,
                    requestDataFormatter: @escaping DataFormatterType = defaultDataFormatter,
                    responseDataFormatter: @escaping DataFormatterType = defaultDataFormatter,