You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/12/17 12:59:42 UTC

(camel) 01/01: CAMEL-17721: camel-core - MDC custom keys should preserve existing value during routing, so users can alter its value.

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch mdc
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 6715a0405c480a4339d9f7dd13310071f7f9c061
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Dec 17 13:59:31 2023 +0100

    CAMEL-17721: camel-core - MDC custom keys should preserve existing value during routing, so users can alter its value.
---
 .../apache/camel/impl/engine/MDCUnitOfWork.java    |   7 +-
 .../apache/camel/processor/MDCCustomKeysTest.java  | 141 +++++++++++++++++++++
 2 files changed, 147 insertions(+), 1 deletion(-)

diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/MDCUnitOfWork.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/MDCUnitOfWork.java
index e7c6c748849..d497fdbeb99 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/MDCUnitOfWork.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/MDCUnitOfWork.java
@@ -309,7 +309,12 @@ public class MDCUnitOfWork extends DefaultUnitOfWork implements Service {
                         MDC.put(MDC_CAMEL_CONTEXT_ID, camelContextId);
                     }
                     if (custom != null) {
-                        custom.forEach(MDC::put);
+                        // keep existing custom value to not override
+                        custom.forEach((k, v) -> {
+                            if (MDC.get(k) == null) {
+                                MDC.put(k, v);
+                            }
+                        });
                     }
                 }
                 // need to setup the routeId finally
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/MDCCustomKeysTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/MDCCustomKeysTest.java
new file mode 100644
index 00000000000..f76e54f2750
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/MDCCustomKeysTest.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import org.slf4j.MDC;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class MDCCustomKeysTest extends ContextTestSupport {
+
+    @Test
+    public void testMdcPreserved() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:end");
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:a", "A,B");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // enable MDC and breadcrumb
+                context.setUseMDCLogging(true);
+                context.setUseBreadcrumb(true);
+                context.setMDCLoggingKeysPattern("custom*,my*");
+
+                MdcCheckerProcessor checker1 = new MdcCheckerProcessor("N/A");
+                MdcCheckerProcessor checker2 = new MdcCheckerProcessor("World");
+
+                from("direct:a").process(e -> {
+                    // custom is propagated
+                    MDC.put("custom.hello", "N/A");
+                    // foo is propagated due we use the same thread
+                    MDC.put("foo", "Bar");
+                    // myKey is propagated
+                    MDC.put("myKey", "Baz");
+                }).process(checker1)
+                        .to("log:foo")
+                        .process(e -> {
+                            MDC.put("custom.hello", "World");
+                        })
+                        .process(checker2)
+                        .to("mock:end");
+            }
+        };
+    }
+
+    /**
+     * Stores values from the first invocation to compare them with the second invocation later.
+     */
+    private static class MdcCheckerProcessor implements Processor {
+
+        private String exchangeId;
+        private String messageId;
+        private String breadcrumbId;
+        private String contextId;
+        private Long threadId;
+        private String foo;
+
+        private final String expected;
+
+        public MdcCheckerProcessor(String expected) {
+            this.expected = expected;
+        }
+
+        @Override
+        public void process(Exchange exchange) throws Exception {
+            // custom is propagated as its pattern matches
+            assertEquals(expected, MDC.get("custom.hello"));
+            assertEquals("Baz", MDC.get("myKey"));
+
+            if (foo != null) {
+                // foo propagated because its the same thread
+                assertEquals(foo, MDC.get("foo"));
+            } else {
+                foo = MDC.get("foo");
+            }
+
+            if (threadId != null) {
+                long currId = Thread.currentThread().getId();
+                assertEquals(threadId, (Object) currId);
+            } else {
+                threadId = Thread.currentThread().getId();
+            }
+            if (exchangeId != null) {
+                assertNotEquals(exchangeId, MDC.get("camel.exchangeId"));
+            } else {
+                exchangeId = MDC.get("camel.exchangeId");
+                assertTrue(exchangeId != null && exchangeId.length() > 0);
+            }
+
+            if (messageId != null) {
+                assertNotEquals(messageId, MDC.get("camel.messageId"));
+            } else {
+                messageId = MDC.get("camel.messageId");
+                assertTrue(messageId != null && messageId.length() > 0);
+            }
+
+            if (breadcrumbId != null) {
+                assertEquals(breadcrumbId, MDC.get("camel.breadcrumbId"));
+            } else {
+                breadcrumbId = MDC.get("camel.breadcrumbId");
+                assertTrue(breadcrumbId != null && breadcrumbId.length() > 0);
+            }
+
+            if (contextId != null) {
+                assertEquals(contextId, MDC.get("camel.contextId"));
+            } else {
+                contextId = MDC.get("camel.contextId");
+                assertTrue(contextId != null && contextId.length() > 0);
+            }
+        }
+    }
+
+}