Skip to content

Commit

Permalink
Merge pull request #13 from lukepistrol/chore/logger-improvements
Browse files Browse the repository at this point in the history
refactor PSLogger, add PSLoggerDelegate for receiving logs in an app
  • Loading branch information
lukepistrol authored Oct 5, 2022
2 parents 54a5d4a + c825ad3 commit f5c36de
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 31 deletions.
88 changes: 66 additions & 22 deletions Sources/PexelsSwift/Logger/PSLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,38 @@

import Foundation

/// The delegate for receiving log messages.
///
/// This is useful if you use a logging service like Sentry and need to inject the messages.
public protocol PSLoggerDelegate: AnyObject {
/// This is called whenever a log happens in the scope of the ``PSLogLevel``
func psLoggerMessageReceived(_ message: String)
}

/// A logger for displaying logs in the console.
///
/// Setup the logger through ``PexelsSwift/PexelsSwift``'s ``PexelsSwift/PexelsSwift/setup(apiKey:logLevel:)`` method.
///
/// - Note: Remember to set the ``PSLogLevel`` to ``PSLogLevel/off`` once
/// moving to `production`!
public struct PSLogger {
public class PSLogger {

private typealias RateLimit = PexelsSwift.RateLimitType

/// Returns the current ``PSLogLevel``.
public private(set) var logLevel: PSLogLevel

/// The delegate for receiving log messages.
///
/// This is useful if you use a logging service like Sentry and need to inject the messages.
public weak var delegate: PSLoggerDelegate?

internal init() {
self.logLevel = .info
}

/// Set the ``logLevel`` of the logger.
/// - Parameter logLevel: The log level
mutating
func setLogLevel(_ logLevel: PSLogLevel) {
self.logLevel = logLevel
}
Expand All @@ -36,55 +48,87 @@ public struct PSLogger {
/// - Note: Only logs to the console if the ``logLevel`` is
/// **not** set to ``PSLogLevel/off``
/// - Parameter message: The message to log.
func log(_ message: String) {
func message(_ message: String) {
guard logLevel != .off else { return }
print("💬 Pexels-Swift")
print("\t\(message)")
var logMessage = logTitle(for: .info)
logMessage.append(message)
print(logMessage)
delegate?.psLoggerMessageReceived(logMessage)
}

/// Logs a ``PSError`` to the console
///
/// - Note: Only logs to the console if the ``logLevel`` is
/// set to ``PSLogLevel/error``, ``PSLogLevel/info``, or ``PSLogLevel/debug``.
/// - Parameter error: The error to log.
func logError(_ error: PSError) {
func error(_ error: PSError) {
guard logLevel != .off else { return }
print("🛑 Pexels-Swift")
print("\tError:", error.description)
var logMessage = logTitle(for: .error)
logMessage.append("Error: \(error.description)")
print(logMessage)
delegate?.psLoggerMessageReceived(logMessage)
}

/// Logs a [HTTPURLResponse](https://developer.apple.com/documentation/foundation/httpurlresponse) to the console
///
/// - Note: Only logs to the console if the ``logLevel`` is
/// ``PSLogLevel/info`` or ``PSLogLevel/debug``.
/// - Parameter response: The response to log.
func logResponse(_ response: HTTPURLResponse) {
func response(_ response: HTTPURLResponse) {
guard logLevel == .info || logLevel == .debug else { return }
print("🔁 Pexels-Swift")
print("\tCode: \(response.statusCode),")
print("\tURL: \(response.url?.absoluteString ?? "Invalid URL")")
var logMessage = logTitle(for: .info)
logMessage.append("Code: \(response.statusCode),")
logMessage.append("URL: \(response.url?.absoluteString ?? "Invalid URL"),")
if (200...299).contains(response.statusCode) {
print("\tRate Limit: \(response.pexelsLimit?.string ?? "Fetching failed")")
print("\tRemaining: \(response.pexelsRemaining?.string ?? "Fetching failed")")
print("\tReset on: \(response.pexelsReset?.description ?? "Fetching Failed")")
logMessage.append("Rate Limit: \(response.pexelsLimit?.string ?? "Fetching failed"),")
logMessage.append("Remaining: \(response.pexelsRemaining?.string ?? "Fetching failed"),")
logMessage.append("Reset on: \(response.pexelsReset?.description ?? "Fetching Failed")")
} else {
print("\tResponse: \(response.description)")
logMessage.append("Response: \(response.description)")
}
print(logMessage)
delegate?.psLoggerMessageReceived(logMessage)
}

/// Logs data to the console in a prettified JSON string
/// - Note: Only logs to the console if the ``logLevel`` is
/// ``PSLogLevel/debug``
/// - Parameter data: The data to log.
func logData(_ data: Data) {
func data(_ data: Data) {
guard logLevel == .debug else { return }
if let json = data.prettyJSON() {
print("✅ Pexels-Swift")
print("\tData:")
print(json)
var logMessage = logTitle(for: .success)
logMessage.append("Data: \(json)")
print(logMessage)
delegate?.psLoggerMessageReceived(logMessage)
} else {
print("⚠️ Pexels-Swift")
print("\tInvalid JSON Data")
var logMessage = logTitle(for: .warning)
logMessage.append("Invalid JSON Data")
print(logMessage)
delegate?.psLoggerMessageReceived(logMessage)
}
}
}

extension PSLogger {
private func logTitle(for logType: PSLogType) -> String {
"\(icon(for: logType)) Pexels-Swift: "
}

private enum PSLogType {
case info, success, warning, error
}

private func icon(for logType: PSLogType) -> String {
switch logType {
case .info:
return "💬"
case .success:
return ""
case .warning:
return "⚠️"
case .error:
return "🛑"
}
}
}
18 changes: 9 additions & 9 deletions Sources/PexelsSwift/PexelsSwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class PexelsSwift {
internal var apiKey: String = ""

/// An instance of ``PSLogger``
internal var logger: PSLogger = .init()
public var logger: PSLogger = .init()

// MARK: - Public Methods

Expand All @@ -81,7 +81,7 @@ public class PexelsSwift {
public func setup(apiKey: String, logLevel: PSLogLevel = .info) {
self.apiKey = apiKey
self.logger.setLogLevel(logLevel)
logger.log("Setup Pexels-Swift complete")
logger.message("Setup Pexels-Swift complete")
}

/// Holds the most recent values for Rate Limit statistics.
Expand Down Expand Up @@ -151,9 +151,9 @@ public class PexelsSwift {
/// - Parameter url: The URL to fetch from.
/// - Returns: A result type of ``PSResult``.
internal func fetch<T: Codable>(url: URL) async -> PSResult<T> {
logger.log("Start fetching from URL: \(url.absoluteString)")
logger.message("Start fetching from URL: \(url.absoluteString)")
guard !apiKey.isEmpty else {
logger.logError(.noAPIKey)
logger.error(.noAPIKey)
return .failure(.noAPIKey)
}
var req = URLRequest(url: url)
Expand All @@ -168,25 +168,25 @@ public class PexelsSwift {
}

guard let response = response as? HTTPURLResponse else {
logger.logError(.noResponse(req.debugDescription))
logger.error(.noResponse(req.debugDescription))
return .failure(.noResponse(req.debugDescription))
}

logger.logResponse(response)
logger.response(response)
saveRateLimits(for: response)

guard (200...299).contains(response.statusCode) else {
logger.logError(.httpResponse(response.statusCode))
logger.error(.httpResponse(response.statusCode))
return .failure(.httpResponse(response.statusCode))
}

logger.logData(data)
logger.data(data)

let result = try JSONDecoder().decode(T.self, from: data)
return .success((result, response))

} catch {
logger.logError(.generic(error.localizedDescription))
logger.error(.generic(error.localizedDescription))
return .failure(.generic(error.localizedDescription))
}
}
Expand Down

0 comments on commit f5c36de

Please sign in to comment.