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.

>

Reply via email to