-
Notifications
You must be signed in to change notification settings - Fork 0
Filtering
One of the major ideas behind Beacon is the ability to filter signals programmatically and do so with great flexibility. This means being able to filter by arbitrary logic that may include:
- type of a signal
- values captured by a signal
- source of a signal (file, function, class)
- signal's destination - both the beacon object where signals are emitted and the loggers that observe those beacons
Probably the most obvious place to filter signals is at the logger level. For example, to log only errors:
ConsoleLogger.starting(name: "Console") { $0 is ErrorSignal }
All subclasses of SignalLogger
accept a filter block as their final argument. If you're implementing your own logger - it's best to follow the lead here.
We can get more creative here and filter in only errors and any signal that originates from files with a certain path:
ConsoleLogger.starting(name: "Console") { aSignal in
if aSignal is ErrorSignal { return true }
guard let source = aSignal.source else { return false }
return source.fileName.contains("some/path")
}
Another way of filtering signals is by constraining signals to beacons and loggers. For example, to filter out all string signals:
StringSignal.disable(loggingTo: nil, on: nil)
To filter in string signals across all beacons and loggers:
StringSignal.enable(loggingTo: nil, on: nil)
Fine tune these operations for specific loggers:
extension Beacon {
static let debug: Beacon = .init()
}
let console = ConsoleLogger.starting(name: "Console")
let memory = MemoryLogger.starting(name: "Memory", on: [.debug])
// Disable logging of string signals across all loggers and beacons
StringSignal.disable(loggingTo: nil, on: nil)
ErrorSignal.disable(loggingTo: nil, on: nil)
// Enable logging of string signals to console logger via any beacon
StringSignal.enable(loggingTo: console, on: nil)
// Enable logging of error signals to any logger via 'debug' beacon
ErrorSignal.enable(loggingTo: nil, on: .debug)
// will log only to console
emit("Hello World", on: [.shared, .debug])
// will log only to memory
emit(error: "OMG" as Error, on: [.shared, .debug])
Be mindful that loggers retain their filtering block they were started with. Constraint-based filtering takes place before that block is evaluated.
In the event where logging may be too expensive an operation - perhaps it's a large payload, or requires making a trip to disk or network - it may be a good idea to forego all of the required work if there aren't any loggers that would process a signal. Constraints make it possible to know this. Borrowing from earlier examples:
willLog(type: StringSelf.self, on: [.debug]) // false
willLog(type: StringSelf.self, on: [.shared]) // true
willLog(type: ErrorSignal.self, on: [.debug]) // true
willLog(type: ErrorSignal.self, on: [.shared]) // false
This logic is used inside all emit()
methods. If for some reason you need to provide your own implementation of that method, be sure to check willLog()
before emitting the actual signal! See any of the emit()
methods for examples.