In Boot 3.0.3 you can add Hooks.enableAutomaticContextPropagation() to enable context propagation, resulting in trace IDs working in logs. Here is an issue to enable it by default https://github.com/spring-projects/spring-boot/issues/34201

However, this does not seem to work in a native image. This is reproducible by creating a minimal project and logging in a reactive context like a Kotlin suspend function. When the app is run in the JVM, there are trace IDs in logs; when built to a native image, the trace IDs are null. Checking in Zipkin, traces are produced. I cannot see any errors.

I've created a small reproducer. Here it is easy to see that running with bootRun and nativeRun results in different logs https://github.com/eduanb/trace-demo

Here is a little bit more context in the Micrometer slack . @chemicL already had a look from the Reactor side and believes the issue is Boot side.

Comment From: wilkinsona

@violetagg noticed that context propagation is not available during native compilation:

Field reactor.core.publisher.ContextPropagation#isContextPropagationAvailable set to false at build time

And that this is due to the following exception:

java.util.ServiceConfigurationError: io.micrometer.context.ContextAccessor: reactor.netty.contextpropagation.ChannelContextAccessor not a subtype
        at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:593)
        at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1244)
        at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273)
        at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1309)
        at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1393)
        at java.base/java.lang.Iterable.forEach(Iterable.java:74)
        at io.micrometer.context.ContextRegistry.loadContextAccessors(ContextRegistry.java:179)
        at io.micrometer.context.ContextRegistry.<clinit>(ContextRegistry.java:40)
        at reactor.core.publisher.ContextPropagation.<clinit>(ContextPropagation.java:69)
        at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
        at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1155)
        at java.base/jdk.internal.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:42)
        at java.base/jdk.internal.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:185)
        at java.base/java.lang.reflect.Field.acquireFieldAccessor(Field.java:1132)
        at java.base/java.lang.reflect.Field.getFieldAccessor(Field.java:1113)
        at java.base/java.lang.reflect.Field.get(Field.java:425)
        at org.springframework.aot.nativex.feature.PreComputeFieldFeature.provideFieldValue(PreComputeFieldFeature.java:85)
        at org.springframework.aot.nativex.feature.PreComputeFieldFeature.iterateFields(PreComputeFieldFeature.java:64)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisElement$SubtypeReachableNotification.lambda$notifyCallback$0(AnalysisElement.java:129)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisFuture.ensureDone(AnalysisFuture.java:63)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisElement.lambda$execute$2(AnalysisElement.java:170)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:193)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:177)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
        at java.base/java.util.concurrent.ForkJoinPool.externalHelpQuiescePool(ForkJoinPool.java:2104)
        at java.base/java.util.concurrent.ForkJoinPool.awaitQuiescence(ForkJoinPool.java:3321)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.complete(CompletionExecutor.java:243)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis.doTypeflow(PointsToAnalysis.java:541)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis.finish(PointsToAnalysis.java:529)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.AbstractAnalysisEngine.runAnalysis(AbstractAnalysisEngine.java:143)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:745)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:578)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:535)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:403)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:580)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:128)

This is happening at build time due to Spring Framework's PreComputeFieldFeature.

Comment From: violetagg

When reflection is used, Reactor Core handles some fields in a special way. Recently reflection was removed from reactor.core.publisher.ContextPropagation. I'm gonna provide a fix in Reactor Core.

Comment From: sdeleuze

Looks like this could be solved on Reactor side, so I close this issue for now.