aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Song <songy23@users.noreply.github.com>2018-04-26 09:53:32 -0700
committerGitHub <noreply@github.com>2018-04-26 09:53:32 -0700
commit86dadeeae96698c24489ce5817e6474224be8802 (patch)
tree37a7278247c7f1d6df6dd12e6377efc68d714a21
parent610ff80ebec2b831a7ea6cc73ad4614152a36ad9 (diff)
downloadopencensus-java-86dadeeae96698c24489ce5817e6474224be8802.tar.gz
Move monitored resource detection utils to a separate artifact. (#1135)
Move monitored resource detection utils to a separate artifact, so that it can be reused by both Stackdriver Monitoring and Stackdriver Trace.
-rw-r--r--all/build.gradle2
-rw-r--r--build.gradle1
-rw-r--r--buildscripts/import-control.xml4
-rw-r--r--contrib/monitored_resource_util/README.md34
-rw-r--r--contrib/monitored_resource_util/build.gradle14
-rw-r--r--contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtils.java (renamed from exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/AwsIdentityDocUtils.java)33
-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.java252
-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.java (renamed from exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/AwsIdentityDocUtilsTest.java)2
-rw-r--r--contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/MonitoredResourceUtilsTest.java42
-rw-r--r--exporters/stats/stackdriver/build.gradle1
-rw-r--r--exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java188
-rw-r--r--exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java15
-rw-r--r--settings.gradle3
16 files changed, 624 insertions, 158 deletions
diff --git a/all/build.gradle b/all/build.gradle
index e8440728..044dc13f 100644
--- a/all/build.gradle
+++ b/all/build.gradle
@@ -16,6 +16,7 @@ def subprojects = [
project(':opencensus-contrib-grpc-util'),
project(':opencensus-contrib-grpc-metrics'),
project(':opencensus-contrib-http-util'),
+ project(':opencensus-contrib-monitored-resource-util'),
project(':opencensus-contrib-zpages'),
project(':opencensus-exporter-trace-logging'),
project(':opencensus-exporter-trace-stackdriver'),
@@ -34,6 +35,7 @@ def subprojects_javadoc = [
project(':opencensus-contrib-grpc-util'),
project(':opencensus-contrib-grpc-metrics'),
project(':opencensus-contrib-http-util'),
+ project(':opencensus-contrib-monitored-resource-util'),
project(':opencensus-contrib-zpages'),
project(':opencensus-exporter-trace-logging'),
project(':opencensus-exporter-trace-stackdriver'),
diff --git a/build.gradle b/build.gradle
index d36b571a..47b7502e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -362,6 +362,7 @@ subprojects {
'opencensus-contrib-grpc-metrics',
'opencensus-contrib-grpc-util',
'opencensus-contrib-http-util',
+ 'opencensus-contrib-monitored-resource-util',
'opencensus-contrib-zpages',
'opencensus-exporter-stats-prometheus',
'opencensus-exporter-stats-signalfx',
diff --git a/buildscripts/import-control.xml b/buildscripts/import-control.xml
index 75ae826a..38cd747d 100644
--- a/buildscripts/import-control.xml
+++ b/buildscripts/import-control.xml
@@ -92,6 +92,9 @@ General guidelines on imports:
<allow pkg="io.opencensus.tags"/>
<allow pkg="io.opencensus.trace"/>
</subpackage>
+ <subpackage name="monitoredresource.util">
+ <allow pkg="io.opencensus.contrib.monitoredresource.util"/>
+ </subpackage>
</subpackage>
<subpackage name="exporter">
<allow pkg="com.google.common"/>
@@ -113,6 +116,7 @@ General guidelines on imports:
<allow pkg="com.google"/>
<allow pkg="io.opencensus.exporter.stats.stackdriver"/>
<allow pkg="io.opencensus.trace"/>
+ <allow pkg="io.opencensus.contrib.monitoredresource.util"/>
</subpackage>
</subpackage>
<subpackage name="trace">
diff --git a/contrib/monitored_resource_util/README.md b/contrib/monitored_resource_util/README.md
new file mode 100644
index 00000000..00b9feaf
--- /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.13.0</version>
+ </dependency>
+</dependencies>
+```
+
+For Gradle add to your dependencies:
+```gradle
+compile 'io.opencensus:opencensus-contrib-monitored-resource-util:0.13.0'
+```
+
+[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..141ff7fc
--- /dev/null
+++ b/contrib/monitored_resource_util/build.gradle
@@ -0,0 +1,14 @@
+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:java16:+@signature"
+}
diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/AwsIdentityDocUtils.java b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtils.java
index fbbdf80b..03b0bd4d 100644
--- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/AwsIdentityDocUtils.java
+++ b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtils.java
@@ -14,12 +14,8 @@
* limitations under the License.
*/
-package io.opencensus.exporter.stats.stackdriver;
+package io.opencensus.contrib.monitoredresource.util;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Maps;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -27,7 +23,8 @@ import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.CharBuffer;
-import java.util.List;
+import java.nio.charset.Charset;
+import java.util.HashMap;
import java.util.Map;
import javax.annotation.concurrent.GuardedBy;
@@ -36,11 +33,10 @@ 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 Splitter AWS_IDENTITY_DOC_LINE_BREAK_SPLITTER = Splitter.on('\n');
- private static final Splitter AWS_IDENTITY_DOC_COLON_SPLITTER = Splitter.on(':');
+ private static final String AWS_IDENTITY_DOC_LINE_BREAK_SPLITTER = "\n";
+ private static final String AWS_IDENTITY_DOC_COLON_SPLITTER = ":";
- @VisibleForTesting
- static final URI AWS_INSTANCE_IDENTITY_DOCUMENT_URI =
+ private static final URI AWS_INSTANCE_IDENTITY_DOCUMENT_URI =
URI.create("http://169.254.169.254/latest/dynamic/instance-identity/document");
@GuardedBy("monitor")
@@ -67,7 +63,7 @@ final class AwsIdentityDocUtils {
InputStream stream = null;
try {
stream = openStream(AWS_INSTANCE_IDENTITY_DOCUMENT_URI);
- String awsIdentityDocument = slurp(new InputStreamReader(stream, Charsets.UTF_8));
+ String awsIdentityDocument = slurp(new InputStreamReader(stream, Charset.forName("UTF-8")));
synchronized (monitor) {
awsEnvVarMap = parseAwsIdentityDocument(awsIdentityDocument);
}
@@ -110,17 +106,18 @@ final class AwsIdentityDocUtils {
// AWS Instance Identity Document is a JSON file.
// See docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html.
- @VisibleForTesting
static Map<String, String> parseAwsIdentityDocument(String awsIdentityDocument) {
- Map<String, String> map = Maps.newHashMap();
- List<String> lines = AWS_IDENTITY_DOC_LINE_BREAK_SPLITTER.splitToList(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) {
- List<String> keyValuePair = AWS_IDENTITY_DOC_COLON_SPLITTER.splitToList(line);
- if (keyValuePair.size() != 2) {
+ @SuppressWarnings("StringSplitter")
+ String[] keyValuePair = line.split(AWS_IDENTITY_DOC_COLON_SPLITTER, -1);
+ if (keyValuePair.length != 2) {
continue;
}
- String key = keyValuePair.get(0).replaceAll("[\" ]", "");
- String value = keyValuePair.get(1).replaceAll("[\" ,]", "");
+ String key = keyValuePair[0].replaceAll("[\" ]", "");
+ String value = keyValuePair[1].replaceAll("[\" ,]", "");
map.put(key, value);
}
return map;
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..c7e91117
--- /dev/null
+++ b/contrib/monitored_resource_util/src/main/java/io/opencensus/contrib/monitoredresource/util/MonitoredResource.java
@@ -0,0 +1,252 @@
+/*
+ * 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();
+
+ static AwsEc2InstanceMonitoredResource create() {
+ return new AutoValue_MonitoredResource_AwsEc2InstanceMonitoredResource(
+ 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();
+
+ static GcpGceInstanceMonitoredResource create() {
+ return new AutoValue_MonitoredResource_GcpGceInstanceMonitoredResource(
+ 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();
+
+ static GcpGkeContainerMonitoredResource create() {
+ return new AutoValue_MonitoredResource_GcpGkeContainerMonitoredResource(
+ 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/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/AwsIdentityDocUtilsTest.java b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtilsTest.java
index 9c15f087..77d98493 100644
--- a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/AwsIdentityDocUtilsTest.java
+++ b/contrib/monitored_resource_util/src/test/java/io/opencensus/contrib/monitoredresource/util/AwsIdentityDocUtilsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package io.opencensus.exporter.stats.stackdriver;
+package io.opencensus.contrib.monitoredresource.util;
import static com.google.common.truth.Truth.assertThat;
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();
+ }
+ }
+}
diff --git a/exporters/stats/stackdriver/build.gradle b/exporters/stats/stackdriver/build.gradle
index c2ed07aa..ebf59b70 100644
--- a/exporters/stats/stackdriver/build.gradle
+++ b/exporters/stats/stackdriver/build.gradle
@@ -9,6 +9,7 @@ dependencies {
compileOnly libraries.auto_value
compile project(':opencensus-api'),
+ project(':opencensus-contrib-monitored-resource-util'),
libraries.google_auth
compile (libraries.google_cloud_monitoring) {
diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java
index f97217b5..8dc5f76c 100644
--- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java
+++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java
@@ -29,7 +29,6 @@ import com.google.api.MetricDescriptor.MetricKind;
import com.google.api.MonitoredResource;
import com.google.cloud.MetadataConfig;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.monitoring.v3.Point;
@@ -39,6 +38,11 @@ import com.google.monitoring.v3.TypedValue;
import com.google.protobuf.Timestamp;
import io.opencensus.common.Function;
import io.opencensus.common.Functions;
+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 io.opencensus.contrib.monitoredresource.util.MonitoredResourceUtils;
+import io.opencensus.contrib.monitoredresource.util.ResourceType;
import io.opencensus.stats.Aggregation;
import io.opencensus.stats.AggregationData;
import io.opencensus.stats.AggregationData.CountData;
@@ -72,10 +76,10 @@ final class StackdriverExportUtils {
@VisibleForTesting static final String LABEL_DESCRIPTION = "OpenCensus TagKey";
@VisibleForTesting static final String OPENCENSUS_TASK = "opencensus_task";
@VisibleForTesting static final String OPENCENSUS_TASK_DESCRIPTION = "Opencensus task identifier";
- @VisibleForTesting static final String GCP_GKE_CONTAINER = "gke_container";
- @VisibleForTesting static final String GCP_GCE_INSTANCE = "gce_instance";
- @VisibleForTesting static final String AWS_EC2_INSTANCE = "aws_ec2_instance";
- @VisibleForTesting static final String GLOBAL = "global";
+ private static final String GCP_GKE_CONTAINER = "gke_container";
+ private static final String GCP_GCE_INSTANCE = "gce_instance";
+ private static final String AWS_EC2_INSTANCE = "aws_ec2_instance";
+ private static final String GLOBAL = "global";
private static final Logger logger = Logger.getLogger(StackdriverExportUtils.class.getName());
private static final String CUSTOM_METRIC_DOMAIN = "custom.googleapis.com";
@@ -356,135 +360,71 @@ final class StackdriverExportUtils {
.build();
}
- private enum Label {
- GcpClusterName("cluster_name"),
- GcpContainerName("container_name"),
- GcpNamespaceId("namespace_id"),
- GcpInstanceId("instance_id"),
- GcpInstanceName("instance_name"),
- GcpGkePodId("pod_id"),
- GcpZone("zone"),
- AwsAccount("aws_account"),
- AwsInstanceId("instance_id"),
- AwsRegion("region");
-
- private final String key;
-
- Label(String key) {
- this.key = key;
- }
-
- String getKey() {
- return key;
- }
- }
-
- private enum Resource {
- GkeContainer(GCP_GKE_CONTAINER),
- GceInstance(GCP_GCE_INSTANCE),
- AwsEc2Instance(AWS_EC2_INSTANCE),
- Global(GLOBAL);
-
- private final String key;
-
- Resource(String key) {
- this.key = key;
- }
-
- String getKey() {
- return key;
- }
- }
-
- private static final ImmutableMultimap<Resource, Label> RESOURCE_TYPE_WITH_LABELS =
- ImmutableMultimap.<Resource, Label>builder()
- .putAll(
- Resource.GkeContainer,
- Label.GcpClusterName,
- Label.GcpContainerName,
- Label.GcpNamespaceId,
- Label.GcpInstanceId,
- Label.GcpGkePodId,
- Label.GcpZone)
- .putAll(Resource.GceInstance, Label.GcpInstanceId, Label.GcpZone)
- .putAll(Resource.AwsEc2Instance, Label.AwsAccount, Label.AwsInstanceId, Label.AwsRegion)
- .build();
-
- /* Return a self-configured monitored Resource. */
+ /* Return a self-configured Stackdriver monitored resource. */
static MonitoredResource getDefaultResource() {
- Resource detectedResourceType = getAutoDetectedResourceType();
- String resourceType = detectedResourceType.getKey();
- MonitoredResource.Builder builder = MonitoredResource.newBuilder().setType(resourceType);
- if (MetadataConfig.getProjectId() != null) {
- // For default resource, always use the project id from MetadataConfig. This allows stats from
- // other projects (e.g from GCE running in another project) to be collected.
- builder.putLabels(PROJECT_ID_LABEL_KEY, MetadataConfig.getProjectId());
- }
- for (Label label : RESOURCE_TYPE_WITH_LABELS.get(detectedResourceType)) {
- String value = getValue(label);
- if (value == null) {
- value = "";
+ MonitoredResource.Builder builder = MonitoredResource.newBuilder();
+ io.opencensus.contrib.monitoredresource.util.MonitoredResource autoDetectedResource =
+ MonitoredResourceUtils.getDefaultResource();
+ if (autoDetectedResource == null) {
+ builder.setType(GLOBAL);
+ if (MetadataConfig.getProjectId() != null) {
+ // For default global resource, always use the project id from MetadataConfig. This allows
+ // stats from other projects (e.g from GAE running in another project) to be collected.
+ builder.putLabels(PROJECT_ID_LABEL_KEY, MetadataConfig.getProjectId());
}
- // Label values can be null or empty, but each label key must have an associated value.
- builder.putLabels(label.getKey(), value);
+ return builder.build();
}
+ builder.setType(mapToStackdriverResourceType(autoDetectedResource.getResourceType()));
+ setMonitoredResourceLabelsForBuilder(builder, autoDetectedResource);
return builder.build();
}
- @javax.annotation.Nullable
- private static String getValue(Label label) {
- String value;
- switch (label) {
- case GcpClusterName:
- value = MetadataConfig.getClusterName();
- break;
- case GcpInstanceId:
- value = MetadataConfig.getInstanceId();
- break;
- case GcpInstanceName:
- value = System.getenv("GAE_INSTANCE");
- break;
- case GcpGkePodId:
- value = System.getenv("HOSTNAME");
- break;
- case GcpZone:
- value = MetadataConfig.getZone();
- break;
- case GcpContainerName:
- value = System.getenv("CONTAINER_NAME");
- break;
- case GcpNamespaceId:
- value = System.getenv("NAMESPACE");
- break;
- case AwsAccount:
- value = AwsIdentityDocUtils.getValueFromAwsIdentityDocument("accountId");
- break;
- case AwsInstanceId:
- value = AwsIdentityDocUtils.getValueFromAwsIdentityDocument("instanceId");
- break;
- case AwsRegion:
- value = "aws:" + AwsIdentityDocUtils.getValueFromAwsIdentityDocument("region");
- break;
- default:
- value = null;
- break;
+ private static String mapToStackdriverResourceType(ResourceType resourceType) {
+ switch (resourceType) {
+ case GCP_GCE_INSTANCE:
+ return GCP_GCE_INSTANCE;
+ case GCP_GKE_CONTAINER:
+ return GCP_GKE_CONTAINER;
+ case AWS_EC2_INSTANCE:
+ return AWS_EC2_INSTANCE;
}
- return value;
+ throw new IllegalArgumentException("Unknown resource type.");
}
- /* Detects monitored Resource type using environment variables, else return global as default. */
- private static Resource getAutoDetectedResourceType() {
- if (System.getenv("KUBERNETES_SERVICE_HOST") != null) {
- return Resource.GkeContainer;
- }
- if (MetadataConfig.getInstanceId() != null) {
- return Resource.GceInstance;
- }
- if (AwsIdentityDocUtils.isRunningOnAwsEc2()) {
- return Resource.AwsEc2Instance;
+ private static void setMonitoredResourceLabelsForBuilder(
+ MonitoredResource.Builder builder,
+ io.opencensus.contrib.monitoredresource.util.MonitoredResource autoDetectedResource) {
+ switch (autoDetectedResource.getResourceType()) {
+ case GCP_GCE_INSTANCE:
+ @SuppressWarnings("unchecked")
+ GcpGceInstanceMonitoredResource gcpGceInstanceMonitoredResource =
+ (GcpGceInstanceMonitoredResource) autoDetectedResource;
+ builder.putLabels(PROJECT_ID_LABEL_KEY, gcpGceInstanceMonitoredResource.getAccount());
+ builder.putLabels("instance_id", gcpGceInstanceMonitoredResource.getInstanceId());
+ builder.putLabels("zone", gcpGceInstanceMonitoredResource.getZone());
+ return;
+ case GCP_GKE_CONTAINER:
+ @SuppressWarnings("unchecked")
+ GcpGkeContainerMonitoredResource gcpGkeContainerMonitoredResource =
+ (GcpGkeContainerMonitoredResource) autoDetectedResource;
+ builder.putLabels(PROJECT_ID_LABEL_KEY, gcpGkeContainerMonitoredResource.getAccount());
+ builder.putLabels("cluster_name", gcpGkeContainerMonitoredResource.getClusterName());
+ builder.putLabels("container_name", gcpGkeContainerMonitoredResource.getContainerName());
+ builder.putLabels("namespace_id", gcpGkeContainerMonitoredResource.getNamespaceId());
+ builder.putLabels("instance_id", gcpGkeContainerMonitoredResource.getInstanceId());
+ builder.putLabels("pod_id", gcpGkeContainerMonitoredResource.getPodId());
+ builder.putLabels("zone", gcpGkeContainerMonitoredResource.getZone());
+ return;
+ case AWS_EC2_INSTANCE:
+ @SuppressWarnings("unchecked")
+ AwsEc2InstanceMonitoredResource awsEc2InstanceMonitoredResource =
+ (AwsEc2InstanceMonitoredResource) autoDetectedResource;
+ builder.putLabels("aws_account", awsEc2InstanceMonitoredResource.getAccount());
+ builder.putLabels("instance_id", awsEc2InstanceMonitoredResource.getInstanceId());
+ builder.putLabels("region", "aws:" + awsEc2InstanceMonitoredResource.getRegion());
+ return;
}
- // default Resource type
- return Resource.Global;
+ throw new IllegalArgumentException("Unknown subclass of MonitoredResource.");
}
private StackdriverExportUtils() {}
diff --git a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java
index 16e73b1f..a78a96ea 100644
--- a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java
+++ b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java
@@ -26,7 +26,6 @@ import com.google.api.Metric;
import com.google.api.MetricDescriptor;
import com.google.api.MetricDescriptor.MetricKind;
import com.google.api.MonitoredResource;
-import com.google.cloud.MetadataConfig;
import com.google.common.collect.ImmutableMap;
import com.google.monitoring.v3.Point;
import com.google.monitoring.v3.TimeInterval;
@@ -501,18 +500,4 @@ public class StackdriverExportUtilsTest {
.addPoints(StackdriverExportUtils.createPoint(sumData, cumulativeData, SUM))
.build());
}
-
- @Test
- public void testGetDefaultResource() {
- MonitoredResource resource = StackdriverExportUtils.getDefaultResource();
- if (System.getenv("KUBERNETES_SERVICE_HOST") != null) {
- assertThat(resource.getType()).isEqualTo(StackdriverExportUtils.GCP_GKE_CONTAINER);
- } else if (MetadataConfig.getInstanceId() != null) {
- assertThat(resource.getType()).isEqualTo(StackdriverExportUtils.GCP_GCE_INSTANCE);
- } else if (AwsIdentityDocUtils.isRunningOnAwsEc2()) {
- assertThat(resource.getType()).isEqualTo(StackdriverExportUtils.AWS_EC2_INSTANCE);
- } else {
- assertThat(resource.getType()).isEqualTo(StackdriverExportUtils.GLOBAL);
- }
- }
}
diff --git a/settings.gradle b/settings.gradle
index 0d2617e2..3d9a0ee0 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -17,6 +17,7 @@ include ":opencensus-contrib-agent"
include ":opencensus-contrib-grpc-metrics"
include ":opencensus-contrib-grpc-util"
include ":opencensus-contrib-http-util"
+include ":opencensus-contrib-monitored-resource-util"
project(':opencensus-api').projectDir = "$rootDir/api" as File
project(':opencensus-impl-core').projectDir = "$rootDir/impl_core" as File
@@ -27,6 +28,8 @@ project(':opencensus-contrib-agent').projectDir = "$rootDir/contrib/agent" as Fi
project(':opencensus-contrib-grpc-metrics').projectDir = "$rootDir/contrib/grpc_metrics" as File
project(':opencensus-contrib-grpc-util').projectDir = "$rootDir/contrib/grpc_util" as File
project(':opencensus-contrib-http-util').projectDir = "$rootDir/contrib/http_util" as File
+project(':opencensus-contrib-monitored-resource-util').projectDir =
+ "$rootDir/contrib/monitored_resource_util" as File
project(':opencensus-exporter-trace-instana').projectDir =
"$rootDir/exporters/trace/instana" as File
project(':opencensus-exporter-trace-logging').projectDir =