From 46326fee3824db67016581d21cbbbf588b4bfa4d Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Tue, 6 Dec 2022 10:52:24 -0800 Subject: [PATCH 1/2] more flexible cgroupv2 container id parsing --- .../CgroupV2ContainerIdExtractor.java | 10 ++-- .../CgroupV2ContainerIdExtractorTest.java | 60 ++++++++++--------- .../test/resources/docker_proc_self_mountinfo | 24 ++++++++ .../test/resources/podman_proc_self_mountinfo | 49 +++++++++++++++ 4 files changed, 112 insertions(+), 31 deletions(-) create mode 100644 instrumentation/resources/library/src/test/resources/docker_proc_self_mountinfo create mode 100644 instrumentation/resources/library/src/test/resources/podman_proc_self_mountinfo diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java index 5e9a1ab2ccb1..f7fc784d1a77 100644 --- a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java @@ -15,6 +15,7 @@ import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Stream; /** Utility for extracting the container ID from runtimes inside cgroup v2 containers. */ class CgroupV2ContainerIdExtractor { @@ -23,8 +24,7 @@ class CgroupV2ContainerIdExtractor { Logger.getLogger(CgroupV2ContainerIdExtractor.class.getName()); static final Path V2_CGROUP_PATH = Paths.get("/proc/self/mountinfo"); - private static final Pattern CONTAINER_RE = - Pattern.compile(".*/docker/containers/([0-9a-f]{64})/.*"); + private static final Pattern CONTAINER_ID_RE = Pattern.compile("^[0-9a-f]{64}$"); private final ContainerResource.Filesystem filesystem; @@ -44,10 +44,12 @@ Optional extractContainerId() { try { return filesystem .lines(V2_CGROUP_PATH) - .map(CONTAINER_RE::matcher) + .filter(line -> line.contains("hostname")) + .flatMap(line -> Stream.of(line.split("/"))) + .map(CONTAINER_ID_RE::matcher) .filter(Matcher::matches) .findFirst() - .map(matcher -> matcher.group(1)); + .map(matcher -> matcher.group(0)); } catch (IOException e) { logger.log(Level.WARNING, "Unable to read v2 cgroup path", e); } diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java index b9cfa49266ca..1f43e126735d 100644 --- a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java @@ -9,6 +9,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Optional; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -30,39 +33,42 @@ void fileNotReadable() { } @Test - void extractSuccess() throws Exception { + void extractSuccess_docker() throws Exception { when(filesystem.isReadable(V2_CGROUP_PATH)).thenReturn(true); - Stream fileContent = getTestFileContent(); + Stream fileContent = getTestDockerFileContent(); when(filesystem.lines(V2_CGROUP_PATH)).thenReturn(fileContent); CgroupV2ContainerIdExtractor extractor = new CgroupV2ContainerIdExtractor(filesystem); Optional result = extractor.extractContainerId(); assertThat(result.orElse("fail")) - .isEqualTo("dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183"); + .isEqualTo("be522444b60caf2d3934b8b24b916a8a314f4b68d4595aa419874657e8d103f2"); } - private static Stream getTestFileContent() { - return Stream.of( - "456 375 0:143 / / rw,relatime master:175 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/37L57D2IM7MEWLVE2Q2ECNDT67:/var/lib/docker/overlay2/l/46FCA2JFPCSNFGAR5TSYLLNHLK,upperdir=/var/lib/docker/overlay2/4e82c300793d703c19bdf887bfdad8b0354edda884ea27a8a2df89ab292719a4/diff,workdir=/var/lib/docker/overlay2/4e82c300793d703c19bdf887bfdad8b0354edda884ea27a8a2df89ab292719a4/work", - "457 456 0:146 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw", - "466 456 0:147 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", - "467 466 0:148 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666", - "468 456 0:149 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro", - "469 468 0:30 / /sys/fs/cgroup ro,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw", - "470 466 0:145 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw", - "471 466 0:150 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k", - "472 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw", - "473 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw", - "474 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/hosts /etc/hosts rw,relatime - ext4 /dev/vda1 rw", - "376 466 0:148 /0 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666", - "377 457 0:146 /bus /proc/bus ro,nosuid,nodev,noexec,relatime - proc proc rw", - "378 457 0:146 /fs /proc/fs ro,nosuid,nodev,noexec,relatime - proc proc rw", - "379 457 0:146 /irq /proc/irq ro,nosuid,nodev,noexec,relatime - proc proc rw", - "380 457 0:146 /sys /proc/sys ro,nosuid,nodev,noexec,relatime - proc proc rw", - "381 457 0:146 /sysrq-trigger /proc/sysrq-trigger ro,nosuid,nodev,noexec,relatime - proc proc rw", - "382 457 0:151 / /proc/acpi ro,relatime - tmpfs tmpfs ro", - "383 457 0:147 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", - "384 457 0:147 /null /proc/keys rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", - "385 457 0:147 /null /proc/timer_list rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", - "386 468 0:152 / /sys/firmware ro,relatime - tmpfs tmpfs "); + @Test + void extractSuccess_podman() throws Exception { + when(filesystem.isReadable(V2_CGROUP_PATH)).thenReturn(true); + Stream fileContent = getTestPodmanFileContent(); + when(filesystem.lines(V2_CGROUP_PATH)).thenReturn(fileContent); + CgroupV2ContainerIdExtractor extractor = new CgroupV2ContainerIdExtractor(filesystem); + Optional result = extractor.extractContainerId(); + assertThat(result.orElse("fail")) + .isEqualTo("2a33efc76e519c137fe6093179653788bed6162d4a15e5131c8e835c968afbe6"); + } + + private static Stream getTestDockerFileContent() throws Exception { + return fileToStreamOfLines("docker_proc_self_mountinfo"); + } + + private static Stream getTestPodmanFileContent() throws Exception { + return fileToStreamOfLines("podman_proc_self_mountinfo"); + } + + private static Stream fileToStreamOfLines(String filename) throws IOException { + try (InputStream in = + CgroupV2ContainerIdExtractorTest.class.getClassLoader().getResourceAsStream(filename)) { + byte[] buff = new byte[100 * 1024]; + int rc = in.read(buff); + String file = new String(buff, 0, rc, StandardCharsets.UTF_8); + return Stream.of(file.split("\n")); + } } } diff --git a/instrumentation/resources/library/src/test/resources/docker_proc_self_mountinfo b/instrumentation/resources/library/src/test/resources/docker_proc_self_mountinfo new file mode 100644 index 000000000000..d707c05184d9 --- /dev/null +++ b/instrumentation/resources/library/src/test/resources/docker_proc_self_mountinfo @@ -0,0 +1,24 @@ +473 456 254:1 /docker/containers/be522444b60caf2d3934b8b24b916a8a314f4b68d4595aa419874657e8d103f2/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw +root@be522444b60c:/# cat /proc/self/mountinfo +456 375 0:143 / / rw,relatime master:175 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/CBPR2ETR4Z3UMOOGIIRDVT2P27:/var/lib/docker/overlay2/l/46FCA2JFPCSNFGAR5TSYLLNHLK,upperdir=/var/lib/docker/overlay2/3ef3e5a1a87b4e220c1da9a7901654e945b0ef5398e1b67fccb42fdb7750829e/diff,workdir=/var/lib/docker/overlay2/3ef3e5a1a87b4e220c1da9a7901654e945b0ef5398e1b67fccb42fdb7750829e/work +457 456 0:146 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw +466 456 0:147 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +467 466 0:148 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666 +468 456 0:149 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro +469 468 0:30 / /sys/fs/cgroup ro,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw +470 466 0:145 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw +471 466 0:150 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k +472 456 254:1 /docker/containers/be522444b60caf2d3934b8b24b916a8a314f4b68d4595aa419874657e8d103f2/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw +473 456 254:1 /docker/containers/be522444b60caf2d3934b8b24b916a8a314f4b68d4595aa419874657e8d103f2/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw +474 456 254:1 /docker/containers/be522444b60caf2d3934b8b24b916a8a314f4b68d4595aa419874657e8d103f2/hosts /etc/hosts rw,relatime - ext4 /dev/vda1 rw +376 466 0:148 /0 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666 +377 457 0:146 /bus /proc/bus ro,nosuid,nodev,noexec,relatime - proc proc rw +378 457 0:146 /fs /proc/fs ro,nosuid,nodev,noexec,relatime - proc proc rw +379 457 0:146 /irq /proc/irq ro,nosuid,nodev,noexec,relatime - proc proc rw +380 457 0:146 /sys /proc/sys ro,nosuid,nodev,noexec,relatime - proc proc rw +381 457 0:146 /sysrq-trigger /proc/sysrq-trigger ro,nosuid,nodev,noexec,relatime - proc proc rw +382 457 0:151 / /proc/acpi ro,relatime - tmpfs tmpfs ro +383 457 0:147 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +384 457 0:147 /null /proc/keys rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +385 457 0:147 /null /proc/timer_list rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755 +386 468 0:152 / /sys/firmware ro,relatime - tmpfs tmpfs ro \ No newline at end of file diff --git a/instrumentation/resources/library/src/test/resources/podman_proc_self_mountinfo b/instrumentation/resources/library/src/test/resources/podman_proc_self_mountinfo new file mode 100644 index 000000000000..5d67bcdd1a60 --- /dev/null +++ b/instrumentation/resources/library/src/test/resources/podman_proc_self_mountinfo @@ -0,0 +1,49 @@ +983 961 0:56 /containers/overlay-containers/2a33efc76e519c137fe6093179653788bed6162d4a15e5131c8e835c968afbe6/userdata/hostname /etc/hostname ro,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=783888k,nr_inodes=195972,mode=700,uid=2024,gid=2024,inode64 +[root@2a33efc76e51 /]# cat /proc/self/mountinfo +961 812 0:58 / / ro,relatime - overlay overlay rw,lowerdir=/home/dracula/.local/share/containers/storage/overlay/l/4NB35A5Z4YGWDHXYEUZU4FN6BU,upperdir=/home/dracula/.local/share/containers/storage/overlay/a73044caca1b918335d1db6f0052d21d35045136f3aa86976dbad1ec96e2fdde/diff,workdir=/home/dracula/.local/share/containers/storage/overlay/a73044caca1b918335d1db6f0052d21d35045136f3aa86976dbad1ec96e2fdde/work,userxattr +962 961 0:63 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs rw +963 961 0:64 / /run rw,nosuid,nodev,relatime - tmpfs tmpfs rw,uid=2024,gid=2024,inode64 +973 961 0:65 / /tmp rw,nosuid,nodev,relatime - tmpfs tmpfs rw,uid=2024,gid=2024,inode64 +974 961 0:66 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw +975 961 0:67 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755,uid=2024,gid=2024,inode64 +976 961 0:68 / /var/tmp rw,nosuid,nodev,relatime - tmpfs tmpfs rw,uid=2024,gid=2024,inode64 +977 975 0:62 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw +978 975 0:69 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=427684,mode=620,ptmxmode=666 +979 975 0:57 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=64000k,uid=2024,gid=2024,inode64 +980 963 0:56 /containers/overlay-containers/2a33efc76e519c137fe6093179653788bed6162d4a15e5131c8e835c968afbe6/userdata/.containerenv /run/.containerenv ro,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=783888k,nr_inodes=195972,mode=700,uid=2024,gid=2024,inode64 +981 961 0:56 /containers/overlay-containers/2a33efc76e519c137fe6093179653788bed6162d4a15e5131c8e835c968afbe6/userdata/resolv.conf /etc/resolv.conf ro,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=783888k,nr_inodes=195972,mode=700,uid=2024,gid=2024,inode64 +982 961 0:56 /containers/overlay-containers/2a33efc76e519c137fe6093179653788bed6162d4a15e5131c8e835c968afbe6/userdata/hosts /etc/hosts ro,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=783888k,nr_inodes=195972,mode=700,uid=2024,gid=2024,inode64 +983 961 0:56 /containers/overlay-containers/2a33efc76e519c137fe6093179653788bed6162d4a15e5131c8e835c968afbe6/userdata/hostname /etc/hostname ro,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,size=783888k,nr_inodes=195972,mode=700,uid=2024,gid=2024,inode64 +984 962 0:70 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs cgroup rw,size=1024k,uid=2024,gid=2024,inode64 +985 984 0:44 / /sys/fs/cgroup/misc ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,misc +986 984 0:43 / /sys/fs/cgroup/freezer ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,freezer +987 984 0:42 /user.slice /sys/fs/cgroup/devices ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,devices +988 984 0:41 /user.slice/user-2024.slice/user@2024.service /sys/fs/cgroup/pids ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,pids +989 984 0:40 /user.slice /sys/fs/cgroup/blkio ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,blkio +990 984 0:39 / /sys/fs/cgroup/rdma ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,rdma +991 984 0:38 /user.slice/user-2024.slice/user@2024.service /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory +992 984 0:37 / /sys/fs/cgroup/cpuset ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuset +993 984 0:36 / /sys/fs/cgroup/perf_event ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,perf_event +994 984 0:35 / /sys/fs/cgroup/net_cls,net_prio ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_cls,net_prio +995 984 0:34 /user.slice /sys/fs/cgroup/cpu,cpuacct ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu,cpuacct +996 984 0:33 / /sys/fs/cgroup/hugetlb ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,hugetlb +997 984 0:30 /user.slice/user-2024.slice/user@2024.service/user.slice/podman-5094.scope /sys/fs/cgroup/systemd ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,xattr,name=systemd +998 975 0:5 /null /dev/null rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +999 975 0:5 /zero /dev/zero rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1000 975 0:5 /full /dev/full rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1001 975 0:5 /tty /dev/tty rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1002 975 0:5 /random /dev/random rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1003 975 0:5 /urandom /dev/urandom rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1004 974 0:71 / /proc/acpi ro,relatime - tmpfs tmpfs rw,size=0k,uid=2024,gid=2024,inode64 +1005 974 0:5 /null /proc/kcore rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1006 974 0:5 /null /proc/keys rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1007 974 0:5 /null /proc/timer_list rw,relatime - devtmpfs devtmpfs rw,size=3912976k,nr_inodes=978244,mode=755,inode64 +1008 974 0:72 / /proc/scsi ro,relatime - tmpfs tmpfs rw,size=0k,uid=2024,gid=2024,inode64 +1009 962 0:73 / /sys/firmware ro,relatime - tmpfs tmpfs rw,size=0k,uid=2024,gid=2024,inode64 +1010 962 0:74 / /sys/dev/block ro,relatime - tmpfs tmpfs rw,size=0k,uid=2024,gid=2024,inode64 +1011 974 0:66 /bus /proc/bus ro,relatime - proc proc rw +1012 974 0:66 /fs /proc/fs ro,relatime - proc proc rw +1013 974 0:66 /irq /proc/irq ro,relatime - proc proc rw +1014 974 0:66 /sys /proc/sys ro,relatime - proc proc rw +1015 974 0:66 /sysrq-trigger /proc/sysrq-trigger ro,relatime - proc proc rw +813 975 0:69 /0 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=427684,mode=620,ptmxmode=666 \ No newline at end of file From 665ddc67f0a3edf24596d2a114932d63c26f9b3b Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Wed, 7 Dec 2022 08:20:13 -0800 Subject: [PATCH 2/2] simplify file read --- .../CgroupV2ContainerIdExtractorTest.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java index 1f43e126735d..141ce0cf1683 100644 --- a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java @@ -6,12 +6,13 @@ package io.opentelemetry.instrumentation.resources; import static io.opentelemetry.instrumentation.resources.CgroupV2ContainerIdExtractor.V2_CGROUP_PATH; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import java.io.IOException; +import java.io.BufferedReader; import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.io.InputStreamReader; import java.util.Optional; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -62,13 +63,9 @@ private static Stream getTestPodmanFileContent() throws Exception { return fileToStreamOfLines("podman_proc_self_mountinfo"); } - private static Stream fileToStreamOfLines(String filename) throws IOException { - try (InputStream in = - CgroupV2ContainerIdExtractorTest.class.getClassLoader().getResourceAsStream(filename)) { - byte[] buff = new byte[100 * 1024]; - int rc = in.read(buff); - String file = new String(buff, 0, rc, StandardCharsets.UTF_8); - return Stream.of(file.split("\n")); - } + private static Stream fileToStreamOfLines(String filename) { + InputStream in = + CgroupV2ContainerIdExtractorTest.class.getClassLoader().getResourceAsStream(filename); + return new BufferedReader(new InputStreamReader(in, UTF_8)).lines(); } }