Skip to content

Commit

Permalink
Improve logging (#277)
Browse files Browse the repository at this point in the history
* Add logging

* Improve
  • Loading branch information
3lvis authored Jul 17, 2024
1 parent eb9e79a commit 3c6d746
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
50 changes: 35 additions & 15 deletions Sources/Networking/Networking+New.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Foundation
extension Networking {
func handle<T: Decodable>(_ requestType: RequestType, path: String, parameters: Any?) async -> Result<T, NetworkingError> {
do {
logger.info("Starting \(requestType.rawValue) request to \(path, privacy: .public)")

if let fakeRequest = try FakeRequest.find(ofType: requestType, forPath: path, in: fakeRequests) {
let (_, response, error) = try handleFakeRequest(fakeRequest, path: path, cacheName: nil, cachingLevel: .none)
if fakeRequest.delay > 0 {
Expand All @@ -13,9 +15,11 @@ extension Networking {
switch result {
case .success(let response):
let decodedResponse = try JSONDecoder().decode(T.self, from: response.data)
logger.info("Successfully decoded response from fake request to \(path, privacy: .public)")
return .success(decodedResponse)
case .failure(let response):
return .failure(.unexpectedError(statusCode: nil, message: "Failed to process fake raquest (error: \(response.error.localizedDescription))."))
logger.error("Failed to process fake request to \(path, privacy: .public): \(response.error.localizedDescription, privacy: .public)")
return .failure(.unexpectedError(statusCode: nil, message: "Failed to process fake request (error: \(response.error.localizedDescription))."))
}
}

Expand All @@ -28,38 +32,54 @@ extension Networking {

let (data, response) = try await session.data(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
logger.error("Invalid response received from \(path, privacy: .public)")
return .failure(.invalidResponse)
}

let statusCode = httpResponse.statusCode
if (200...299).contains(statusCode) {
switch statusCode.statusCodeType {
case .informational, .successful:
logger.info("Received successful response with status code \(statusCode) from \(path, privacy: .public)")
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let decodedResponse = try decoder.decode(T.self, from: data)
logger.info("Successfully decoded response from \(path, privacy: .public)")
return .success(decodedResponse)
} else {
case .redirection:
logger.warning("Redirection response with status code \(statusCode) from \(path, privacy: .public)")
return .failure(.unexpectedError(statusCode: statusCode, message: "Redirection occurred."))
case .clientError:
let errorMessage = HTTPURLResponse.localizedString(forStatusCode: statusCode)
if let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: data) {
logger.warning("Client error: \(errorResponse.combinedMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
return .failure(.clientError(statusCode: statusCode, message: errorResponse.combinedMessage))
} else {
logger.warning("Client error: \(errorMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
return .failure(.clientError(statusCode: statusCode, message: errorMessage))
}
case .serverError:
let errorMessage = HTTPURLResponse.localizedString(forStatusCode: statusCode)
var message = errorMessage
var errorDetails: [String: Any]? = nil

if let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: data) {
message = errorResponse.combinedMessage
errorDetails = ["error": errorResponse.error ?? "",
"message": errorResponse.message ?? "",
"errors": errorResponse.errors ?? [:]]
}

if (400...499).contains(statusCode) {
return .failure(.clientError(statusCode: statusCode, message: message))
} else if (500...599).contains(statusCode) {
return .failure(.serverError(statusCode: statusCode, message: message, details: errorDetails))
logger.error("Server error: \(errorResponse.combinedMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
return .failure(.serverError(statusCode: statusCode, message: errorResponse.combinedMessage, details: errorDetails))
} else {
return .failure(.unexpectedError(statusCode: statusCode, message: "An unexpected error occurred."))
logger.error("Server error: \(errorMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
return .failure(.serverError(statusCode: statusCode, message: errorMessage, details: errorDetails))
}
case .cancelled:
logger.info("Request cancelled with status code \(statusCode) from \(path, privacy: .public)")
return .failure(.unexpectedError(statusCode: statusCode, message: "Request was cancelled."))
case .unknown:
logger.error("Unexpected error with status code \(statusCode) from \(path, privacy: .public)")
return .failure(.unexpectedError(statusCode: statusCode, message: "An unexpected error occurred."))
}

} catch let error as NSError {
return .failure(.unexpectedError(statusCode: nil, message: "Failed to process fake raquest (error: \(error.localizedDescription))."))
logger.error("Unexpected error occurred: \(error.localizedDescription, privacy: .public)")
return .failure(.unexpectedError(statusCode: nil, message: "Failed to process request (error: \(error.localizedDescription))."))
}
}
}
8 changes: 6 additions & 2 deletions Sources/Networking/Networking.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import os.log

public enum NetworkingError: Error {
case invalidURL
Expand Down Expand Up @@ -156,7 +157,7 @@ open class Networking {
public var isErrorLoggingEnabled = true

/// The boundary used for multipart requests.
let boundary = String(format: "net.3lvis.networking.%08x%08x", arc4random(), arc4random())
let boundary = String(format: "com.elvisnunez.networking.%08x%08x", arc4random(), arc4random())

lazy var session: URLSession = {
URLSession(configuration: self.configuration)
Expand All @@ -169,16 +170,19 @@ open class Networking {
case none
}

var logger = Logger(subsystem: "com.elvisnunez.networking", category: "network")

/// Base initializer, it creates an instance of `Networking`.
///
/// - Parameters:
/// - baseURL: The base URL for HTTP requests under `Networking`.
/// - configuration: The URLSessionConfiguration configuration to be used
/// - cache: The NSCache to use, it has a built-in default one.
public init(baseURL: String = "", configuration: URLSessionConfiguration = .default, cache: NSCache<AnyObject, AnyObject>? = nil) {
public init(baseURL: String = "", configuration: URLSessionConfiguration = .default, cache: NSCache<AnyObject, AnyObject>? = nil, logger: Logger) {
self.baseURL = baseURL
self.configuration = configuration
self.cache = cache ?? NSCache()
self.logger = logger
}

/// Authenticates using Basic Authentication, it converts username:password to Base64 then sets the Authorization header to "Basic \(Base64(username:password))".
Expand Down

0 comments on commit 3c6d746

Please sign in to comment.