EventLogger.swift 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. //
  2. // EventLogger.swift
  3. // ReactiveSwift
  4. //
  5. // Created by Rui Peres on 30/04/2016.
  6. // Copyright © 2016 GitHub. All rights reserved.
  7. //
  8. import Foundation
  9. /// A namespace for logging event types.
  10. public enum LoggingEvent {
  11. public enum Signal: String {
  12. case value, completed, failed, terminated, disposed, interrupted
  13. public static let allEvents: Set<Signal> = [
  14. .value, .completed, .failed, .terminated, .disposed, .interrupted,
  15. ]
  16. }
  17. public enum SignalProducer: String {
  18. case starting, started, value, completed, failed, terminated, disposed, interrupted
  19. public static let allEvents: Set<SignalProducer> = [
  20. .starting, .started, .value, .completed, .failed, .terminated, .disposed, .interrupted,
  21. ]
  22. }
  23. }
  24. private func defaultEventLog(identifier: String, event: String, fileName: String, functionName: String, lineNumber: Int) {
  25. print("[\(identifier)] \(event) fileName: \(fileName), functionName: \(functionName), lineNumber: \(lineNumber)")
  26. }
  27. /// A type that represents an event logging function.
  28. public typealias EventLogger = (
  29. _ identifier: String,
  30. _ event: String,
  31. _ fileName: String,
  32. _ functionName: String,
  33. _ lineNumber: Int
  34. ) -> Void
  35. extension SignalProtocol {
  36. /// Logs all events that the receiver sends. By default, it will print to
  37. /// the standard output.
  38. ///
  39. /// - parameters:
  40. /// - identifier: a string to identify the Signal firing events.
  41. /// - events: Types of events to log.
  42. /// - fileName: Name of the file containing the code which fired the
  43. /// event.
  44. /// - functionName: Function where event was fired.
  45. /// - lineNumber: Line number where event was fired.
  46. /// - logger: Logger that logs the events.
  47. ///
  48. /// - returns: Signal that, when observed, logs the fired events.
  49. public func logEvents(identifier: String = "", events: Set<LoggingEvent.Signal> = LoggingEvent.Signal.allEvents, fileName: String = #file, functionName: String = #function, lineNumber: Int = #line, logger: @escaping EventLogger = defaultEventLog) -> Signal<Value, Error> {
  50. func log<T>(_ event: LoggingEvent.Signal) -> ((T) -> Void)? {
  51. return event.logIfNeeded(events: events) { event in
  52. logger(identifier, event, fileName, functionName, lineNumber)
  53. }
  54. }
  55. return self.on(
  56. failed: log(.failed),
  57. completed: log(.completed),
  58. interrupted: log(.interrupted),
  59. terminated: log(.terminated),
  60. disposed: log(.disposed),
  61. value: log(.value)
  62. )
  63. }
  64. }
  65. extension SignalProducerProtocol {
  66. /// Logs all events that the receiver sends. By default, it will print to
  67. /// the standard output.
  68. ///
  69. /// - parameters:
  70. /// - identifier: a string to identify the SignalProducer firing events.
  71. /// - events: Types of events to log.
  72. /// - fileName: Name of the file containing the code which fired the
  73. /// event.
  74. /// - functionName: Function where event was fired.
  75. /// - lineNumber: Line number where event was fired.
  76. /// - logger: Logger that logs the events.
  77. ///
  78. /// - returns: Signal producer that, when started, logs the fired events.
  79. public func logEvents(identifier: String = "",
  80. events: Set<LoggingEvent.SignalProducer> = LoggingEvent.SignalProducer.allEvents,
  81. fileName: String = #file,
  82. functionName: String = #function,
  83. lineNumber: Int = #line,
  84. logger: @escaping EventLogger = defaultEventLog
  85. ) -> SignalProducer<Value, Error> {
  86. func log<T>(_ event: LoggingEvent.SignalProducer) -> ((T) -> Void)? {
  87. return event.logIfNeeded(events: events) { event in
  88. logger(identifier, event, fileName, functionName, lineNumber)
  89. }
  90. }
  91. return self.on(
  92. starting: log(.starting),
  93. started: log(.started),
  94. failed: log(.failed),
  95. completed: log(.completed),
  96. interrupted: log(.interrupted),
  97. terminated: log(.terminated),
  98. disposed: log(.disposed),
  99. value: log(.value)
  100. )
  101. }
  102. }
  103. private protocol LoggingEventProtocol: Hashable, RawRepresentable {}
  104. extension LoggingEvent.Signal: LoggingEventProtocol {}
  105. extension LoggingEvent.SignalProducer: LoggingEventProtocol {}
  106. private extension LoggingEventProtocol {
  107. func logIfNeeded<T>(events: Set<Self>, logger: @escaping (String) -> Void) -> ((T) -> Void)? {
  108. guard events.contains(self) else {
  109. return nil
  110. }
  111. return { value in
  112. if value is Void {
  113. logger("\(self.rawValue)")
  114. } else {
  115. logger("\(self.rawValue) \(value)")
  116. }
  117. }
  118. }
  119. }