/* * Copyright 2020, OpenTelemetry Authors * * Licensed 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. */ import com.ning.http.client.AsyncCompletionHandler import com.ning.http.client.AsyncHttpClient import com.ning.http.client.AsyncHttpClientConfig import com.ning.http.client.Response import io.opentelemetry.auto.test.base.HttpClientTest import spock.lang.AutoCleanup import spock.lang.Shared import java.util.concurrent.ExecutionException import java.util.concurrent.TimeUnit import static io.opentelemetry.auto.test.utils.PortUtils.UNUSABLE_PORT import static io.opentelemetry.auto.test.utils.TraceUtils.basicSpan import static io.opentelemetry.auto.test.utils.TraceUtils.runUnderTrace class Netty38ClientTest extends HttpClientTest { @Shared def clientConfig = new AsyncHttpClientConfig.Builder() .setRequestTimeoutInMs(TimeUnit.SECONDS.toMillis(10).toInteger()) .build() @Shared @AutoCleanup AsyncHttpClient asyncHttpClient = new AsyncHttpClient(clientConfig) @Override int doRequest(String method, URI uri, Map headers, Closure callback) { def methodName = "prepare" + method.toLowerCase().capitalize() def requestBuilder = asyncHttpClient."$methodName"(uri.toString()) headers.each { requestBuilder.setHeader(it.key, it.value) } def response = requestBuilder.execute(new AsyncCompletionHandler() { @Override Object onCompleted(Response response) throws Exception { callback?.call() return response } }).get() return response.statusCode } @Override boolean testRedirects() { false } @Override boolean testConnectionFailure() { false } @Override boolean testRemoteConnection() { return false } def "connection error (unopened port)"() { given: def uri = new URI("http://127.0.0.1:$UNUSABLE_PORT/") when: runUnderTrace("parent") { doRequest(method, uri) } then: def ex = thrown(Exception) def thrownException = ex instanceof ExecutionException ? ex.cause : ex and: assertTraces(1) { trace(0, 2) { basicSpan(it, 0, "parent", null, thrownException) span(1) { operationName "CONNECT" childOf span(0) errored true tags { Class errorClass = ConnectException try { errorClass = Class.forName('io.netty.channel.AbstractChannel$AnnotatedConnectException') } catch (ClassNotFoundException e) { // Older versions use 'java.net.ConnectException' and do not have 'io.netty.channel.AbstractChannel$AnnotatedConnectException' } "error.type" errorClass.name "error.stack" String // slightly different message on windows "error.msg" ~/Connection refused:( no further information:)? \/127.0.0.1:$UNUSABLE_PORT/ } } } } where: method = "GET" } }