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

Support for Contextual Logging / Log Correlation #22724

Closed
renegrob opened this issue Jan 7, 2022 · 37 comments
Closed

Support for Contextual Logging / Log Correlation #22724

renegrob opened this issue Jan 7, 2022 · 37 comments
Labels
area/context-propagation kind/enhancement New feature or request triage/out-of-date This issue/PR is no longer valid or relevant

Comments

@renegrob
Copy link
Contributor

renegrob commented Jan 7, 2022

Description

Currently it is very hard if not impossible to enrich log messages related to a request or message with additional context information (e.g. a "correlation-id"). For SREs / operations it is very important to be able to correlate log messages and filter the messages in a log management tool for faster issue analysis. This is often achieved by passing some context attributes along the processing chain that will appear in all logs of related tasks of all involved systems.
JBoss-Logging and slf4j provide an MDC object that allows to set context information that is available in the logger and can be included in the log-format. Since the MDC internally uses a ThreadLocal object to associate the context information, this information is lost, if the thread is switched (e.g. due to a blocking execution from a vert.x-eventloop-thread to an executor-thread).
The goal of this ticket is to either make MDC work or offer an alternative solution to be able to include context information in the related log messages - which means passing context information along the execution chain.

Implementation ideas

See also https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/Contextual.20Logging.20in.20Quarkus

@renegrob renegrob added the kind/enhancement New feature or request label Jan 7, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Jan 7, 2022

You added a link to a Zulip discussion, please make sure the description of the issue is comprehensive and doesn't require accessing Zulip.

This message is automatically generated by a bot.

@renegrob
Copy link
Contributor Author

renegrob commented Jan 7, 2022

@Ladicek FYI

@quarkus-bot
Copy link

quarkus-bot bot commented Jan 7, 2022

/cc @FroMage, @manovotn

@Ladicek
Copy link
Contributor

Ladicek commented Jan 7, 2022

The suggestion on Zulip, which I mostly agree with, is that we should provide MP ConProp ThreadContextProvider implementation(s) out of the box (though perhaps not enabled out of the box).

There are basically 2 levels on which a context provider could work:

  • logging facade (JBoss Logging, SLF4J)
  • logging backend (JBoss LogManager, Logback, Log4j 1/2)

I briefly looked at a couple of those and my impression is that most of these only hand out copies of the backing contextual storage, so while forward propagation would be possible, back-propagation not so much.

@renegrob
Copy link
Contributor Author

renegrob commented Jan 7, 2022

The propagation could be enabled as soon as the logging pattern contains a variable referencing the MDC. Using the MDC without having the propagation enabled doesn't really make sense, does it?

@josephearl
Copy link

Forgive my ignorance but is a handle to the underlying map necessary for back-propagation? Given thread 1 -> 2 -> 1, is it not possible to set the context map (with MDC.setContextMap) on returning to thread 1 with a copy retrieved from thread 2?

If it is then probably the only implementation that would support it is logback:

if (MDC.getAdapter() instanceof ch.qos.logback.classic.util.LogbackMDCAdapter logbackMdc) {
  logbackMdc.getPropertyMap();
}

@renegrob
Copy link
Contributor Author

@josephearl A handle to the underlying map would make things more lightweight and easier, but it is not necessary. However, if we are looking only at the lowest common denominator then we'll not come up with a great solution. Often things get possible if you try and convince others (e.g. to adjust their API). Reactive programming does not only exist in Quarkus and I believe that these requirements will become more common.

@kostacasa
Copy link

Agreed, this would be an incredible value add for any cloud logging solution and allow request metadata to be associated with log messages (user identities, request ids etc). Considering the focus on reactive libraries in Quarkus, MDC should be a supported as default.

@luneo7
Copy link
Contributor

luneo7 commented Apr 11, 2022

When trying to solve OTEL MDC log metadata, I did the dmlloyd/jboss-logmanager-embedded#4 PR and now I am waiting for a new version of it to be released... What I planned was to create a Quarkus Vert.x MDC Provider extension, with this extension using MDC as we normally would use works without any code change to existing MDC usage, and It would also make the OTEL feature work as intended. What do you guys think about this approach?

@renegrob
Copy link
Contributor Author

renegrob commented Apr 11, 2022

Important to me is that the context does not get lost along its processing chain. E.g. Vert.x request -> blocking call -> back to vert.x thread or vert.x event-loop thread -> managed thread pool - > vert.x thread or scheduler event -> blocking call -> remote call -> finish blocking call. As long as I was only dealing with reactive calls or only with blocking calls, everything was at least somehow working. The problems did arise in mixed environments. I need the context along with an event that is handled (e.g. http request, Kafka message or scheduler event).

@luneo7 luneo7 mentioned this issue May 2, 2022
@renegrob
Copy link
Contributor Author

renegrob commented May 4, 2022

@mkouba Is #22319 related to this issue?

@mkouba
Copy link
Contributor

mkouba commented May 4, 2022

@mkouba Is #22319 related to this issue?

@renegrob I don't think so. #22319 is purely about CDI contexts.

@luneo7
Copy link
Contributor

luneo7 commented May 18, 2022

#25311 was merged, we should have MDC working with Vert.x now =]

@renegrob
Copy link
Contributor Author

Great! Thanks @luneo7!
I guess we stil need to somehow bridge the gap between Vertx and worker threads as we still lose the context when switching to a worker-thread.

@luneo7
Copy link
Contributor

luneo7 commented May 19, 2022

Switching between Vertx main threads and worker threads works out of the box, if you use your own worker threads you will need to follow the Quarkus context propagation guide. https://quarkus.io/guides/context-propagation

If you check the test here:

LOGGER.info("Blocking task executed ### " + requestId);
you will see that we do a log in a Vertx Main loop thread, and later in a blocking thread, that is a worker thread, and they work =]

@renegrob
Copy link
Contributor Author

Thanks a lot @luneo7 for the example.

I tried it out with resteasy-reactive and created a reproducer project:
https://github.com/renegrob/quarkus-maven-reproducers/tree/mdc-propagation

Note: The unit tests do not (yet) test the log output. I just use them to invoke the methods.

This one works as expected:

@GET
@Path("vertx/blocking/new-context")
@Produces(MediaType.TEXT_PLAIN)
public Uni<String> vertxBlockingOnNewContext() {
    return Vertx.vertx().executeBlocking(Uni.createFrom().item(service::getBlocking));
}
2022-05-22 22:13:18,101 MDC:{} DEBUG [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) Created new correlationId: fb414b5f-7cd6-403b-b27d-caa65cd2dbb5.
2022-05-22 22:13:18,101 MDC:{correlationId=fb414b5f-7cd6-403b-b27d-caa65cd2dbb5} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) fb414b5f-7cd6-403b-b27d-caa65cd2dbb5: GET /v1/vertx/blocking/new-context
2022-05-22 22:13:18,103 MDC:{correlationId=fb414b5f-7cd6-403b-b27d-caa65cd2dbb5} WARN  [io.ver.cor.imp.VertxImpl] (vert.x-eventloop-thread-1) You're already on a Vert.x context, are you sure you want to create a new Vertx instance?
2022-05-22 22:13:18,357 MDC:{correlationId=fb414b5f-7cd6-403b-b27d-caa65cd2dbb5} INFO  [com.git.ren.ExampleService] (vert.x-worker-thread-0) Creating result: 2
2022-05-22 22:13:18,359 MDC:{correlationId=fb414b5f-7cd6-403b-b27d-caa65cd2dbb5} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) fb414b5f-7cd6-403b-b27d-caa65cd2dbb5: 200 OK

While this version loses the MDC:

    @GET
    @Path("vertx/blocking/new-context")
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> vertxBlockingOnNewContext() {
        return Vertx.vertx().executeBlocking(Uni.createFrom().item(service::getBlocking));
    }
2022-05-22 22:13:17,828 MDC:{} DEBUG [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) Created new correlationId: e5c3ee7a-efba-4835-b29e-0a2f308ce3c4.
2022-05-22 22:13:17,828 MDC:{correlationId=e5c3ee7a-efba-4835-b29e-0a2f308ce3c4} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) e5c3ee7a-efba-4835-b29e-0a2f308ce3c4: GET /v1/vertx/blocking
2022-05-22 22:13:18,084 MDC:{} INFO  [com.git.ren.ExampleService] (executor-thread-0) Creating result: 1
2022-05-22 22:13:18,085 MDC:{correlationId=e5c3ee7a-efba-4835-b29e-0a2f308ce3c4} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) e5c3ee7a-efba-4835-b29e-0a2f308ce3c4: 200 OK

Also this very simple example loses the MDC:

@GET
@Path("hello")
@Produces(MediaType.TEXT_PLAIN)
@Blocking
public String hello() {
    logger.info("hello endpoint");
    return "Hello from RESTEasy Reactive";
}
2022-05-22 22:13:18,372 MDC:{} DEBUG [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) Extracted correlationId: MY_CORRELATION_ID from header X-Correlation-ID.
2022-05-22 22:13:18,373 MDC:{correlationId=MY_CORRELATION_ID} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) MY_CORRELATION_ID: GET /v1/hello
2022-05-22 22:13:18,373 MDC:{} INFO  [com.git.ren.MyResource] (executor-thread-0) hello endpoint
2022-05-22 22:13:18,375 MDC:{} INFO  [com.git.ren.CorrelationIdFilter] (executor-thread-0) MY_CORRELATION_ID: 200 OK

-> Here even the Vert.x BodyEndHandler is called on the executor-thread.

What am I doing wrong?

@renegrob
Copy link
Contributor Author

@geoand Do you have a hint since I'm using resteasy-reactive?

@geoand
Copy link
Contributor

geoand commented May 23, 2022

I do not unfortunately as I haven not followed the MDC stuff in Vert.x

@luneo7
Copy link
Contributor

luneo7 commented May 24, 2022

@renegrob you did nothing wrong hahaha
The only thing is that you are running Quarkus 2.9.1.Final which doesn't contain the Vert.x MDC stuff, I think it will be out in 2.10... if you clone quarkus master repo, do a ./mvnw -Dquickly and later change you pom so the bom comes from:

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-bom</artifactId>
        <version>999-SNAPSHOT</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

You will see that all the tests are passing, the ones using resteasy-reactive, ant the other using vert.x directly.

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.github.renegrob.MyResourceTest
2022-05-24 09:57:23,841 MDC:{} INFO  [org.jbo.threads] (main) JBoss Threads version 3.4.2.Final
2022-05-24 09:57:27,006 MDC:{correlationId=a00017b1-d54c-4b8d-91f3-958a9e1586d2} INFO  [com.git.ren.MyScheduler] (executor-thread-0) scheduledTask invoked
2022-05-24 09:57:27,061 MDC:{} INFO  [io.quarkus] (main) quarkus-maven-reproducers 999-SNAPSHOT on JVM (powered by Quarkus 999-SNAPSHOT) started in 5.101s. Listening on: http://localhost:8081
2022-05-24 09:57:27,062 MDC:{} INFO  [io.quarkus] (main) Profile test activated. 
2022-05-24 09:57:27,063 MDC:{} INFO  [io.quarkus] (main) Installed features: [cdi, config-yaml, hibernate-validator, resteasy-reactive, resteasy-reactive-jackson, scheduler, smallrye-context-propagation, smallrye-openapi, swagger-ui, vertx]
2022-05-24 09:57:27,080 MDC:{correlationId=a00017b1-d54c-4b8d-91f3-958a9e1586d2} INFO  [com.git.ren.MyScheduler] (executor-thread-1) Getting: 09:57:27.011423
2022-05-24 09:57:27,082 MDC:{correlationId=a00017b1-d54c-4b8d-91f3-958a9e1586d2} INFO  [com.git.ren.MyScheduler] (executor-thread-0) result: 09:57:27.011423
2022-05-24 09:57:29,937 MDC:{} DEBUG [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) Created new correlationId: bf0d0737-3f91-4bce-bf97-6c5c7bf00812.
2022-05-24 09:57:29,940 MDC:{correlationId=bf0d0737-3f91-4bce-bf97-6c5c7bf00812} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) bf0d0737-3f91-4bce-bf97-6c5c7bf00812: GET /v1/worker-pool/blocking
2022-05-24 09:57:30,208 MDC:{} INFO  [com.git.ren.ExampleService] (executor-thread-0) Creating result: 1
2022-05-24 09:57:30,222 MDC:{correlationId=bf0d0737-3f91-4bce-bf97-6c5c7bf00812} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) bf0d0737-3f91-4bce-bf97-6c5c7bf00812: 200 OK
2022-05-24 09:57:30,477 MDC:{} DEBUG [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) Created new correlationId: c2827604-2e5f-4f3c-9e2c-97bd8404276b.
2022-05-24 09:57:30,477 MDC:{correlationId=c2827604-2e5f-4f3c-9e2c-97bd8404276b} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) c2827604-2e5f-4f3c-9e2c-97bd8404276b: GET /v1/vertx/blocking
2022-05-24 09:57:30,736 MDC:{correlationId=c2827604-2e5f-4f3c-9e2c-97bd8404276b} INFO  [com.git.ren.ExampleService] (executor-thread-0) Creating result: 2
2022-05-24 09:57:30,738 MDC:{correlationId=c2827604-2e5f-4f3c-9e2c-97bd8404276b} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) c2827604-2e5f-4f3c-9e2c-97bd8404276b: 200 OK
2022-05-24 09:57:30,760 MDC:{} DEBUG [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) Created new correlationId: ee5c160b-51b2-4284-8b08-5b5517a77710.
2022-05-24 09:57:30,760 MDC:{correlationId=ee5c160b-51b2-4284-8b08-5b5517a77710} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) ee5c160b-51b2-4284-8b08-5b5517a77710: GET /v1/vertx/blocking/new-context
2022-05-24 09:57:30,764 MDC:{correlationId=ee5c160b-51b2-4284-8b08-5b5517a77710} WARN  [io.ver.cor.imp.VertxImpl] (vert.x-eventloop-thread-1) You're already on a Vert.x context, are you sure you want to create a new Vertx instance?
2022-05-24 09:57:31,021 MDC:{} INFO  [com.git.ren.ExampleService] (vert.x-worker-thread-0) Creating result: 3
2022-05-24 09:57:31,023 MDC:{correlationId=ee5c160b-51b2-4284-8b08-5b5517a77710} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-1) ee5c160b-51b2-4284-8b08-5b5517a77710: 200 OK
2022-05-24 09:57:31,049 MDC:{} DEBUG [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) Extracted correlationId: MY_CORRELATION_ID from header X-Correlation-ID.
2022-05-24 09:57:31,049 MDC:{correlationId=MY_CORRELATION_ID} INFO  [com.git.ren.CorrelationIdFilter] (vert.x-eventloop-thread-0) MY_CORRELATION_ID: GET /v1/hello
2022-05-24 09:57:31,050 MDC:{correlationId=MY_CORRELATION_ID} INFO  [com.git.ren.MyResource] (executor-thread-0) hello endpoint
2022-05-24 09:57:31,052 MDC:{correlationId=MY_CORRELATION_ID} INFO  [com.git.ren.CorrelationIdFilter] (executor-thread-0) MY_CORRELATION_ID: 200 OK
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 13.71 s - in com.github.renegrob.MyResourceTest
[INFO] Running com.github.renegrob.MySchedulerTest
2022-05-24 09:57:32,003 MDC:{correlationId=da94966f-d067-4f76-bb93-8871199ea84d} INFO  [com.git.ren.MyScheduler] (executor-thread-0) scheduledTask invoked
2022-05-24 09:57:32,056 MDC:{correlationId=a00017b1-d54c-4b8d-91f3-958a9e1586d2} INFO  [com.git.ren.MyScheduler] (executor-thread-1) Getting: 09:57:32.004317
2022-05-24 09:57:32,057 MDC:{correlationId=da94966f-d067-4f76-bb93-8871199ea84d} INFO  [com.git.ren.MyScheduler] (executor-thread-0) result: 09:57:32.004317
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.022 s - in com.github.renegrob.MySchedulerTest
2022-05-24 09:57:32,359 MDC:{} INFO  [io.quarkus] (main) quarkus-maven-reproducers stopped in 0.074s
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  44.082 s
[INFO] Finished at: 2022-05-24T09:57:32-05:00
[INFO] ------------------------------------------------------------------------

@luneo7
Copy link
Contributor

luneo7 commented May 24, 2022

So, how does the Vert.x MDC works?

  • When you call the MDC from a Vert.x thread (which means that is is an instance of VertxThread and has a Vert.x Context attached to it) it uses Vert.x localContext (a data map that is attached to standard and worker contexts) to store all the MDC stuff, and Vert.x and everything detailed in the Quarkus context propagation guide works out of the box with the MDC stuff being propagated to Vert.x threads.
  • When you call the MDC from a thread that is not a Vert.x thread, a regular thread, it will fallback to the original InheritableThreadLocal MDC map, and will work as it always used to work.

@renegrob
Copy link
Contributor Author

@luneo7 Oh sorry, my bad. Thanks for the information about Vert.x MDC.
Looking at the log, there are still some cases that don't work properly yet. I will update the reproducer and implement proper tests so that they will not just run through without testing.

@luneo7
Copy link
Contributor

luneo7 commented May 24, 2022

@renegrob the worker-pool/blocking if you convert it to:

    @GET
    @Path("worker-pool/blocking")
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> blockingCall() {
        return Uni.createFrom()
                  .item(service::getBlocking)
                  .runSubscriptionOn(Infrastructure.getDefaultExecutor());
    }

It works as expected (as stated in the context propagation guide).

The vertx/blocking/new-context won't work because you are not creating a new context, you are creating a new vertx, you can see the log You're already on a Vert.x context, are you sure you want to create a new Vertx instance?, so it won't work since if you create a new vertx instance it won't inherit anything from the actual context, and you lose the MDC context since it is stored in the vertx context

@luneo7
Copy link
Contributor

luneo7 commented May 24, 2022

@cescoffier might be able to explain better why using Infrastructure.getDefaultWorkerPool() doesn't propagate the context correctly and Infrastructure.getDefaultExecutor() does =]

@renegrob
Copy link
Contributor Author

@luneo7 Thanks a lot! I will try to fix my tests. We probably should write a guide for this or update existing ones, there are some pitfalls but if it is done correctly, then it works.

@renegrob
Copy link
Contributor Author

I updated the reproducer. The tests are now green and will fail, if the blocking call is done on the eventloop-thread or if the MDC is not logged correctly.
Now we have a great feature. I think we should document it, so that people can actually understand and use it.
Especially, we should document what doesn't work (e.g. Infrastructure.getDefaultWorkerPool()) and why.

@luneo7
Copy link
Contributor

luneo7 commented May 26, 2022

For sure we should document it, but if you follow the context propagation guide exactly as it is it works, there it states to use the getDefaultExecutor. The context propagation guide should also be updated, the MDC is directly attached to context propagation, getDefaultWorkerPool needs to be mentioned there, since if you follow the example there and don't use the getDefaultExecutor it will fail

@cescoffier
Copy link
Member

cescoffier commented May 26, 2022

@cescoffier might be able to explain better why using Infrastructure.getDefaultWorkerPool() doesn't propagate the context correctly and Infrastructure.getDefaultExecutor() does =]

That's a very good question. Probably a bug. (One is implemented on top of the other one)

@luneo7
Copy link
Contributor

luneo7 commented May 26, 2022

For what I see, it is a design flaw, the executor that Quarkus uses is the EnhancedQueueExecutor (https://github.com/jbossas/jboss-threads/blob/main/src/main/java/org/jboss/threads/EnhancedQueueExecutor.java) it has a context handler that is set to get the current Vertx context. But SmallRye Infrastructure. getDefaultWorkerPool() uses a MutinyScheduler that wraps the EnhancedQueueExecutor and it is a ScheduledThreadPoolExecutor, the EnhancedQueueExecutor just fetches the context when the task is about to run, not when you submit the task to the executor, so when/where the task is actually run in the MutinyScheduler the vertx context doesn't exists, thus it is always null, and it doesn't get propagated.

@luneo7
Copy link
Contributor

luneo7 commented May 26, 2022

So, that is what happens when you use Infrastructure.getDefaultWorkerPool(), when the task is run the context is null, so nothing is propagated =]

Screen Shot 2022-05-26 at 9 51 52 AM

Screen Shot 2022-05-26 at 9 52 12 AM

@luneo7
Copy link
Contributor

luneo7 commented May 26, 2022

The way that I got Infrastructure.getDefaultWorkerPool() to work was to create a VertxContextProvider.java

package com.luneo7.tests;

import io.vertx.core.Context;
import io.vertx.core.Vertx;
import io.vertx.core.impl.ContextInternal;
import org.eclipse.microprofile.context.spi.ThreadContextProvider;
import org.eclipse.microprofile.context.spi.ThreadContextSnapshot;

import java.util.Map;

public class VertxContextProvider implements ThreadContextProvider {

    @Override
    public ThreadContextSnapshot currentContext(Map<String, String> props) {
        Context context = Vertx.currentContext();
        return () -> {
            if (context != null) {
                final ContextInternal vertxContext = (ContextInternal) context;
                vertxContext.beginDispatch();
                return () -> vertxContext.endDispatch(null);
            }
            return () -> {};
        };
    }

    @Override
    public ThreadContextSnapshot clearedContext(Map<String, String> props) {
        return () -> () -> {};
    }

    @Override
    public String getThreadContextType() {
        return "Vertx";
    }
}

And later create a src/main/resources/META-INF/services/org.eclipse.microprofile.context.spi.ThreadContextProvider file with com.luneo7.tests.VertxContextProvider

With this class the Vertx context gets propagated with smallrye context propagation... since the currentContext method is called in the calling thread and not in the executor thread =]

@cescoffier what do you think? should we open a new bug ticket for vertx context propagation with Infrastructure.getDefaultWorkerPool() ?

@luneo7
Copy link
Contributor

luneo7 commented May 26, 2022

This also impacts OpenTelemetry, since it has a QuarkusContextStorage that stores OTEL Context inside the Vert.x Context... if you do one endpoint that uses Infrastructure.getDefaultWorkerPool() to do something and try to create a span, it won't properly be a child span of the request... since the vertx context is lost....

@luneo7
Copy link
Contributor

luneo7 commented May 26, 2022

Created a new issue (#25818) to track Infrastructure.getDefaultWorkerPool() not propagating Vert.x Context, and used OpenTelemetry as a reproducer there.

@nithinbandaru1
Copy link

Any update on this feature?

@cescoffier
Copy link
Member

Both the MDC and the trace propagation have been implemented.

If you still see a problem, please re-open an issue with an updated and standalone reproducer.

@cescoffier cescoffier added the triage/out-of-date This issue/PR is no longer valid or relevant label Dec 14, 2023
@vsolopov
Copy link

vsolopov commented Jan 4, 2024

@cescoffier how to use Log Correlation? Do you have any example or doc to look at result?

@vsolopov
Copy link

vsolopov commented Jan 8, 2024

Answering on question, to use it needs to make sure if Quarkus version supports "smallrye-context-propagation" (needs to be printed in logs on startup in "Installed features" block).

To make a log correlation needs to put some unique ID into MDC. In my case, I added it to the request filter:

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
import java.util.UUID;

@Provider
@PreMatching
public class MdcRequestFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) {
        MDC.put("id", UUID.randomUUID());
    }

}

Then, to show this ID in logs, added it manually in JsonProvider implementation:

import io.quarkiverse.loggingjson.JsonProvider;
import io.quarkiverse.loggingjson.JsonGenerator;
import org.jboss.logmanager.ExtLogRecord;

import javax.inject.Singleton;

@Singleton
public class MyJsonProvider implements JsonProvider {

    @Override
    public void writeTo(JsonGenerator generator, ExtLogRecord event) throws IOException {
        generator.writeStringField("mdc", event.getMdcCopy().toString());
    }
    
}

Used:
quarkus 2.12.2
and io.quarkiverse.loggingjson:quarkus-logging-json:3.0.0

@cescoffier
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/context-propagation kind/enhancement New feature or request triage/out-of-date This issue/PR is no longer valid or relevant
Projects
None yet
Development

No branches or pull requests

10 participants