EventLogger.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. //
  2. // EventLogger.swift
  3. // ReactiveCocoa
  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 Next, Completed, Failed, Terminated, Disposed, Interrupted
  13. public static let allEvents: Set<Signal> = [
  14. .Next, .Completed, .Failed, .Terminated, .Disposed, .Interrupted,
  15. ]
  16. }
  17. public enum SignalProducer: String {
  18. case Started, Next, Completed, Failed, Terminated, Disposed, Interrupted
  19. public static let allEvents: Set<SignalProducer> = [
  20. .Started, .Next, .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 = (identifier: String, event: String, fileName: String, functionName: String, lineNumber: Int) -> Void
  29. extension SignalType {
  30. /// Logs all events that the receiver sends. By default, it will print to
  31. /// the standard output.
  32. ///
  33. /// - parameters:
  34. /// - identifier: a string to identify the Signal firing events.
  35. /// - events: Types of events to log.
  36. /// - fileName: Name of the file containing the code which fired the
  37. /// event.
  38. /// - functionName: Function where event was fired.
  39. /// - lineNumber: Line number where event was fired.
  40. /// - logger: Logger that logs the events.
  41. ///
  42. /// - returns: Signal that, when observed, logs the fired events.
  43. @warn_unused_result(message="Did you forget to call `observe` on the signal?")
  44. public func logEvents(identifier identifier: String = "", events: Set<LoggingEvent.Signal> = LoggingEvent.Signal.allEvents, fileName: String = #file, functionName: String = #function, lineNumber: Int = #line, logger: EventLogger = defaultEventLog) -> Signal<Value, Error> {
  45. func log<T>(event: LoggingEvent.Signal) -> (T -> Void)? {
  46. return event.logIfNeeded(events) { event in
  47. logger(identifier: identifier, event: event, fileName: fileName, functionName: functionName, lineNumber: lineNumber)
  48. }
  49. }
  50. return self.on(
  51. failed: log(.Failed),
  52. completed: log(.Completed),
  53. interrupted: log(.Interrupted),
  54. terminated: log(.Terminated),
  55. disposed: log(.Disposed),
  56. next: log(.Next)
  57. )
  58. }
  59. }
  60. extension SignalProducerType {
  61. /// Logs all events that the receiver sends. By default, it will print to
  62. /// the standard output.
  63. ///
  64. /// - parameters:
  65. /// - identifier: a string to identify the SignalProducer firing events.
  66. /// - events: Types of events to log.
  67. /// - fileName: Name of the file containing the code which fired the
  68. /// event.
  69. /// - functionName: Function where event was fired.
  70. /// - lineNumber: Line number where event was fired.
  71. /// - logger: Logger that logs the events.
  72. ///
  73. /// - returns: Signal producer that, when started, logs the fired events.
  74. @warn_unused_result(message="Did you forget to call `start` on the producer?")
  75. public func logEvents(identifier identifier: String = "", events: Set<LoggingEvent.SignalProducer> = LoggingEvent.SignalProducer.allEvents, fileName: String = #file, functionName: String = #function, lineNumber: Int = #line, logger: EventLogger = defaultEventLog) -> SignalProducer<Value, Error> {
  76. func log<T>(event: LoggingEvent.SignalProducer) -> (T -> Void)? {
  77. return event.logIfNeeded(events) { event in
  78. logger(identifier: identifier, event: event, fileName: fileName, functionName: functionName, lineNumber: lineNumber)
  79. }
  80. }
  81. return self.on(
  82. started: log(.Started),
  83. failed: log(.Failed),
  84. completed: log(.Completed),
  85. interrupted: log(.Interrupted),
  86. terminated: log(.Terminated),
  87. disposed: log(.Disposed),
  88. next: log(.Next)
  89. )
  90. }
  91. }
  92. private protocol LoggingEventType: Hashable, RawRepresentable {}
  93. extension LoggingEvent.Signal: LoggingEventType {}
  94. extension LoggingEvent.SignalProducer: LoggingEventType {}
  95. private extension LoggingEventType {
  96. func logIfNeeded<T>(events: Set<Self>, logger: String -> Void) -> (T -> Void)? {
  97. guard events.contains(self) else {
  98. return nil
  99. }
  100. return { value in
  101. if value is Void {
  102. logger("\(self.rawValue)")
  103. } else {
  104. logger("\(self.rawValue) \(value)")
  105. }
  106. }
  107. }
  108. }