Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject data in log4j2 that is also propagated via TextMapPropagator #6588

Closed
TopoDiFogna opened this issue Sep 12, 2022 · 9 comments
Closed
Labels
needs author feedback Waiting for additional feedback from the author stale

Comments

@TopoDiFogna
Copy link

Hello,

I currently have created an extension for the otel agent that uses a TextMapPropagator to propagate a custom header; I need to use this extension, together with the agent, of course, with a spring boot application.

My custom TextMapPropagator extracts the header, which value is a JSON, and creates a custom object that implements ImplicitContextKeyed; this TextMapPropagator is then registered using a ConfigurablePropagatorProvider

This object is saved inside the context using the <C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C> getter); method inherited from the interface using as key a public static final ContextKey<LoggingContext> defined in this custom object, then injects the same header using the <C> void inject(Context context, @Nullable C carrier, TextMapSetter<C> setter); method in the downstream http calls using the same key (reference); this works like a charm 😄 .

Now I need to inject some data contained in this custom object (deserialized from JSON) in every log line printed while managing the incoming http call so I defined a new TypeInstrumentation that creates an @Advice.OnMethodExit that basically creates a new ContextDataInjector which first calls injectContextData() on the original ContextDataInjector and then executes its custom logic.

The main problem is that when I try to extract from the context my custom object which was inserted by my TextMapPropagator, and I know that is there from the debugger, cannot be extracted because the public static final ContextKey<LoggingContext> is a different object since it my custom object is loaded also from another classloader.

For the TextMapPropagator my custom object is loaded from the application classloader but for the ContextDataInjector my custom object is loaded from the agent classpath.

Is there something that I'm missing in my implementation?

I followed this readme to implement my custom Instrumentation module for log4j.

@TopoDiFogna
Copy link
Author

TopoDiFogna commented Sep 13, 2022

Actually yes, and I also peeked how traceId and spanId are injected inside MDC for log4j2 from the classes present here.

The main difference is that when in my code I do:
Context context = Java8BytecodeBridge.currentContext();
from the debugger I can see there the entry I need, but just after that line I do:
LoggingContext loggingContext = context.get(LOGGING_CONTEXT_KEY);
and here the LOGGING_CONTEXT_KEY, despite being declared static public final, it is loaded again from a different classloader; This means that I have 2 instances of LOGGING_CONTEXT_KEY and the matching inside context.get() is done by reference so I don't get the value associated to that key 😢

LoggingContext is my object deserialized from json contained in the incoming requests header, it is injected in the context by my custom TextMapPropagator and contains the previously mentioned public static final ContextKey<LoggingContext> LOGGING_CONTEXT_KEY

@TopoDiFogna
Copy link
Author

TopoDiFogna commented Sep 13, 2022

I just noted that for log4j version 2.17 there's more code. I'll try to review my code following what is there and report asap

@laurit
Copy link
Contributor

laurit commented Sep 13, 2022

Agent code is isolated from application code. If you need to share a key between the application and agent code you'll have to define it in boot loader, or build an api in boot loader that bridges the calls between application and agent.

@TopoDiFogna
Copy link
Author

I was just saying that after having updated the code I noticed that the common key is loaded inside the application classloader by the instrumentation module and it is loaded again by the TextMapPropagator in the agent classloader.

@laurit how can be achieved what you are suggesting ?

Main goal of this extension was to be plug and play to the SpringBoot application with the agent so it can be included only when needed, so modifying the application itself can be problematic.

@laurit
Copy link
Contributor

laurit commented Sep 13, 2022

@TopoDiFogna
Copy link
Author

Thank you, I'll try the custom distro example first then if that's the "easy" way.

@trask
Copy link
Member

trask commented Aug 15, 2023

hi @TopoDiFogna, I'm not super clear on your use case, but baggage might be a good option, this was recently implemented for logback, and could be implemented similarly for log4j2

@trask trask added the needs author feedback Waiting for additional feedback from the author label Aug 15, 2023
@github-actions
Copy link
Contributor

This has been automatically marked as stale because it has been marked as needing author feedback and has not had any activity for 7 days. It will be closed automatically if there is no response from the author within 7 additional days from this comment.

@github-actions github-actions bot added the stale label Aug 22, 2023
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Aug 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs author feedback Waiting for additional feedback from the author stale
Projects
None yet
Development

No branches or pull requests

3 participants