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));
+ }
+
+}