Skip to content

Commit 241017b

Browse files
authored
support container id in AWS ECS plugin (#1384)
* support container id in AWS ECS plugin * fix comments; change apache common to guava
1 parent 890ba28 commit 241017b

File tree

5 files changed

+161
-6
lines changed

5 files changed

+161
-6
lines changed

sdk/src/main/java/io/opentelemetry/sdk/resources/ResourceConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public class ResourceConstants {
5050
public static final String LIBRARY_VERSION = "library.version";
5151
/** Container name. */
5252
public static final String CONTAINER_NAME = "container.name";
53+
/** Container id. */
54+
public static final String CONTAINER_ID = "container.id";
5355
/** Name of the image the container was built on. */
5456
public static final String CONTAINER_IMAGE_NAME = "container.image.name";
5557
/** Container image tag. */
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2020, OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.opentelemetry.sdk.extensions.trace.aws.resource;
18+
19+
import com.google.common.annotations.VisibleForTesting;
20+
import java.io.BufferedReader;
21+
import java.io.FileNotFoundException;
22+
import java.io.FileReader;
23+
import java.io.IOException;
24+
import java.util.logging.Level;
25+
import java.util.logging.Logger;
26+
27+
class DockerHelper {
28+
29+
private static final Logger logger = Logger.getLogger(DockerHelper.class.getName());
30+
private static final int CONTAINER_ID_LENGTH = 64;
31+
private static final String DEFAULT_CGROUP_PATH = "/proc/self/cgroup";
32+
33+
private final String cgroupPath;
34+
35+
DockerHelper() {
36+
this(DEFAULT_CGROUP_PATH);
37+
}
38+
39+
@VisibleForTesting
40+
DockerHelper(String cgroupPath) {
41+
this.cgroupPath = cgroupPath;
42+
}
43+
44+
/**
45+
* Get docker container id from local cgroup file.
46+
*
47+
* @return docker container ID. Empty string if it can`t be found.
48+
*/
49+
@SuppressWarnings("DefaultCharset")
50+
public String getContainerId() {
51+
try (BufferedReader br = new BufferedReader(new FileReader(cgroupPath))) {
52+
String line;
53+
while ((line = br.readLine()) != null) {
54+
if (line.length() > CONTAINER_ID_LENGTH) {
55+
return line.substring(line.length() - CONTAINER_ID_LENGTH);
56+
}
57+
}
58+
} catch (FileNotFoundException e) {
59+
logger.log(Level.WARNING, "Failed to read container id, cgroup file does not exist.");
60+
} catch (IOException e) {
61+
logger.log(Level.WARNING, "Unable to read container id: " + e.getMessage());
62+
}
63+
64+
return "";
65+
}
66+
}

sdk_extensions/aws_v1_support/src/main/java/io/opentelemetry/sdk/extensions/trace/aws/resource/EcsResource.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,16 @@ class EcsResource extends AwsResource {
3434
private static final String ECS_METADATA_KEY_V3 = "ECS_CONTAINER_METADATA_URI";
3535

3636
private final Map<String, String> sysEnv;
37+
private final DockerHelper dockerHelper;
3738

3839
EcsResource() {
39-
this(System.getenv());
40+
this(System.getenv(), new DockerHelper());
4041
}
4142

4243
@VisibleForTesting
43-
EcsResource(Map<String, String> sysEnv) {
44+
EcsResource(Map<String, String> sysEnv, DockerHelper dockerHelper) {
4445
this.sysEnv = sysEnv;
46+
this.dockerHelper = dockerHelper;
4547
}
4648

4749
@Override
@@ -54,11 +56,15 @@ Attributes createAttributes() {
5456
try {
5557
String hostName = InetAddress.getLocalHost().getHostName();
5658
attrBuilders.setAttribute(ResourceConstants.CONTAINER_NAME, hostName);
57-
5859
} catch (UnknownHostException e) {
5960
logger.log(Level.WARNING, "Could not get docker container name from hostname.", e);
6061
}
6162

63+
String containerId = dockerHelper.getContainerId();
64+
if (!Strings.isNullOrEmpty(containerId)) {
65+
attrBuilders.setAttribute(ResourceConstants.CONTAINER_ID, containerId);
66+
}
67+
6268
return attrBuilders.build();
6369
}
6470

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2020, OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.opentelemetry.sdk.extensions.trace.aws.resource;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
21+
import com.google.common.base.Charsets;
22+
import com.google.common.io.Files;
23+
import java.io.File;
24+
import java.io.IOException;
25+
import org.junit.Rule;
26+
import org.junit.Test;
27+
import org.junit.rules.TemporaryFolder;
28+
29+
public class DockerHelperTest {
30+
31+
@Rule public TemporaryFolder tempFolder = new TemporaryFolder();
32+
33+
@Test
34+
public void testCgroupFileMissing() {
35+
DockerHelper dockerHelper = new DockerHelper("a_file_never_existing");
36+
assertThat(dockerHelper.getContainerId()).isEmpty();
37+
}
38+
39+
@Test
40+
public void testContainerIdMissing() throws IOException {
41+
File file = tempFolder.newFile("no_container_id");
42+
String content = "13:pids:/\n" + "12:hugetlb:/\n" + "11:net_prio:/";
43+
Files.write(content.getBytes(Charsets.UTF_8), file);
44+
45+
DockerHelper dockerHelper = new DockerHelper(file.getPath());
46+
assertThat(dockerHelper.getContainerId()).isEmpty();
47+
}
48+
49+
@Test
50+
public void testGetContainerId() throws IOException {
51+
File file = tempFolder.newFile("cgroup");
52+
String expected = "386a1920640799b5bf5a39bd94e489e5159a88677d96ca822ce7c433ff350163";
53+
String content = "dummy\n11:devices:/ecs/bbc36dd0-5ee0-4007-ba96-c590e0b278d2/" + expected;
54+
Files.write(content.getBytes(Charsets.UTF_8), file);
55+
56+
DockerHelper dockerHelper = new DockerHelper(file.getPath());
57+
assertThat(dockerHelper.getContainerId()).isEqualTo(expected);
58+
}
59+
}

sdk_extensions/aws_v1_support/src/test/java/io/opentelemetry/sdk/extensions/trace/aws/resource/EcsResourceTest.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.common.truth.Truth.assertThat;
2020
import static io.opentelemetry.common.AttributeValue.stringAttributeValue;
21+
import static org.mockito.Mockito.when;
2122

2223
import io.opentelemetry.common.Attributes;
2324
import io.opentelemetry.sdk.resources.ResourceConstants;
@@ -27,6 +28,7 @@
2728
import java.util.Map;
2829
import org.junit.Rule;
2930
import org.junit.Test;
31+
import org.mockito.Mock;
3032
import org.mockito.junit.MockitoJUnit;
3133
import org.mockito.junit.MockitoRule;
3234

@@ -36,26 +38,46 @@ public class EcsResourceTest {
3638

3739
@Rule public MockitoRule mocks = MockitoJUnit.rule();
3840

41+
@Mock private DockerHelper mockDockerHelper;
42+
3943
@Test
4044
public void testCreateAttributes() throws UnknownHostException {
45+
when(mockDockerHelper.getContainerId()).thenReturn("0123456789A");
4146
Map<String, String> mockSysEnv = new HashMap<>();
4247
mockSysEnv.put(ECS_METADATA_KEY_V3, "ecs_metadata_v3_uri");
43-
EcsResource populator = new EcsResource(mockSysEnv);
48+
EcsResource populator = new EcsResource(mockSysEnv, mockDockerHelper);
4449
Attributes attributes = populator.createAttributes();
4550
assertThat(attributes)
4651
.isEqualTo(
4752
Attributes.of(
4853
ResourceConstants.CONTAINER_NAME,
49-
stringAttributeValue(InetAddress.getLocalHost().getHostName())));
54+
stringAttributeValue(InetAddress.getLocalHost().getHostName()),
55+
ResourceConstants.CONTAINER_ID,
56+
stringAttributeValue("0123456789A")));
5057
}
5158

5259
@Test
5360
public void testNotOnEcs() {
61+
when(mockDockerHelper.getContainerId()).thenReturn("0123456789A");
5462
Map<String, String> mockSysEnv = new HashMap<>();
5563
mockSysEnv.put(ECS_METADATA_KEY_V3, "");
5664
mockSysEnv.put(ECS_METADATA_KEY_V4, "");
57-
EcsResource populator = new EcsResource(mockSysEnv);
65+
EcsResource populator = new EcsResource(mockSysEnv, mockDockerHelper);
5866
Attributes attributes = populator.createAttributes();
5967
assertThat(attributes.isEmpty()).isTrue();
6068
}
69+
70+
@Test
71+
public void testContainerIdMissing() throws UnknownHostException {
72+
when(mockDockerHelper.getContainerId()).thenReturn("");
73+
Map<String, String> mockSysEnv = new HashMap<>();
74+
mockSysEnv.put(ECS_METADATA_KEY_V4, "ecs_metadata_v4_uri");
75+
EcsResource populator = new EcsResource(mockSysEnv, mockDockerHelper);
76+
Attributes attributes = populator.createAttributes();
77+
assertThat(attributes)
78+
.isEqualTo(
79+
Attributes.of(
80+
ResourceConstants.CONTAINER_NAME,
81+
stringAttributeValue(InetAddress.getLocalHost().getHostName())));
82+
}
6183
}

0 commit comments

Comments
 (0)