Skip to content

Commit f15d425

Browse files
Add integration tests for aws2-translate #2403
1 parent 4dbcf34 commit f15d425

10 files changed

Lines changed: 530 additions & 1 deletion

File tree

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.opentelemetry2;
18+
19+
import io.opentelemetry.api.baggage.Baggage;
20+
import io.opentelemetry.api.trace.SpanBuilder;
21+
import io.opentelemetry.api.trace.SpanKind;
22+
import io.opentelemetry.api.trace.Tracer;
23+
import io.opentelemetry.context.Context;
24+
import io.opentelemetry.context.propagation.ContextPropagators;
25+
import io.opentelemetry.context.propagation.TextMapGetter;
26+
import org.apache.camel.Endpoint;
27+
import org.apache.camel.Exchange;
28+
import org.apache.camel.telemetry.Op;
29+
import org.apache.camel.telemetry.SpanContextPropagationExtractor;
30+
import org.apache.camel.telemetry.SpanContextPropagationInjector;
31+
import org.apache.camel.telemetry.SpanLifecycleManager;
32+
import org.apache.camel.telemetry.decorators.PlatformHttpSpanDecorator;
33+
import org.apache.camel.telemetry.decorators.ServletSpanDecorator;
34+
35+
public class CamelQuarkusOpenTelemetry2Tracer extends OpenTelemetryTracer {
36+
37+
private final ThreadLocal<Op> currentOp = new ThreadLocal<>();
38+
private final ThreadLocal<Endpoint> currentEndpoint = new ThreadLocal<>();
39+
40+
private Tracer otelTracer;
41+
private ContextPropagators contextPropagators;
42+
private org.apache.camel.telemetry.SpanDecoratorManager spanDecoratorManager;
43+
44+
@Override
45+
public void setTracer(Tracer tracer) {
46+
super.setTracer(tracer);
47+
this.otelTracer = tracer;
48+
}
49+
50+
@Override
51+
public void setContextPropagators(ContextPropagators contextPropagators) {
52+
super.setContextPropagators(contextPropagators);
53+
this.contextPropagators = contextPropagators;
54+
}
55+
56+
@Override
57+
protected void beginEventSpan(Exchange exchange, Endpoint endpoint, Op op) throws Exception {
58+
currentOp.set(op);
59+
currentEndpoint.set(endpoint);
60+
try {
61+
super.beginEventSpan(exchange, endpoint, op);
62+
} finally {
63+
currentOp.remove();
64+
currentEndpoint.remove();
65+
}
66+
}
67+
68+
@Override
69+
protected void initTracer() {
70+
super.initTracer();
71+
setSpanLifecycleManager(new QuarkusSpanLifecycleManager());
72+
// Use reflection to get the private spanDecoratorManager from Tracer
73+
try {
74+
java.lang.reflect.Field field = org.apache.camel.telemetry.Tracer.class.getDeclaredField("spanDecoratorManager");
75+
field.setAccessible(true);
76+
this.spanDecoratorManager = (org.apache.camel.telemetry.SpanDecoratorManager) field.get(this);
77+
} catch (Exception e) {
78+
throw new RuntimeException("Failed to access spanDecoratorManager from Tracer", e);
79+
}
80+
}
81+
82+
private org.apache.camel.telemetry.SpanDecoratorManager getSpanDecoratorManager() {
83+
return spanDecoratorManager;
84+
}
85+
86+
private class QuarkusSpanLifecycleManager implements SpanLifecycleManager {
87+
88+
@Override
89+
public org.apache.camel.telemetry.Span create(String spanName, org.apache.camel.telemetry.Span parent,
90+
SpanContextPropagationExtractor extractor) {
91+
Endpoint endpoint = currentEndpoint.get();
92+
if (endpoint != null) {
93+
org.apache.camel.telemetry.SpanDecorator sd = CamelQuarkusOpenTelemetry2Tracer.this.getSpanDecoratorManager()
94+
.get(endpoint);
95+
if (sd instanceof PlatformHttpSpanDecorator || sd instanceof ServletSpanDecorator) {
96+
io.opentelemetry.api.trace.Span span = io.opentelemetry.api.trace.Span.fromContext(Context.current());
97+
Baggage baggage = Baggage.fromContext(Context.current());
98+
if (span != null && span.getSpanContext().isValid()) {
99+
return new OpenTelemetrySpanAdapter(span, baggage);
100+
}
101+
}
102+
}
103+
104+
SpanBuilder builder = otelTracer.spanBuilder(spanName);
105+
Baggage baggage = null;
106+
if (parent != null) {
107+
OpenTelemetrySpanAdapter otelParent = (OpenTelemetrySpanAdapter) parent;
108+
builder.setParent(Context.current().with(otelParent.getSpan()));
109+
baggage = otelParent.getBaggage();
110+
} else {
111+
Context extractedContext = contextPropagators.getTextMapPropagator().extract(Context.root(), extractor,
112+
new TextMapGetter<SpanContextPropagationExtractor>() {
113+
@Override
114+
public Iterable<String> keys(SpanContextPropagationExtractor carrier) {
115+
return carrier.keys();
116+
}
117+
118+
@Override
119+
public String get(SpanContextPropagationExtractor carrier, String key) {
120+
return (String) carrier.get(key);
121+
}
122+
});
123+
builder.setParent(extractedContext);
124+
baggage = Baggage.fromContext(extractedContext);
125+
}
126+
127+
Op op = currentOp.get();
128+
if (op != null) {
129+
builder.setSpanKind(mapOpToKind(op));
130+
}
131+
132+
return new OpenTelemetrySpanAdapter(builder.startSpan(), baggage);
133+
}
134+
135+
private SpanKind mapOpToKind(Op op) {
136+
if (op == null) {
137+
return SpanKind.INTERNAL;
138+
}
139+
switch (op) {
140+
case EVENT_SENT:
141+
return SpanKind.CLIENT;
142+
case EVENT_RECEIVED:
143+
return SpanKind.SERVER;
144+
default:
145+
return SpanKind.INTERNAL;
146+
}
147+
}
148+
149+
@Override
150+
public void activate(org.apache.camel.telemetry.Span span) {
151+
((OpenTelemetrySpanAdapter) span).makeCurrent();
152+
}
153+
154+
@Override
155+
public void deactivate(org.apache.camel.telemetry.Span span) {
156+
((OpenTelemetrySpanAdapter) span).end();
157+
}
158+
159+
@Override
160+
public void close(org.apache.camel.telemetry.Span span) {
161+
((OpenTelemetrySpanAdapter) span).close();
162+
}
163+
164+
@Override
165+
public void inject(org.apache.camel.telemetry.Span span, SpanContextPropagationInjector injector,
166+
boolean includeTracing) {
167+
OpenTelemetrySpanAdapter otelSpan = (OpenTelemetrySpanAdapter) span;
168+
Context ctx = Context.current().with(otelSpan.getSpan());
169+
if (otelSpan.getBaggage() != null) {
170+
ctx = ctx.with(otelSpan.getBaggage());
171+
}
172+
contextPropagators.getTextMapPropagator().inject(ctx, injector, (carrier, key, value) -> carrier.put(key, value));
173+
174+
if (includeTracing) {
175+
injector.put("CAMEL_TRACE_ID", otelSpan.getSpan().getSpanContext().getTraceId());
176+
injector.put("CAMEL_SPAN_ID", otelSpan.getSpan().getSpanContext().getSpanId());
177+
}
178+
}
179+
}
180+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Licensed to the Apache Software Foundation (ASF) under one or more
5+
contributor license agreements. See the NOTICE file distributed with
6+
this work for additional information regarding copyright ownership.
7+
The ASF licenses this file to You under the Apache License, Version 2.0
8+
(the "License"); you may not use this file except in compliance with
9+
the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
<parent>
23+
<groupId>org.apache.camel.quarkus</groupId>
24+
<artifactId>camel-quarkus-build-parent-it</artifactId>
25+
<version>3.32.0-SNAPSHOT</version>
26+
<relativePath>../../../poms/build-parent-it/pom.xml</relativePath>
27+
</parent>
28+
29+
<artifactId>camel-quarkus-integration-test-aws2-translate</artifactId>
30+
<name>Camel Quarkus :: Integration Tests :: AWS2 Translate</name>
31+
<description>The camel integration tests</description>
32+
33+
<dependencies>
34+
<dependency>
35+
<groupId>org.apache.camel.quarkus</groupId>
36+
<artifactId>camel-quarkus-aws2-translate</artifactId>
37+
</dependency>
38+
<dependency>
39+
<groupId>io.quarkus</groupId>
40+
<artifactId>quarkus-resteasy</artifactId>
41+
</dependency>
42+
<dependency>
43+
<groupId>io.quarkus</groupId>
44+
<artifactId>quarkus-resteasy-jackson</artifactId>
45+
</dependency>
46+
47+
<!-- test dependencies -->
48+
<dependency>
49+
<groupId>io.quarkus</groupId>
50+
<artifactId>quarkus-junit</artifactId>
51+
<scope>test</scope>
52+
</dependency>
53+
<dependency>
54+
<groupId>io.rest-assured</groupId>
55+
<artifactId>rest-assured</artifactId>
56+
<scope>test</scope>
57+
</dependency>
58+
<dependency>
59+
<groupId>org.apache.camel.quarkus</groupId>
60+
<artifactId>camel-quarkus-integration-tests-support-aws2</artifactId>
61+
</dependency>
62+
<dependency>
63+
<groupId>org.apache.camel.quarkus</groupId>
64+
<artifactId>camel-quarkus-integration-tests-support-aws2</artifactId>
65+
<type>test-jar</type>
66+
<scope>test</scope>
67+
</dependency>
68+
</dependencies>
69+
70+
<profiles>
71+
<profile>
72+
<id>native</id>
73+
<activation>
74+
<property>
75+
<name>native</name>
76+
</property>
77+
</activation>
78+
<properties>
79+
<quarkus.native.enabled>true</quarkus.native.enabled>
80+
</properties>
81+
<build>
82+
<plugins>
83+
<plugin>
84+
<groupId>org.apache.maven.plugins</groupId>
85+
<artifactId>maven-failsafe-plugin</artifactId>
86+
<executions>
87+
<execution>
88+
<goals>
89+
<goal>integration-test</goal>
90+
<goal>verify</goal>
91+
</goals>
92+
</execution>
93+
</executions>
94+
</plugin>
95+
</plugins>
96+
</build>
97+
</profile>
98+
<profile>
99+
<id>virtualDependencies</id>
100+
<activation>
101+
<property>
102+
<name>!noVirtualDependencies</name>
103+
</property>
104+
</activation>
105+
<dependencies>
106+
<!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory -->
107+
<dependency>
108+
<groupId>org.apache.camel.quarkus</groupId>
109+
<artifactId>camel-quarkus-aws2-translate-deployment</artifactId>
110+
<version>${project.version}</version>
111+
<type>pom</type>
112+
<scope>test</scope>
113+
<exclusions>
114+
<exclusion>
115+
<groupId>*</groupId>
116+
<artifactId>*</artifactId>
117+
</exclusion>
118+
</exclusions>
119+
</dependency>
120+
</dependencies>
121+
</profile>
122+
<profile>
123+
<id>skip-testcontainers-tests</id>
124+
<activation>
125+
<property>
126+
<name>skip-testcontainers-tests</name>
127+
</property>
128+
</activation>
129+
<properties>
130+
<skipTests>true</skipTests>
131+
</properties>
132+
</profile>
133+
</profiles>
134+
135+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.quarkus.component.aws2.translate.it;
18+
19+
import jakarta.enterprise.context.ApplicationScoped;
20+
import jakarta.inject.Inject;
21+
import jakarta.ws.rs.Consumes;
22+
import jakarta.ws.rs.POST;
23+
import jakarta.ws.rs.Path;
24+
import jakarta.ws.rs.Produces;
25+
import jakarta.ws.rs.QueryParam;
26+
import jakarta.ws.rs.core.MediaType;
27+
import org.apache.camel.ProducerTemplate;
28+
import org.apache.camel.component.aws2.translate.Translate2Constants;
29+
import org.apache.camel.quarkus.test.support.aws2.BaseAws2Resource;
30+
31+
@Path("/aws2-translate")
32+
@ApplicationScoped
33+
public class Aws2TranslateResource extends BaseAws2Resource {
34+
35+
@Inject
36+
ProducerTemplate producerTemplate;
37+
38+
public Aws2TranslateResource() {
39+
super("translate");
40+
}
41+
42+
@Path("/translate")
43+
@POST
44+
@Consumes(MediaType.TEXT_PLAIN)
45+
@Produces(MediaType.TEXT_PLAIN)
46+
public String translate(
47+
String text,
48+
@QueryParam("sourceLanguage") String sourceLanguage,
49+
@QueryParam("targetLanguage") String targetLanguage) throws Exception {
50+
return producerTemplate.requestBodyAndHeaders(
51+
"aws2-translate://test?operation=translateText",
52+
text,
53+
java.util.Map.of(
54+
Translate2Constants.SOURCE_LANGUAGE, sourceLanguage,
55+
Translate2Constants.TARGET_LANGUAGE, targetLanguage),
56+
String.class);
57+
}
58+
59+
@Path("/languages")
60+
@POST
61+
@Produces(MediaType.APPLICATION_JSON)
62+
public java.util.List<String> listLanguages() throws Exception {
63+
return producerTemplate.requestBody(
64+
"aws2-translate://test?operation=listLanguages",
65+
null,
66+
java.util.List.class);
67+
}
68+
}

0 commit comments

Comments
 (0)