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

sumitagrawl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 210839df457 HDDS-14903. Fix Trace Hierarchy for Freon s3bg Command 
(#10020)
210839df457 is described below

commit 210839df45724e8ccc49e0ef531746174b108da6
Author: sravani <[email protected]>
AuthorDate: Thu May 14 20:03:30 2026 +0530

    HDDS-14903. Fix Trace Hierarchy for Freon s3bg Command (#10020)
---
 .../apache/hadoop/hdds/tracing/TracingUtil.java    | 44 +++++++++++++++++++
 ...OzoneManagerProtocolClientSideTranslatorPB.java |  2 +
 .../freon/FreonS3TraceContextRequestHandler.java   | 42 +++++++++++++++++++
 .../hadoop/ozone/freon/S3EntityGenerator.java      |  1 +
 .../org/apache/hadoop/ozone/s3/TracingFilter.java  | 49 ++++++++++++++++------
 5 files changed, 125 insertions(+), 13 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/tracing/TracingUtil.java
 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/tracing/TracingUtil.java
index 9b7f6347fef..b2263c4f5be 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/tracing/TracingUtil.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/tracing/TracingUtil.java
@@ -26,6 +26,7 @@
 import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
 import io.opentelemetry.context.Context;
 import io.opentelemetry.context.Scope;
+import io.opentelemetry.context.propagation.TextMapGetter;
 import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
 import io.opentelemetry.sdk.OpenTelemetrySdk;
 import io.opentelemetry.sdk.resources.Resource;
@@ -36,6 +37,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Function;
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.ratis.util.function.CheckedRunnable;
 import org.apache.ratis.util.function.CheckedSupplier;
@@ -387,4 +389,46 @@ private static Span buildSpan(String spanName) {
       return tracer.spanBuilder(spanName).setNoParent().startSpan();
     }
   }
+
+  /**
+   * A TextMapGetter implementation to extract tracing info from getHeader.
+   */
+  public static class HttpHeaderGetter implements 
TextMapGetter<Function<String, String>> {
+
+    @Override
+    public Iterable<String> keys(Function<String, String> carrier) {
+      // Not used during the extract call, so returning an empty list.
+      return Collections.emptyList();
+    }
+
+    @Override
+    public String get(Function<String, String> carrier, String key) {
+      return carrier == null ? null : carrier.apply(key);
+    }
+  }
+
+  public static TraceCloseable createActivatedSpanFromW3cHttpHeaders(
+      String spanName, Function<String, String> getHeader, ConfigurationSource 
conf) {
+    if (conf == null || !isTracingEnabled(conf)) {
+      return () -> { };
+    }
+
+    Context remote = W3CTraceContextPropagator.getInstance()
+        .extract(Context.current(), getHeader, new HttpHeaderGetter());
+
+    if (!Span.fromContext(remote).getSpanContext().isValid()) {
+      return createActivatedSpan(spanName);
+    }
+
+    Span span = tracer.spanBuilder(spanName)
+        .setParent(remote)
+        .startSpan();
+
+    Scope scope = span.makeCurrent();
+
+    return () -> {
+      scope.close();
+      span.end();
+    };
+  }
 }
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
index 604298b3c89..2131eaaf906 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java
@@ -2164,12 +2164,14 @@ public void 
cancelDelegationToken(Token<OzoneTokenIdentifier> token)
   }
 
   @Override
+  @SkipTracing
   public void setThreadLocalS3Auth(
       S3Auth s3Auth) {
     this.threadLocalS3Auth.set(s3Auth);
   }
 
   @Override
+  @SkipTracing
   public void clearThreadLocalS3Auth() {
     this.threadLocalS3Auth.remove();
   }
diff --git 
a/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/FreonS3TraceContextRequestHandler.java
 
b/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/FreonS3TraceContextRequestHandler.java
new file mode 100644
index 00000000000..a5f40c6412b
--- /dev/null
+++ 
b/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/FreonS3TraceContextRequestHandler.java
@@ -0,0 +1,42 @@
+/*
+ * 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.hadoop.ozone.freon;
+
+import com.amazonaws.Request;
+import com.amazonaws.handlers.RequestHandler2;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
+import io.opentelemetry.context.Context;
+
+/**
+ * Adds W3C trace context headers to each outgoing S3 request so the S3 Gateway
+ * can attach its spans to the Freon task span, using {@link 
W3CTraceContextPropagator}.
+ */
+public final class FreonS3TraceContextRequestHandler extends RequestHandler2 {
+
+  @Override
+  public void beforeRequest(Request<?> request) {
+    if (!Span.current().getSpanContext().isValid()) {
+      return;
+    }
+    W3CTraceContextPropagator.getInstance().inject(
+        Context.current(),
+        request,
+        (carrier, key, value) -> carrier.addHeader(key, value));
+  }
+}
diff --git 
a/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/S3EntityGenerator.java
 
b/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/S3EntityGenerator.java
index 6e2e728a81e..bc866048987 100644
--- 
a/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/S3EntityGenerator.java
+++ 
b/hadoop-ozone/freon/src/main/java/org/apache/hadoop/ozone/freon/S3EntityGenerator.java
@@ -51,6 +51,7 @@ protected void s3ClientInit() {
       amazonS3ClientBuilder.withRegion(Regions.DEFAULT_REGION);
     }
 
+    amazonS3ClientBuilder.withRequestHandlers(new 
FreonS3TraceContextRequestHandler());
     s3 = amazonS3ClientBuilder.build();
   }
 
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/TracingFilter.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/TracingFilter.java
index 4e95a4849e6..21bcf8aa7bd 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/TracingFilter.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/TracingFilter.java
@@ -38,6 +38,9 @@ public class TracingFilter implements ContainerRequestFilter,
     ContainerResponseFilter {
 
   public static final String TRACING_SPAN_CLOSABLE = "TRACING_SPAN_CLOSABLE";
+  private static final String HTTP_GET_METHOD = "GET";
+  private static final String OBJECT_ENDPOINT_CLASS_NAME = "ObjectEndpoint";
+  private static final String OBJECT_GET_METHOD_NAME = "get";
 
   @Context
   private ResourceInfo resourceInfo;
@@ -46,10 +49,14 @@ public class TracingFilter implements 
ContainerRequestFilter,
   public void filter(ContainerRequestContext requestContext) {
     finishAndCloseActiveSpan();
 
-    TracingUtil.TraceCloseable activatedSpan =
-        
TracingUtil.createActivatedSpan(resourceInfo.getResourceClass().getSimpleName() 
+ "." +
-            resourceInfo.getResourceMethod().getName());
-    requestContext.setProperty(TRACING_SPAN_CLOSABLE, activatedSpan);
+    String spanName = resourceInfo.getResourceClass().getSimpleName() + "." +
+        resourceInfo.getResourceMethod().getName();
+
+    TracingUtil.TraceCloseable traceCloseable =
+        TracingUtil.createActivatedSpanFromW3cHttpHeaders(
+            spanName, requestContext::getHeaderString,
+            OzoneConfigurationHolder.configuration());
+    requestContext.setProperty(TRACING_SPAN_CLOSABLE, traceCloseable);
   }
 
   @Override
@@ -57,23 +64,39 @@ public void filter(ContainerRequestContext requestContext,
       ContainerResponseContext responseContext) {
     final TracingUtil.TraceCloseable spanClosable
         = (TracingUtil.TraceCloseable) 
requestContext.getProperty(TRACING_SPAN_CLOSABLE);
+    if (spanClosable == null) {
+      return;
+    }
     // HDDS-7064: Operation performed while writing StreamingOutput response
     // should only be closed once the StreamingOutput callback has completely
     // written the data to the destination
-    OutputStream out = responseContext.getEntityStream();
-    if (out != null) {
-      responseContext.setEntityStream(new WrappedOutputStream(out) {
-        @Override
-        public void close() throws IOException {
-          super.close();
-          finishAndClose(spanClosable);
-        }
-      });
+    if (isStreamingGetObject(requestContext)) {
+      OutputStream out = responseContext.getEntityStream();
+      if (out != null) {
+        responseContext.setEntityStream(new WrappedOutputStream(out) {
+          @Override
+          public void close() throws IOException {
+            super.close();
+            finishAndClose(spanClosable);
+          }
+        });
+      } else {
+        finishAndClose(spanClosable);
+      }
     } else {
       finishAndClose(spanClosable);
     }
   }
 
+  private boolean isStreamingGetObject(ContainerRequestContext req) {
+    if (!HTTP_GET_METHOD.equalsIgnoreCase(req.getMethod())) {
+      return false;
+    }
+    String cls = resourceInfo.getResourceClass().getSimpleName();
+    String method = resourceInfo.getResourceMethod().getName();
+    return OBJECT_ENDPOINT_CLASS_NAME.equals(cls) && 
OBJECT_GET_METHOD_NAME.equals(method);
+  }
+
   private static void finishAndClose(TracingUtil.TraceCloseable spanClosable) {
     try {
       spanClosable.close();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to