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

oscerd 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 e65f83623299 CAMEL-23387: camel-telemetry - Add span decorators for 
AWS EC2, ECS and EKS (#23081)
e65f83623299 is described below

commit e65f836232999b4dd54fa0003c6943ba32e68a0a
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri May 8 11:24:22 2026 +0200

    CAMEL-23387: camel-telemetry - Add span decorators for AWS EC2, ECS and EKS 
(#23081)
    
    Fifth batch of AWS span decorators for camel-telemetry, covering the
    Compute group: EC2, ECS and EKS. All three are producer-only management
    APIs and extend AbstractSpanDecorator, registered alphabetically in
    META-INF/services. Tag selection follows two rules: never emit values
    that may contain secrets or large payloads (VPC config, placement
    objects, security-group/instance-ID/tag collections, free-form
    descriptions) and prefer the request target (clusterName, imageId,
    subnetId, instanceType) over response ARNs that are not visible in
    beforeTracingEvent. Header constants are mirrored from each
    component's *Constants interface to avoid hard module dependencies,
    matching the convention from #23038, #23040, #23045 and #23077. After
    review, dropped roleArn from EKS to avoid surfacing IAM principal
    ARNs to observability backends, in line with the same minimization
    applied to IAM userName / KMS keyId / CloudTrail username in earlier
    batches.
    
    The originally projected aws-xray decorator is intentionally not in
    scope: camel-aws-xray was the deprecated AWS X-Ray tracer integration
    (its own SegmentDecorator system parallel to OpenTracing) and was
    removed in commit ba9f8c5340a — there is no producer-style component
    to decorate.
    
    CAMEL-23387 stays open; only the AI/ML batch (Polly, Rekognition,
    Textract, Transcribe, Translate, Comprehend, S3 Vectors) remains for
    AWS coverage.
---
 .../telemetry/decorators/AwsEc2SpanDecorator.java  | 73 ++++++++++++++++++++++
 .../telemetry/decorators/AwsEcsSpanDecorator.java  | 59 +++++++++++++++++
 .../telemetry/decorators/AwsEksSpanDecorator.java  | 59 +++++++++++++++++
 .../org.apache.camel.telemetry.SpanDecorator       |  3 +
 .../decorators/AwsEc2SpanDecoratorTest.java        | 61 ++++++++++++++++++
 .../decorators/AwsEcsSpanDecoratorTest.java        | 55 ++++++++++++++++
 .../decorators/AwsEksSpanDecoratorTest.java        | 55 ++++++++++++++++
 7 files changed, 365 insertions(+)

diff --git 
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEc2SpanDecorator.java
 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEc2SpanDecorator.java
new file mode 100644
index 000000000000..18dc6d44d594
--- /dev/null
+++ 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEc2SpanDecorator.java
@@ -0,0 +1,73 @@
+/*
+ * 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.telemetry.decorators;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.telemetry.Span;
+
+public class AwsEc2SpanDecorator extends AbstractSpanDecorator {
+
+    static final String EC2_OPERATION = "operation";
+    static final String EC2_IMAGE_ID = "imageId";
+    static final String EC2_INSTANCE_TYPE = "instanceType";
+    static final String EC2_SUBNET_ID = "subnetId";
+
+    /**
+     * Constants copied from {@link 
org.apache.camel.component.aws2.ec2.AWS2EC2Constants}
+     */
+    static final String OPERATION = "CamelAwsEC2Operation";
+    static final String IMAGE_ID = "CamelAwsEC2ImageId";
+    static final String INSTANCE_TYPE = "CamelAwsEC2InstanceType";
+    static final String SUBNET_ID = "CamelAwsEC2SubnetId";
+
+    @Override
+    public String getComponent() {
+        return "aws2-ec2";
+    }
+
+    @Override
+    public String getComponentClassName() {
+        return "org.apache.camel.component.aws2.ec2.AWS2EC2Component";
+    }
+
+    @Override
+    public void beforeTracingEvent(Span span, Exchange exchange, Endpoint 
endpoint) {
+        super.beforeTracingEvent(span, exchange, endpoint);
+
+        String operation = exchange.getIn().getHeader(OPERATION, String.class);
+        if (operation != null) {
+            span.setTag(EC2_OPERATION, operation);
+        }
+
+        String imageId = exchange.getIn().getHeader(IMAGE_ID, String.class);
+        if (imageId != null) {
+            span.setTag(EC2_IMAGE_ID, imageId);
+        }
+
+        String instanceType = exchange.getIn().getHeader(INSTANCE_TYPE, 
String.class);
+        if (instanceType != null) {
+            span.setTag(EC2_INSTANCE_TYPE, instanceType);
+        }
+
+        String subnetId = exchange.getIn().getHeader(SUBNET_ID, String.class);
+        if (subnetId != null) {
+            span.setTag(EC2_SUBNET_ID, subnetId);
+        }
+    }
+
+}
diff --git 
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEcsSpanDecorator.java
 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEcsSpanDecorator.java
new file mode 100644
index 000000000000..5a425b4cc512
--- /dev/null
+++ 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEcsSpanDecorator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.telemetry.decorators;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.telemetry.Span;
+
+public class AwsEcsSpanDecorator extends AbstractSpanDecorator {
+
+    static final String ECS_OPERATION = "operation";
+    static final String ECS_CLUSTER_NAME = "clusterName";
+
+    /**
+     * Constants copied from {@link 
org.apache.camel.component.aws2.ecs.ECS2Constants}
+     */
+    static final String OPERATION = "CamelAwsECSOperation";
+    static final String CLUSTER_NAME = "CamelAwsECSClusterName";
+
+    @Override
+    public String getComponent() {
+        return "aws2-ecs";
+    }
+
+    @Override
+    public String getComponentClassName() {
+        return "org.apache.camel.component.aws2.ecs.ECS2Component";
+    }
+
+    @Override
+    public void beforeTracingEvent(Span span, Exchange exchange, Endpoint 
endpoint) {
+        super.beforeTracingEvent(span, exchange, endpoint);
+
+        String operation = exchange.getIn().getHeader(OPERATION, String.class);
+        if (operation != null) {
+            span.setTag(ECS_OPERATION, operation);
+        }
+
+        String clusterName = exchange.getIn().getHeader(CLUSTER_NAME, 
String.class);
+        if (clusterName != null) {
+            span.setTag(ECS_CLUSTER_NAME, clusterName);
+        }
+    }
+
+}
diff --git 
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEksSpanDecorator.java
 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEksSpanDecorator.java
new file mode 100644
index 000000000000..84ed3c860776
--- /dev/null
+++ 
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AwsEksSpanDecorator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.telemetry.decorators;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.telemetry.Span;
+
+public class AwsEksSpanDecorator extends AbstractSpanDecorator {
+
+    static final String EKS_OPERATION = "operation";
+    static final String EKS_CLUSTER_NAME = "clusterName";
+
+    /**
+     * Constants copied from {@link 
org.apache.camel.component.aws2.eks.EKS2Constants}
+     */
+    static final String OPERATION = "CamelAwsEKSOperation";
+    static final String CLUSTER_NAME = "CamelAwsEKSClusterName";
+
+    @Override
+    public String getComponent() {
+        return "aws2-eks";
+    }
+
+    @Override
+    public String getComponentClassName() {
+        return "org.apache.camel.component.aws2.eks.EKS2Component";
+    }
+
+    @Override
+    public void beforeTracingEvent(Span span, Exchange exchange, Endpoint 
endpoint) {
+        super.beforeTracingEvent(span, exchange, endpoint);
+
+        String operation = exchange.getIn().getHeader(OPERATION, String.class);
+        if (operation != null) {
+            span.setTag(EKS_OPERATION, operation);
+        }
+
+        String clusterName = exchange.getIn().getHeader(CLUSTER_NAME, 
String.class);
+        if (clusterName != null) {
+            span.setTag(EKS_CLUSTER_NAME, clusterName);
+        }
+    }
+
+}
diff --git 
a/components/camel-telemetry/src/main/resources/META-INF/services/org.apache.camel.telemetry.SpanDecorator
 
b/components/camel-telemetry/src/main/resources/META-INF/services/org.apache.camel.telemetry.SpanDecorator
index 3c8600fb70dd..9999dde8ac1d 100644
--- 
a/components/camel-telemetry/src/main/resources/META-INF/services/org.apache.camel.telemetry.SpanDecorator
+++ 
b/components/camel-telemetry/src/main/resources/META-INF/services/org.apache.camel.telemetry.SpanDecorator
@@ -26,6 +26,9 @@ org.apache.camel.telemetry.decorators.AwsConfigSpanDecorator
 org.apache.camel.telemetry.decorators.AwsCwSpanDecorator
 org.apache.camel.telemetry.decorators.AwsDdbSpanDecorator
 org.apache.camel.telemetry.decorators.AwsDdbStreamSpanDecorator
+org.apache.camel.telemetry.decorators.AwsEc2SpanDecorator
+org.apache.camel.telemetry.decorators.AwsEcsSpanDecorator
+org.apache.camel.telemetry.decorators.AwsEksSpanDecorator
 org.apache.camel.telemetry.decorators.AwsEventbridgeSpanDecorator
 org.apache.camel.telemetry.decorators.AwsIamSpanDecorator
 org.apache.camel.telemetry.decorators.AwsKinesisFirehoseSpanDecorator
diff --git 
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEc2SpanDecoratorTest.java
 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEc2SpanDecoratorTest.java
new file mode 100644
index 000000000000..10ca733be63c
--- /dev/null
+++ 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEc2SpanDecoratorTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.telemetry.decorators;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.telemetry.mock.MockSpanAdapter;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AwsEc2SpanDecoratorTest {
+
+    @Test
+    public void testPre() {
+        String operation = "createAndRunInstances";
+        String imageId = "ami-0abcdef1234567890";
+        String instanceType = "t2.micro";
+        String subnetId = "subnet-0abcd1234efgh5678";
+
+        Endpoint endpoint = Mockito.mock(Endpoint.class);
+        Exchange exchange = Mockito.mock(Exchange.class);
+        Message message = Mockito.mock(Message.class);
+
+        Mockito.when(endpoint.getEndpointUri()).thenReturn("aws2-ec2:default");
+        Mockito.when(exchange.getIn()).thenReturn(message);
+        Mockito.when(exchange.getExchangeId()).thenReturn("exchange-1");
+        Mockito.when(message.getHeader(AwsEc2SpanDecorator.OPERATION, 
String.class)).thenReturn(operation);
+        Mockito.when(message.getHeader(AwsEc2SpanDecorator.IMAGE_ID, 
String.class)).thenReturn(imageId);
+        Mockito.when(message.getHeader(AwsEc2SpanDecorator.INSTANCE_TYPE, 
String.class)).thenReturn(instanceType);
+        Mockito.when(message.getHeader(AwsEc2SpanDecorator.SUBNET_ID, 
String.class)).thenReturn(subnetId);
+
+        AbstractSpanDecorator decorator = new AwsEc2SpanDecorator();
+
+        MockSpanAdapter span = new MockSpanAdapter();
+
+        decorator.beforeTracingEvent(span, exchange, endpoint);
+
+        assertEquals(operation, 
span.tags().get(AwsEc2SpanDecorator.EC2_OPERATION));
+        assertEquals(imageId, 
span.tags().get(AwsEc2SpanDecorator.EC2_IMAGE_ID));
+        assertEquals(instanceType, 
span.tags().get(AwsEc2SpanDecorator.EC2_INSTANCE_TYPE));
+        assertEquals(subnetId, 
span.tags().get(AwsEc2SpanDecorator.EC2_SUBNET_ID));
+    }
+
+}
diff --git 
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEcsSpanDecoratorTest.java
 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEcsSpanDecoratorTest.java
new file mode 100644
index 000000000000..475d6a153d6c
--- /dev/null
+++ 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEcsSpanDecoratorTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.telemetry.decorators;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.telemetry.mock.MockSpanAdapter;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AwsEcsSpanDecoratorTest {
+
+    @Test
+    public void testPre() {
+        String operation = "createCluster";
+        String clusterName = "production";
+
+        Endpoint endpoint = Mockito.mock(Endpoint.class);
+        Exchange exchange = Mockito.mock(Exchange.class);
+        Message message = Mockito.mock(Message.class);
+
+        Mockito.when(endpoint.getEndpointUri()).thenReturn("aws2-ecs:default");
+        Mockito.when(exchange.getIn()).thenReturn(message);
+        Mockito.when(exchange.getExchangeId()).thenReturn("exchange-1");
+        Mockito.when(message.getHeader(AwsEcsSpanDecorator.OPERATION, 
String.class)).thenReturn(operation);
+        Mockito.when(message.getHeader(AwsEcsSpanDecorator.CLUSTER_NAME, 
String.class)).thenReturn(clusterName);
+
+        AbstractSpanDecorator decorator = new AwsEcsSpanDecorator();
+
+        MockSpanAdapter span = new MockSpanAdapter();
+
+        decorator.beforeTracingEvent(span, exchange, endpoint);
+
+        assertEquals(operation, 
span.tags().get(AwsEcsSpanDecorator.ECS_OPERATION));
+        assertEquals(clusterName, 
span.tags().get(AwsEcsSpanDecorator.ECS_CLUSTER_NAME));
+    }
+
+}
diff --git 
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEksSpanDecoratorTest.java
 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEksSpanDecoratorTest.java
new file mode 100644
index 000000000000..6114c5b7491b
--- /dev/null
+++ 
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AwsEksSpanDecoratorTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.telemetry.decorators;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.telemetry.mock.MockSpanAdapter;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class AwsEksSpanDecoratorTest {
+
+    @Test
+    public void testPre() {
+        String operation = "createCluster";
+        String clusterName = "prod-eks";
+
+        Endpoint endpoint = Mockito.mock(Endpoint.class);
+        Exchange exchange = Mockito.mock(Exchange.class);
+        Message message = Mockito.mock(Message.class);
+
+        Mockito.when(endpoint.getEndpointUri()).thenReturn("aws2-eks:default");
+        Mockito.when(exchange.getIn()).thenReturn(message);
+        Mockito.when(exchange.getExchangeId()).thenReturn("exchange-1");
+        Mockito.when(message.getHeader(AwsEksSpanDecorator.OPERATION, 
String.class)).thenReturn(operation);
+        Mockito.when(message.getHeader(AwsEksSpanDecorator.CLUSTER_NAME, 
String.class)).thenReturn(clusterName);
+
+        AbstractSpanDecorator decorator = new AwsEksSpanDecorator();
+
+        MockSpanAdapter span = new MockSpanAdapter();
+
+        decorator.beforeTracingEvent(span, exchange, endpoint);
+
+        assertEquals(operation, 
span.tags().get(AwsEksSpanDecorator.EKS_OPERATION));
+        assertEquals(clusterName, 
span.tags().get(AwsEksSpanDecorator.EKS_CLUSTER_NAME));
+    }
+
+}

Reply via email to