Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a customisation point for injecting a logger in RxBluetoothKit #341

Merged
merged 5 commits into from
Jul 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions RxBluetoothKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,14 @@
D74B16861ED417AA006D5996 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74B16841ED417AA006D5996 /* Logging.swift */; };
FA947A3B1EB1C41C000ED0B1 /* UUIDIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA947A3A1EB1C41C000ED0B1 /* UUIDIdentifiable.swift */; };
FA947A3C1EB1C42F000ED0B1 /* UUIDIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA947A3A1EB1C41C000ED0B1 /* UUIDIdentifiable.swift */; };
FDA404272294386300386BB8 /* RxBluetoothKitLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA404262294386300386BB8 /* RxBluetoothKitLogger.swift */; };
FDA404282294532D00386BB8 /* RxBluetoothKitLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA404262294386300386BB8 /* RxBluetoothKitLogger.swift */; };
FDA404292294532E00386BB8 /* RxBluetoothKitLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA404262294386300386BB8 /* RxBluetoothKitLogger.swift */; };
FDA4042A2294532F00386BB8 /* RxBluetoothKitLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA404262294386300386BB8 /* RxBluetoothKitLogger.swift */; };
FDC43FB222AFED1700995355 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC43FB122AFED1700995355 /* Logger.swift */; };
FDC43FB322AFED1700995355 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC43FB122AFED1700995355 /* Logger.swift */; };
FDC43FB422AFED1700995355 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC43FB122AFED1700995355 /* Logger.swift */; };
FDC43FB522AFED1700995355 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC43FB122AFED1700995355 /* Logger.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -415,6 +423,8 @@
BB2FF3341F9EAF2B00A12E10 /* CBCentralManagerDelegateWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CBCentralManagerDelegateWrapper.swift; sourceTree = "<group>"; };
D74B16841ED417AA006D5996 /* Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
FA947A3A1EB1C41C000ED0B1 /* UUIDIdentifiable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UUIDIdentifiable.swift; sourceTree = "<group>"; };
FDA404262294386300386BB8 /* RxBluetoothKitLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RxBluetoothKitLogger.swift; sourceTree = "<group>"; };
FDC43FB122AFED1700995355 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -627,13 +637,15 @@
265CD5FA1CBED323007120AB /* Shared */ = {
isa = PBXGroup;
children = (
A1299C241CBE3DEE005DEA5B /* Unimplemented.swift */,
A1299C131CBE3DEE005DEA5B /* Observable+Absorb.swift */,
1D9C509A202064CC006B21E4 /* Array+Utils.swift */,
A1299C0F1CBE3DEE005DEA5B /* Boxes.swift */,
A1299C0D1CBE3DEE005DEA5B /* BluetoothError.swift */,
FA947A3A1EB1C41C000ED0B1 /* UUIDIdentifiable.swift */,
D74B16841ED417AA006D5996 /* Logging.swift */,
1D9C509A202064CC006B21E4 /* Array+Utils.swift */,
FDC43FB122AFED1700995355 /* Logger.swift */,
FDA404262294386300386BB8 /* RxBluetoothKitLogger.swift */,
A1299C131CBE3DEE005DEA5B /* Observable+Absorb.swift */,
FA947A3A1EB1C41C000ED0B1 /* UUIDIdentifiable.swift */,
A1299C241CBE3DEE005DEA5B /* Unimplemented.swift */,
);
name = Shared;
sourceTree = "<group>";
Expand Down Expand Up @@ -1195,6 +1207,7 @@
0A7B27E71F9F177A003F950E /* Peripheral.swift in Sources */,
0A7B27DE1F9F1771003F950E /* Logging.swift in Sources */,
0A7B27DB1F9F1771003F950E /* Boxes.swift in Sources */,
FDA404292294532E00386BB8 /* RxBluetoothKitLogger.swift in Sources */,
0A7B27E31F9F1776003F950E /* Service.swift in Sources */,
0A7B27DA1F9F1771003F950E /* Observable+Absorb.swift in Sources */,
1D73E85320A431F0009167AA /* PeripheralManager.swift in Sources */,
Expand All @@ -1216,6 +1229,7 @@
0A7B27D91F9F1771003F950E /* Unimplemented.swift in Sources */,
0A7B27D71F9F176D003F950E /* BluetoothState.swift in Sources */,
1D73E85120A43033009167AA /* CBCentral+Uuid.swift in Sources */,
FDC43FB422AFED1700995355 /* Logger.swift in Sources */,
1DAAB03F2024673A0023BAC0 /* CharacteristicNotificationManager.swift in Sources */,
0A7B27EA1F9F177A003F950E /* Peripheral+Convenience.swift in Sources */,
37B645F7C86ECC95C20EB188 /* PeripheralProvider.swift in Sources */,
Expand All @@ -1230,6 +1244,7 @@
0A7B28291F9F1B33003F950E /* Unimplemented.swift in Sources */,
0A7B28321F9F1B39003F950E /* CentralManager.swift in Sources */,
0A339D741FA1C0ED008385C8 /* CBPeripheralDelegateWrapper.swift in Sources */,
FDA4042A2294532F00386BB8 /* RxBluetoothKitLogger.swift in Sources */,
0A7B282E1F9F1B33003F950E /* Logging.swift in Sources */,
0A7B28201F9F1B25003F950E /* DeviceIdentifiers.swift in Sources */,
1D73E85420A43338009167AA /* PeripheralManager.swift in Sources */,
Expand All @@ -1251,6 +1266,7 @@
0A7B28331F9F1B39003F950E /* AdvertisementData.swift in Sources */,
0A7B281D1F9F1B25003F950E /* ScannedPeripheral.swift in Sources */,
1D73E85220A43033009167AA /* CBCentral+Uuid.swift in Sources */,
FDC43FB522AFED1700995355 /* Logger.swift in Sources */,
1DAAB0402024673A0023BAC0 /* CharacteristicNotificationManager.swift in Sources */,
0A7B282D1F9F1B33003F950E /* UUIDIdentifiable.swift in Sources */,
37B649D72EF8C7867D811C8F /* PeripheralProvider.swift in Sources */,
Expand Down Expand Up @@ -1311,6 +1327,7 @@
buildActionMask = 2147483647;
files = (
2666FE491CCE4732005E81CE /* CentralManager.swift in Sources */,
FDA404272294386300386BB8 /* RxBluetoothKitLogger.swift in Sources */,
1D73E84F20A43033009167AA /* CBCentral+Uuid.swift in Sources */,
2666FE401CCE4732005E81CE /* Unimplemented.swift in Sources */,
1D6E36C820A07057009900A6 /* ManagerType.swift in Sources */,
Expand All @@ -1334,6 +1351,7 @@
1D9C50AF2021CC70006B21E4 /* Connector.swift in Sources */,
1D1C9828201B195000DCF299 /* CentralManager+RestoredState.swift in Sources */,
2666FE3E1CCE4732005E81CE /* Characteristic.swift in Sources */,
FDC43FB222AFED1700995355 /* Logger.swift in Sources */,
1D73E85620A434B0009167AA /* PeripheralManager+RestoredState.swift in Sources */,
2666FE321CCE4732005E81CE /* Descriptor.swift in Sources */,
1DA3453820A07FA800F7D629 /* PeripheralManager.swift in Sources */,
Expand Down Expand Up @@ -1405,6 +1423,7 @@
1DA3453920A07FA800F7D629 /* PeripheralManager.swift in Sources */,
2666FE2E1CCE4731005E81CE /* CentralManager.swift in Sources */,
2666FE251CCE4731005E81CE /* Unimplemented.swift in Sources */,
FDA404282294532D00386BB8 /* RxBluetoothKitLogger.swift in Sources */,
D74B16861ED417AA006D5996 /* Logging.swift in Sources */,
2666FE1C1CCE4731005E81CE /* DeviceIdentifiers.swift in Sources */,
FA947A3C1EB1C42F000ED0B1 /* UUIDIdentifiable.swift in Sources */,
Expand All @@ -1426,6 +1445,7 @@
2666FE2F1CCE4731005E81CE /* AdvertisementData.swift in Sources */,
2666FE271CCE4731005E81CE /* Observable+Absorb.swift in Sources */,
1D73E85020A43033009167AA /* CBCentral+Uuid.swift in Sources */,
FDC43FB322AFED1700995355 /* Logger.swift in Sources */,
1DAAB03E2024673A0023BAC0 /* CharacteristicNotificationManager.swift in Sources */,
2666FE191CCE4731005E81CE /* ScannedPeripheral.swift in Sources */,
37B642B5C45841BEDB86D35E /* PeripheralProvider.swift in Sources */,
Expand Down
54 changes: 54 additions & 0 deletions Source/Logger.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/// Simple logging interface.
///
/// An application that wants RxBluetoothKit to use its logging solution will
/// need to provide a type that conforms to this signature and assign it to
/// `RxBluetoothKitLogger.defaultLogger`.
public protocol Logger {
/// Logs the given message (using StaticString parameters).
///
/// - Parameters:
/// - message: The message to be logger.
/// Provided as a closure to avoid performing interpolation if
/// the message is not going to be logged.
/// - level: The severity of the message.
/// A logger can use this flag to decide if to log or ignore
/// this specific message.
/// - file: The file name of the file where the message was created.
/// - function: The function name where the message was created.
/// - line: The line number in the file where the message was created.
func log(
_ message: @autoclosure () -> String,
level: RxBluetoothKitLog.LogLevel,
file: StaticString,
function: StaticString,
line: UInt
)

/// Logs the given message (using regular String parameters).
///
/// - Parameters:
/// - message: The message to be logger.
/// Provided as a closure to avoid performing interpolation if
/// the message is not going to be logged.
/// - level: The severity of the message.
/// A logger can use this flag to decide if to log or ignore
/// this specific message.
/// - file: The file name of the file where the message was created.
/// - function: The function name where the message was created.
/// - line: The line number in the file where the message was created.
func log(
_ message: @autoclosure () -> String,
level: RxBluetoothKitLog.LogLevel,
file: String,
function: String,
line: UInt
)

/// Set new log level.
/// - Parameter logLevel: New log level to be applied.
func setLogLevel(_ logLevel: RxBluetoothKitLog.LogLevel)

/// Get current log level.
/// - Returns: Currently set log level.
func getLogLevel() -> RxBluetoothKitLog.LogLevel
}
134 changes: 72 additions & 62 deletions Source/Logging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@ import RxSwift
/// RxBluetoothKit specific logging class which gives access to its settings.
public class RxBluetoothKitLog: ReactiveCompatible {

fileprivate static var currentLogLevel: LogLevel = .none

fileprivate static let subject = PublishSubject<String>()

/// Set new log level.
/// - Parameter logLevel: New log level to be applied.
public static func setLogLevel(_ logLevel: RxBluetoothKitLog.LogLevel) {
RxBluetoothKitLogger.defaultLogger.setLogLevel(logLevel)
}

/// Get current log level.
/// - Returns: Currently set log level.
public static func getLogLevel() -> RxBluetoothKitLog.LogLevel {
return RxBluetoothKitLogger.defaultLogger.getLogLevel()
}

private init() {
}

Expand All @@ -28,69 +38,69 @@ public class RxBluetoothKitLog: ReactiveCompatible {
case error = 4
}

/// Set new log level.
/// - Parameter logLevel: New log level to be applied.
public static func setLogLevel(_ logLevel: LogLevel) {
currentLogLevel = logLevel
}

/// Get current log level.
/// - Returns: Currently set log level.
public static func getLogLevel() -> LogLevel {
return currentLogLevel
}

fileprivate static func tag(with logLevel: LogLevel) -> String {
let prefix: String

switch logLevel {
case .none:
prefix = "[RxBLEKit|NONE|"
case .verbose:
prefix = "[RxBLEKit|VERB|"
case .debug:
prefix = "[RxBLEKit|DEBG|"
case .info:
prefix = "[RxBLEKit|INFO|"
case .warning:
prefix = "[RxBLEKit|WARN|"
case .error:
prefix = "[RxBLEKit|ERRO|"
fileprivate static func log(
with logLevel: LogLevel,
message: @autoclosure () -> String,
file: StaticString,
function: StaticString,
line: UInt
) {
let loggedMessage = message()
RxBluetoothKitLogger.defaultLogger.log(
loggedMessage,
level: logLevel,
file: file,
function: function,
line: line
)
if getLogLevel() <= logLevel {
subject.onNext(loggedMessage)
}
let time = Date().timeIntervalSinceReferenceDate
return prefix + String(format: "%02.0f:%02.0f:%02.0f.%03.f]:",
floor(time / 3600.0).truncatingRemainder(dividingBy: 24),
floor(time / 60.0).truncatingRemainder(dividingBy: 60),
floor(time).truncatingRemainder(dividingBy: 60),
floor(time * 1000).truncatingRemainder(dividingBy: 1000))
}

fileprivate static func log(with logLevel: LogLevel, message: @autoclosure () -> String) {
if currentLogLevel <= logLevel {
let string = "\(tag(with: logLevel)) \(message())"
subject.onNext(string)
print(string)
}
}

static func v(_ message: @autoclosure () -> String) {
log(with: .verbose, message: message())
}

static func d(_ message: @autoclosure () -> String) {
log(with: .debug, message: message())
}

static func i(_ message: @autoclosure () -> String) {
log(with: .info, message: message())
}

static func w(_ message: @autoclosure () -> String) {
log(with: .warning, message: message())
}

static func e(_ message: @autoclosure () -> String) {
log(with: .error, message: message())
static func v(
_ message: @autoclosure () -> String,
file: StaticString = #file,
function: StaticString = #function,
line: UInt = #line
) {
log(with: .verbose, message: message(), file: file, function: function, line: line)
}

static func d(
_ message: @autoclosure () -> String,
file: StaticString = #file,
function: StaticString = #function,
line: UInt = #line
) {
log(with: .debug, message: message(), file: file, function: function, line: line)
}

static func i(
_ message: @autoclosure () -> String,
file: StaticString = #file,
function: StaticString = #function,
line: UInt = #line
) {
log(with: .info, message: message(), file: file, function: function, line: line)
}

static func w(
_ message: @autoclosure () -> String,
file: StaticString = #file,
function: StaticString = #function,
line: UInt = #line
) {
log(with: .warning, message: message(), file: file, function: function, line: line)
}

static func e(
_ message: @autoclosure () -> String,
file: StaticString = #file,
function: StaticString = #function,
line: UInt = #line
) {
log(with: .error, message: message(), file: file, function: function, line: line)
}
}

Expand Down
79 changes: 79 additions & 0 deletions Source/RxBluetoothKitLogger.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import Foundation

/// Namespace for assigning the default logger.
public enum RxBluetoothKitLogger {
/// The default logger that will be used by RxBluetoothKit
public static var defaultLogger: Logger = SimplePrintLogger()
}

private class SimplePrintLogger: Logger {
private var currentLogLevel: RxBluetoothKitLog.LogLevel = .none

/// Set new log level.
/// - Parameter logLevel: New log level to be applied.
public func setLogLevel(_ logLevel: RxBluetoothKitLog.LogLevel) {
self.currentLogLevel = logLevel
}

/// Get current log level.
/// - Returns: Currently set log level.
public func getLogLevel() -> RxBluetoothKitLog.LogLevel {
return currentLogLevel
}

func log(
_ message: @autoclosure () -> String,
level: RxBluetoothKitLog.LogLevel,
file: StaticString,
function: StaticString,
line: UInt
) {
log(
message() + " file: \(file) function: \(function) line: \(line)",
level: level,
file: String(describing: file),
function: String(describing: function),
line: line
)
}

func log(
_ message: @autoclosure () -> String,
level: RxBluetoothKitLog.LogLevel,
file: String,
function: String,
line: UInt
) {
if currentLogLevel <= level {
print("\(tag(with: level)) \(message())")
}
}

fileprivate func tag(with logLevel: RxBluetoothKitLog.LogLevel) -> String {
let prefix: String

switch logLevel {
case .none:
prefix = "[RxBLEKit|NONE|"
case .verbose:
prefix = "[RxBLEKit|VERB|"
case .debug:
prefix = "[RxBLEKit|DEBG|"
case .info:
prefix = "[RxBLEKit|INFO|"
case .warning:
prefix = "[RxBLEKit|WARN|"
case .error:
prefix = "[RxBLEKit|ERRO|"
}
let time = Date().timeIntervalSinceReferenceDate

return prefix + String(
format: "%02.0f:%02.0f:%02.0f.%03.f]:",
floor(time / 3600.0).truncatingRemainder(dividingBy: 24),
floor(time / 60.0).truncatingRemainder(dividingBy: 60),
floor(time).truncatingRemainder(dividingBy: 60),
floor(time * 1000).truncatingRemainder(dividingBy: 1000)
)
}
}