388 lines
14 KiB
Groovy
388 lines
14 KiB
Groovy
/*
|
|
* Copyright The OpenTelemetry Authors
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package io.opentelemetry.smoketest
|
|
|
|
import io.opentelemetry.proto.trace.v1.Span
|
|
import spock.lang.Shared
|
|
import spock.lang.Unroll
|
|
|
|
import java.util.jar.Attributes
|
|
import java.util.jar.JarFile
|
|
|
|
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.OS_TYPE
|
|
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.OsTypeValues.LINUX
|
|
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.OsTypeValues.WINDOWS
|
|
import static org.junit.Assume.assumeFalse
|
|
import static org.junit.Assume.assumeTrue
|
|
|
|
abstract class AppServerTest extends SmokeTest {
|
|
@Shared
|
|
String jdk
|
|
@Shared
|
|
String serverVersion
|
|
@Shared
|
|
boolean isWindows
|
|
|
|
def setupSpec() {
|
|
(serverVersion, jdk) = getAppServer()
|
|
isWindows = System.getProperty("os.name").toLowerCase().contains("windows") &&
|
|
"1" != System.getenv("USE_LINUX_CONTAINERS")
|
|
|
|
// ibm-semeru-runtimes doesn't publish windows images
|
|
// adoptopenjdk is deprecated and doesn't publish Windows 2022 images
|
|
assumeFalse(isWindows && jdk.endsWith("-openj9"))
|
|
|
|
startTarget(jdk, serverVersion, isWindows)
|
|
}
|
|
|
|
protected Tuple<String> getAppServer() {
|
|
def appServer = getClass().getAnnotation(AppServer)
|
|
if (appServer == null) {
|
|
throw new IllegalStateException("Server not specified, either add @AppServer annotation or override getAppServer method")
|
|
}
|
|
return new Tuple(appServer.version(), appServer.jdk())
|
|
}
|
|
|
|
@Override
|
|
protected String getTargetImage(String jdk) {
|
|
throw new UnsupportedOperationException("App servers tests should use getTargetImagePrefix")
|
|
}
|
|
|
|
@Override
|
|
protected String getTargetImage(String jdk, String serverVersion, boolean windows) {
|
|
String platformSuffix = windows ? "-windows" : ""
|
|
String extraTag = "20221127.3559314888"
|
|
String fullSuffix = "${serverVersion}-jdk$jdk$platformSuffix-$extraTag"
|
|
return getTargetImagePrefix() + ":" + fullSuffix
|
|
}
|
|
|
|
protected abstract String getTargetImagePrefix()
|
|
|
|
def cleanupSpec() {
|
|
stopTarget()
|
|
}
|
|
|
|
boolean testSmoke() {
|
|
true
|
|
}
|
|
|
|
boolean testAsyncSmoke() {
|
|
true
|
|
}
|
|
|
|
boolean testException() {
|
|
true
|
|
}
|
|
|
|
boolean testRequestWebInfWebXml() {
|
|
true
|
|
}
|
|
|
|
boolean testRequestOutsideDeployedApp() {
|
|
true
|
|
}
|
|
|
|
//TODO add assert that server spans were created by servers, not by servlets
|
|
@Unroll
|
|
def "#appServer smoke test on JDK #jdk"(String appServer, String jdk, boolean isWindows) {
|
|
assumeTrue(testSmoke())
|
|
|
|
def currentAgentVersion = new JarFile(agentPath).getManifest().getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION)
|
|
|
|
when:
|
|
def response = client().get("/app/greeting").aggregate().join()
|
|
TraceInspector traces = new TraceInspector(waitForTraces())
|
|
Set<String> traceIds = traces.traceIds
|
|
String responseBody = response.contentUtf8()
|
|
|
|
then: "There is one trace"
|
|
traceIds.size() == 1
|
|
|
|
and: "trace id is present in the HTTP headers as reported by the called endpoint"
|
|
responseBody.contains(traceIds.find())
|
|
|
|
and: "Server spans in the distributed trace"
|
|
traces.countSpansByKind(Span.SpanKind.SPAN_KIND_SERVER) == 2
|
|
|
|
and: "Expected span names"
|
|
traces.countSpansByName(getSpanName('/app/greeting')) == 1
|
|
traces.countSpansByName(getSpanName('/app/headers')) == 1
|
|
|
|
and: "The span for the initial web request"
|
|
traces.countFilteredAttributes("http.target", "/app/greeting") == 1
|
|
|
|
and: "Client span for the remote call"
|
|
traces.countFilteredAttributes("http.url", "http://localhost:8080/app/headers") == 1
|
|
|
|
and: "Server span for the remote call"
|
|
traces.countFilteredAttributes("http.target", "/app/headers") == 1
|
|
|
|
and: "Number of spans with http protocol version"
|
|
traces.countFilteredAttributes("http.flavor", "1.1") == 3
|
|
|
|
and: "Number of spans tagged with current otel library version"
|
|
traces.countFilteredResourceAttributes("telemetry.auto.version", currentAgentVersion) == 3
|
|
|
|
and: "Number of spans tagged with expected OS type"
|
|
traces.countFilteredResourceAttributes(OS_TYPE.key, isWindows ? WINDOWS : LINUX) == 3
|
|
|
|
where:
|
|
[appServer, jdk, isWindows] << getTestParams()
|
|
}
|
|
|
|
@Unroll
|
|
def "#appServer test static file found on JDK #jdk"(String appServer, String jdk, boolean isWindows) {
|
|
def currentAgentVersion = new JarFile(agentPath).getManifest().getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION)
|
|
|
|
when:
|
|
def response = client().get("/app/hello.txt").aggregate().join()
|
|
TraceInspector traces = new TraceInspector(waitForTraces())
|
|
Set<String> traceIds = traces.traceIds
|
|
String responseBody = response.contentUtf8()
|
|
|
|
then: "There is one trace"
|
|
traceIds.size() == 1
|
|
|
|
and: "Response contains Hello"
|
|
responseBody.contains("Hello")
|
|
|
|
and: "There is one server span"
|
|
traces.countSpansByKind(Span.SpanKind.SPAN_KIND_SERVER) == 1
|
|
|
|
and: "Expected span names"
|
|
traces.countSpansByName(getSpanName('/app/hello.txt')) == 1
|
|
|
|
and: "The span for the initial web request"
|
|
traces.countFilteredAttributes("http.target", "/app/hello.txt") == 1
|
|
|
|
and: "Number of spans tagged with current otel library version"
|
|
traces.countFilteredResourceAttributes("telemetry.auto.version", currentAgentVersion) == 1
|
|
|
|
and: "Number of spans tagged with expected OS type"
|
|
traces.countFilteredResourceAttributes(OS_TYPE.key, isWindows ? WINDOWS : LINUX) == 1
|
|
|
|
where:
|
|
[appServer, jdk, isWindows] << getTestParams()
|
|
}
|
|
|
|
@Unroll
|
|
def "#appServer test static file not found on JDK #jdk"(String appServer, String jdk, boolean isWindows) {
|
|
def currentAgentVersion = new JarFile(agentPath).getManifest().getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION)
|
|
|
|
when:
|
|
def response = client().get("/app/file-that-does-not-exist").aggregate().join()
|
|
TraceInspector traces = new TraceInspector(waitForTraces())
|
|
Set<String> traceIds = traces.traceIds
|
|
|
|
then: "There is one trace"
|
|
traceIds.size() == 1
|
|
|
|
and: "Response code is 404"
|
|
response.status().code() == 404
|
|
|
|
and: "There is one server span"
|
|
traces.countSpansByKind(Span.SpanKind.SPAN_KIND_SERVER) == 1
|
|
|
|
and: "Expected span names"
|
|
traces.countSpansByName(getSpanName('/app/file-that-does-not-exist')) == 1
|
|
|
|
and: "The span for the initial web request"
|
|
traces.countFilteredAttributes("http.target", "/app/file-that-does-not-exist") == 1
|
|
|
|
and: "Number of spans tagged with current otel library version"
|
|
traces.countFilteredResourceAttributes("telemetry.auto.version", currentAgentVersion) == traces.countSpans()
|
|
|
|
and: "Number of spans tagged with expected OS type"
|
|
traces.countFilteredResourceAttributes(OS_TYPE.key, isWindows ? WINDOWS : LINUX) == traces.countSpans()
|
|
|
|
where:
|
|
[appServer, jdk, isWindows] << getTestParams()
|
|
}
|
|
|
|
@Unroll
|
|
def "#appServer test request for WEB-INF/web.xml on JDK #jdk"(String appServer, String jdk, boolean isWindows) {
|
|
assumeTrue(testRequestWebInfWebXml())
|
|
|
|
def currentAgentVersion = new JarFile(agentPath).getManifest().getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION)
|
|
|
|
when:
|
|
def response = client().get("/app/WEB-INF/web.xml").aggregate().join()
|
|
TraceInspector traces = new TraceInspector(waitForTraces())
|
|
Set<String> traceIds = traces.traceIds
|
|
|
|
then: "There is one trace"
|
|
traceIds.size() == 1
|
|
|
|
and: "Response code is 404"
|
|
response.status().code() == 404
|
|
|
|
and: "There is one server span"
|
|
traces.countSpansByKind(Span.SpanKind.SPAN_KIND_SERVER) == 1
|
|
|
|
and: "Expected span names"
|
|
traces.countSpansByName(getSpanName('/app/WEB-INF/web.xml')) == 1
|
|
|
|
and: "The span for the initial web request"
|
|
traces.countFilteredAttributes("http.target", "/app/WEB-INF/web.xml") == 1
|
|
|
|
and: "Number of spans with http protocol version"
|
|
traces.countFilteredAttributes("http.flavor", "1.1") == 1
|
|
|
|
and: "Number of spans tagged with current otel library version"
|
|
traces.countFilteredResourceAttributes("telemetry.auto.version", currentAgentVersion) == traces.countSpans()
|
|
|
|
and: "Number of spans tagged with expected OS type"
|
|
traces.countFilteredResourceAttributes(OS_TYPE.key, isWindows ? WINDOWS : LINUX) == traces.countSpans()
|
|
|
|
where:
|
|
[appServer, jdk, isWindows] << getTestParams()
|
|
}
|
|
|
|
@Unroll
|
|
def "#appServer test request with error JDK #jdk"(String appServer, String jdk, boolean isWindows) {
|
|
assumeTrue(testException())
|
|
|
|
def currentAgentVersion = new JarFile(agentPath).getManifest().getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION)
|
|
|
|
when:
|
|
def response = client().get("/app/exception").aggregate().join()
|
|
TraceInspector traces = new TraceInspector(waitForTraces())
|
|
Set<String> traceIds = traces.traceIds
|
|
|
|
then: "There is one trace"
|
|
traceIds.size() == 1
|
|
|
|
and: "Response code is 500"
|
|
response.status().code() == 500
|
|
|
|
and: "There is one server span"
|
|
traces.countSpansByKind(Span.SpanKind.SPAN_KIND_SERVER) == 1
|
|
|
|
and: "Expected span names"
|
|
traces.countSpansByName(getSpanName('/app/exception')) == 1
|
|
|
|
and: "There is one exception"
|
|
traces.countFilteredEventAttributes('exception.message', 'This is expected') == 1
|
|
|
|
and: "The span for the initial web request"
|
|
traces.countFilteredAttributes("http.target", "/app/exception") == 1
|
|
|
|
and: "Number of spans tagged with current otel library version"
|
|
traces.countFilteredResourceAttributes("telemetry.auto.version", currentAgentVersion) == traces.countSpans()
|
|
|
|
and: "Number of spans tagged with expected OS type"
|
|
traces.countFilteredResourceAttributes(OS_TYPE.key, isWindows ? WINDOWS : LINUX) == traces.countSpans()
|
|
|
|
where:
|
|
[appServer, jdk, isWindows] << getTestParams()
|
|
}
|
|
|
|
@Unroll
|
|
def "#appServer test request outside deployed application JDK #jdk"(String appServer, String jdk, boolean isWindows) {
|
|
assumeTrue(testRequestOutsideDeployedApp())
|
|
def currentAgentVersion = new JarFile(agentPath).getManifest().getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION)
|
|
|
|
when:
|
|
def response = client().get("/this-is-definitely-not-there-but-there-should-be-a-trace-nevertheless").aggregate().join()
|
|
TraceInspector traces = new TraceInspector(waitForTraces())
|
|
Set<String> traceIds = traces.traceIds
|
|
|
|
then: "There is one trace"
|
|
traceIds.size() == 1
|
|
|
|
and: "Response code is 404"
|
|
response.status().code() == 404
|
|
|
|
and: "There is one server span"
|
|
traces.countSpansByKind(Span.SpanKind.SPAN_KIND_SERVER) == 1
|
|
|
|
and: "Expected span names"
|
|
traces.countSpansByName(getSpanName('/this-is-definitely-not-there-but-there-should-be-a-trace-nevertheless')) == 1
|
|
|
|
and: "The span for the initial web request"
|
|
traces.countFilteredAttributes("http.target", "/this-is-definitely-not-there-but-there-should-be-a-trace-nevertheless") == 1
|
|
|
|
and: "Number of spans with http protocol version"
|
|
traces.countFilteredAttributes("http.flavor", "1.1") == 1
|
|
|
|
and: "Number of spans tagged with current otel library version"
|
|
traces.countFilteredResourceAttributes("telemetry.auto.version", currentAgentVersion) == traces.countSpans()
|
|
|
|
and: "Number of spans tagged with expected OS type"
|
|
traces.countFilteredResourceAttributes(OS_TYPE.key, isWindows ? WINDOWS : LINUX) == traces.countSpans()
|
|
|
|
where:
|
|
[appServer, jdk, isWindows] << getTestParams()
|
|
}
|
|
|
|
@Unroll
|
|
def "#appServer async smoke test on JDK #jdk"(String appServer, String jdk, boolean isWindows) {
|
|
assumeTrue(testAsyncSmoke())
|
|
|
|
def currentAgentVersion = new JarFile(agentPath).getManifest().getMainAttributes().get(Attributes.Name.IMPLEMENTATION_VERSION)
|
|
|
|
when:
|
|
def response = client().get("/app/asyncgreeting").aggregate().join()
|
|
TraceInspector traces = new TraceInspector(waitForTraces())
|
|
Set<String> traceIds = traces.traceIds
|
|
String responseBody = response.contentUtf8()
|
|
|
|
then: "There is one trace"
|
|
traceIds.size() == 1
|
|
|
|
and: "trace id is present in the HTTP headers as reported by the called endpoint"
|
|
responseBody.contains(traceIds.find())
|
|
|
|
and: "Server spans in the distributed trace"
|
|
traces.countSpansByKind(Span.SpanKind.SPAN_KIND_SERVER) == 2
|
|
|
|
and: "Expected span names"
|
|
traces.countSpansByName(getSpanName('/app/asyncgreeting')) == 1
|
|
traces.countSpansByName(getSpanName('/app/headers')) == 1
|
|
|
|
and: "The span for the initial web request"
|
|
traces.countFilteredAttributes("http.target", "/app/asyncgreeting") == 1
|
|
|
|
and: "Client span for the remote call"
|
|
traces.countFilteredAttributes("http.url", "http://localhost:8080/app/headers") == 1
|
|
|
|
and: "Server span for the remote call"
|
|
traces.countFilteredAttributes("http.target", "/app/headers") == 1
|
|
|
|
and: "Number of spans with http protocol version"
|
|
traces.countFilteredAttributes("http.flavor", "1.1") == 3
|
|
|
|
and: "Number of spans tagged with current otel library version"
|
|
traces.countFilteredResourceAttributes("telemetry.auto.version", currentAgentVersion) == 3
|
|
|
|
and: "Number of spans tagged with expected OS type"
|
|
traces.countFilteredResourceAttributes(OS_TYPE.key, isWindows ? WINDOWS : LINUX) == 3
|
|
|
|
where:
|
|
[appServer, jdk, isWindows] << getTestParams()
|
|
}
|
|
|
|
protected String getSpanName(String path) {
|
|
switch (path) {
|
|
case "/app/greeting":
|
|
case "/app/headers":
|
|
case "/app/exception":
|
|
case "/app/asyncgreeting":
|
|
return path
|
|
case "/app/hello.txt":
|
|
case "/app/file-that-does-not-exist":
|
|
return "/app/*"
|
|
}
|
|
return "HTTP GET"
|
|
}
|
|
|
|
protected List<List<Object>> getTestParams() {
|
|
return [
|
|
[serverVersion, jdk, isWindows]
|
|
]
|
|
}
|
|
}
|