aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Song <songy23@users.noreply.github.com>2018-09-26 10:29:35 -0700
committerGitHub <noreply@github.com>2018-09-26 10:29:35 -0700
commit9580d5f56a6bd14751632a1d4af8a8b0d259ac0e (patch)
treeba37de3886b4716307c8bd48ae57476fde237abe
parent8ca454685adeede687b4857270c590f642d3c415 (diff)
downloadopencensus-java-9580d5f56a6bd14751632a1d4af8a8b0d259ac0e.tar.gz
Exporter/OCAgent: Add OcAgentNodeUtils. (#1471)
* Exporter/OCAgent: Add OcAgentNodeUtils. Add utilities for detecting and creating Node. Equivalent to https://github.com/census-ecosystem/opencensus-go-exporter-ocagent/blob/master/nodeinfo.go. * Fix nullness checker. * Use a local VERSION string in OC-Agent Exporter.
-rw-r--r--RELEASING.md1
-rw-r--r--buildscripts/import-control.xml1
-rw-r--r--exporters/trace/ocagent/build.gradle1
-rw-r--r--exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtils.java184
-rw-r--r--exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentTraceExporterHandler.java7
-rw-r--r--exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/TraceProtoUtils.java2
-rw-r--r--exporters/trace/ocagent/src/test/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtilsTest.java122
7 files changed, 314 insertions, 4 deletions
diff --git a/RELEASING.md b/RELEASING.md
index e4315cd2..649ac81f 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -65,6 +65,7 @@ token](https://help.github.com/articles/creating-a-personal-access-token-for-the
examples/build.gradle
examples/pom.xml
api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java
+ exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtils.java
)
$ git checkout -b v$MAJOR.$MINOR.x master
$ git push upstream v$MAJOR.$MINOR.x
diff --git a/buildscripts/import-control.xml b/buildscripts/import-control.xml
index b4c7410b..002820d8 100644
--- a/buildscripts/import-control.xml
+++ b/buildscripts/import-control.xml
@@ -170,6 +170,7 @@ General guidelines on imports:
</subpackage>
<subpackage name="ocagent">
<allow pkg="com.google.protobuf"/>
+ <allow pkg="io.opencensus.contrib.monitoredresource.util"/>
<allow pkg="io.opencensus.contrib.opencensus.proto.util"/>
<allow pkg="io.opencensus.exporter.trace.ocagent"/>
<allow pkg="io.opencensus.proto"/>
diff --git a/exporters/trace/ocagent/build.gradle b/exporters/trace/ocagent/build.gradle
index 7214eb58..b9489864 100644
--- a/exporters/trace/ocagent/build.gradle
+++ b/exporters/trace/ocagent/build.gradle
@@ -15,5 +15,4 @@ dependencies {
testCompile project(':opencensus-api')
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/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtils.java b/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtils.java
new file mode 100644
index 00000000..65729803
--- /dev/null
+++ b/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtils.java
@@ -0,0 +1,184 @@
+/*
+ * 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.exporter.trace.ocagent;
+
+import com.google.common.annotations.VisibleForTesting;
+import io.opencensus.common.OpenCensusLibraryInformation;
+import io.opencensus.common.Timestamp;
+import io.opencensus.contrib.monitoredresource.util.MonitoredResource;
+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.proto.agent.common.v1.LibraryInfo;
+import io.opencensus.proto.agent.common.v1.LibraryInfo.Language;
+import io.opencensus.proto.agent.common.v1.Node;
+import io.opencensus.proto.agent.common.v1.ProcessIdentifier;
+import io.opencensus.proto.agent.common.v1.ServiceInfo;
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.SecureRandom;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+
+/** Utilities for detecting and creating {@link Node}. */
+final class OcAgentNodeUtils {
+
+ // The current version of the OpenCensus OC-Agent Exporter.
+ @VisibleForTesting
+ static final String OC_AGENT_EXPORTER_VERSION = "0.17.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION
+
+ @VisibleForTesting static final String RESOURCE_TYPE_ATTRIBUTE_KEY = "OPENCENSUS_SOURCE_TYPE";
+ @VisibleForTesting static final String RESOURCE_LABEL_ATTRIBUTE_KEY = "OPENCENSUS_SOURCE_LABELS";
+
+ @Nullable
+ private static final MonitoredResource RESOURCE = MonitoredResourceUtils.getDefaultResource();
+
+ // Creates a Node with information from the OpenCensus library and environment variables.
+ static Node getNodeInfo(String serviceName) {
+ String jvmName = ManagementFactory.getRuntimeMXBean().getName();
+ Timestamp censusTimestamp = Timestamp.fromMillis(System.currentTimeMillis());
+ return Node.newBuilder()
+ .setIdentifier(getProcessIdentifier(jvmName, censusTimestamp))
+ .setLibraryInfo(getLibraryInfo(OpenCensusLibraryInformation.VERSION))
+ .setServiceInfo(getServiceInfo(serviceName))
+ .putAllAttributes(getAttributeMap(RESOURCE))
+ .build();
+ }
+
+ // Creates process identifier with the given JVM name and start time.
+ @VisibleForTesting
+ static ProcessIdentifier getProcessIdentifier(String jvmName, Timestamp censusTimestamp) {
+ String hostname;
+ int pid;
+ // jvmName should be something like '<pid>@<hostname>', at least in Oracle and OpenJdk JVMs
+ int delimiterIndex = jvmName.indexOf('@');
+ if (delimiterIndex < 1) {
+ // Not the expected format, generate a random number.
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException e) {
+ hostname = "localhost";
+ }
+ // Generate a random number as the PID.
+ pid = new SecureRandom().nextInt();
+ } else {
+ hostname = jvmName.substring(delimiterIndex + 1, jvmName.length());
+ try {
+ pid = Integer.parseInt(jvmName.substring(0, delimiterIndex));
+ } catch (NumberFormatException e) {
+ // Generate a random number as the PID if format is unexpected.
+ pid = new SecureRandom().nextInt();
+ }
+ }
+
+ return ProcessIdentifier.newBuilder()
+ .setHostName(hostname)
+ .setPid(pid)
+ .setStartTimestamp(TraceProtoUtils.toTimestampProto(censusTimestamp))
+ .build();
+ }
+
+ // Creates library info with the given OpenCensus Java version.
+ @VisibleForTesting
+ static LibraryInfo getLibraryInfo(String currentOcJavaVersion) {
+ return LibraryInfo.newBuilder()
+ .setLanguage(Language.JAVA)
+ .setCoreLibraryVersion(currentOcJavaVersion)
+ .setExporterVersion(OC_AGENT_EXPORTER_VERSION)
+ .build();
+ }
+
+ // Creates service info with the given service name.
+ @VisibleForTesting
+ static ServiceInfo getServiceInfo(String serviceName) {
+ return ServiceInfo.newBuilder().setName(serviceName).build();
+ }
+
+ /*
+ * Creates an attribute map with the given MonitoredResource.
+ * If the given resource is not null, the attribute map contains exactly two entries:
+ *
+ * OPENCENSUS_SOURCE_TYPE:
+ * A string that describes the type of the resource prefixed by a domain namespace,
+ * e.g. “kubernetes.io/container”.
+ * OPENCENSUS_SOURCE_LABELS:
+ * A comma-separated list of labels describing the source in more detail,
+ * e.g. “key1=val1,key2=val2”. The allowed character set is appropriately constrained.
+ */
+ // TODO: update the resource attributes once we have an agreement on the resource specs:
+ // https://github.com/census-instrumentation/opencensus-specs/pull/162.
+ @VisibleForTesting
+ static Map<String, String> getAttributeMap(@Nullable MonitoredResource resource) {
+ if (resource == null) {
+ return Collections.emptyMap();
+ } else {
+ Map<String, String> resourceAttributes = new HashMap<String, String>();
+ resourceAttributes.put(RESOURCE_TYPE_ATTRIBUTE_KEY, resource.getResourceType().name());
+ resourceAttributes.put(RESOURCE_LABEL_ATTRIBUTE_KEY, getConcatenatedResourceLabels(resource));
+ return resourceAttributes;
+ }
+ }
+
+ // Encodes the attributes of MonitoredResource into a comma-separated list of labels.
+ // For example "aws_account=account1,instance_id=instance1,region=us-east-2".
+ private static String getConcatenatedResourceLabels(MonitoredResource resource) {
+ StringBuilder resourceLabels = new StringBuilder();
+ if (resource instanceof AwsEc2InstanceMonitoredResource) {
+ AwsEc2InstanceMonitoredResource awsEc2Resource = (AwsEc2InstanceMonitoredResource) resource;
+ putIntoBuilderIfHasValue(resourceLabels, "aws_account", awsEc2Resource.getAccount());
+ putIntoBuilderIfHasValue(resourceLabels, "instance_id", awsEc2Resource.getInstanceId());
+ putIntoBuilderIfHasValue(resourceLabels, "region", awsEc2Resource.getRegion());
+ } else if (resource instanceof GcpGceInstanceMonitoredResource) {
+ GcpGceInstanceMonitoredResource gceResource = (GcpGceInstanceMonitoredResource) resource;
+ putIntoBuilderIfHasValue(resourceLabels, "gcp_account", gceResource.getAccount());
+ putIntoBuilderIfHasValue(resourceLabels, "instance_id", gceResource.getInstanceId());
+ putIntoBuilderIfHasValue(resourceLabels, "zone", gceResource.getZone());
+ } else if (resource instanceof GcpGkeContainerMonitoredResource) {
+ GcpGkeContainerMonitoredResource gkeResource = (GcpGkeContainerMonitoredResource) resource;
+ putIntoBuilderIfHasValue(resourceLabels, "gcp_account", gkeResource.getAccount());
+ putIntoBuilderIfHasValue(resourceLabels, "instance_id", gkeResource.getInstanceId());
+ putIntoBuilderIfHasValue(resourceLabels, "location", gkeResource.getZone());
+ putIntoBuilderIfHasValue(resourceLabels, "namespace_name", gkeResource.getNamespaceId());
+ putIntoBuilderIfHasValue(resourceLabels, "cluster_name", gkeResource.getClusterName());
+ putIntoBuilderIfHasValue(resourceLabels, "container_name", gkeResource.getContainerName());
+ putIntoBuilderIfHasValue(resourceLabels, "pod_name", gkeResource.getPodId());
+ }
+ return resourceLabels.toString();
+ }
+
+ // If the given resourceValue is not empty, encodes resourceKey and resourceValue as
+ // "resourceKey:resourceValue" and puts it into the given StringBuilder. Otherwise skip the value.
+ private static void putIntoBuilderIfHasValue(
+ StringBuilder builder, String resourceKey, String resourceValue) {
+ if (resourceValue.isEmpty()) {
+ return;
+ }
+ if (!(builder.length() == 0)) {
+ // Appends the comma separator to the front, if the StringBuilder already has entries.
+ builder.append(',');
+ }
+ builder.append(resourceKey);
+ builder.append('=');
+ builder.append(resourceValue);
+ }
+
+ private OcAgentNodeUtils() {}
+}
diff --git a/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentTraceExporterHandler.java b/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentTraceExporterHandler.java
index 27e56c66..cb4b06aa 100644
--- a/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentTraceExporterHandler.java
+++ b/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/OcAgentTraceExporterHandler.java
@@ -28,7 +28,7 @@ final class OcAgentTraceExporterHandler extends Handler {
private static final String DEFAULT_SERVICE_NAME = "OpenCensus";
// private final String endPoint;
- // private final String serviceName;
+ // private final Node node;
// private final boolean useInsecure;
OcAgentTraceExporterHandler() {
@@ -38,7 +38,10 @@ final class OcAgentTraceExporterHandler extends Handler {
OcAgentTraceExporterHandler(
@Nullable String endPoint, @Nullable String serviceName, @Nullable Boolean useInsecure) {
// this.endPoint = endPoint == null ? DEFAULT_END_POINT : endPoint;
- // this.serviceName = serviceName == null ? DEFAULT_SERVICE_NAME : serviceName;
+ // if (serviceName == null) {
+ // serviceName = DEFAULT_SERVICE_NAME;
+ // }
+ // this.node = OcAgentNodeUtils.getNodeInfo(serviceName);
// this.useInsecure = useInsecure == null ? false : useInsecure;
}
diff --git a/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/TraceProtoUtils.java b/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/TraceProtoUtils.java
index 26bae0ac..df11ef58 100644
--- a/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/TraceProtoUtils.java
+++ b/exporters/trace/ocagent/src/main/java/io/opencensus/exporter/trace/ocagent/TraceProtoUtils.java
@@ -283,7 +283,7 @@ public final class TraceProtoUtils {
return TruncatableString.newBuilder().setValue(string).setTruncatedByteCount(0).build();
}
- private static com.google.protobuf.Timestamp toTimestampProto(Timestamp timestamp) {
+ static com.google.protobuf.Timestamp toTimestampProto(Timestamp timestamp) {
return com.google.protobuf.Timestamp.newBuilder()
.setSeconds(timestamp.getSeconds())
.setNanos(timestamp.getNanos())
diff --git a/exporters/trace/ocagent/src/test/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtilsTest.java b/exporters/trace/ocagent/src/test/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtilsTest.java
new file mode 100644
index 00000000..813066bc
--- /dev/null
+++ b/exporters/trace/ocagent/src/test/java/io/opencensus/exporter/trace/ocagent/OcAgentNodeUtilsTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.exporter.trace.ocagent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static io.opencensus.exporter.trace.ocagent.OcAgentNodeUtils.OC_AGENT_EXPORTER_VERSION;
+import static io.opencensus.exporter.trace.ocagent.OcAgentNodeUtils.RESOURCE_LABEL_ATTRIBUTE_KEY;
+import static io.opencensus.exporter.trace.ocagent.OcAgentNodeUtils.RESOURCE_TYPE_ATTRIBUTE_KEY;
+
+import io.opencensus.common.Timestamp;
+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.proto.agent.common.v1.LibraryInfo;
+import io.opencensus.proto.agent.common.v1.LibraryInfo.Language;
+import io.opencensus.proto.agent.common.v1.ProcessIdentifier;
+import io.opencensus.proto.agent.common.v1.ServiceInfo;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link OcAgentNodeUtils}. */
+@RunWith(JUnit4.class)
+public class OcAgentNodeUtilsTest {
+
+ private static final AwsEc2InstanceMonitoredResource AWS_RESOURCE =
+ AwsEc2InstanceMonitoredResource.create("account1", "instance1", "us-east-2");
+ private static final GcpGceInstanceMonitoredResource GCE_RESOURCE =
+ GcpGceInstanceMonitoredResource.create("account2", "instance2", "us-west2");
+ private static final GcpGkeContainerMonitoredResource GKE_RESOURCE =
+ GcpGkeContainerMonitoredResource.create(
+ "account3", "cluster", "container", "", "instance3", "", "us-west4");
+
+ @Test
+ public void testConstants() {
+ assertThat(OC_AGENT_EXPORTER_VERSION).isEqualTo("0.17.0-SNAPSHOT");
+ assertThat(RESOURCE_TYPE_ATTRIBUTE_KEY).isEqualTo("OPENCENSUS_SOURCE_TYPE");
+ assertThat(RESOURCE_LABEL_ATTRIBUTE_KEY).isEqualTo("OPENCENSUS_SOURCE_LABELS");
+ }
+
+ @Test
+ public void getProcessIdentifier() {
+ String jvmName = "54321@my.org";
+ Timestamp timestamp = Timestamp.create(10, 20);
+ ProcessIdentifier processIdentifier = OcAgentNodeUtils.getProcessIdentifier(jvmName, timestamp);
+ assertThat(processIdentifier.getHostName()).isEqualTo("my.org");
+ assertThat(processIdentifier.getPid()).isEqualTo(54321);
+ assertThat(processIdentifier.getStartTimestamp())
+ .isEqualTo(com.google.protobuf.Timestamp.newBuilder().setSeconds(10).setNanos(20).build());
+ }
+
+ @Test
+ public void getLibraryInfo() {
+ String currentOcJavaVersion = "0.16.0";
+ LibraryInfo libraryInfo = OcAgentNodeUtils.getLibraryInfo(currentOcJavaVersion);
+ assertThat(libraryInfo.getLanguage()).isEqualTo(Language.JAVA);
+ assertThat(libraryInfo.getCoreLibraryVersion()).isEqualTo(currentOcJavaVersion);
+ assertThat(libraryInfo.getExporterVersion()).isEqualTo(OC_AGENT_EXPORTER_VERSION);
+ }
+
+ @Test
+ public void getServiceInfo() {
+ String serviceName = "my-service";
+ ServiceInfo serviceInfo = OcAgentNodeUtils.getServiceInfo(serviceName);
+ assertThat(serviceInfo.getName()).isEqualTo(serviceName);
+ }
+
+ @Test
+ public void getAttributeMap_Null() {
+ Map<String, String> attributeMap = OcAgentNodeUtils.getAttributeMap(null);
+ assertThat(attributeMap).isEmpty();
+ }
+
+ @Test
+ public void getAttributeMap_AwsEc2Resource() {
+ Map<String, String> attributeMap = OcAgentNodeUtils.getAttributeMap(AWS_RESOURCE);
+ assertThat(attributeMap)
+ .containsExactly(
+ RESOURCE_TYPE_ATTRIBUTE_KEY,
+ "AWS_EC2_INSTANCE",
+ RESOURCE_LABEL_ATTRIBUTE_KEY,
+ "aws_account=account1,instance_id=instance1,region=us-east-2");
+ }
+
+ @Test
+ public void getAttributeMap_GceResource() {
+ Map<String, String> attributeMap = OcAgentNodeUtils.getAttributeMap(GCE_RESOURCE);
+ assertThat(attributeMap)
+ .containsExactly(
+ RESOURCE_TYPE_ATTRIBUTE_KEY,
+ "GCP_GCE_INSTANCE",
+ RESOURCE_LABEL_ATTRIBUTE_KEY,
+ "gcp_account=account2,instance_id=instance2,zone=us-west2");
+ }
+
+ @Test
+ public void getAttributeMap_GkeResource() {
+ Map<String, String> attributeMap = OcAgentNodeUtils.getAttributeMap(GKE_RESOURCE);
+ assertThat(attributeMap)
+ .containsExactly(
+ RESOURCE_TYPE_ATTRIBUTE_KEY,
+ "GCP_GKE_CONTAINER",
+ RESOURCE_LABEL_ATTRIBUTE_KEY,
+ "gcp_account=account3,instance_id=instance3,location=us-west4,"
+ + "cluster_name=cluster,container_name=container");
+ }
+}