On Sat, Jul 9, 2022 at 8:16 PM Ralph Goers <ralph.go...@dslextreme.com> wrote:
> 1. I’d like to not have to generate new source code for every class doing > logging. > I am not sure how Lombok does it but I will want to investigate that. > I have studied (at least tried to!) Lombok sources a bit... They are pretty arcane. Nevertheless, I will continue doing so. (I also have my reservations whether Lombok constitutes a good reference model for us where we can borrow some ideas from or if it just happens to be the only tool that we know of which performs some sort of bytecode weaving similar to what we have in mind.) To the best of my knowledge... You need to scan a class to spot Log4j usages and perform necessary magic. There is no other way to figure out if Log4j is used or not. (Once the scan results in negative, you don't need to override the bytecode of that class, obviously.) > 2. Your solution looks like it is still done at runtime. Yes, but that is only for the demonstration purposes of the bytecode generation. Using the generated bytecode, you can override the class at either compile time or runtime. (See the answer from Piotr.) > I would like to do it at compile > time. My though is to use the annotation processor and generate a new > class that > captures all the stack trace elements.I would then replace every logging > call with > a LogBuilder call. So > logger.info <http://logger.info/>(“Hello {}”, user); > would become > > > logger.atInfo().withLocation(Log4jLocations.locations.get(“ThisFQCN”)).log(“Hello > {}”, user); > > So, like Lombok, any class wanting this would be annotated with @Log4j2, > but > in addition to getting a logger declared they would also have the > locations generated. > For one, why the extra annotation indirection when we can perform this processing for existing class files without recompilation or whatsoever? Second, spotting all call-sites, registering them to a `Log4jLocations.locations` map could also be done. (Actually, this was my first idea too. Though I continued with thread-locals since it is simpler.) Though I have my doubts if transforming logger calls to their fluent-API counterparts could be done _easily_. It feels to me this would need specialization on every single logger API call. > > The issues I have are a) I haven’t figured out how Logbok performs its > magic without > generating new code Lombok generates bytecode and overrides the original class file. That is why you cannot make a Lombok-using project work in IDEA without installing its plugin. > or affecting line numbers, Preserving line numbers is indeed a black magic. ASM, the library I used for bytecode weaving, does this for us. > b) I haven’t figured out how to get > the location information while in the annotation processor. ASM helps here. I have used ASM for two main purposes: 1) collecting the source location information and 2) adding new bytecode before every logger call. >