[Discussion] Server Logging API

Right, but that's not solved by custom log levels either, right?

Yes, these are all valid issues. I personally am the 'passing the logger around explicitly' kind of person which makes the contextual logging fairly straightforward and Loggers can be value types etc. But it does make it harder to have per sub-system logging messages. Sometimes you can use #file as a proxy for what sub-system it is but it's not great either. The thing is that I don't think there's a good answer for everybody, we just can't force everybody to pass loggers around explicitly nor can we tell people that that's not supported.

If you want to have both 'sub-system' loggers and contextual logging then I think the only way is to built the context separately and then pass it onto the logging methods manually (with added metadata: parameters to every log method, like @artemredkin was proposing up-thread). Or obviously MDC which propagates the contextual information through thread-locals but sub-system loggers + MDC + Dispatch == needs-manual-assistance propagating the context :slight_smile:

I know, there's no perfect solutions here that work for every architecture and belief...

Sure, at the moment in Swift, both @autoclosure and closure arguments (with non-nil contexts) will allocate (ie. call malloc). So if you have a ModuleA which defines func foo(_ body: () -> String) and you call it from ModuleB as

let a = "hello"
foo {
  return a
}

an allocation will happen when foo is called for the closure's context (the captured variables). @autoclosures are the same, they just are a nicer syntax for this. The only way to get around that is inlining. Ie. making it @inlinable func foo(_ body: () -> String). That way the compiler will (hopefully) inline foo's body into the caller and it's no longer actually building a closure.

That's why Logger is a struct and all its methods are inlineable: Within the (hopefully) inlined code we know if we need to produce the log message string (by evaluating the @autoclosure) or not. And only after having decided that we do need to log, we evaluate the @autoclosure and pass the result on as a String to the LogHandler. So with a bit of support from the inlining gods, we no longer need to allocate.

If we passed the @autoclosure straight through to the LogHandler, it can't inline that and we do actually need to allocate for the closure. And there's no way we can inline the LogHandler implementation into the caller because the LogHandler is selected at runtime.

Really, this should be addressed in the compiler and the closure context should be stack allocated (because the closure is non-escaping) but that hasn't been done AFAIK.

Agreed, but then every log message would be an allocation, if actually logged or not. That's unacceptable for a non-starter for now. I'd hope that this is fixed in Swift rather sooner than later but I think we need a solution before that. For more information, check this thread, especially the newer messages.

I still think that it might open a kitchen sink of information that one or the other person needs and (totally contrary to my normal opinions) I think here stringly typed is okay. Why? Because everybody I've seen on the server-side analyses logs with textual tools anyway. I mean we teach Splunk how to parse the messages that we serialised costly on the other end. But I don't want to say 'no' to this but for this proposal at this stage I don't think we should do it. If this goes forward and we have gained experience, then I think we can pitch enhancements but at this point I feel it's too risky to design features for a system that nobody has used in production quite yet.

yes

I do too but the same applies to me, can't speak for the community hence I'm considering asking (on a separate thread) if we should change. But that's really a small detail so maybe not now :).

1 Like