Stop publishing opentelemetry-sdk-extension-aws artifact (#4830)
This commit is contained in:
parent
ebb97dad81
commit
cc22880bb8
|
|
@ -271,7 +271,6 @@ dependency as follows, replacing `{{artifact-id}}` with the value from the "Arti
|
|||
| [SDK Autoconfigure Extension](./sdk-extensions/autoconfigure) | Autoconfigure OpenTelemetry SDK from env vars, system properties, and SPI | `opentelemetry-sdk-extension-autoconfigure` | <!--VERSION_UNSTABLE-->1.19.0-alpha<!--/VERSION_UNSTABLE--> |
|
||||
| [SDK Autoconfigure SPI](./sdk-extensions/autoconfigure-spi) | Service Provider Interface (SPI) definitions for autoconfigure | `opentelemetry-sdk-extension-autoconfigure-spi` | <!--VERSION_STABLE-->1.19.0<!--/VERSION_STABLE--> |
|
||||
| [SDK Resources Extension](./sdk-extensions/resources) | Resource providers, including container, host, os, and process (deprecated) | `opentelemetry-sdk-extension-resources` | <!--VERSION_STABLE-->1.19.0<!--/VERSION_STABLE--> |
|
||||
| [SDK AWS Extension](./sdk-extensions/aws) | AWS resource providers, including beanstalk, ec2, ecs, eks, and lambda (deprecated) | `opentelemetry-sdk-extension-aws` | <!--VERSION_STABLE-->1.19.0<!--/VERSION_STABLE--> |
|
||||
| [SDK Jaeger Remote Sampler Extension](./sdk-extensions/jaeger-remote-sampler) | Sampler which obtains sampling configuration from remote Jaeger server | `opentelemetry-sdk-extension-jaeger-remote-sampler` | <!--VERSION_STABLE-->1.19.0<!--/VERSION_STABLE--> |
|
||||
| [SDK Incubator](./sdk-extensions/incubator) | SDK incubator, including YAML based view configuration, LeakDetectingSpanProcessor, and zPages | `opentelemetry-sdk-extension-incubator` | <!--VERSION_UNSTABLE-->1.19.0-alpha<!--/VERSION_UNSTABLE--> |
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ dependencies {
|
|||
testImplementation("io.grpc:grpc-protobuf")
|
||||
testImplementation("io.grpc:grpc-stub")
|
||||
testImplementation("io.opentelemetry:opentelemetry-extension-annotations")
|
||||
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-aws")
|
||||
|
||||
testImplementation("com.tngtech.archunit:archunit-junit5")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ package io.opentelemetry.all;
|
|||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* This test asserts that artifacts which are no longer published continue to be referenced in
|
||||
* {@code opentelemetry-bom}.
|
||||
*/
|
||||
class FallbackArtifactsTest {
|
||||
|
||||
@Test
|
||||
|
|
@ -23,6 +27,21 @@ class FallbackArtifactsTest {
|
|||
classAvailable("io.opentelemetry.extension.annotations.SpanAttribute");
|
||||
}
|
||||
|
||||
@Test
|
||||
void sdkExtensionAws() {
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.BeanstalkResource");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.BeanstalkResourceProvider");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.Ec2Resource");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.Ec2ResourceProvider");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.EcsResource");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.EcsResourceProvider");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.EksResource");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.EksResourceProvider");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.LambdaResource");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.resource.LambdaResourceProvider");
|
||||
classAvailable("io.opentelemetry.sdk.extension.aws.trace.AwsXrayIdGenerator");
|
||||
}
|
||||
|
||||
private static void classAvailable(String fqcn) {
|
||||
Assertions.assertThatCode(() -> Class.forName(fqcn)).doesNotThrowAnyException();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ otelBom.projectFilter.set { !it.hasProperty("otel.release") }
|
|||
// Artifacts that were previously published and included in the BOM for backwards compatibility
|
||||
otelBom.addFallback("opentelemetry-exporter-jaeger-proto", "1.17.0")
|
||||
otelBom.addFallback("opentelemetry-extension-annotations", "1.18.0")
|
||||
otelBom.addFallback("opentelemetry-sdk-extension-aws", "1.19.0")
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
Comparing source compatibility of against
|
||||
No changes.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# OpenTelemetry AWS Utils
|
||||
|
||||
[![Javadocs][javadoc-image]][javadoc-url]
|
||||
|
||||
> **NOTICE**: This artifact is deprecated and its contents have been moved
|
||||
> to [io.opentelemetry.contrib:opentelemetry-aws-resources](https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources).
|
||||
> Version 1.19.0 will be the last minor version published. However, it will continue to receive
|
||||
> patches for security vulnerabilities, and`io.opentelemetry:opentelemetry-bom` will reference the
|
||||
> last published version.
|
||||
|
||||
---
|
||||
#### Running micro-benchmarks
|
||||
From the root of the repo run `./gradlew clean :opentelemetry-sdk-extension-aws:jmh` to run all the benchmarks
|
||||
or run `./gradlew clean :opentelemetry-sdk-extension-aws:jmh -PjmhIncludeSingleClass=<ClassNameHere>`
|
||||
to run a specific benchmark class.
|
||||
|
||||
[javadoc-image]: https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-sdk-extension-aws.svg
|
||||
[javadoc-url]: https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-aws
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
plugins {
|
||||
id("otel.java-conventions")
|
||||
id("otel.publish-conventions")
|
||||
|
||||
id("otel.jmh-conventions")
|
||||
}
|
||||
|
||||
description = "OpenTelemetry SDK AWS Instrumentation Support"
|
||||
otelJava.moduleName.set("io.opentelemetry.sdk.extension.trace.aws")
|
||||
|
||||
dependencies {
|
||||
api(project(":api:all"))
|
||||
api(project(":sdk:all"))
|
||||
|
||||
compileOnly(project(":sdk-extensions:autoconfigure"))
|
||||
|
||||
annotationProcessor("com.google.auto.value:auto-value")
|
||||
|
||||
implementation(project(":semconv"))
|
||||
|
||||
implementation("com.fasterxml.jackson.core:jackson-core")
|
||||
implementation("com.squareup.okhttp3:okhttp")
|
||||
|
||||
testImplementation(project(":sdk:testing"))
|
||||
testImplementation(project(":sdk-extensions:autoconfigure"))
|
||||
|
||||
testImplementation("com.linecorp.armeria:armeria-junit5")
|
||||
testRuntimeOnly("org.bouncycastle:bcpkix-jdk15on")
|
||||
|
||||
testImplementation("com.google.guava:guava")
|
||||
testImplementation("org.skyscreamer:jsonassert")
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@SuppressWarnings("deprecation") // Moved to contrib
|
||||
public class AwsXrayIdGeneratorBenchmark {
|
||||
private final io.opentelemetry.sdk.extension.aws.trace.AwsXrayIdGenerator idGenerator =
|
||||
io.opentelemetry.sdk.extension.aws.trace.AwsXrayIdGenerator.getInstance();
|
||||
|
||||
@Benchmark
|
||||
@Measurement(iterations = 15, time = 1)
|
||||
@Warmup(iterations = 5, time = 1)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Fork(1)
|
||||
public String generateTraceId() {
|
||||
return idGenerator.generateTraceId();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Measurement(iterations = 15, time = 1)
|
||||
@Warmup(iterations = 5, time = 1)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Fork(1)
|
||||
public String generateSpanId() {
|
||||
return idGenerator.generateSpanId();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A factory for a {@link Resource} which provides information about the current EC2 instance if
|
||||
* running on AWS Elastic Beanstalk.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class BeanstalkResource {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(BeanstalkResource.class.getName());
|
||||
|
||||
private static final String DEVELOPMENT_ID = "deployment_id";
|
||||
private static final String VERSION_LABEL = "version_label";
|
||||
private static final String ENVIRONMENT_NAME = "environment_name";
|
||||
private static final String BEANSTALK_CONF_PATH = "/var/elasticbeanstalk/xray/environment.conf";
|
||||
private static final JsonFactory JSON_FACTORY = new JsonFactory();
|
||||
|
||||
private static final Resource INSTANCE = buildResource();
|
||||
|
||||
/**
|
||||
* Returns a factory for a {@link Resource} which provides information about the current EC2
|
||||
* instance if running on AWS Elastic Beanstalk.
|
||||
*/
|
||||
public static Resource get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static Resource buildResource() {
|
||||
return buildResource(BEANSTALK_CONF_PATH);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static Resource buildResource(String configPath) {
|
||||
File configFile = new File(configPath);
|
||||
if (!configFile.exists()) {
|
||||
return Resource.empty();
|
||||
}
|
||||
|
||||
AttributesBuilder attrBuilders = Attributes.builder();
|
||||
try (JsonParser parser = JSON_FACTORY.createParser(configFile)) {
|
||||
parser.nextToken();
|
||||
|
||||
if (!parser.isExpectedStartObjectToken()) {
|
||||
logger.log(Level.WARNING, "Invalid Beanstalk config: ", configPath);
|
||||
return Resource.create(attrBuilders.build(), ResourceAttributes.SCHEMA_URL);
|
||||
}
|
||||
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
parser.nextValue();
|
||||
String value = parser.getText();
|
||||
switch (parser.getCurrentName()) {
|
||||
case DEVELOPMENT_ID:
|
||||
attrBuilders.put(ResourceAttributes.SERVICE_INSTANCE_ID, value);
|
||||
break;
|
||||
case VERSION_LABEL:
|
||||
attrBuilders.put(ResourceAttributes.SERVICE_VERSION, value);
|
||||
break;
|
||||
case ENVIRONMENT_NAME:
|
||||
attrBuilders.put(ResourceAttributes.SERVICE_NAMESPACE, value);
|
||||
break;
|
||||
default:
|
||||
parser.skipChildren();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Could not parse Beanstalk config.", e);
|
||||
return Resource.empty();
|
||||
}
|
||||
|
||||
attrBuilders.put(ResourceAttributes.CLOUD_PROVIDER, ResourceAttributes.CloudProviderValues.AWS);
|
||||
attrBuilders.put(
|
||||
ResourceAttributes.CLOUD_PLATFORM,
|
||||
ResourceAttributes.CloudPlatformValues.AWS_ELASTIC_BEANSTALK);
|
||||
|
||||
return Resource.create(attrBuilders.build(), ResourceAttributes.SCHEMA_URL);
|
||||
}
|
||||
|
||||
private BeanstalkResource() {}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
||||
/**
|
||||
* {@link ResourceProvider} for automatically configuring {@link BeanstalkResource}.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class BeanstalkResourceProvider implements ResourceProvider {
|
||||
@Override
|
||||
public Resource createResource(ConfigProperties config) {
|
||||
return BeanstalkResource.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
class DockerHelper {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DockerHelper.class.getName());
|
||||
private static final int CONTAINER_ID_LENGTH = 64;
|
||||
private static final String DEFAULT_CGROUP_PATH = "/proc/self/cgroup";
|
||||
|
||||
private final String cgroupPath;
|
||||
|
||||
DockerHelper() {
|
||||
this(DEFAULT_CGROUP_PATH);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
DockerHelper(String cgroupPath) {
|
||||
this.cgroupPath = cgroupPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get docker container id from local cgroup file.
|
||||
*
|
||||
* @return docker container ID. Empty string if it can`t be found.
|
||||
*/
|
||||
@SuppressWarnings("DefaultCharset")
|
||||
public String getContainerId() {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(cgroupPath))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (line.length() > CONTAINER_ID_LENGTH) {
|
||||
return line.substring(line.length() - CONTAINER_ID_LENGTH);
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.log(Level.WARNING, "Failed to read container id, cgroup file does not exist.");
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Unable to read container id: " + e.getMessage());
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A factory for a {@link Resource} which provides information about the current EC2 instance if
|
||||
* running on AWS EC2.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Ec2Resource {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Ec2Resource.class.getName());
|
||||
|
||||
private static final JsonFactory JSON_FACTORY = new JsonFactory();
|
||||
|
||||
private static final String DEFAULT_IMDS_ENDPOINT = "169.254.169.254";
|
||||
|
||||
private static final Resource INSTANCE = buildResource();
|
||||
|
||||
/**
|
||||
* Returns a @link Resource} which provides information about the current EC2 instance if running
|
||||
* on AWS EC2.
|
||||
*/
|
||||
public static Resource get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static Resource buildResource() {
|
||||
// This property is only for testing e.g., with a mock IMDS server and never in production so we
|
||||
// just
|
||||
// read from a system property. This is similar to the AWS SDK.
|
||||
return buildResource(
|
||||
System.getProperty("otel.aws.imds.endpointOverride", DEFAULT_IMDS_ENDPOINT));
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static Resource buildResource(String endpoint) {
|
||||
String urlBase = "http://" + endpoint;
|
||||
URL identityDocumentUrl;
|
||||
URL hostnameUrl;
|
||||
URL tokenUrl;
|
||||
try {
|
||||
identityDocumentUrl = new URL(urlBase + "/latest/dynamic/instance-identity/document");
|
||||
hostnameUrl = new URL(urlBase + "/latest/meta-data/hostname");
|
||||
tokenUrl = new URL(urlBase + "/latest/api/token");
|
||||
} catch (MalformedURLException e) {
|
||||
// Can only happen when overriding the endpoint in testing so just throw.
|
||||
throw new IllegalArgumentException("Illegal endpoint: " + endpoint, e);
|
||||
}
|
||||
|
||||
String token = fetchToken(tokenUrl);
|
||||
|
||||
// If token is empty, either IMDSv2 isn't enabled or an unexpected failure happened. We can
|
||||
// still get data if IMDSv1 is enabled.
|
||||
String identity = fetchIdentity(identityDocumentUrl, token);
|
||||
if (identity.isEmpty()) {
|
||||
// If no identity document, assume we are not actually running on EC2.
|
||||
return Resource.empty();
|
||||
}
|
||||
|
||||
String hostname = fetchHostname(hostnameUrl, token);
|
||||
|
||||
AttributesBuilder attrBuilders = Attributes.builder();
|
||||
attrBuilders.put(ResourceAttributes.CLOUD_PROVIDER, ResourceAttributes.CloudProviderValues.AWS);
|
||||
attrBuilders.put(
|
||||
ResourceAttributes.CLOUD_PLATFORM, ResourceAttributes.CloudPlatformValues.AWS_EC2);
|
||||
|
||||
try (JsonParser parser = JSON_FACTORY.createParser(identity)) {
|
||||
parser.nextToken();
|
||||
|
||||
if (!parser.isExpectedStartObjectToken()) {
|
||||
throw new IOException("Invalid JSON:" + identity);
|
||||
}
|
||||
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
String value = parser.nextTextValue();
|
||||
switch (parser.getCurrentName()) {
|
||||
case "instanceId":
|
||||
attrBuilders.put(ResourceAttributes.HOST_ID, value);
|
||||
break;
|
||||
case "availabilityZone":
|
||||
attrBuilders.put(ResourceAttributes.CLOUD_AVAILABILITY_ZONE, value);
|
||||
break;
|
||||
case "instanceType":
|
||||
attrBuilders.put(ResourceAttributes.HOST_TYPE, value);
|
||||
break;
|
||||
case "imageId":
|
||||
attrBuilders.put(ResourceAttributes.HOST_IMAGE_ID, value);
|
||||
break;
|
||||
case "accountId":
|
||||
attrBuilders.put(ResourceAttributes.CLOUD_ACCOUNT_ID, value);
|
||||
break;
|
||||
case "region":
|
||||
attrBuilders.put(ResourceAttributes.CLOUD_REGION, value);
|
||||
break;
|
||||
default:
|
||||
parser.skipChildren();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Could not parse identity document, resource not filled.", e);
|
||||
return Resource.empty();
|
||||
}
|
||||
|
||||
attrBuilders.put(ResourceAttributes.HOST_NAME, hostname);
|
||||
|
||||
return Resource.create(attrBuilders.build(), ResourceAttributes.SCHEMA_URL);
|
||||
}
|
||||
|
||||
private static String fetchToken(URL tokenUrl) {
|
||||
return fetchString("PUT", tokenUrl, "", /* includeTtl= */ true);
|
||||
}
|
||||
|
||||
private static String fetchIdentity(URL identityDocumentUrl, String token) {
|
||||
return fetchString("GET", identityDocumentUrl, token, /* includeTtl= */ false);
|
||||
}
|
||||
|
||||
private static String fetchHostname(URL hostnameUrl, String token) {
|
||||
return fetchString("GET", hostnameUrl, token, /* includeTtl= */ false);
|
||||
}
|
||||
|
||||
// Generic HTTP fetch function for IMDS.
|
||||
private static String fetchString(String httpMethod, URL url, String token, boolean includeTtl) {
|
||||
SimpleHttpClient client = new SimpleHttpClient();
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
|
||||
if (includeTtl) {
|
||||
headers.put("X-aws-ec2-metadata-token-ttl-seconds", "60");
|
||||
}
|
||||
if (!token.isEmpty()) {
|
||||
headers.put("X-aws-ec2-metadata-token", token);
|
||||
}
|
||||
|
||||
return client.fetchString(httpMethod, url.toString(), headers, null);
|
||||
}
|
||||
|
||||
private Ec2Resource() {}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
||||
/**
|
||||
* {@link ResourceProvider} for automatically configuring {@link Ec2Resource}.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Ec2ResourceProvider implements ResourceProvider {
|
||||
@Override
|
||||
public Resource createResource(ConfigProperties config) {
|
||||
return Ec2Resource.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A factory for a {@link Resource} which provides information about the current ECS container if
|
||||
* running on AWS ECS.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class EcsResource {
|
||||
private static final Logger logger = Logger.getLogger(EcsResource.class.getName());
|
||||
private static final JsonFactory JSON_FACTORY = new JsonFactory();
|
||||
private static final String ECS_METADATA_KEY_V4 = "ECS_CONTAINER_METADATA_URI_V4";
|
||||
private static final String ECS_METADATA_KEY_V3 = "ECS_CONTAINER_METADATA_URI";
|
||||
|
||||
private static final Resource INSTANCE = buildResource();
|
||||
|
||||
/**
|
||||
* Returns a factory for a {@link Resource} which provides information about the current ECS
|
||||
* container if running on AWS ECS.
|
||||
*/
|
||||
public static Resource get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static Resource buildResource() {
|
||||
return buildResource(System.getenv(), new SimpleHttpClient());
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static Resource buildResource(Map<String, String> sysEnv, SimpleHttpClient httpClient) {
|
||||
// Note: If V4 is set V3 is set as well, so check V4 first.
|
||||
String ecsMetadataUrl =
|
||||
sysEnv.getOrDefault(ECS_METADATA_KEY_V4, sysEnv.getOrDefault(ECS_METADATA_KEY_V3, ""));
|
||||
if (!ecsMetadataUrl.isEmpty()) {
|
||||
AttributesBuilder attrBuilders = Attributes.builder();
|
||||
fetchMetadata(httpClient, ecsMetadataUrl, attrBuilders);
|
||||
// For TaskARN, Family, Revision.
|
||||
// May put the same attribute twice but that shouldn't matter.
|
||||
fetchMetadata(httpClient, ecsMetadataUrl + "/task", attrBuilders);
|
||||
return Resource.create(attrBuilders.build(), ResourceAttributes.SCHEMA_URL);
|
||||
}
|
||||
// Not running on ECS
|
||||
return Resource.empty();
|
||||
}
|
||||
|
||||
static void fetchMetadata(
|
||||
SimpleHttpClient httpClient, String url, AttributesBuilder attrBuilders) {
|
||||
String json = httpClient.fetchString("GET", url, Collections.emptyMap(), null);
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
attrBuilders.put(ResourceAttributes.CLOUD_PROVIDER, ResourceAttributes.CloudProviderValues.AWS);
|
||||
attrBuilders.put(
|
||||
ResourceAttributes.CLOUD_PLATFORM, ResourceAttributes.CloudPlatformValues.AWS_ECS);
|
||||
try (JsonParser parser = JSON_FACTORY.createParser(json)) {
|
||||
parser.nextToken();
|
||||
LogArnBuilder logArnBuilder = new LogArnBuilder();
|
||||
parseResponse(parser, attrBuilders, logArnBuilder);
|
||||
|
||||
logArnBuilder
|
||||
.getLogGroupArn()
|
||||
.ifPresent(
|
||||
logGroupArn -> {
|
||||
attrBuilders.put(
|
||||
ResourceAttributes.AWS_LOG_GROUP_ARNS, Collections.singletonList(logGroupArn));
|
||||
});
|
||||
|
||||
logArnBuilder
|
||||
.getLogStreamArn()
|
||||
.ifPresent(
|
||||
logStreamArn -> {
|
||||
attrBuilders.put(
|
||||
ResourceAttributes.AWS_LOG_STREAM_ARNS,
|
||||
Collections.singletonList(logStreamArn));
|
||||
});
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Can't get ECS metadata", e);
|
||||
}
|
||||
}
|
||||
|
||||
static void parseResponse(
|
||||
JsonParser parser, AttributesBuilder attrBuilders, LogArnBuilder logArnBuilder)
|
||||
throws IOException {
|
||||
if (!parser.isExpectedStartObjectToken()) {
|
||||
logger.log(Level.WARNING, "Couldn't parse ECS metadata, invalid JSON");
|
||||
return;
|
||||
}
|
||||
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
String value = parser.nextTextValue();
|
||||
switch (parser.getCurrentName()) {
|
||||
case "DockerId":
|
||||
attrBuilders.put(ResourceAttributes.CONTAINER_ID, value);
|
||||
break;
|
||||
case "DockerName":
|
||||
attrBuilders.put(ResourceAttributes.CONTAINER_NAME, value);
|
||||
break;
|
||||
case "ContainerARN":
|
||||
attrBuilders.put(ResourceAttributes.AWS_ECS_CONTAINER_ARN, value);
|
||||
logArnBuilder.setContainerArn(value);
|
||||
break;
|
||||
case "Image":
|
||||
DockerImage parsedImage = DockerImage.parse(value);
|
||||
if (parsedImage != null) {
|
||||
attrBuilders.put(ResourceAttributes.CONTAINER_IMAGE_NAME, parsedImage.getRepository());
|
||||
attrBuilders.put(ResourceAttributes.CONTAINER_IMAGE_TAG, parsedImage.getTag());
|
||||
}
|
||||
break;
|
||||
case "ImageID":
|
||||
attrBuilders.put("aws.ecs.container.image.id", value);
|
||||
break;
|
||||
case "LogOptions":
|
||||
// Recursively parse LogOptions
|
||||
parseResponse(parser, attrBuilders, logArnBuilder);
|
||||
break;
|
||||
case "awslogs-group":
|
||||
attrBuilders.put(ResourceAttributes.AWS_LOG_GROUP_NAMES, value);
|
||||
logArnBuilder.setLogGroupName(value);
|
||||
break;
|
||||
case "awslogs-stream":
|
||||
attrBuilders.put(ResourceAttributes.AWS_LOG_STREAM_NAMES, value);
|
||||
logArnBuilder.setLogStreamName(value);
|
||||
break;
|
||||
case "awslogs-region":
|
||||
logArnBuilder.setRegion(value);
|
||||
break;
|
||||
case "TaskARN":
|
||||
attrBuilders.put(ResourceAttributes.AWS_ECS_TASK_ARN, value);
|
||||
break;
|
||||
case "LaunchType":
|
||||
attrBuilders.put(ResourceAttributes.AWS_ECS_LAUNCHTYPE, value.toLowerCase());
|
||||
break;
|
||||
case "Family":
|
||||
attrBuilders.put(ResourceAttributes.AWS_ECS_TASK_FAMILY, value);
|
||||
break;
|
||||
case "Revision":
|
||||
attrBuilders.put(ResourceAttributes.AWS_ECS_TASK_REVISION, value);
|
||||
break;
|
||||
default:
|
||||
parser.skipChildren();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EcsResource() {}
|
||||
|
||||
/**
|
||||
* This builder can piece together the ARN of a log group or a log stream from region, account,
|
||||
* group name and stream name as the ARN isn't part of the ECS metadata.
|
||||
*
|
||||
* <p>If we just set AWS_LOG_GROUP_NAMES then the CloudWatch X-Ray traces view displays "An error
|
||||
* occurred fetching your data". That's why it's important we set the ARN.
|
||||
*/
|
||||
private static class LogArnBuilder {
|
||||
|
||||
@Nullable String region;
|
||||
@Nullable String account;
|
||||
@Nullable String logGroupName;
|
||||
@Nullable String logStreamName;
|
||||
|
||||
void setRegion(@Nullable String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
void setLogGroupName(@Nullable String logGroupName) {
|
||||
this.logGroupName = logGroupName;
|
||||
}
|
||||
|
||||
void setLogStreamName(@Nullable String logStreamName) {
|
||||
this.logStreamName = logStreamName;
|
||||
}
|
||||
|
||||
void setContainerArn(@Nullable String containerArn) {
|
||||
if (containerArn != null) {
|
||||
account = containerArn.split(":")[4];
|
||||
}
|
||||
}
|
||||
|
||||
Optional<String> getLogGroupArn() {
|
||||
if (region == null || account == null || logGroupName == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of("arn:aws:logs:" + region + ":" + account + ":log-group:" + logGroupName);
|
||||
}
|
||||
|
||||
Optional<String> getLogStreamArn() {
|
||||
if (region == null || account == null || logGroupName == null || logStreamName == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(
|
||||
"arn:aws:logs:"
|
||||
+ region
|
||||
+ ":"
|
||||
+ account
|
||||
+ ":log-group:"
|
||||
+ logGroupName
|
||||
+ ":log-stream:"
|
||||
+ logStreamName);
|
||||
}
|
||||
}
|
||||
|
||||
/** This can parse a Docker image name into its parts: repository, tag and sha256. */
|
||||
private static class DockerImage {
|
||||
|
||||
private static final Pattern imagePattern =
|
||||
Pattern.compile(
|
||||
"^(?<repository>([^/\\s]+/)?([^:\\s]+))(:(?<tag>[^@\\s]+))?(@sha256:(?<sha256>\\d+))?$");
|
||||
|
||||
final String repository;
|
||||
final String tag;
|
||||
|
||||
private DockerImage(String repository, String tag) {
|
||||
this.repository = repository;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
String getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static DockerImage parse(@Nullable String image) {
|
||||
if (image == null || image.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Matcher matcher = imagePattern.matcher(image);
|
||||
if (!matcher.matches()) {
|
||||
logger.log(Level.WARNING, "Couldn't parse image '" + image + "'");
|
||||
return null;
|
||||
}
|
||||
String repository = matcher.group("repository");
|
||||
String tag = matcher.group("tag");
|
||||
if (tag == null || tag.isEmpty()) {
|
||||
tag = "latest";
|
||||
}
|
||||
return new DockerImage(repository, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
||||
/**
|
||||
* {@link ResourceProvider} for automatically configuring {@link EcsResource}.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class EcsResourceProvider implements ResourceProvider {
|
||||
@Override
|
||||
public Resource createResource(ConfigProperties config) {
|
||||
return EcsResource.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A factory for a {@link Resource} which provides information about the current ECS container if
|
||||
* running on AWS EKS.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class EksResource {
|
||||
private static final Logger logger = Logger.getLogger(EksResource.class.getName());
|
||||
|
||||
private static final JsonFactory JSON_FACTORY = new JsonFactory();
|
||||
|
||||
static final String K8S_SVC_URL = "https://kubernetes.default.svc";
|
||||
static final String AUTH_CONFIGMAP_PATH = "/api/v1/namespaces/kube-system/configmaps/aws-auth";
|
||||
static final String CW_CONFIGMAP_PATH =
|
||||
"/api/v1/namespaces/amazon-cloudwatch/configmaps/cluster-info";
|
||||
private static final String K8S_TOKEN_PATH =
|
||||
"/var/run/secrets/kubernetes.io/serviceaccount/token";
|
||||
private static final String K8S_CERT_PATH =
|
||||
"/var/run/secrets/kubernetes.io/serviceaccount/ca.crt";
|
||||
|
||||
private static final Resource INSTANCE = buildResource();
|
||||
|
||||
/**
|
||||
* Returns a factory for a {@link Resource} which provides information about the current ECS
|
||||
* container if running on AWS EKS.
|
||||
*/
|
||||
public static Resource get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static Resource buildResource() {
|
||||
return buildResource(new SimpleHttpClient(), new DockerHelper(), K8S_TOKEN_PATH, K8S_CERT_PATH);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static Resource buildResource(
|
||||
SimpleHttpClient httpClient,
|
||||
DockerHelper dockerHelper,
|
||||
String k8sTokenPath,
|
||||
String k8sKeystorePath) {
|
||||
if (!isEks(k8sTokenPath, k8sKeystorePath, httpClient)) {
|
||||
return Resource.empty();
|
||||
}
|
||||
|
||||
AttributesBuilder attrBuilders = Attributes.builder();
|
||||
attrBuilders.put(ResourceAttributes.CLOUD_PROVIDER, ResourceAttributes.CloudProviderValues.AWS);
|
||||
attrBuilders.put(
|
||||
ResourceAttributes.CLOUD_PLATFORM, ResourceAttributes.CloudPlatformValues.AWS_EKS);
|
||||
|
||||
String clusterName = getClusterName(httpClient);
|
||||
if (clusterName != null && !clusterName.isEmpty()) {
|
||||
attrBuilders.put(ResourceAttributes.K8S_CLUSTER_NAME, clusterName);
|
||||
}
|
||||
|
||||
String containerId = dockerHelper.getContainerId();
|
||||
if (containerId != null && !containerId.isEmpty()) {
|
||||
attrBuilders.put(ResourceAttributes.CONTAINER_ID, containerId);
|
||||
}
|
||||
|
||||
return Resource.create(attrBuilders.build(), ResourceAttributes.SCHEMA_URL);
|
||||
}
|
||||
|
||||
private static boolean isEks(
|
||||
String k8sTokenPath, String k8sKeystorePath, SimpleHttpClient httpClient) {
|
||||
if (!isK8s(k8sTokenPath, k8sKeystorePath)) {
|
||||
logger.log(Level.FINE, "Not running on k8s.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, String> requestProperties = new HashMap<>();
|
||||
requestProperties.put("Authorization", getK8sCredHeader());
|
||||
String awsAuth =
|
||||
httpClient.fetchString(
|
||||
"GET", K8S_SVC_URL + AUTH_CONFIGMAP_PATH, requestProperties, K8S_CERT_PATH);
|
||||
|
||||
return awsAuth != null && !awsAuth.isEmpty();
|
||||
}
|
||||
|
||||
private static boolean isK8s(String k8sTokenPath, String k8sKeystorePath) {
|
||||
File k8sTokeyFile = new File(k8sTokenPath);
|
||||
File k8sKeystoreFile = new File(k8sKeystorePath);
|
||||
return k8sTokeyFile.exists() && k8sKeystoreFile.exists();
|
||||
}
|
||||
|
||||
private static String getClusterName(SimpleHttpClient httpClient) {
|
||||
Map<String, String> requestProperties = new HashMap<>();
|
||||
requestProperties.put("Authorization", getK8sCredHeader());
|
||||
String json =
|
||||
httpClient.fetchString(
|
||||
"GET", K8S_SVC_URL + CW_CONFIGMAP_PATH, requestProperties, K8S_CERT_PATH);
|
||||
|
||||
try (JsonParser parser = JSON_FACTORY.createParser(json)) {
|
||||
parser.nextToken();
|
||||
|
||||
if (!parser.isExpectedStartObjectToken()) {
|
||||
throw new IOException("Invalid JSON:" + json);
|
||||
}
|
||||
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
parser.nextToken();
|
||||
if (!parser.getCurrentName().equals("data")) {
|
||||
parser.skipChildren();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parser.isExpectedStartObjectToken()) {
|
||||
throw new IOException("Invalid JSON:" + json);
|
||||
}
|
||||
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
String value = parser.nextTextValue();
|
||||
if (!parser.getCurrentName().equals("cluster.name")) {
|
||||
parser.skipChildren();
|
||||
continue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Can't get cluster name on EKS.", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getK8sCredHeader() {
|
||||
try {
|
||||
String content =
|
||||
new String(Files.readAllBytes(Paths.get(K8S_TOKEN_PATH)), StandardCharsets.UTF_8);
|
||||
return "Bearer " + content;
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Unable to load K8s client token.", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private EksResource() {}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
||||
/**
|
||||
* {@link ResourceProvider} for automatically configuring {@link EksResource}.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class EksResourceProvider implements ResourceProvider {
|
||||
@Override
|
||||
public Resource createResource(ConfigProperties config) {
|
||||
return EksResource.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A factory for a {@link Resource} which provides information about the AWS Lambda function.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class LambdaResource {
|
||||
|
||||
private static final Resource INSTANCE = buildResource();
|
||||
|
||||
/**
|
||||
* Returns a factory for a {@link Resource} which provides information about the AWS Lambda
|
||||
* function.
|
||||
*/
|
||||
public static Resource get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static Resource buildResource() {
|
||||
return buildResource(System.getenv());
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static Resource buildResource(Map<String, String> environmentVariables) {
|
||||
String region = environmentVariables.getOrDefault("AWS_REGION", "");
|
||||
String functionName = environmentVariables.getOrDefault("AWS_LAMBDA_FUNCTION_NAME", "");
|
||||
String functionVersion = environmentVariables.getOrDefault("AWS_LAMBDA_FUNCTION_VERSION", "");
|
||||
|
||||
if (!isLambda(functionName, functionVersion)) {
|
||||
return Resource.empty();
|
||||
}
|
||||
|
||||
AttributesBuilder builder =
|
||||
Attributes.builder()
|
||||
.put(ResourceAttributes.CLOUD_PROVIDER, ResourceAttributes.CloudProviderValues.AWS);
|
||||
builder.put(
|
||||
ResourceAttributes.CLOUD_PLATFORM, ResourceAttributes.CloudPlatformValues.AWS_LAMBDA);
|
||||
|
||||
if (!region.isEmpty()) {
|
||||
builder.put(ResourceAttributes.CLOUD_REGION, region);
|
||||
}
|
||||
if (!functionName.isEmpty()) {
|
||||
builder.put(ResourceAttributes.FAAS_NAME, functionName);
|
||||
}
|
||||
if (!functionVersion.isEmpty()) {
|
||||
builder.put(ResourceAttributes.FAAS_VERSION, functionVersion);
|
||||
}
|
||||
|
||||
return Resource.create(builder.build(), ResourceAttributes.SCHEMA_URL);
|
||||
}
|
||||
|
||||
private static boolean isLambda(String... envVariables) {
|
||||
return Stream.of(envVariables).anyMatch(v -> !v.isEmpty());
|
||||
}
|
||||
|
||||
private LambdaResource() {}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
|
||||
/**
|
||||
* {@link ResourceProvider} for automatically configuring {@link LambdaResource}.
|
||||
*
|
||||
* @deprecated Moved to <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">io.opentelemetry.contrib:opentelemetry-aws-resources</a>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class LambdaResourceProvider implements ResourceProvider {
|
||||
@Override
|
||||
public Resource createResource(ConfigProperties config) {
|
||||
return LambdaResource.get();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
/** A simple HTTP client based on OkHttp. Not meant for high throughput. */
|
||||
final class SimpleHttpClient {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SimpleHttpClient.class.getName());
|
||||
|
||||
private static final Duration TIMEOUT = Duration.ofSeconds(2);
|
||||
|
||||
private static final RequestBody EMPTY_BODY = RequestBody.create(new byte[0]);
|
||||
|
||||
/** Fetch a string from a remote server. */
|
||||
public String fetchString(
|
||||
String httpMethod, String urlStr, Map<String, String> headers, @Nullable String certPath) {
|
||||
|
||||
OkHttpClient.Builder clientBuilder =
|
||||
new OkHttpClient.Builder()
|
||||
.callTimeout(TIMEOUT)
|
||||
.connectTimeout(TIMEOUT)
|
||||
.readTimeout(TIMEOUT);
|
||||
|
||||
if (urlStr.startsWith("https") && certPath != null) {
|
||||
KeyStore keyStore = getKeystoreForTrustedCert(certPath);
|
||||
X509TrustManager trustManager = buildTrustManager(keyStore);
|
||||
SSLSocketFactory socketFactory = buildSslSocketFactory(trustManager);
|
||||
if (socketFactory != null) {
|
||||
clientBuilder.sslSocketFactory(socketFactory, trustManager);
|
||||
}
|
||||
}
|
||||
|
||||
OkHttpClient client = clientBuilder.build();
|
||||
|
||||
// AWS incorrectly uses PUT despite having no request body, OkHttp will only allow us to send
|
||||
// GET with null body or PUT with empty string body
|
||||
RequestBody requestBody = null;
|
||||
if (httpMethod.equals("PUT")) {
|
||||
requestBody = EMPTY_BODY;
|
||||
}
|
||||
Request.Builder requestBuilder =
|
||||
new Request.Builder().url(urlStr).method(httpMethod, requestBody);
|
||||
|
||||
headers.forEach(requestBuilder::addHeader);
|
||||
|
||||
try (Response response = client.newCall(requestBuilder.build()).execute()) {
|
||||
int responseCode = response.code();
|
||||
if (responseCode != 200) {
|
||||
logger.log(
|
||||
Level.FINE,
|
||||
"Error response from "
|
||||
+ urlStr
|
||||
+ " code ("
|
||||
+ responseCode
|
||||
+ ") text "
|
||||
+ response.message());
|
||||
return "";
|
||||
}
|
||||
ResponseBody body = response.body();
|
||||
return body != null ? body.string() : "";
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.FINE, "SimpleHttpClient fetch string failed.", e);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static X509TrustManager buildTrustManager(@Nullable KeyStore keyStore) {
|
||||
if (keyStore == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
|
||||
tmf.init(keyStore);
|
||||
return (X509TrustManager) tmf.getTrustManagers()[0];
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SSLSocketFactory buildSslSocketFactory(@Nullable TrustManager trustManager) {
|
||||
if (trustManager == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
context.init(null, new TrustManager[] {trustManager}, null);
|
||||
return context.getSocketFactory();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static KeyStore getKeystoreForTrustedCert(String certPath) {
|
||||
try (FileInputStream fis = new FileInputStream(certPath)) {
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
trustStore.load(null, null);
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
|
||||
Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(fis);
|
||||
|
||||
int i = 0;
|
||||
for (Certificate certificate : certificates) {
|
||||
trustStore.setCertificateEntry("cert_" + i, certificate);
|
||||
i++;
|
||||
}
|
||||
return trustStore;
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Cannot load KeyStore from " + certPath);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider} implementations for inferring
|
||||
* resource information for AWS services.
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.trace;
|
||||
|
||||
import io.opentelemetry.api.trace.TraceId;
|
||||
import io.opentelemetry.sdk.trace.IdGenerator;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Generates tracing ids compatible with the AWS X-Ray tracing service. In the X-Ray system the
|
||||
* first 32 bits of the trace id are the Unix epoch time in secords. Spans (AWS calls them segments)
|
||||
* submit with trace id timestamps outside of the last 30 days are rejected.
|
||||
*
|
||||
* @see <a
|
||||
* href="https://docs.aws.amazon.com/xray/latest/devguide/xray-api-sendingdata.html#xray-api-traceids">Generating
|
||||
* Trace IDs</a>
|
||||
* @deprecated Use the AwsXrayIdGenerator provided in the <a
|
||||
* href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-xray">
|
||||
* io.opentelemetry.contrib:opentelemetry-aws-xray</a> artifact instead of this one.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class AwsXrayIdGenerator implements IdGenerator {
|
||||
|
||||
private static final AwsXrayIdGenerator INSTANCE = new AwsXrayIdGenerator();
|
||||
|
||||
private static final IdGenerator RANDOM_ID_GENERATOR = IdGenerator.random();
|
||||
|
||||
/** Returns a singleton instance of {@link AwsXrayIdGenerator}. */
|
||||
public static AwsXrayIdGenerator getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateSpanId() {
|
||||
return RANDOM_ID_GENERATOR.generateSpanId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateTraceId() {
|
||||
// hi - 4 bytes timestamp, 4 bytes random
|
||||
// low - 8 bytes random.
|
||||
// Since we include timestamp, impossible to be invalid.
|
||||
|
||||
Random random = ThreadLocalRandom.current();
|
||||
long timestampSecs = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
|
||||
long hiRandom = random.nextInt() & 0xFFFFFFFFL;
|
||||
|
||||
long lowRandom = random.nextLong();
|
||||
|
||||
return TraceId.fromLongs(timestampSecs << 32 | hiRandom, lowRandom);
|
||||
}
|
||||
|
||||
private AwsXrayIdGenerator() {}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** Provides implementations of SDK interfaces which integrate natively with AWS infrastructure. */
|
||||
@ParametersAreNonnullByDefault
|
||||
package io.opentelemetry.sdk.extension.aws.trace;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
io.opentelemetry.sdk.extension.aws.resource.BeanstalkResourceProvider
|
||||
io.opentelemetry.sdk.extension.aws.resource.Ec2ResourceProvider
|
||||
io.opentelemetry.sdk.extension.aws.resource.EcsResourceProvider
|
||||
io.opentelemetry.sdk.extension.aws.resource.EksResourceProvider
|
||||
io.opentelemetry.sdk.extension.aws.resource.LambdaResourceProvider
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ServiceLoader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
@SuppressWarnings("deprecation") // Moved to contrib
|
||||
class BeanstalkResourceTest {
|
||||
|
||||
@Test
|
||||
void testCreateAttributes(@TempDir File tempFolder) throws IOException {
|
||||
File file = new File(tempFolder, "beanstalk.config");
|
||||
String content =
|
||||
"{\"noise\": \"noise\", \"deployment_id\":4,\""
|
||||
+ "version_label\":\"2\",\"environment_name\":\"HttpSubscriber-env\"}";
|
||||
Files.write(content.getBytes(Charsets.UTF_8), file);
|
||||
Resource resource = BeanstalkResource.buildResource(file.getPath());
|
||||
Attributes attributes = resource.getAttributes();
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_elastic_beanstalk"),
|
||||
entry(ResourceAttributes.SERVICE_INSTANCE_ID, "4"),
|
||||
entry(ResourceAttributes.SERVICE_VERSION, "2"),
|
||||
entry(ResourceAttributes.SERVICE_NAMESPACE, "HttpSubscriber-env"));
|
||||
assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConfigFileMissing() {
|
||||
Attributes attributes =
|
||||
BeanstalkResource.buildResource("a_file_never_existing").getAttributes();
|
||||
assertThat(attributes).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressLogger(BeanstalkResource.class)
|
||||
void testBadConfigFile(@TempDir File tempFolder) throws IOException {
|
||||
File file = new File(tempFolder, "beanstalk.config");
|
||||
String content =
|
||||
"\"deployment_id\":4,\"version_label\":\"2\",\""
|
||||
+ "environment_name\":\"HttpSubscriber-env\"}";
|
||||
Files.write(content.getBytes(Charsets.UTF_8), file);
|
||||
Attributes attributes = BeanstalkResource.buildResource(file.getPath()).getAttributes();
|
||||
assertThat(attributes).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void inServiceLoader() {
|
||||
// No practical way to test the attributes themselves so at least check the service loader picks
|
||||
// it up.
|
||||
assertThat(ServiceLoader.load(ResourceProvider.class))
|
||||
.anyMatch(BeanstalkResourceProvider.class::isInstance);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
class DockerHelperTest {
|
||||
|
||||
@Test
|
||||
@SuppressLogger(DockerHelper.class)
|
||||
void testCgroupFileMissing() {
|
||||
DockerHelper dockerHelper = new DockerHelper("a_file_never_existing");
|
||||
assertThat(dockerHelper.getContainerId()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContainerIdMissing(@TempDir File tempFolder) throws IOException {
|
||||
File file = new File(tempFolder, "no_container_id");
|
||||
String content = "13:pids:/\n" + "12:hugetlb:/\n" + "11:net_prio:/";
|
||||
Files.write(content.getBytes(Charsets.UTF_8), file);
|
||||
|
||||
DockerHelper dockerHelper = new DockerHelper(file.getPath());
|
||||
assertThat(dockerHelper.getContainerId()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetContainerId(@TempDir File tempFolder) throws IOException {
|
||||
File file = new File(tempFolder, "cgroup");
|
||||
String expected = "386a1920640799b5bf5a39bd94e489e5159a88677d96ca822ce7c433ff350163";
|
||||
String content = "dummy\n11:devices:/ecs/bbc36dd0-5ee0-4007-ba96-c590e0b278d2/" + expected;
|
||||
Files.write(content.getBytes(Charsets.UTF_8), file);
|
||||
|
||||
DockerHelper dockerHelper = new DockerHelper(file.getPath());
|
||||
assertThat(dockerHelper.getContainerId()).isEqualTo(expected);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
import com.linecorp.armeria.common.AggregatedHttpRequest;
|
||||
import com.linecorp.armeria.common.HttpResponse;
|
||||
import com.linecorp.armeria.common.HttpStatus;
|
||||
import com.linecorp.armeria.common.MediaType;
|
||||
import com.linecorp.armeria.testing.junit5.server.mock.MockWebServerExtension;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.util.ServiceLoader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@SuppressWarnings("deprecation") // Moved to contrib
|
||||
class Ec2ResourceTest {
|
||||
|
||||
// From https://docs.amazonaws.cn/en_us/AWSEC2/latest/UserGuide/instance-identity-documents.html
|
||||
private static final String IDENTITY_DOCUMENT =
|
||||
"{\n"
|
||||
+ " \"devpayProductCodes\" : null,\n"
|
||||
+ " \"marketplaceProductCodes\" : [ \"1abc2defghijklm3nopqrs4tu\" ], \n"
|
||||
+ " \"availabilityZone\" : \"us-west-2b\",\n"
|
||||
+ " \"privateIp\" : \"10.158.112.84\",\n"
|
||||
+ " \"version\" : \"2017-09-30\",\n"
|
||||
+ " \"instanceId\" : \"i-1234567890abcdef0\",\n"
|
||||
+ " \"billingProducts\" : null,\n"
|
||||
+ " \"instanceType\" : \"t2.micro\",\n"
|
||||
+ " \"accountId\" : \"123456789012\",\n"
|
||||
+ " \"imageId\" : \"ami-5fb8c835\",\n"
|
||||
+ " \"pendingTime\" : \"2016-11-19T16:32:11Z\",\n"
|
||||
+ " \"architecture\" : \"x86_64\",\n"
|
||||
+ " \"kernelId\" : null,\n"
|
||||
+ " \"ramdiskId\" : null,\n"
|
||||
+ " \"region\" : \"us-west-2\"\n"
|
||||
+ "}";
|
||||
|
||||
@RegisterExtension public static MockWebServerExtension server = new MockWebServerExtension();
|
||||
|
||||
@Test
|
||||
void imdsv2() {
|
||||
server.enqueue(HttpResponse.of("token"));
|
||||
server.enqueue(HttpResponse.of(MediaType.JSON_UTF_8, IDENTITY_DOCUMENT));
|
||||
server.enqueue(HttpResponse.of("ec2-1-2-3-4"));
|
||||
|
||||
Resource resource = Ec2Resource.buildResource("localhost:" + server.httpPort());
|
||||
assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
Attributes attributes = resource.getAttributes();
|
||||
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_ec2"),
|
||||
entry(ResourceAttributes.HOST_ID, "i-1234567890abcdef0"),
|
||||
entry(ResourceAttributes.CLOUD_AVAILABILITY_ZONE, "us-west-2b"),
|
||||
entry(ResourceAttributes.HOST_TYPE, "t2.micro"),
|
||||
entry(ResourceAttributes.HOST_IMAGE_ID, "ami-5fb8c835"),
|
||||
entry(ResourceAttributes.CLOUD_ACCOUNT_ID, "123456789012"),
|
||||
entry(ResourceAttributes.CLOUD_REGION, "us-west-2"),
|
||||
entry(ResourceAttributes.HOST_NAME, "ec2-1-2-3-4"));
|
||||
|
||||
AggregatedHttpRequest request1 = server.takeRequest().request();
|
||||
assertThat(request1.path()).isEqualTo("/latest/api/token");
|
||||
assertThat(request1.headers().get("X-aws-ec2-metadata-token-ttl-seconds")).isEqualTo("60");
|
||||
|
||||
AggregatedHttpRequest request2 = server.takeRequest().request();
|
||||
assertThat(request2.path()).isEqualTo("/latest/dynamic/instance-identity/document");
|
||||
assertThat(request2.headers().get("X-aws-ec2-metadata-token")).isEqualTo("token");
|
||||
|
||||
AggregatedHttpRequest request3 = server.takeRequest().request();
|
||||
assertThat(request3.path()).isEqualTo("/latest/meta-data/hostname");
|
||||
assertThat(request3.headers().get("X-aws-ec2-metadata-token")).isEqualTo("token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void imdsv1() {
|
||||
server.enqueue(HttpResponse.of(HttpStatus.NOT_FOUND));
|
||||
server.enqueue(HttpResponse.of(MediaType.JSON_UTF_8, IDENTITY_DOCUMENT));
|
||||
server.enqueue(HttpResponse.of("ec2-1-2-3-4"));
|
||||
|
||||
Resource resource = Ec2Resource.buildResource("localhost:" + server.httpPort());
|
||||
assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
Attributes attributes = resource.getAttributes();
|
||||
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_ec2"),
|
||||
entry(ResourceAttributes.HOST_ID, "i-1234567890abcdef0"),
|
||||
entry(ResourceAttributes.CLOUD_AVAILABILITY_ZONE, "us-west-2b"),
|
||||
entry(ResourceAttributes.HOST_TYPE, "t2.micro"),
|
||||
entry(ResourceAttributes.HOST_IMAGE_ID, "ami-5fb8c835"),
|
||||
entry(ResourceAttributes.CLOUD_ACCOUNT_ID, "123456789012"),
|
||||
entry(ResourceAttributes.CLOUD_REGION, "us-west-2"),
|
||||
entry(ResourceAttributes.HOST_NAME, "ec2-1-2-3-4"));
|
||||
|
||||
AggregatedHttpRequest request1 = server.takeRequest().request();
|
||||
assertThat(request1.path()).isEqualTo("/latest/api/token");
|
||||
assertThat(request1.headers().get("X-aws-ec2-metadata-token-ttl-seconds")).isEqualTo("60");
|
||||
|
||||
AggregatedHttpRequest request2 = server.takeRequest().request();
|
||||
assertThat(request2.path()).isEqualTo("/latest/dynamic/instance-identity/document");
|
||||
assertThat(request2.headers().get("X-aws-ec2-metadata-token")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressLogger(Ec2Resource.class)
|
||||
void badJson() {
|
||||
server.enqueue(HttpResponse.of(HttpStatus.NOT_FOUND));
|
||||
server.enqueue(HttpResponse.of(MediaType.JSON_UTF_8, "I'm not JSON"));
|
||||
|
||||
Attributes attributes =
|
||||
Ec2Resource.buildResource("localhost:" + server.httpPort()).getAttributes();
|
||||
assertThat(attributes).isEmpty();
|
||||
|
||||
AggregatedHttpRequest request1 = server.takeRequest().request();
|
||||
assertThat(request1.path()).isEqualTo("/latest/api/token");
|
||||
assertThat(request1.headers().get("X-aws-ec2-metadata-token-ttl-seconds")).isEqualTo("60");
|
||||
|
||||
AggregatedHttpRequest request2 = server.takeRequest().request();
|
||||
assertThat(request2.path()).isEqualTo("/latest/dynamic/instance-identity/document");
|
||||
assertThat(request2.headers().get("X-aws-ec2-metadata-token")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void inServiceLoader() {
|
||||
// No practical way to test the attributes themselves so at least check the service loader picks
|
||||
// it up.
|
||||
assertThat(ServiceLoader.load(ResourceProvider.class))
|
||||
.anyMatch(Ec2ResourceProvider.class::isInstance);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@SuppressWarnings("deprecation") // Moved to contrib
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class EcsResourceTest {
|
||||
private static final String ECS_METADATA_KEY_V4 = "ECS_CONTAINER_METADATA_URI_V4";
|
||||
private static final String ECS_METADATA_KEY_V3 = "ECS_CONTAINER_METADATA_URI";
|
||||
|
||||
@Mock private SimpleHttpClient mockHttpClient;
|
||||
|
||||
@Test
|
||||
void testCreateAttributesV3() throws IOException {
|
||||
Map<String, String> mockSysEnv = new HashMap<>();
|
||||
mockSysEnv.put(ECS_METADATA_KEY_V3, "ecs_metadata_v3_uri");
|
||||
when(mockHttpClient.fetchString("GET", "ecs_metadata_v3_uri", Collections.emptyMap(), null))
|
||||
.thenReturn(readResourceJson("ecs-container-metadata-v3.json"));
|
||||
when(mockHttpClient.fetchString(
|
||||
"GET", "ecs_metadata_v3_uri/task", Collections.emptyMap(), null))
|
||||
.thenReturn(readResourceJson("ecs-task-metadata-v3.json"));
|
||||
|
||||
Resource resource = EcsResource.buildResource(mockSysEnv, mockHttpClient);
|
||||
Attributes attributes = resource.getAttributes();
|
||||
|
||||
assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_ecs"),
|
||||
entry(ResourceAttributes.CONTAINER_NAME, "ecs-nginx-5-nginx-curl-ccccb9f49db0dfe0d901"),
|
||||
entry(
|
||||
ResourceAttributes.CONTAINER_ID,
|
||||
"43481a6ce4842eec8fe72fc28500c6b52edcc0917f105b83379f88cac1ff3946"),
|
||||
entry(ResourceAttributes.CONTAINER_IMAGE_NAME, "nrdlngr/nginx-curl"),
|
||||
entry(ResourceAttributes.CONTAINER_IMAGE_TAG, "latest"),
|
||||
entry(
|
||||
AttributeKey.stringKey("aws.ecs.container.image.id"),
|
||||
"sha256:2e00ae64383cfc865ba0a2ba37f61b50a120d2d9378559dcd458dc0de47bc165"),
|
||||
entry(
|
||||
ResourceAttributes.AWS_ECS_TASK_ARN,
|
||||
"arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3"),
|
||||
entry(ResourceAttributes.AWS_ECS_TASK_FAMILY, "nginx"),
|
||||
entry(ResourceAttributes.AWS_ECS_TASK_REVISION, "5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateAttributesV4() throws IOException {
|
||||
Map<String, String> mockSysEnv = new HashMap<>();
|
||||
mockSysEnv.put(ECS_METADATA_KEY_V4, "ecs_metadata_v4_uri");
|
||||
when(mockHttpClient.fetchString("GET", "ecs_metadata_v4_uri", Collections.emptyMap(), null))
|
||||
.thenReturn(readResourceJson("ecs-container-metadata-v4.json"));
|
||||
when(mockHttpClient.fetchString(
|
||||
"GET", "ecs_metadata_v4_uri/task", Collections.emptyMap(), null))
|
||||
.thenReturn(readResourceJson("ecs-task-metadata-v4.json"));
|
||||
|
||||
Resource resource = EcsResource.buildResource(mockSysEnv, mockHttpClient);
|
||||
Attributes attributes = resource.getAttributes();
|
||||
|
||||
assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_ecs"),
|
||||
entry(ResourceAttributes.CONTAINER_NAME, "ecs-curltest-26-curl-cca48e8dcadd97805600"),
|
||||
entry(
|
||||
ResourceAttributes.CONTAINER_ID,
|
||||
"ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66"),
|
||||
entry(
|
||||
ResourceAttributes.CONTAINER_IMAGE_NAME,
|
||||
"111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest"),
|
||||
entry(ResourceAttributes.CONTAINER_IMAGE_TAG, "latest"),
|
||||
entry(
|
||||
AttributeKey.stringKey("aws.ecs.container.image.id"),
|
||||
"sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553"),
|
||||
entry(
|
||||
ResourceAttributes.AWS_ECS_CONTAINER_ARN,
|
||||
"arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9"),
|
||||
entry(
|
||||
ResourceAttributes.AWS_LOG_GROUP_NAMES, Collections.singletonList("/ecs/metadata")),
|
||||
entry(
|
||||
ResourceAttributes.AWS_LOG_GROUP_ARNS,
|
||||
Collections.singletonList(
|
||||
"arn:aws:logs:us-west-2:111122223333:log-group:/ecs/metadata")),
|
||||
entry(
|
||||
ResourceAttributes.AWS_LOG_STREAM_NAMES,
|
||||
Collections.singletonList("ecs/curl/8f03e41243824aea923aca126495f665")),
|
||||
entry(
|
||||
ResourceAttributes.AWS_LOG_STREAM_ARNS,
|
||||
Collections.singletonList(
|
||||
"arn:aws:logs:us-west-2:111122223333:log-group:/ecs/metadata:log-stream:ecs/curl/8f03e41243824aea923aca126495f665")),
|
||||
entry(
|
||||
ResourceAttributes.AWS_ECS_TASK_ARN,
|
||||
"arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c"),
|
||||
entry(ResourceAttributes.AWS_ECS_LAUNCHTYPE, "ec2"),
|
||||
entry(ResourceAttributes.AWS_ECS_TASK_FAMILY, "curltest"),
|
||||
entry(ResourceAttributes.AWS_ECS_TASK_REVISION, "26"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotOnEcs() {
|
||||
Map<String, String> mockSysEnv = new HashMap<>();
|
||||
mockSysEnv.put(ECS_METADATA_KEY_V3, "");
|
||||
mockSysEnv.put(ECS_METADATA_KEY_V4, "");
|
||||
Attributes attributes = EcsResource.buildResource(mockSysEnv, mockHttpClient).getAttributes();
|
||||
assertThat(attributes).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void inServiceLoader() {
|
||||
// No practical way to test the attributes themselves so at least check the service loader picks
|
||||
// it up.
|
||||
assertThat(ServiceLoader.load(ResourceProvider.class))
|
||||
.anyMatch(EcsResourceProvider.class::isInstance);
|
||||
}
|
||||
|
||||
String readResourceJson(String resourceName) throws IOException {
|
||||
return Resources.toString(Resources.getResource(resourceName), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ServiceLoader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@SuppressWarnings("deprecation") // Moved to contrib
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class EksResourceTest {
|
||||
|
||||
@Mock private DockerHelper mockDockerHelper;
|
||||
|
||||
@Mock private SimpleHttpClient httpClient;
|
||||
|
||||
@Test
|
||||
@SuppressLogger(EksResource.class)
|
||||
void testEks(@TempDir File tempFolder) throws IOException {
|
||||
File mockK8sTokenFile = new File(tempFolder, "k8sToken");
|
||||
String token = "token123";
|
||||
Files.write(token.getBytes(Charsets.UTF_8), mockK8sTokenFile);
|
||||
File mockK8sKeystoreFile = new File(tempFolder, "k8sCert");
|
||||
String truststore = "truststore123";
|
||||
Files.write(truststore.getBytes(Charsets.UTF_8), mockK8sKeystoreFile);
|
||||
|
||||
when(httpClient.fetchString(
|
||||
any(),
|
||||
Mockito.eq(
|
||||
io.opentelemetry.sdk.extension.aws.resource.EksResource.K8S_SVC_URL
|
||||
+ io.opentelemetry.sdk.extension.aws.resource.EksResource.AUTH_CONFIGMAP_PATH),
|
||||
any(),
|
||||
any()))
|
||||
.thenReturn("not empty");
|
||||
when(httpClient.fetchString(
|
||||
any(),
|
||||
Mockito.eq(
|
||||
io.opentelemetry.sdk.extension.aws.resource.EksResource.K8S_SVC_URL
|
||||
+ io.opentelemetry.sdk.extension.aws.resource.EksResource.CW_CONFIGMAP_PATH),
|
||||
any(),
|
||||
any()))
|
||||
.thenReturn("{\"data\":{\"cluster.name\":\"my-cluster\"}}");
|
||||
when(mockDockerHelper.getContainerId()).thenReturn("0123456789A");
|
||||
|
||||
Resource eksResource =
|
||||
EksResource.buildResource(
|
||||
httpClient,
|
||||
mockDockerHelper,
|
||||
mockK8sTokenFile.getPath(),
|
||||
mockK8sKeystoreFile.getPath());
|
||||
Attributes attributes = eksResource.getAttributes();
|
||||
|
||||
assertThat(eksResource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_eks"),
|
||||
entry(ResourceAttributes.K8S_CLUSTER_NAME, "my-cluster"),
|
||||
entry(ResourceAttributes.CONTAINER_ID, "0123456789A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNotEks() {
|
||||
Resource eksResource = EksResource.buildResource(httpClient, mockDockerHelper, "", "");
|
||||
Attributes attributes = eksResource.getAttributes();
|
||||
assertThat(attributes).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void inServiceLoader() {
|
||||
// No practical way to test the attributes themselves so at least check the service loader picks
|
||||
// it up.
|
||||
assertThat(ServiceLoader.load(ResourceProvider.class))
|
||||
.anyMatch(EksResourceProvider.class::isInstance);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@SuppressWarnings("deprecation") // Moved to contrib
|
||||
class LambdaResourceTest {
|
||||
@Test
|
||||
void shouldNotCreateResourceForNotLambda() {
|
||||
Attributes attributes = LambdaResource.buildResource(emptyMap()).getAttributes();
|
||||
assertThat(attributes).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAddNonEmptyAttributes() {
|
||||
Resource resource =
|
||||
LambdaResource.buildResource(singletonMap("AWS_LAMBDA_FUNCTION_NAME", "my-function"));
|
||||
Attributes attributes = resource.getAttributes();
|
||||
|
||||
assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_lambda"),
|
||||
entry(ResourceAttributes.FAAS_NAME, "my-function"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAddAllAttributes() {
|
||||
Map<String, String> envVars = new HashMap<>();
|
||||
envVars.put("AWS_REGION", "us-east-1");
|
||||
envVars.put("AWS_LAMBDA_FUNCTION_NAME", "my-function");
|
||||
envVars.put("AWS_LAMBDA_FUNCTION_VERSION", "1.2.3");
|
||||
|
||||
Resource resource = LambdaResource.buildResource(envVars);
|
||||
Attributes attributes = resource.getAttributes();
|
||||
|
||||
assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL);
|
||||
assertThat(attributes)
|
||||
.containsOnly(
|
||||
entry(ResourceAttributes.CLOUD_PROVIDER, "aws"),
|
||||
entry(ResourceAttributes.CLOUD_PLATFORM, "aws_lambda"),
|
||||
entry(ResourceAttributes.CLOUD_REGION, "us-east-1"),
|
||||
entry(ResourceAttributes.FAAS_NAME, "my-function"),
|
||||
entry(ResourceAttributes.FAAS_VERSION, "1.2.3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void inServiceLoader() {
|
||||
// No practical way to test the attributes themselves so at least check the service loader picks
|
||||
// it up.
|
||||
assertThat(ServiceLoader.load(ResourceProvider.class))
|
||||
.anyMatch(LambdaResourceProvider.class::isInstance);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.linecorp.armeria.common.AggregatedHttpRequest;
|
||||
import com.linecorp.armeria.common.HttpResponse;
|
||||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
|
||||
import com.linecorp.armeria.testing.junit5.server.mock.MockWebServerExtension;
|
||||
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
class SimpleHttpClientTest {
|
||||
|
||||
@RegisterExtension public static MockWebServerExtension server = new MockWebServerExtension();
|
||||
|
||||
@Test
|
||||
void testFetchString() {
|
||||
server.enqueue(HttpResponse.of("expected result"));
|
||||
|
||||
Map<String, String> requestPropertyMap = ImmutableMap.of("key1", "value1", "key2", "value2");
|
||||
String urlStr = String.format("http://localhost:%s%s", server.httpPort(), "/path");
|
||||
SimpleHttpClient httpClient = new SimpleHttpClient();
|
||||
String result = httpClient.fetchString("GET", urlStr, requestPropertyMap, null);
|
||||
|
||||
assertThat(result).isEqualTo("expected result");
|
||||
|
||||
AggregatedHttpRequest request1 = server.takeRequest().request();
|
||||
assertThat(request1.path()).isEqualTo("/path");
|
||||
assertThat(request1.headers().get("key1")).isEqualTo("value1");
|
||||
assertThat(request1.headers().get("key2")).isEqualTo("value2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailedFetchString() {
|
||||
Map<String, String> requestPropertyMap = ImmutableMap.of("key1", "value1", "key2", "value2");
|
||||
String urlStr = String.format("http://localhost:%s%s", server.httpPort(), "/path");
|
||||
SimpleHttpClient httpClient = new SimpleHttpClient();
|
||||
String result = httpClient.fetchString("GET", urlStr, requestPropertyMap, null);
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
static class HttpsServerTest {
|
||||
@RegisterExtension
|
||||
@Order(1)
|
||||
public static SelfSignedCertificateExtension certificate = new SelfSignedCertificateExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(2)
|
||||
public static ServerExtension server =
|
||||
new ServerExtension() {
|
||||
@Override
|
||||
protected void configure(ServerBuilder sb) {
|
||||
sb.tls(certificate.certificateFile(), certificate.privateKeyFile());
|
||||
|
||||
sb.service("/", (ctx, req) -> HttpResponse.of("Thanks for trusting me"));
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void goodCert() {
|
||||
SimpleHttpClient httpClient = new SimpleHttpClient();
|
||||
String result =
|
||||
httpClient.fetchString(
|
||||
"GET",
|
||||
"https://localhost:" + server.httpsPort() + "/",
|
||||
Collections.emptyMap(),
|
||||
certificate.certificateFile().getAbsolutePath());
|
||||
assertThat(result).isEqualTo("Thanks for trusting me");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressLogger(SimpleHttpClient.class)
|
||||
void missingCert() {
|
||||
SimpleHttpClient httpClient = new SimpleHttpClient();
|
||||
String result =
|
||||
httpClient.fetchString(
|
||||
"GET",
|
||||
"https://localhost:" + server.httpsPort() + "/",
|
||||
Collections.emptyMap(),
|
||||
"/foo/bar/bad");
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressLogger(SimpleHttpClient.class)
|
||||
void badCert(@TempDir Path tempDir) throws Exception {
|
||||
Path certFile = tempDir.resolve("test.crt");
|
||||
Files.write(certFile, "bad cert".getBytes(StandardCharsets.UTF_8));
|
||||
SimpleHttpClient httpClient = new SimpleHttpClient();
|
||||
String result =
|
||||
httpClient.fetchString(
|
||||
"GET",
|
||||
"https://localhost:" + server.httpsPort() + "/",
|
||||
Collections.emptyMap(),
|
||||
certFile.toString());
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.aws.trace;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.trace.SpanId;
|
||||
import io.opentelemetry.api.trace.TraceId;
|
||||
import io.opentelemetry.sdk.trace.IdGenerator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link AwsXrayIdGenerator}. */
|
||||
@SuppressWarnings("deprecation") // Moved to contrib
|
||||
class AwsXRayIdGeneratorTest {
|
||||
|
||||
@Test
|
||||
void shouldGenerateValidIds() {
|
||||
AwsXrayIdGenerator generator = AwsXrayIdGenerator.getInstance();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
String traceId = generator.generateTraceId();
|
||||
assertThat(TraceId.isValid(traceId)).isTrue();
|
||||
String spanId = generator.generateSpanId();
|
||||
assertThat(SpanId.isValid(spanId)).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGenerateTraceIdsWithTimestampsWithAllowedXrayTimeRange() {
|
||||
AwsXrayIdGenerator generator = AwsXrayIdGenerator.getInstance();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
String traceId = generator.generateTraceId();
|
||||
long unixSeconds = Long.valueOf(traceId.subSequence(0, 8).toString(), 16);
|
||||
long ts = unixSeconds * 1000L;
|
||||
long currentTs = System.currentTimeMillis();
|
||||
assertThat(ts).isLessThanOrEqualTo(currentTs);
|
||||
long month = 86400000L * 30L;
|
||||
assertThat(ts).isGreaterThan(currentTs - month);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGenerateUniqueIdsInMultithreadedEnvironment()
|
||||
throws BrokenBarrierException, InterruptedException {
|
||||
AwsXrayIdGenerator generator = AwsXrayIdGenerator.getInstance();
|
||||
Set<String> traceIds = new CopyOnWriteArraySet<>();
|
||||
Set<String> spanIds = new CopyOnWriteArraySet<>();
|
||||
int threads = 8;
|
||||
int generations = 128;
|
||||
CyclicBarrier barrier = new CyclicBarrier(threads + 1);
|
||||
Executor executor = Executors.newFixedThreadPool(threads);
|
||||
for (int i = 0; i < threads; i++) {
|
||||
executor.execute(new GenerateRunner(generations, generator, barrier, traceIds, spanIds));
|
||||
}
|
||||
barrier.await();
|
||||
barrier.await();
|
||||
assertThat(traceIds).hasSize(threads * generations);
|
||||
assertThat(spanIds).hasSize(threads * generations);
|
||||
}
|
||||
|
||||
static class GenerateRunner implements Runnable {
|
||||
|
||||
private final int generations;
|
||||
private final IdGenerator idsGenerator;
|
||||
private final CyclicBarrier barrier;
|
||||
private final Set<String> traceIds;
|
||||
private final Set<String> spanIds;
|
||||
|
||||
GenerateRunner(
|
||||
int generations,
|
||||
IdGenerator idsGenerator,
|
||||
CyclicBarrier barrier,
|
||||
Set<String> traceIds,
|
||||
Set<String> spanIds) {
|
||||
this.generations = generations;
|
||||
this.idsGenerator = idsGenerator;
|
||||
this.barrier = barrier;
|
||||
this.traceIds = traceIds;
|
||||
this.spanIds = spanIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
barrier.await();
|
||||
for (int i = 0; i < generations; i++) {
|
||||
traceIds.add(idsGenerator.generateTraceId());
|
||||
spanIds.add(idsGenerator.generateSpanId());
|
||||
}
|
||||
barrier.await();
|
||||
} catch (InterruptedException | BrokenBarrierException cause) {
|
||||
throw new IllegalStateException(cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"DockerId": "43481a6ce4842eec8fe72fc28500c6b52edcc0917f105b83379f88cac1ff3946",
|
||||
"Name": "nginx-curl",
|
||||
"DockerName": "ecs-nginx-5-nginx-curl-ccccb9f49db0dfe0d901",
|
||||
"Image": "nrdlngr/nginx-curl",
|
||||
"ImageID": "sha256:2e00ae64383cfc865ba0a2ba37f61b50a120d2d9378559dcd458dc0de47bc165",
|
||||
"Labels": {
|
||||
"com.amazonaws.ecs.cluster": "default",
|
||||
"com.amazonaws.ecs.container-name": "nginx-curl",
|
||||
"com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3",
|
||||
"com.amazonaws.ecs.task-definition-family": "nginx",
|
||||
"com.amazonaws.ecs.task-definition-version": "5"
|
||||
},
|
||||
"DesiredStatus": "RUNNING",
|
||||
"KnownStatus": "RUNNING",
|
||||
"Limits": {
|
||||
"CPU": 512,
|
||||
"Memory": 512
|
||||
},
|
||||
"CreatedAt": "2018-02-01T20:55:10.554941919Z",
|
||||
"StartedAt": "2018-02-01T20:55:11.064236631Z",
|
||||
"Type": "NORMAL",
|
||||
"Networks": [
|
||||
{
|
||||
"NetworkMode": "awsvpc",
|
||||
"IPv4Addresses": [
|
||||
"10.0.2.106"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
"DockerId": "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66",
|
||||
"Name": "curl",
|
||||
"DockerName": "ecs-curltest-26-curl-cca48e8dcadd97805600",
|
||||
"Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest",
|
||||
"ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553",
|
||||
"Labels": {
|
||||
"com.amazonaws.ecs.cluster": "default",
|
||||
"com.amazonaws.ecs.container-name": "curl",
|
||||
"com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/8f03e41243824aea923aca126495f665",
|
||||
"com.amazonaws.ecs.task-definition-family": "curltest",
|
||||
"com.amazonaws.ecs.task-definition-version": "26"
|
||||
},
|
||||
"DesiredStatus": "RUNNING",
|
||||
"KnownStatus": "RUNNING",
|
||||
"Limits": {
|
||||
"CPU": 10,
|
||||
"Memory": 128
|
||||
},
|
||||
"CreatedAt": "2020-10-02T00:15:07.620912337Z",
|
||||
"StartedAt": "2020-10-02T00:15:08.062559351Z",
|
||||
"Type": "NORMAL",
|
||||
"LogDriver": "awslogs",
|
||||
"LogOptions": {
|
||||
"awslogs-create-group": "true",
|
||||
"awslogs-group": "/ecs/metadata",
|
||||
"awslogs-region": "us-west-2",
|
||||
"awslogs-stream": "ecs/curl/8f03e41243824aea923aca126495f665"
|
||||
},
|
||||
"ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9",
|
||||
"Networks": [
|
||||
{
|
||||
"NetworkMode": "awsvpc",
|
||||
"IPv4Addresses": [
|
||||
"10.0.2.100"
|
||||
],
|
||||
"AttachmentIndex": 0,
|
||||
"MACAddress": "0e:9e:32:c7:48:85",
|
||||
"IPv4SubnetCIDRBlock": "10.0.2.0/24",
|
||||
"PrivateDNSName": "ip-10-0-2-100.us-west-2.compute.internal",
|
||||
"SubnetGatewayIpv4Address": "10.0.2.1/24"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
"Cluster": "default",
|
||||
"TaskARN": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3",
|
||||
"Family": "nginx",
|
||||
"Revision": "5",
|
||||
"DesiredStatus": "RUNNING",
|
||||
"KnownStatus": "RUNNING",
|
||||
"Containers": [
|
||||
{
|
||||
"DockerId": "731a0d6a3b4210e2448339bc7015aaa79bfe4fa256384f4102db86ef94cbbc4c",
|
||||
"Name": "~internal~ecs~pause",
|
||||
"DockerName": "ecs-nginx-5-internalecspause-acc699c0cbf2d6d11700",
|
||||
"Image": "amazon/amazon-ecs-pause:0.1.0",
|
||||
"ImageID": "",
|
||||
"Labels": {
|
||||
"com.amazonaws.ecs.cluster": "default",
|
||||
"com.amazonaws.ecs.container-name": "~internal~ecs~pause",
|
||||
"com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3",
|
||||
"com.amazonaws.ecs.task-definition-family": "nginx",
|
||||
"com.amazonaws.ecs.task-definition-version": "5"
|
||||
},
|
||||
"DesiredStatus": "RESOURCES_PROVISIONED",
|
||||
"KnownStatus": "RESOURCES_PROVISIONED",
|
||||
"Limits": {
|
||||
"CPU": 0,
|
||||
"Memory": 0
|
||||
},
|
||||
"CreatedAt": "2018-02-01T20:55:08.366329616Z",
|
||||
"StartedAt": "2018-02-01T20:55:09.058354915Z",
|
||||
"Type": "CNI_PAUSE",
|
||||
"Networks": [
|
||||
{
|
||||
"NetworkMode": "awsvpc",
|
||||
"IPv4Addresses": [
|
||||
"10.0.2.106"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DockerId": "43481a6ce4842eec8fe72fc28500c6b52edcc0917f105b83379f88cac1ff3946",
|
||||
"Name": "nginx-curl",
|
||||
"DockerName": "ecs-nginx-5-nginx-curl-ccccb9f49db0dfe0d901",
|
||||
"Image": "nrdlngr/nginx-curl",
|
||||
"ImageID": "sha256:2e00ae64383cfc865ba0a2ba37f61b50a120d2d9378559dcd458dc0de47bc165",
|
||||
"Labels": {
|
||||
"com.amazonaws.ecs.cluster": "default",
|
||||
"com.amazonaws.ecs.container-name": "nginx-curl",
|
||||
"com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3",
|
||||
"com.amazonaws.ecs.task-definition-family": "nginx",
|
||||
"com.amazonaws.ecs.task-definition-version": "5"
|
||||
},
|
||||
"DesiredStatus": "RUNNING",
|
||||
"KnownStatus": "RUNNING",
|
||||
"Limits": {
|
||||
"CPU": 512,
|
||||
"Memory": 512
|
||||
},
|
||||
"CreatedAt": "2018-02-01T20:55:10.554941919Z",
|
||||
"StartedAt": "2018-02-01T20:55:11.064236631Z",
|
||||
"Type": "NORMAL",
|
||||
"Networks": [
|
||||
{
|
||||
"NetworkMode": "awsvpc",
|
||||
"IPv4Addresses": [
|
||||
"10.0.2.106"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PullStartedAt": "2018-02-01T20:55:09.372495529Z",
|
||||
"PullStoppedAt": "2018-02-01T20:55:10.552018345Z",
|
||||
"AvailabilityZone": "us-east-2b"
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
{
|
||||
"Cluster": "default",
|
||||
"TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c",
|
||||
"Family": "curltest",
|
||||
"Revision": "26",
|
||||
"DesiredStatus": "RUNNING",
|
||||
"KnownStatus": "RUNNING",
|
||||
"PullStartedAt": "2020-10-02T00:43:06.202617438Z",
|
||||
"PullStoppedAt": "2020-10-02T00:43:06.31288465Z",
|
||||
"AvailabilityZone": "us-west-2d",
|
||||
"LaunchType": "EC2",
|
||||
"Containers": [
|
||||
{
|
||||
"DockerId": "598cba581fe3f939459eaba1e071d5c93bb2c49b7d1ba7db6bb19deeb70d8e38",
|
||||
"Name": "~internal~ecs~pause",
|
||||
"DockerName": "ecs-curltest-26-internalecspause-e292d586b6f9dade4a00",
|
||||
"Image": "amazon/amazon-ecs-pause:0.1.0",
|
||||
"ImageID": "",
|
||||
"Labels": {
|
||||
"com.amazonaws.ecs.cluster": "default",
|
||||
"com.amazonaws.ecs.container-name": "~internal~ecs~pause",
|
||||
"com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c",
|
||||
"com.amazonaws.ecs.task-definition-family": "curltest",
|
||||
"com.amazonaws.ecs.task-definition-version": "26"
|
||||
},
|
||||
"DesiredStatus": "RESOURCES_PROVISIONED",
|
||||
"KnownStatus": "RESOURCES_PROVISIONED",
|
||||
"Limits": {
|
||||
"CPU": 0,
|
||||
"Memory": 0
|
||||
},
|
||||
"CreatedAt": "2020-10-02T00:43:05.602352471Z",
|
||||
"StartedAt": "2020-10-02T00:43:06.076707576Z",
|
||||
"Type": "CNI_PAUSE",
|
||||
"Networks": [
|
||||
{
|
||||
"NetworkMode": "awsvpc",
|
||||
"IPv4Addresses": [
|
||||
"10.0.2.61"
|
||||
],
|
||||
"AttachmentIndex": 0,
|
||||
"MACAddress": "0e:10:e2:01:bd:91",
|
||||
"IPv4SubnetCIDRBlock": "10.0.2.0/24",
|
||||
"PrivateDNSName": "ip-10-0-2-61.us-west-2.compute.internal",
|
||||
"SubnetGatewayIpv4Address": "10.0.2.1/24"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DockerId": "ee08638adaaf009d78c248913f629e38299471d45fe7dc944d1039077e3424ca",
|
||||
"Name": "curl",
|
||||
"DockerName": "ecs-curltest-26-curl-a0e7dba5aca6d8cb2e00",
|
||||
"Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest",
|
||||
"ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553",
|
||||
"Labels": {
|
||||
"com.amazonaws.ecs.cluster": "default",
|
||||
"com.amazonaws.ecs.container-name": "curl",
|
||||
"com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c",
|
||||
"com.amazonaws.ecs.task-definition-family": "curltest",
|
||||
"com.amazonaws.ecs.task-definition-version": "26"
|
||||
},
|
||||
"DesiredStatus": "RUNNING",
|
||||
"KnownStatus": "RUNNING",
|
||||
"Limits": {
|
||||
"CPU": 10,
|
||||
"Memory": 128
|
||||
},
|
||||
"CreatedAt": "2020-10-02T00:43:06.326590752Z",
|
||||
"StartedAt": "2020-10-02T00:43:06.767535449Z",
|
||||
"Type": "NORMAL",
|
||||
"LogDriver": "awslogs",
|
||||
"LogOptions": {
|
||||
"awslogs-create-group": "true",
|
||||
"awslogs-group": "/ecs/metadata",
|
||||
"awslogs-region": "us-west-2",
|
||||
"awslogs-stream": "ecs/curl/158d1c8083dd49d6b527399fd6414f5c"
|
||||
},
|
||||
"ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/abb51bdd-11b4-467f-8f6c-adcfe1fe059d",
|
||||
"Networks": [
|
||||
{
|
||||
"NetworkMode": "awsvpc",
|
||||
"IPv4Addresses": [
|
||||
"10.0.2.61"
|
||||
],
|
||||
"AttachmentIndex": 0,
|
||||
"MACAddress": "0e:10:e2:01:bd:91",
|
||||
"IPv4SubnetCIDRBlock": "10.0.2.0/24",
|
||||
"PrivateDNSName": "ip-10-0-2-61.us-west-2.compute.internal",
|
||||
"SubnetGatewayIpv4Address": "10.0.2.1/24"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -61,7 +61,6 @@ include(":sdk:trace")
|
|||
include(":sdk:trace-shaded-deps")
|
||||
include(":sdk-extensions:autoconfigure")
|
||||
include(":sdk-extensions:autoconfigure-spi")
|
||||
include(":sdk-extensions:aws")
|
||||
include(":sdk-extensions:resources")
|
||||
include(":sdk-extensions:incubator")
|
||||
include(":sdk-extensions:jaeger-remote-sampler")
|
||||
|
|
|
|||
Loading…
Reference in New Issue