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 2021/07/08 04:59:07 UTC

[camel] branch main updated: implement logging mdc support CAMEL-12879 (#5806)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 04916f4  implement logging mdc support CAMEL-12879 (#5806)
04916f4 is described below

commit 04916f4e601d1c1cdb9c22cff9ff40e0a1070ffe
Author: Jose Montoya <ja...@users.noreply.github.com>
AuthorDate: Wed Jul 7 23:58:26 2021 -0500

    implement logging mdc support CAMEL-12879 (#5806)
    
    * implement logging mdc support CAMEL-12879
    
    Adds traceId and spanId string methods to SpanAdapter
    Adds and removes MDC fields when activating, deactivating a span
    
    * add mdc section in tracing docs
---
 .../src/main/docs/opentelemetry.adoc               |  3 +
 .../opentelemetry/OpenTelemetrySpanAdapter.java    | 10 +++
 .../src/main/docs/opentracing.adoc                 |  5 ++
 .../camel/opentracing/OpenTracingSpanAdapter.java  | 10 +++
 .../camel/opentracing/OpenTracingTracer.java       |  4 +-
 .../apache/camel/opentracing/MDCSupportTest.java   | 72 ++++++++++++++++++++++
 .../apache/camel/tracing/ActiveSpanManager.java    | 20 ++++++
 .../java/org/apache/camel/tracing/SpanAdapter.java |  4 ++
 .../camel/tracing/ActiveSpanManagerTest.java       | 37 +++++++++++
 .../org/apache/camel/tracing/MockSpanAdapter.java  | 20 ++++++
 10 files changed, 182 insertions(+), 3 deletions(-)

diff --git a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc
index 0bc16ef..709d656 100644
--- a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc
+++ b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc
@@ -51,3 +51,6 @@ otelTracer.init(camelContext);
 --------------------------------------------------------------------------------------------------
 
 include::{page-component-version}@camel-spring-boot::page$opentelemetry-starter.adoc[]
+
+== MDC Logging
+When MDC Logging is enabled for the active Camel context the Trace ID and Span ID will be added and removed from the MDC for each route, the keys are `traceId` and `spanId`, respectively.
diff --git a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetrySpanAdapter.java b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetrySpanAdapter.java
index 2c0be0f..48b2946 100644
--- a/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetrySpanAdapter.java
+++ b/components/camel-opentelemetry/src/main/java/org/apache/camel/opentelemetry/OpenTelemetrySpanAdapter.java
@@ -98,6 +98,16 @@ public class OpenTelemetrySpanAdapter implements SpanAdapter {
         span.addEvent(getEventNameFromFields(fields), convertToAttributes(fields));
     }
 
+    @Override
+    public String traceId() {
+        return span.getSpanContext().getTraceId();
+    }
+
+    @Override
+    public String spanId() {
+        return span.getSpanContext().getSpanId();
+    }
+
     String getEventNameFromFields(Map<String, ?> fields) {
         Object eventValue = fields == null ? null : fields.get("event");
         if (eventValue != null) {
diff --git a/components/camel-opentracing/src/main/docs/opentracing.adoc b/components/camel-opentracing/src/main/docs/opentracing.adoc
index ad53667..b104334 100644
--- a/components/camel-opentracing/src/main/docs/opentracing.adoc
+++ b/components/camel-opentracing/src/main/docs/opentracing.adoc
@@ -135,3 +135,8 @@ Where the value of header "request-header" is "foo", the resulting trace from ex
 and the resulting message would contain:
 
 * Header "baggage-header" of value "foo"
+
+== MDC Logging
+When MDC Logging is enabled for the active Camel context the Trace ID and Span ID will be added and removed from the MDC for each route or processor (depending on the tracing strategy configured), the keys are `traceId` and `spanId`, respectively.
+
+If the `OpenTracingTracingStrategy` is enabled the span ID will be the one for the current processor that logs an entry, otherwise it will be the one for the current route.
diff --git a/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingSpanAdapter.java b/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingSpanAdapter.java
index 0e3d399..d7aeb0c 100644
--- a/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingSpanAdapter.java
+++ b/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingSpanAdapter.java
@@ -90,4 +90,14 @@ public class OpenTracingSpanAdapter implements SpanAdapter {
         this.span.log(fields);
     }
 
+    @Override
+    public String traceId() {
+        return this.span.context().toTraceId();
+    }
+
+    @Override
+    public String spanId() {
+        return this.span.context().toSpanId();
+    }
+
 }
diff --git a/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java b/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java
index 6311c39..b44e702 100644
--- a/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java
+++ b/components/camel-opentracing/src/main/java/org/apache/camel/opentracing/OpenTracingTracer.java
@@ -88,9 +88,7 @@ public class OpenTracingTracer extends org.apache.camel.tracing.Tracer {
 
         if (tracer != null) {
             try { // Take care NOT to import GlobalTracer as it is an optional dependency and may not be on the classpath.
-                if (!io.opentracing.util.GlobalTracer.isRegistered()) {
-                    io.opentracing.util.GlobalTracer.register(tracer);
-                }
+                io.opentracing.util.GlobalTracer.registerIfAbsent(tracer);
             } catch (NoClassDefFoundError globalTracerNotInClasspath) {
                 LOG.trace("GlobalTracer is not found on the classpath.");
             }
diff --git a/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/MDCSupportTest.java b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/MDCSupportTest.java
new file mode 100644
index 0000000..19fa1f9
--- /dev/null
+++ b/components/camel-opentracing/src/test/java/org/apache/camel/opentracing/MDCSupportTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.opentracing;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+import org.slf4j.MDC;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class MDCSupportTest extends CamelOpenTracingTestSupport {
+
+    private static SpanTestData[] testdata = {
+            new SpanTestData().setLabel("seda:a server").setUri("seda://a").setOperation("a")
+                    .setParentId(1),
+            new SpanTestData().setLabel("direct:start server").setUri("direct://start").setOperation("start")
+    };
+
+    public MDCSupportTest() {
+        super(testdata);
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext camelContext = super.createCamelContext();
+        camelContext.setUseMDCLogging(true);
+        return camelContext;
+    }
+
+    @Test
+    public void testRoute() throws Exception {
+        template.requestBody("direct:start", "Hello");
+
+        verify();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").to("seda:a").routeId("start");
+
+                from("seda:a").routeId("a")
+                        .process(new Processor() {
+                            public void process(Exchange exchange) throws Exception {
+                                assertNotNull(MDC.get("traceId"));
+                                assertNotNull(MDC.get("spanId"));
+                            }
+                        });
+            }
+        };
+    }
+}
diff --git a/components/camel-tracing/src/main/java/org/apache/camel/tracing/ActiveSpanManager.java b/components/camel-tracing/src/main/java/org/apache/camel/tracing/ActiveSpanManager.java
index d57fe24..5c86279 100644
--- a/components/camel-tracing/src/main/java/org/apache/camel/tracing/ActiveSpanManager.java
+++ b/components/camel-tracing/src/main/java/org/apache/camel/tracing/ActiveSpanManager.java
@@ -17,12 +17,15 @@
 package org.apache.camel.tracing;
 
 import org.apache.camel.Exchange;
+import org.slf4j.MDC;
 
 /**
  * Utility class for managing active spans as a stack associated with an exchange.
  */
 public final class ActiveSpanManager {
 
+    public static final String MDC_TRACE_ID = "traceId";
+    public static final String MDC_SPAN_ID = "spanId";
     private static final String ACTIVE_SPAN_PROPERTY = "OpenTracing.activeSpan";
 
     private ActiveSpanManager() {
@@ -52,6 +55,11 @@ public final class ActiveSpanManager {
     public static void activate(Exchange exchange, SpanAdapter span) {
         exchange.setProperty(ACTIVE_SPAN_PROPERTY,
                 new Holder((Holder) exchange.getProperty(ACTIVE_SPAN_PROPERTY), span));
+
+        if (exchange.getContext().isUseMDCLogging()) {
+            MDC.put(MDC_TRACE_ID, "" + span.traceId());
+            MDC.put(MDC_SPAN_ID, "" + span.spanId());
+        }
     }
 
     /**
@@ -65,6 +73,18 @@ public final class ActiveSpanManager {
         Holder holder = (Holder) exchange.getProperty(ACTIVE_SPAN_PROPERTY);
         if (holder != null) {
             exchange.setProperty(ACTIVE_SPAN_PROPERTY, holder.getParent());
+
+            if (exchange.getContext().isUseMDCLogging()) {
+                Holder parent = holder.getParent();
+                if (parent != null) {
+                    SpanAdapter span = holder.getParent().getSpan();
+                    MDC.put(MDC_TRACE_ID, "" + span.traceId());
+                    MDC.put(MDC_SPAN_ID, "" + span.spanId());
+                } else {
+                    MDC.remove(MDC_TRACE_ID);
+                    MDC.remove(MDC_SPAN_ID);
+                }
+            }
         }
     }
 
diff --git a/components/camel-tracing/src/main/java/org/apache/camel/tracing/SpanAdapter.java b/components/camel-tracing/src/main/java/org/apache/camel/tracing/SpanAdapter.java
index 8c8fd52..ce52c38 100644
--- a/components/camel-tracing/src/main/java/org/apache/camel/tracing/SpanAdapter.java
+++ b/components/camel-tracing/src/main/java/org/apache/camel/tracing/SpanAdapter.java
@@ -34,4 +34,8 @@ public interface SpanAdapter {
     void setTag(String key, Boolean value);
 
     void log(Map<String, String> log);
+
+    String traceId();
+
+    String spanId();
 }
diff --git a/components/camel-tracing/src/test/java/org/apache/camel/tracing/ActiveSpanManagerTest.java b/components/camel-tracing/src/test/java/org/apache/camel/tracing/ActiveSpanManagerTest.java
index df1b654..3da5f11 100644
--- a/components/camel-tracing/src/test/java/org/apache/camel/tracing/ActiveSpanManagerTest.java
+++ b/components/camel-tracing/src/test/java/org/apache/camel/tracing/ActiveSpanManagerTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.tracing;
 import org.apache.camel.Exchange;
 import org.apache.camel.test.junit5.ExchangeTestSupport;
 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.assertNull;
@@ -81,4 +82,40 @@ public class ActiveSpanManagerTest extends ExchangeTestSupport {
         // and hasn't been affected by path1 creating its own child
         ActiveSpanManager.activate(path2, parent);
     }
+
+    @Test
+    public void testMDCSupport() {
+        Exchange exchange = createExchange();
+        exchange.getContext().setUseMDCLogging(true);
+
+        SpanAdapter parent = MockSpanAdapter.buildSpan("parent");
+        ((MockSpanAdapter) parent).setTraceId("0");
+        ((MockSpanAdapter) parent).setSpanId("1");
+
+        // no MDC entries before
+        // 0 and 1 after activating parent
+        assertNull(MDC.get(ActiveSpanManager.MDC_TRACE_ID));
+        assertNull(MDC.get(ActiveSpanManager.MDC_SPAN_ID));
+        ActiveSpanManager.activate(exchange, parent);
+        assertEquals("0", MDC.get(ActiveSpanManager.MDC_TRACE_ID));
+        assertEquals("1", MDC.get(ActiveSpanManager.MDC_SPAN_ID));
+
+        // 1 and 2 after activating child1
+        SpanAdapter child1 = MockSpanAdapter.buildSpan("child1");
+        ((MockSpanAdapter) child1).setTraceId("1");
+        ((MockSpanAdapter) child1).setSpanId("2");
+        ActiveSpanManager.activate(exchange, child1);
+        assertEquals("1", MDC.get(ActiveSpanManager.MDC_TRACE_ID));
+        assertEquals("2", MDC.get(ActiveSpanManager.MDC_SPAN_ID));
+
+        // back to 0 and 1 after deactivating child1
+        ActiveSpanManager.deactivate(exchange);
+        assertEquals("0", MDC.get(ActiveSpanManager.MDC_TRACE_ID));
+        assertEquals("1", MDC.get(ActiveSpanManager.MDC_SPAN_ID));
+
+        // back to no MDC entries after deactivating parent
+        ActiveSpanManager.deactivate(exchange);
+        assertNull(MDC.get(ActiveSpanManager.MDC_TRACE_ID));
+        assertNull(MDC.get(ActiveSpanManager.MDC_SPAN_ID));
+    }
 }
diff --git a/components/camel-tracing/src/test/java/org/apache/camel/tracing/MockSpanAdapter.java b/components/camel-tracing/src/test/java/org/apache/camel/tracing/MockSpanAdapter.java
index 547fcac..61cff5c 100644
--- a/components/camel-tracing/src/test/java/org/apache/camel/tracing/MockSpanAdapter.java
+++ b/components/camel-tracing/src/test/java/org/apache/camel/tracing/MockSpanAdapter.java
@@ -25,6 +25,8 @@ public class MockSpanAdapter implements SpanAdapter {
 
     private List<LogEntry> logEntries = new ArrayList<>();
     private HashMap<String, Object> tags = new HashMap<>();
+    private String traceId;
+    private String spanId;
 
     static long nowMicros() {
         return System.currentTimeMillis() * 1000;
@@ -73,11 +75,29 @@ public class MockSpanAdapter implements SpanAdapter {
         this.tags.put(key, value);
     }
 
+    public void setTraceId(String traceId) {
+        this.traceId = traceId;
+    }
+
+    public void setSpanId(String spanId) {
+        this.spanId = spanId;
+    }
+
     @Override
     public void log(Map<String, String> fields) {
         this.logEntries.add(new LogEntry(nowMicros(), fields));
     }
 
+    @Override
+    public String traceId() {
+        return this.traceId;
+    }
+
+    @Override
+    public String spanId() {
+        return this.spanId;
+    }
+
     public List<LogEntry> logEntries() {
         return new ArrayList<>(this.logEntries);
     }