Skip to content

Commit 0d23bba

Browse files
authored
Add test for TracingFilter (#2847)
1 parent 076438e commit 0d23bba

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

runtime/service/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ dependencies {
133133
testImplementation("io.quarkus:quarkus-rest-client-jackson")
134134
testImplementation("io.quarkus:quarkus-jdbc-h2")
135135

136+
testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
137+
136138
testImplementation("io.rest-assured:rest-assured")
137139

138140
testImplementation(platform(libs.testcontainers.bom))
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.polaris.service.tracing;
21+
22+
import static io.opentelemetry.api.common.AttributeKey.stringKey;
23+
import static io.restassured.RestAssured.given;
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
import static org.awaitility.Awaitility.await;
26+
27+
import io.opentelemetry.api.common.AttributeKey;
28+
import io.opentelemetry.api.trace.SpanContext;
29+
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
30+
import io.opentelemetry.sdk.trace.data.SpanData;
31+
import io.quarkus.test.common.http.TestHTTPEndpoint;
32+
import io.quarkus.test.junit.QuarkusTest;
33+
import io.quarkus.test.junit.QuarkusTestProfile;
34+
import io.quarkus.test.junit.TestProfile;
35+
import io.restassured.http.ContentType;
36+
import jakarta.enterprise.inject.Produces;
37+
import jakarta.inject.Inject;
38+
import jakarta.inject.Singleton;
39+
import java.time.Duration;
40+
import java.util.List;
41+
import java.util.Map;
42+
import org.apache.polaris.service.catalog.api.IcebergRestOAuth2Api;
43+
import org.junit.jupiter.api.Test;
44+
45+
@QuarkusTest
46+
@TestProfile(TracingFilterTest.Profile.class)
47+
@TestHTTPEndpoint(IcebergRestOAuth2Api.class)
48+
public class TracingFilterTest {
49+
50+
public static class Profile implements QuarkusTestProfile {
51+
52+
@Produces
53+
@Singleton
54+
InMemorySpanExporter inMemorySpanExporter() {
55+
return InMemorySpanExporter.create();
56+
}
57+
58+
@Override
59+
public Map<String, String> getConfigOverrides() {
60+
return Map.of("quarkus.otel.sdk.disabled", "false");
61+
}
62+
}
63+
64+
@Inject InMemorySpanExporter inMemorySpanExporter;
65+
66+
@Test
67+
void testW3CTraceContextPropagation() {
68+
69+
// Emulate an incoming request with a W3C trace context
70+
// Example taken from:
71+
// https://www.w3.org/TR/trace-context/#traceparent-header-field-values
72+
String traceId = "4bf92f3577b34da6a3ce929d0e0e4736";
73+
String spanId = "00f067aa0ba902b7";
74+
String traceparent = "00-" + traceId + "-" + spanId + "-01";
75+
String rojoState = spanId;
76+
String congoState = "t61rcWkgMzE";
77+
String tracestate = "rojo=" + rojoState + ",congo=" + congoState;
78+
79+
given()
80+
.contentType(ContentType.URLENC)
81+
.formParam("grant_type", "client_credentials")
82+
.formParam("scope", "PRINCIPAL_ROLE:ALL")
83+
.formParam("client_id", "test-admin")
84+
.formParam("client_secret", "test-secret")
85+
// W3C headers
86+
.header("traceparent", traceparent)
87+
.header("tracestate", tracestate)
88+
// Polaris request ID
89+
.header("X-Request-ID", "12345")
90+
.when()
91+
.post()
92+
.then()
93+
.statusCode(200)
94+
.header("X-Request-ID", "12345");
95+
96+
List<SpanData> spans =
97+
await()
98+
.atMost(Duration.ofSeconds(30))
99+
.until(inMemorySpanExporter::getFinishedSpanItems, sp -> !sp.isEmpty());
100+
101+
SpanData span = spans.getFirst();
102+
103+
Map<AttributeKey<?>, Object> attributes = span.getAttributes().asMap();
104+
assertThat(attributes)
105+
.containsEntry(stringKey(TracingFilter.REALM_ID_ATTRIBUTE), "POLARIS")
106+
.containsEntry(stringKey(TracingFilter.REQUEST_ID_ATTRIBUTE), "12345");
107+
108+
SpanContext parent = span.getParentSpanContext();
109+
assertThat(parent.getTraceId()).isEqualTo(traceId);
110+
assertThat(parent.getSpanId()).isEqualTo(spanId);
111+
assertThat(parent.isRemote()).isTrue();
112+
assertThat(parent.getTraceFlags().asByte()).isEqualTo((byte) 1);
113+
assertThat(parent.getTraceState().asMap())
114+
.containsEntry("rojo", rojoState)
115+
.containsEntry("congo", congoState);
116+
}
117+
}

0 commit comments

Comments
 (0)