Since the output stream of the log is wrapped by a remote proxy in StreamBuildListener, every log message on the slave gets transferred to the master. That's a lot of throughput, and it requires a lot of storage for verbose builds. This slows down our builds. There are workarounds, but they don't address the core scalability issue.
I propose that, just like with abstract artifacts (see VirtualFile, ArtifactManager), task/build listeners be made extensible, so that users can choose something other than a StreamBuildListener in a build. Further, the log should no longer be file-based; the Listener provides the input and output stream. This should be easy to serialize in the "remote logging service" perspective: just provide the service configuration, and an API call can be made from the slave to publish to the log, and any authorized user of the log can subscribe. The master can either directly subscribe and pipe the log through the UI, or another service which is authorized to subscribe to the logging service can provide the UI externally.
One of the tougher things about this change is that it will not be compatible with any BuildWrapper and ConsoleLogFilter plugins. Those plugins decorate the OutputStream on master referred to by the slave's proxy stream. Since the plugins are on the master, it forces the slave to send all log lines to the master for decoration. This pattern tightly couples the logging concept with a master-based file. In order to maintain compatibility for those users for whom this is not an issue, I recommend a "high availability mode" feature flag. This flag will enable certain features that improve availability and scalability, and disable those extension points (BuildWrapper, ConsoleLogFilter) which are incompatible with this new flow.