From a2efd83ca1bc3ce979a3b201c89f98237d7f5b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vandon?= Date: Tue, 14 Apr 2026 11:51:06 +0200 Subject: [PATCH 1/2] fix container ID parsing for cgroup v1 in EKS-Fargate --- .../common/container/ContainerInfo.java | 33 ++++++++++++++++++- .../common/container/ContainerInfoTest.groovy | 15 +++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java b/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java index bffdf80d1a2..511a3b3960e 100644 --- a/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java +++ b/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java @@ -252,7 +252,12 @@ public static ContainerInfo parse(final String cgroupsContent) throws ParseExcep containerInfo.setPodId(cGroupInfo.getPodId()); } - if (cGroupInfo.getContainerId() != null) { + if (cGroupInfo.getContainerId() != null + && shouldReplaceContainerId( + containerInfo.getContainerId(), + containerInfo.getPodId(), + cGroupInfo.getContainerId(), + cGroupInfo.getPodId())) { containerInfo.setContainerId(cGroupInfo.getContainerId()); } } @@ -260,6 +265,32 @@ public static ContainerInfo parse(final String cgroupsContent) throws ParseExcep return containerInfo; } + /** + * Keeps the best available container id candidate across cgroup lines. + * + *

Some environments expose both detailed cgroup-v1 controller paths and a cgroup-v2 membership + * path (0::...) where the tail can be task-level and less specific. + */ + private static boolean shouldReplaceContainerId( + @Nullable String currentContainerId, + @Nullable String currentPodId, + String candidateContainerId, + @Nullable String candidatePodId) { + if (currentContainerId == null) { + return true; + } + + if (currentContainerId.matches(CONTAINER_REGEX) && candidateContainerId.matches(TASK_REGEX)) { + // Do not replace a pod-scoped container id with a task-scoped id from a less specific path. + // This protects hybrid cgroup output where trailing 0:: lines contain only task ids. + if (currentPodId != null && candidatePodId == null) { + return false; + } + } + + return true; + } + static CGroupInfo parseLine(final String line) throws ParseException { final Matcher matcher = LINE_PATTERN.matcher(line); diff --git a/utils/container-utils/src/test/groovy/datadog/common/container/ContainerInfoTest.groovy b/utils/container-utils/src/test/groovy/datadog/common/container/ContainerInfoTest.groovy index c8646f918f5..1b74763b5b3 100644 --- a/utils/container-utils/src/test/groovy/datadog/common/container/ContainerInfoTest.groovy +++ b/utils/container-utils/src/test/groovy/datadog/common/container/ContainerInfoTest.groovy @@ -166,6 +166,21 @@ class ContainerInfoTest extends DDSpecification { 2:memory:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da 1:name=systemd:/ecs/34dc0b5e626f2c5c4c5170e34b10e765-1234567890""" + // EKS Fargate cgroup with trailing cgroup v2 membership entry (0::...) + "cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc" | "defa568d-ff14-43d9-9a63-9e39ee9b39b4" | 13 | """12:misc:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +11:cpuset:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +10:perf_event:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +9:blkio:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +8:net_cls,net_prio:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +7:memory:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +6:cpu,cpuacct:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +5:pids:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +4:devices:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +3:hugetlb:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +2:freezer:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +1:name=systemd:/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393/kubepods/burstable/poddefa568d-ff14-43d9-9a63-9e39ee9b39b4/cf1241bbf80ea91eebdd28bf719057380997ca4b0cea16869393b905fb6d52bc +0::/ecs/545b896a072744d186c7fb09a45ec172/545b896a072744d186c7fb09a45ec172-3057940393""" + // PCF file "6f265890-5165-7fab-6b52-18d1" | null | 12 | """12:rdma:/ 11:net_cls,net_prio:/garden/6f265890-5165-7fab-6b52-18d1 From 4ae7a6ae775f158934e143ae4eff6cc1b4276520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vandon?= Date: Tue, 14 Apr 2026 14:48:51 +0200 Subject: [PATCH 2/2] simplify code by centralizing logic --- .../common/container/ContainerInfo.java | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java b/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java index 511a3b3960e..61d174e97c5 100644 --- a/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java +++ b/utils/container-utils/src/main/java/datadog/common/container/ContainerInfo.java @@ -252,14 +252,7 @@ public static ContainerInfo parse(final String cgroupsContent) throws ParseExcep containerInfo.setPodId(cGroupInfo.getPodId()); } - if (cGroupInfo.getContainerId() != null - && shouldReplaceContainerId( - containerInfo.getContainerId(), - containerInfo.getPodId(), - cGroupInfo.getContainerId(), - cGroupInfo.getPodId())) { - containerInfo.setContainerId(cGroupInfo.getContainerId()); - } + replaceContainerIdIfBetter(containerInfo, cGroupInfo); } return containerInfo; @@ -271,24 +264,23 @@ && shouldReplaceContainerId( *

Some environments expose both detailed cgroup-v1 controller paths and a cgroup-v2 membership * path (0::...) where the tail can be task-level and less specific. */ - private static boolean shouldReplaceContainerId( - @Nullable String currentContainerId, - @Nullable String currentPodId, - String candidateContainerId, - @Nullable String candidatePodId) { - if (currentContainerId == null) { - return true; - } - - if (currentContainerId.matches(CONTAINER_REGEX) && candidateContainerId.matches(TASK_REGEX)) { + private static void replaceContainerIdIfBetter( + ContainerInfo currentContainerInfo, CGroupInfo candidate) { + String candidateContainerId = candidate.getContainerId(); + if (candidateContainerId == null) return; + + String currentContainerId = currentContainerInfo.getContainerId(); + if (currentContainerId != null + && currentContainerId.matches(CONTAINER_REGEX) + && candidateContainerId.matches(TASK_REGEX) + && currentContainerInfo.getPodId() != null + && candidate.getPodId() == null) { // Do not replace a pod-scoped container id with a task-scoped id from a less specific path. // This protects hybrid cgroup output where trailing 0:: lines contain only task ids. - if (currentPodId != null && candidatePodId == null) { - return false; - } + return; } - return true; + currentContainerInfo.setContainerId(candidateContainerId); } static CGroupInfo parseLine(final String line) throws ParseException {