aboutsummaryrefslogtreecommitdiff
path: root/contrib/monitored_resource_util
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/monitored_resource_util')
-rw-r--r--contrib/monitored_resource_util/README.md34
-rw-r--r--contrib/monitored_resource_util/build.gradle15
-rw-r--r--contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtils.java137
-rw-r--r--contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/GcpMetadataConfig.java90
-rw-r--r--contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResource.java305
-rw-r--r--contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtils.java54
-rw-r--r--contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/ResourceType.java47
-rw-r--r--contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtilsTest.java57
-rw-r--r--contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceTest.java83
-rw-r--r--contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtilsTest.java42
10 files changed, 864 insertions, 0 deletions
diff --git a/contrib/monitored_resource_util/README.md b/contrib/monitored_resource_util/README.md
new file mode 100644
index 00000000..9d3c754c
--- /dev/null
+++ b/contrib/monitored_resource_util/README.md
@@ -0,0 +1,34 @@
+# OpenCensus Monitored Resources Util
+[![Build Status][travis-image]][travis-url]
+[![Windows Build Status][appveyor-image]][appveyor-url]
+[![Maven Central][maven-image]][maven-url]
+
+The *OpenCensus Monitored Resource Util for Java* is a collection of utilities for auto detecting
+monitored resource when exporting stats, based on the environment where the application is running.
+
+## Quickstart
+
+### Add the dependencies to your project
+
+For Maven add to your `pom.xml`:
+```xml
+<dependencies>
+ <dependency>
+ <groupId>io.opencensus</groupId>
+ <artifactId>opencensus-contrib-monitored-resource-util</artifactId>
+ <version>0.16.1</version>
+ </dependency>
+</dependencies>
+```
+
+For Gradle add to your dependencies:
+```gradle
+compile 'io.opencensus:opencensus-contrib-monitored-resource-util:0.16.1'
+```
+
+[travis-image]: https://travis-ci.org/census-instrumentation/opencensus-java.svg?branch=master
+[travis-url]: https://travis-ci.org/census-instrumentation/opencensus-java
+[appveyor-image]: https://ci.appveyor.com/api/projects/status/hxthmpkxar4jq4be/branch/master?svg=true
+[appveyor-url]: https://ci.appveyor.com/project/opencensusjavateam/opencensus-java/branch/master
+[maven-image]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-contrib-monitoredresource-util/badge.svg
+[maven-url]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-contrib-monitoredresource-util
diff --git a/contrib/monitored_resource_util/build.gradle b/contrib/monitored_resource_util/build.gradle
new file mode 100644
index 00000000..1e25c7cf
--- /dev/null
+++ b/contrib/monitored_resource_util/build.gradle
@@ -0,0 +1,15 @@
+description = 'OpenCensus Monitored Resource Util'
+
+apply plugin: 'java'
+
+[compileJava, compileTestJava].each() {
+ it.sourceCompatibility = 1.6
+ it.targetCompatibility = 1.6
+}
+
+dependencies {
+ compileOnly libraries.auto_value
+
+ signature "org.codehaus.mojo.signature:java17:1.0@signature"
+ signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature"
+}
diff --git a/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtils.java b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtils.java
new file mode 100644
index 00000000..03b0bd4d
--- /dev/null
+++ b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtils.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.concurrent.GuardedBy;
+
+/** Util methods for getting and parsing AWS instance identity document. */
+final class AwsIdentityDocUtils {
+
+ private static final Object monitor = new Object();
+ private static final int AWS_IDENTITY_DOC_BUF_SIZE = 0x800; // 2K chars (4K bytes)
+ private static final String AWS_IDENTITY_DOC_LINE_BREAK_SPLITTER = "\n";
+ private static final String AWS_IDENTITY_DOC_COLON_SPLITTER = ":";
+
+ private static final URI AWS_INSTANCE_IDENTITY_DOCUMENT_URI =
+ URI.create("http://169.254.169.254/latest/dynamic/instance-identity/document");
+
+ @GuardedBy("monitor")
+ @javax.annotation.Nullable
+ private static Map<String, String> awsEnvVarMap = null;
+
+ // Detects if the application is running on EC2 by making a connection to AWS instance
+ // identity document URI. If connection is successful, application should be on an EC2 instance.
+ private static volatile boolean isRunningOnAwsEc2 = false;
+
+ static {
+ initializeAwsIdentityDocument();
+ }
+
+ static boolean isRunningOnAwsEc2() {
+ return isRunningOnAwsEc2;
+ }
+
+ // Tries to establish an HTTP connection to AWS instance identity document url. If the application
+ // is running on an EC2 instance, we should be able to get back a valid JSON document. Parses that
+ // document and stores the identity properties in a local map.
+ // This method should only be called once.
+ private static void initializeAwsIdentityDocument() {
+ InputStream stream = null;
+ try {
+ stream = openStream(AWS_INSTANCE_IDENTITY_DOCUMENT_URI);
+ String awsIdentityDocument = slurp(new InputStreamReader(stream, Charset.forName("UTF-8")));
+ synchronized (monitor) {
+ awsEnvVarMap = parseAwsIdentityDocument(awsIdentityDocument);
+ }
+ isRunningOnAwsEc2 = true;
+ } catch (IOException e) {
+ // Cannot connect to http://169.254.169.254/latest/dynamic/instance-identity/document.
+ // Not on an AWS EC2 instance.
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // Do nothing.
+ }
+ }
+ }
+ }
+
+ /** quick http client that allows no-dependency try at getting instance data. */
+ private static InputStream openStream(URI uri) throws IOException {
+ HttpURLConnection connection = HttpURLConnection.class.cast(uri.toURL().openConnection());
+ connection.setConnectTimeout(1000 * 2);
+ connection.setReadTimeout(1000 * 2);
+ connection.setAllowUserInteraction(false);
+ connection.setInstanceFollowRedirects(false);
+ return connection.getInputStream();
+ }
+
+ /** returns the {@code reader} as a string without closing it. */
+ private static String slurp(Reader reader) throws IOException {
+ StringBuilder to = new StringBuilder();
+ CharBuffer buf = CharBuffer.allocate(AWS_IDENTITY_DOC_BUF_SIZE);
+ while (reader.read(buf) != -1) {
+ buf.flip();
+ to.append(buf);
+ buf.clear();
+ }
+ return to.toString();
+ }
+
+ // AWS Instance Identity Document is a JSON file.
+ // See docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html.
+ static Map<String, String> parseAwsIdentityDocument(String awsIdentityDocument) {
+ Map<String, String> map = new HashMap<String, String>();
+ @SuppressWarnings("StringSplitter")
+ String[] lines = awsIdentityDocument.split(AWS_IDENTITY_DOC_LINE_BREAK_SPLITTER, -1);
+ for (String line : lines) {
+ @SuppressWarnings("StringSplitter")
+ String[] keyValuePair = line.split(AWS_IDENTITY_DOC_COLON_SPLITTER, -1);
+ if (keyValuePair.length != 2) {
+ continue;
+ }
+ String key = keyValuePair[0].replaceAll("[\" ]", "");
+ String value = keyValuePair[1].replaceAll("[\" ,]", "");
+ map.put(key, value);
+ }
+ return map;
+ }
+
+ @javax.annotation.Nullable
+ static String getValueFromAwsIdentityDocument(String key) {
+ synchronized (monitor) {
+ if (awsEnvVarMap == null) {
+ return null;
+ }
+ return awsEnvVarMap.get(key);
+ }
+ }
+
+ private AwsIdentityDocUtils() {}
+}
diff --git a/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/GcpMetadataConfig.java b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/GcpMetadataConfig.java
new file mode 100644
index 00000000..c09d1c65
--- /dev/null
+++ b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/GcpMetadataConfig.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.Charset;
+import javax.annotation.Nullable;
+
+/**
+ * Retrieves Google Cloud project-id and a limited set of instance attributes from Metadata server.
+ *
+ * @see <a href="https://cloud.google.com/compute/docs/storing-retrieving-metadata">
+ * https://cloud.google.com/compute/docs/storing-retrieving-metadata</a>
+ */
+final class GcpMetadataConfig {
+
+ private static final String METADATA_URL = "http://metadata/computeMetadata/v1/";
+
+ private GcpMetadataConfig() {}
+
+ @Nullable
+ static String getProjectId() {
+ return getAttribute("project/project-id");
+ }
+
+ @Nullable
+ static String getZone() {
+ String zoneId = getAttribute("instance/zone");
+ if (zoneId == null) {
+ return null;
+ }
+ if (zoneId.contains("/")) {
+ return zoneId.substring(zoneId.lastIndexOf('/') + 1);
+ }
+ return zoneId;
+ }
+
+ @Nullable
+ static String getInstanceId() {
+ return getAttribute("instance/id");
+ }
+
+ @Nullable
+ static String getClusterName() {
+ return getAttribute("instance/attributes/cluster-name");
+ }
+
+ @Nullable
+ private static String getAttribute(String attributeName) {
+ try {
+ URL url = new URL(METADATA_URL + attributeName);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestProperty("Metadata-Flavor", "Google");
+ InputStream input = connection.getInputStream();
+ if (connection.getResponseCode() == 200) {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(input, Charset.forName("UTF-8")));
+ return reader.readLine();
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+ } catch (IOException ignore) {
+ // ignore
+ }
+ return null;
+ }
+}
diff --git a/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResource.java b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResource.java
new file mode 100644
index 00000000..c828906d
--- /dev/null
+++ b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResource.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+import com.google.auto.value.AutoValue;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * {@link MonitoredResource} represents an auto-detected monitored resource used by application for
+ * exporting stats. It has a {@code ResourceType} associated with a mapping from resource labels to
+ * values.
+ *
+ * @since 0.13
+ */
+@Immutable
+public abstract class MonitoredResource {
+
+ MonitoredResource() {}
+
+ /**
+ * Returns the {@link ResourceType} of this {@link MonitoredResource}.
+ *
+ * @return the {@code ResourceType}.
+ * @since 0.13
+ */
+ public abstract ResourceType getResourceType();
+
+ /*
+ * Returns the first of two given parameters that is not null, if either is, or otherwise
+ * throws a NullPointerException.
+ */
+ private static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
+ if (first != null) {
+ return first;
+ }
+ if (second != null) {
+ return second;
+ }
+ throw new NullPointerException("Both parameters are null");
+ }
+
+ // TODO(songya): consider using a tagged union match() approach (that will introduce
+ // dependency on opencensus-api).
+
+ /**
+ * {@link MonitoredResource} for AWS EC2 instance.
+ *
+ * @since 0.13
+ */
+ @Immutable
+ @AutoValue
+ public abstract static class AwsEc2InstanceMonitoredResource extends MonitoredResource {
+
+ private static final String AWS_ACCOUNT =
+ firstNonNull(AwsIdentityDocUtils.getValueFromAwsIdentityDocument("accountId"), "");
+ private static final String AWS_INSTANCE_ID =
+ firstNonNull(AwsIdentityDocUtils.getValueFromAwsIdentityDocument("instanceId"), "");
+ private static final String AWS_REGION =
+ firstNonNull(AwsIdentityDocUtils.getValueFromAwsIdentityDocument("region"), "");
+
+ @Override
+ public ResourceType getResourceType() {
+ return ResourceType.AWS_EC2_INSTANCE;
+ }
+
+ /**
+ * Returns the AWS account ID.
+ *
+ * @return the AWS account ID.
+ * @since 0.13
+ */
+ public abstract String getAccount();
+
+ /**
+ * Returns the AWS EC2 instance ID.
+ *
+ * @return the AWS EC2 instance ID.
+ * @since 0.13
+ */
+ public abstract String getInstanceId();
+
+ /**
+ * Returns the AWS region.
+ *
+ * @return the AWS region.
+ * @since 0.13
+ */
+ public abstract String getRegion();
+
+ /**
+ * Returns an {@link AwsEc2InstanceMonitoredResource}.
+ *
+ * @param account the AWS account ID.
+ * @param instanceId the AWS EC2 instance ID.
+ * @param region the AWS region.
+ * @return an {@code AwsEc2InstanceMonitoredResource}.
+ * @since 0.15
+ */
+ public static AwsEc2InstanceMonitoredResource create(
+ String account, String instanceId, String region) {
+ return new AutoValue_MonitoredResource_AwsEc2InstanceMonitoredResource(
+ account, instanceId, region);
+ }
+
+ static AwsEc2InstanceMonitoredResource create() {
+ return create(AWS_ACCOUNT, AWS_INSTANCE_ID, AWS_REGION);
+ }
+ }
+
+ /**
+ * {@link MonitoredResource} for GCP GCE instance.
+ *
+ * @since 0.13
+ */
+ @Immutable
+ @AutoValue
+ public abstract static class GcpGceInstanceMonitoredResource extends MonitoredResource {
+
+ private static final String GCP_ACCOUNT_ID = firstNonNull(GcpMetadataConfig.getProjectId(), "");
+ private static final String GCP_INSTANCE_ID =
+ firstNonNull(GcpMetadataConfig.getInstanceId(), "");
+ private static final String GCP_ZONE = firstNonNull(GcpMetadataConfig.getZone(), "");
+
+ @Override
+ public ResourceType getResourceType() {
+ return ResourceType.GCP_GCE_INSTANCE;
+ }
+
+ /**
+ * Returns the GCP account number for the instance.
+ *
+ * @return the GCP account number for the instance.
+ * @since 0.13
+ */
+ public abstract String getAccount();
+
+ /**
+ * Returns the GCP GCE instance ID.
+ *
+ * @return the GCP GCE instance ID.
+ * @since 0.13
+ */
+ public abstract String getInstanceId();
+
+ /**
+ * Returns the GCP zone.
+ *
+ * @return the GCP zone.
+ * @since 0.13
+ */
+ public abstract String getZone();
+
+ /**
+ * Returns a {@link GcpGceInstanceMonitoredResource}.
+ *
+ * @param account the GCP account number.
+ * @param instanceId the GCP GCE instance ID.
+ * @param zone the GCP zone.
+ * @return a {@code GcpGceInstanceMonitoredResource}.
+ * @since 0.15
+ */
+ public static GcpGceInstanceMonitoredResource create(
+ String account, String instanceId, String zone) {
+ return new AutoValue_MonitoredResource_GcpGceInstanceMonitoredResource(
+ account, instanceId, zone);
+ }
+
+ static GcpGceInstanceMonitoredResource create() {
+ return create(GCP_ACCOUNT_ID, GCP_INSTANCE_ID, GCP_ZONE);
+ }
+ }
+
+ /**
+ * {@link MonitoredResource} for GCP GKE container.
+ *
+ * @since 0.13
+ */
+ @Immutable
+ @AutoValue
+ public abstract static class GcpGkeContainerMonitoredResource extends MonitoredResource {
+
+ private static final String GCP_ACCOUNT_ID = firstNonNull(GcpMetadataConfig.getProjectId(), "");
+ private static final String GCP_CLUSTER_NAME =
+ firstNonNull(GcpMetadataConfig.getClusterName(), "");
+ private static final String GCP_CONTAINER_NAME =
+ firstNonNull(System.getenv("CONTAINER_NAME"), "");
+ private static final String GCP_NAMESPACE_ID = firstNonNull(System.getenv("NAMESPACE"), "");
+ private static final String GCP_INSTANCE_ID =
+ firstNonNull(GcpMetadataConfig.getInstanceId(), "");
+ private static final String GCP_POD_ID = firstNonNull(System.getenv("HOSTNAME"), "");
+ private static final String GCP_ZONE = firstNonNull(GcpMetadataConfig.getZone(), "");
+
+ @Override
+ public ResourceType getResourceType() {
+ return ResourceType.GCP_GKE_CONTAINER;
+ }
+
+ /**
+ * Returns the GCP account number for the instance.
+ *
+ * @return the GCP account number for the instance.
+ * @since 0.13
+ */
+ public abstract String getAccount();
+
+ /**
+ * Returns the GCP GKE cluster name.
+ *
+ * @return the GCP GKE cluster name.
+ * @since 0.13
+ */
+ public abstract String getClusterName();
+
+ /**
+ * Returns the GCP GKE container name.
+ *
+ * @return the GCP GKE container name.
+ * @since 0.13
+ */
+ public abstract String getContainerName();
+
+ /**
+ * Returns the GCP GKE namespace ID.
+ *
+ * @return the GCP GKE namespace ID.
+ * @since 0.13
+ */
+ public abstract String getNamespaceId();
+
+ /**
+ * Returns the GCP GKE instance ID.
+ *
+ * @return the GCP GKE instance ID.
+ * @since 0.13
+ */
+ public abstract String getInstanceId();
+
+ /**
+ * Returns the GCP GKE Pod ID.
+ *
+ * @return the GCP GKE Pod ID.
+ * @since 0.13
+ */
+ public abstract String getPodId();
+
+ /**
+ * Returns the GCP zone.
+ *
+ * @return the GCP zone.
+ * @since 0.13
+ */
+ public abstract String getZone();
+
+ /**
+ * Returns a {@link GcpGkeContainerMonitoredResource}.
+ *
+ * @param account the GCP account number.
+ * @param clusterName the GCP GKE cluster name.
+ * @param containerName the GCP GKE container name.
+ * @param namespaceId the GCP GKE namespace ID.
+ * @param instanceId the GCP GKE instance ID.
+ * @param podId the GCP GKE Pod ID.
+ * @param zone the GCP zone.
+ * @return a {@code GcpGkeContainerMonitoredResource}.
+ * @since 0.15
+ */
+ public static GcpGkeContainerMonitoredResource create(
+ String account,
+ String clusterName,
+ String containerName,
+ String namespaceId,
+ String instanceId,
+ String podId,
+ String zone) {
+ return new AutoValue_MonitoredResource_GcpGkeContainerMonitoredResource(
+ account, clusterName, containerName, namespaceId, instanceId, podId, zone);
+ }
+
+ static GcpGkeContainerMonitoredResource create() {
+ return create(
+ GCP_ACCOUNT_ID,
+ GCP_CLUSTER_NAME,
+ GCP_CONTAINER_NAME,
+ GCP_NAMESPACE_ID,
+ GCP_INSTANCE_ID,
+ GCP_POD_ID,
+ GCP_ZONE);
+ }
+ }
+}
diff --git a/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtils.java b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtils.java
new file mode 100644
index 00000000..8ff0ff98
--- /dev/null
+++ b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtils.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+import io.opencensus.contrib.monitoredresource.util.MonitoredResource.AwsEc2InstanceMonitoredResource;
+import io.opencensus.contrib.monitoredresource.util.MonitoredResource.GcpGceInstanceMonitoredResource;
+import io.opencensus.contrib.monitoredresource.util.MonitoredResource.GcpGkeContainerMonitoredResource;
+import javax.annotation.Nullable;
+
+/**
+ * Utilities for for auto detecting monitored resource based on the environment where the
+ * application is running.
+ *
+ * @since 0.13
+ */
+public final class MonitoredResourceUtils {
+
+ /**
+ * Returns a self-configured monitored resource, or {@code null} if the application is not running
+ * on a supported environment.
+ *
+ * @return a {@code MonitoredResource}.
+ * @since 0.13
+ */
+ @Nullable
+ public static MonitoredResource getDefaultResource() {
+ if (System.getenv("KUBERNETES_SERVICE_HOST") != null) {
+ return GcpGkeContainerMonitoredResource.create();
+ }
+ if (GcpMetadataConfig.getInstanceId() != null) {
+ return GcpGceInstanceMonitoredResource.create();
+ }
+ if (AwsIdentityDocUtils.isRunningOnAwsEc2()) {
+ return AwsEc2InstanceMonitoredResource.create();
+ }
+ return null;
+ }
+
+ private MonitoredResourceUtils() {}
+}
diff --git a/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/ResourceType.java b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/ResourceType.java
new file mode 100644
index 00000000..f2816676
--- /dev/null
+++ b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/ResourceType.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+/**
+ * {@link ResourceType} represents the type of supported monitored resources that can be
+ * automatically detected by OpenCensus.
+ *
+ * @since 0.13
+ */
+public enum ResourceType {
+
+ /**
+ * Resource for GCP GKE container.
+ *
+ * @since 0.13
+ */
+ GCP_GKE_CONTAINER,
+
+ /**
+ * Resource for GCP GCE instance.
+ *
+ * @since 0.13
+ */
+ GCP_GCE_INSTANCE,
+
+ /**
+ * Resource for AWS EC2 instance.
+ *
+ * @since 0.13
+ */
+ AWS_EC2_INSTANCE
+}
diff --git a/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtilsTest.java b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtilsTest.java
new file mode 100644
index 00000000..77d98493
--- /dev/null
+++ b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtilsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link AwsIdentityDocUtils}. */
+@RunWith(JUnit4.class)
+public class AwsIdentityDocUtilsTest {
+
+ private static final String SAMPLE_AWS_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"
+ + "}";
+
+ @Test
+ public void testParseAwsIdentityDocument() {
+ Map<String, String> envVarMap =
+ AwsIdentityDocUtils.parseAwsIdentityDocument(SAMPLE_AWS_IDENTITY_DOCUMENT);
+ assertThat(envVarMap).containsEntry("instanceId", "i-1234567890abcdef0");
+ assertThat(envVarMap).containsEntry("accountId", "123456789012");
+ assertThat(envVarMap).containsEntry("region", "us-west-2");
+ }
+}
diff --git a/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceTest.java b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceTest.java
new file mode 100644
index 00000000..0defcbd7
--- /dev/null
+++ b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import io.opencensus.contrib.monitoredresource.util.MonitoredResource.AwsEc2InstanceMonitoredResource;
+import io.opencensus.contrib.monitoredresource.util.MonitoredResource.GcpGceInstanceMonitoredResource;
+import io.opencensus.contrib.monitoredresource.util.MonitoredResource.GcpGkeContainerMonitoredResource;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link MonitoredResource}. */
+@RunWith(JUnit4.class)
+public class MonitoredResourceTest {
+
+ private static final String AWS_ACCOUNT = "aws-account";
+ private static final String AWS_INSTANCE = "instance";
+ private static final String AWS_REGION = "us-west-2";
+ private static final String GCP_PROJECT = "gcp-project";
+ private static final String GCP_INSTANCE = "instance";
+ private static final String GCP_ZONE = "us-east1";
+ private static final String GCP_GKE_NAMESPACE = "namespace";
+ private static final String GCP_GKE_POD_ID = "pod-id";
+ private static final String GCP_GKE_CONTAINER_NAME = "container";
+ private static final String GCP_GKE_CLUSTER_NAME = "cluster";
+
+ @Test
+ public void testAwsEc2InstanceMonitoredResource() {
+ AwsEc2InstanceMonitoredResource resource =
+ AwsEc2InstanceMonitoredResource.create(AWS_ACCOUNT, AWS_INSTANCE, AWS_REGION);
+ assertThat(resource.getResourceType()).isEqualTo(ResourceType.AWS_EC2_INSTANCE);
+ assertThat(resource.getAccount()).isEqualTo(AWS_ACCOUNT);
+ assertThat(resource.getInstanceId()).isEqualTo(AWS_INSTANCE);
+ assertThat(resource.getRegion()).isEqualTo(AWS_REGION);
+ }
+
+ @Test
+ public void testGcpGceInstanceMonitoredResource() {
+ GcpGceInstanceMonitoredResource resource =
+ GcpGceInstanceMonitoredResource.create(GCP_PROJECT, GCP_INSTANCE, GCP_ZONE);
+ assertThat(resource.getResourceType()).isEqualTo(ResourceType.GCP_GCE_INSTANCE);
+ assertThat(resource.getAccount()).isEqualTo(GCP_PROJECT);
+ assertThat(resource.getInstanceId()).isEqualTo(GCP_INSTANCE);
+ assertThat(resource.getZone()).isEqualTo(GCP_ZONE);
+ }
+
+ @Test
+ public void testGcpGkeContainerMonitoredResource() {
+ GcpGkeContainerMonitoredResource resource =
+ GcpGkeContainerMonitoredResource.create(
+ GCP_PROJECT,
+ GCP_GKE_CLUSTER_NAME,
+ GCP_GKE_CONTAINER_NAME,
+ GCP_GKE_NAMESPACE,
+ GCP_INSTANCE,
+ GCP_GKE_POD_ID,
+ GCP_ZONE);
+ assertThat(resource.getResourceType()).isEqualTo(ResourceType.GCP_GKE_CONTAINER);
+ assertThat(resource.getAccount()).isEqualTo(GCP_PROJECT);
+ assertThat(resource.getClusterName()).isEqualTo(GCP_GKE_CLUSTER_NAME);
+ assertThat(resource.getContainerName()).isEqualTo(GCP_GKE_CONTAINER_NAME);
+ assertThat(resource.getNamespaceId()).isEqualTo(GCP_GKE_NAMESPACE);
+ assertThat(resource.getInstanceId()).isEqualTo(GCP_INSTANCE);
+ assertThat(resource.getPodId()).isEqualTo(GCP_GKE_POD_ID);
+ assertThat(resource.getZone()).isEqualTo(GCP_ZONE);
+ }
+}
diff --git a/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtilsTest.java b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtilsTest.java
new file mode 100644
index 00000000..01927a2d
--- /dev/null
+++ b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtilsTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018, OpenCensus Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.opencensus.contrib.monitoredresource.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link MonitoredResourceUtils}. */
+@RunWith(JUnit4.class)
+public class MonitoredResourceUtilsTest {
+
+ @Test
+ public void testGetDefaultResource() {
+ MonitoredResource resource = MonitoredResourceUtils.getDefaultResource();
+ if (System.getenv("KUBERNETES_SERVICE_HOST") != null) {
+ assertThat(resource.getResourceType()).isEqualTo(ResourceType.GCP_GKE_CONTAINER);
+ } else if (GcpMetadataConfig.getInstanceId() != null) {
+ assertThat(resource.getResourceType()).isEqualTo(ResourceType.GCP_GCE_INSTANCE);
+ } else if (AwsIdentityDocUtils.isRunningOnAwsEc2()) {
+ assertThat(resource.getResourceType()).isEqualTo(ResourceType.AWS_EC2_INSTANCE);
+ } else {
+ assertThat(resource).isNull();
+ }
+ }
+}