114 lines
3.9 KiB
Swift
114 lines
3.9 KiB
Swift
import Foundation
|
|
import Alamofire
|
|
|
|
/// Advanced logging system for network requests and responses
|
|
enum NetworkLogger {
|
|
|
|
enum LogLevel {
|
|
case none
|
|
case minimal
|
|
case verbose
|
|
case debug
|
|
}
|
|
|
|
static var logLevel: LogLevel = .debug
|
|
|
|
static func logRequest(_ request: URLRequest) {
|
|
guard logLevel != .none else { return }
|
|
|
|
var log = "\n🌐 ===== HTTP REQUEST ====="
|
|
log += "\n📤 Method: \(request.httpMethod ?? "UNKNOWN")"
|
|
log += "\n🔗 URL: \(request.url?.absoluteString ?? "N/A")"
|
|
|
|
if logLevel == .verbose || logLevel == .debug {
|
|
if let headers = request.allHTTPHeaderFields, !headers.isEmpty {
|
|
log += "\n📋 Headers:"
|
|
headers.forEach { log += "\n \($0.key): \($0.value)" }
|
|
}
|
|
/*
|
|
if let body = request.httpBody {
|
|
if let jsonString = String(data: body, encoding: .utf8) {
|
|
log += "\n📦 Body: \(jsonString)"
|
|
} else {
|
|
log += "\n📦 Body: <binary data, \(body.count) bytes>"
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
log += "\n========================\n"
|
|
fluxlog(log)
|
|
}
|
|
|
|
static func logResponse(_ response: HTTPURLResponse, data: Data?, duration: TimeInterval) {
|
|
guard logLevel != .none else { return }
|
|
|
|
let statusEmoji = getStatusEmoji(for: response.statusCode)
|
|
|
|
var log = "\n✅ ===== HTTP RESPONSE ====="
|
|
log += "\n\(statusEmoji) Status: \(response.statusCode)"
|
|
log += "\n🔗 URL: \(response.url?.absoluteString ?? "N/A")"
|
|
log += "\n⏱️ Duration: \(String(format: "%.3f", duration))s"
|
|
|
|
if logLevel == .verbose || logLevel == .debug {
|
|
if !response.allHeaderFields.isEmpty {
|
|
log += "\n📋 Headers:"
|
|
response.allHeaderFields.forEach { log += "\n \($0.key): \($0.value)" }
|
|
}
|
|
|
|
if let data = data {
|
|
if let jsonString = String(data: data, encoding: .utf8) {
|
|
log += "\n📦 Response Data: \(jsonString.prefix(500))"
|
|
if jsonString.count > 500 {
|
|
log += "... (truncated)"
|
|
}
|
|
} else {
|
|
log += "\n📦 Response Data: <binary data, \(data.count) bytes>"
|
|
}
|
|
}
|
|
}
|
|
|
|
log += "\n=========================\n"
|
|
fluxlog(log)
|
|
}
|
|
|
|
static func logError(_ error: AFError, request: URLRequest?, data: Data?, duration: TimeInterval) {
|
|
guard logLevel != .none else { return }
|
|
|
|
var log = "\n❌ ===== HTTP ERROR ====="
|
|
log += "\n🔗 URL: \(request?.url?.absoluteString ?? "N/A")"
|
|
log += "\n⚠️ Error: \(error.localizedDescription)"
|
|
log += "\n⏱️ Duration: \(String(format: "%.3f", duration))s"
|
|
|
|
if let statusCode = error.responseCode {
|
|
log += "\n🔢 Status Code: \(statusCode)"
|
|
}
|
|
|
|
// ALWAYS log error response JSON (regardless of log level, without truncation)
|
|
if let data = data, let errorString = String(data: data, encoding: .utf8) {
|
|
log += "\n📦 Error Response JSON:"
|
|
log += "\n\(errorString)"
|
|
}
|
|
|
|
// Log underlying error in verbose/debug mode
|
|
if logLevel == .verbose || logLevel == .debug {
|
|
if case .sessionTaskFailed(let underlyingError) = error {
|
|
log += "\n🐛 Underlying Error: \(underlyingError.localizedDescription)"
|
|
}
|
|
}
|
|
|
|
log += "\n======================\n"
|
|
fluxlog(log)
|
|
}
|
|
|
|
private static func getStatusEmoji(for statusCode: Int) -> String {
|
|
switch statusCode {
|
|
case 200...299: return "✅"
|
|
case 300...399: return "🔄"
|
|
case 400...499: return "⚠️"
|
|
case 500...599: return "🔥"
|
|
default: return "❓"
|
|
}
|
|
}
|
|
}
|