-
Notifications
You must be signed in to change notification settings - Fork 1
BaggageContext and Swift Logging: Design alternatives #37
Comments
More approaches to consider (and I guess we may need to PoC around). (I'm not really proposing the below, does not feel right, but let's list potential solutions before we decide on one) (3) Logger to be created or "updated with" a ContextThis would take the form of something like func doThings(..., context: BaggageContext) {
Logger("label", context).info("hello") // ad-hoc creating, some projects do not want that...
}
func doThings(..., log: Logger, context: BaggageContext) {
logger(context).info("hello") // "app wide passed around logger" and "enrich" with context
} // this can get confusing perhaps? Would it be possible perhaps to avoid this with the below? func doThings(..., logger: BaggageLogger) {
logger.baggage // ...
logger.info("xxx") // ...
} It's an opposite take on (2) I guess, rather than the context depending on logging, there could be a special logger... Pros 👍
Cons 👎
See also: https://blog.gopheracademy.com/advent-2016/context-logging/ |
(4) Logger functions to accept baggage context and "merge" with metadata when emitting logsAnother style that comes to mind is providing an extension over // add accepting baggage to loggers
extension Logger {
@inlinable
public func debug(
_ message: @autoclosure () -> Logger.Message,
context: BaggageContext,
metadata: @autoclosure () -> Logger.Metadata? = nil,
file: String = #file, function: String = #function, line: UInt = #line) {
self.log(level: .debug, message(), metadata: merge metadata and context (extract context as Logger.MetadataValue), file: file, function: function, line: line)
}
} We'd provide some protocol and "known key" for setting an "extractor" that would do that Pros 👍
Cons 👎
The go solution AFAICS is to not pass loggers around -- just pass context, and whenever I make a logger just pass a context to it. That's nice and clean. What about the present day pattern in Swift that some people like about "pass logger around" though -- it makes it tricky. We need to figure out how that would look like here to serve all cases and not be too boilerplate heavy; passing both log and context seems to be an unpleasant outcome. |
There is a broader consideration here of how cross-cutting concerns potentially interact with each other. For example, consider a couple of use cases-
We have a number of actors in these scenarios-
The difference between what has been discussed above and these use cases is that these are interactions between Metrics or Logging and Tracing/Spans rather than with the BaggageContext itself but the pattern extends itself to situations where there is just a BaggageContext From an API level, I think we need some mechanism that can tell an implementation - called by the web/request framework and clients as appropriate - here is an existing Metric or Logger and a span/baggage that I want it to operate in, give me back something I can use for metrics/logging within this scope. It is then up to the implementation to decide what to do - potentially nothing and pass back the original object or return some kind of span/baggage-aware Logging or Metrics implementation that handles the interactions between these concerns. let spanAwareLogger = logger.forSpan(currentSpan)
let baggageAwareLogger = logger.forBaggage(currentBaggage)
let spanAwareMetric = metric.forSpan(currentSpan)
let baggageAwareMetric = metric.forBaggage(currentBaggage) |
Thanks for chiming in Simon! Yes, I think that's right -- it's a variation on (3) listed here, but with the implication that we'll want to allow the tracing instrument to decide how things are to be mapped into a logger. I think we can do the right things here... esp. since the forBaggage (good naming idea, we'll see :-)) can then create a special I'm going to poke at this during this week and report back / ask for review :) |
Logging support has now been implemented as part of a
BaggageLogging
library (that depends onswift-log
). It allows for setting a base Logger that is then being used to compute thecontext.logger
property. In the current implementation, this baseLogger
is injected into theBaggageContext
by stuffing it in the baggage via a specialBaggageContext.BaseLoggerKey
.Below are some pro/cons on this approach and a possible alternative.
(1) Storing the Logger inside the BaggageContexts storage
Pros 👍
Logger
while initializing aBaggageContext
logger
property in a separate library, as theBaggageContext
itself becomes the "property storage"Cons 👎
Logger
we had to manually exclude theBaggageContext.BaseLoggerKey
so that it's not included in the logBaggageContext
Logger
as a stored property in theBaggageContext
extension(2) Adding Logger to BaggageContext directly
Pros 👍
BaggageContext
Logger
metadataCons 👎
BaggageContext
would need to depend onswift-log
directlyWhat are your thoughts on this. Other pros/cons, or even other alternatives to this approach?
The text was updated successfully, but these errors were encountered: