diff --git a/README.md b/README.md index 463c911..1976e69 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,15 @@ Timberjack has two modes: Verbose and Light. The default style is `Verbose`. To Timberjack.logStyle = .Verbose //Either .Verbose, or .Light ```` +It is also possible to filtered which URL you want to log. +2 modes exist: *Black list mode* and *White list mode*. The default mode is *Black list* + +````swift +Timberjack.filteredMode = .Black +let urlFiltered = NSURL(string: "http://www.example.com") +Timberjack.blackListUrl = [urlFiltered!] // All requests going and coming from example.com will be ignored +```` + ##License MIT, see LICENSE for details. diff --git a/Source/Timberjack.swift b/Source/Timberjack.swift index 885cd5a..03f0817 100644 --- a/Source/Timberjack.swift +++ b/Source/Timberjack.swift @@ -28,14 +28,27 @@ public enum Style { case Light } +public typealias TimberjackPrint = ((String) -> Void) + public class Timberjack: NSURLProtocol { var connection: NSURLConnection? var data: NSMutableData? var response: NSURLResponse? var newRequest: NSMutableURLRequest? - + + public enum FilterListMode { + case Black + case White + } + + public static var printLog: TimberjackPrint = { log in + print(log) + } public static var logStyle: Style = .Verbose - + public static var filteredMode: FilterListMode = .Black + public static var whiteListUrl: [NSURL]? + public static var blackListUrl: [NSURL]? + public class func register() { NSURLProtocol.registerClass(self) } @@ -117,30 +130,34 @@ public class Timberjack: NSURLProtocol { //MARK: - Logging public func logDivider() { - print("---------------------") + Timberjack.printLog("---------------------") } public func logError(error: NSError) { logDivider() - print("Error: \(error.localizedDescription)") + Timberjack.printLog("Error: \(error.localizedDescription)") if Timberjack.logStyle == .Verbose { if let reason = error.localizedFailureReason { - print("Reason: \(reason)") + Timberjack.printLog("Reason: \(reason)") } if let suggestion = error.localizedRecoverySuggestion { - print("Suggestion: \(suggestion)") + Timberjack.printLog("Suggestion: \(suggestion)") } } } public func logRequest(request: NSURLRequest) { + if !shouldLog(request.URL) { + return + } + logDivider() if let url = request.URL?.absoluteString { - print("Request: \(request.HTTPMethod!) \(url)") + Timberjack.printLog("Request: \(request.HTTPMethod!) \(url)") } if Timberjack.logStyle == .Verbose { @@ -151,15 +168,19 @@ public class Timberjack: NSURLProtocol { } public func logResponse(response: NSURLResponse, data: NSData? = nil) { + if !shouldLog(response.URL) { + return + } + logDivider() if let url = response.URL?.absoluteString { - print("Response: \(url)") + Timberjack.printLog("Response: \(url)") } if let httpResponse = response as? NSHTTPURLResponse { let localisedStatus = NSHTTPURLResponse.localizedStringForStatusCode(httpResponse.statusCode).capitalizedString - print("Status: \(httpResponse.statusCode) - \(localisedStatus)") + Timberjack.printLog("Status: \(httpResponse.statusCode) - \(localisedStatus)") } if Timberjack.logStyle == .Verbose { @@ -169,7 +190,7 @@ public class Timberjack: NSURLProtocol { if let startDate = Timberjack.propertyForKey(TimberjackRequestTimeKey, inRequest: newRequest!) as? NSDate { let difference = fabs(startDate.timeIntervalSinceNow) - print("Duration: \(difference)s") + Timberjack.printLog("Duration: \(difference)s") } guard let data = data else { return } @@ -179,23 +200,56 @@ public class Timberjack: NSURLProtocol { let pretty = try NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted) if let string = NSString(data: pretty, encoding: NSUTF8StringEncoding) { - print("JSON: \(string)") + Timberjack.printLog("JSON: \(string)") } } catch { if let string = NSString(data: data, encoding: NSUTF8StringEncoding) { - print("Data: \(string)") + Timberjack.printLog("Data: \(string)") } } } } public func logHeaders(headers: [String: AnyObject]) { - print("Headers: [") + Timberjack.printLog("Headers: [") for (key, value) in headers { - print(" \(key) : \(value)") + Timberjack.printLog(" \(key) : \(value)") } - print("]") + Timberjack.printLog("]") } + + func shouldLog(url: NSURL?) -> Bool { + let filteredList = Timberjack.filteredMode == .Black ? Timberjack.blackListUrl : Timberjack.whiteListUrl + + switch (Timberjack.filteredMode, url, filteredList) { + case (.Black, let url?, let list?): + return !list.contains(url) + case (.Black, _, _): + return true + case (.White, let url?, let list?): + return list.contains(url) + case (.White, _, _): + return false + } + } +} + +extension String { + func contains(aString: String) -> Bool { + return self.rangeOfString(aString) != nil + } +} + +extension NSURL { + func contains(url: NSURL) -> Bool { + return self.absoluteString.contains(url.absoluteString) + } +} + +extension SequenceType where Generator.Element == NSURL { + func contains(element: NSURL) -> Bool { + return self.reduce(false) { return $0 || element.contains($1) } + } } diff --git a/Tests/TimberjackTests.swift b/Tests/TimberjackTests.swift index 1db2322..a583119 100644 --- a/Tests/TimberjackTests.swift +++ b/Tests/TimberjackTests.swift @@ -9,28 +9,93 @@ import UIKit import XCTest +@testable import Timberjack + class TimberjackTests: XCTestCase { - + + private var buffer: [String] = [] + override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. + buffer = [] + Timberjack.printLog = { log in + self.buffer.append(log) + } } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() + + func testLogDefaultBehavior() { + // Given + let urlRequested = NSURL(string: "http://www.example.com/sample") + let request = NSURLRequest(URL: urlRequested!) + + // When + let instance = Timberjack() + instance.logRequest(request) + + // Then + XCTAssert(buffer.count != 0) } - func testExample() { - // This is an example of a functional test case. - XCTAssert(true, "Pass") + func testLogDisableWithBlackList() { + // Given + let urlFiltered = NSURL(string: "http://www.example.com") + let urlRequested = NSURL(string: "http://www.example.com/sample") + Timberjack.filteredMode = .Black + Timberjack.blackListUrl = [urlFiltered!] + let request = NSURLRequest(URL: urlRequested!) + + // When + let instance = Timberjack() + instance.logRequest(request) + + // Then + XCTAssert(buffer.count == 0) } - func testPerformanceExample() { - // This is an example of a performance test case. - self.measureBlock() { - // Put the code you want to measure the time of here. - } + func testLogEnableWithBlackList() { + // Given + let urlFiltered = NSURL(string: "http://www.example.com") + let urlRequested = NSURL(string: "http://www.example2.com") + Timberjack.filteredMode = .Black + Timberjack.blackListUrl = [urlFiltered!] + let request = NSURLRequest(URL: urlRequested!) + + // When + let instance = Timberjack() + instance.logRequest(request) + + // Then + XCTAssert(buffer.count != 0) } + func testLogEnableWithWhiteList() { + // Given + let urlFiltered = NSURL(string: "http://www.example.com") + let urlRequested = NSURL(string: "http://www.example.com/sample") + Timberjack.filteredMode = .White + Timberjack.whiteListUrl = [urlFiltered!] + let request = NSURLRequest(URL: urlRequested!) + + // When + let instance = Timberjack() + instance.logRequest(request) + + // Then + XCTAssert(buffer.count != 0) + } + + func testLogDisableWithWhiteList() { + // Given + let urlFiltered = NSURL(string: "http://www.example.com") + let urlRequested = NSURL(string: "http://www.example2.com") + Timberjack.filteredMode = .White + Timberjack.whiteListUrl = [urlFiltered!] + let request = NSURLRequest(URL: urlRequested!) + + // When + let instance = Timberjack() + instance.logRequest(request) + + // Then + XCTAssert(buffer.count == 0) + } }