This commit is contained in:
sensorialsn 2026-09-11 13:11:52 -04:00 committed by GitHub
commit cf526bca7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 3 deletions

View File

@ -51,11 +51,18 @@ func ShouldMonitorContainer(containerName string) bool {
return true
}
// GetServiceName returns the deduplication key of a container: its name
// without the swarm task suffix (myapp.1.abc123 → myapp), so replicas of the
// same swarm service are stored once per tick. Names without a task suffix
// (docker compose containers) are already unique per container and are kept
// as-is. Splitting on "-" here used to conflate distinct services sharing a
// name prefix (app-x-mysql and app-x-redis both mapped to "app-x"), so only
// the first of them in `docker stats` output was stored each tick — even
// though metrics are stored and queried by full container_name.
func GetServiceName(containerName string) string {
name := strings.TrimPrefix(containerName, "/")
parts := strings.Split(name, "-")
if len(parts) > 1 {
return strings.Join(parts[:len(parts)-1], "-")
if dot := strings.Index(name, "."); dot != -1 {
return name[:dot]
}
return name
}

View File

@ -0,0 +1,27 @@
package containers
import "testing"
func TestGetServiceName(t *testing.T) {
cases := []struct {
name string
in string
want string
}{
{"swarm replica 1", "myapp-3fa2bc.1.zxc4vplq8m0e", "myapp-3fa2bc"},
{"swarm replica 2 collapses to the same service", "myapp-3fa2bc.2.a1b2c3d4e5f6", "myapp-3fa2bc"},
{"leading slash is stripped", "/myapp-3fa2bc.1.zxc4vplq8m0e", "myapp-3fa2bc"},
{"compose container_name stays distinct", "app-1425-mysql", "app-1425-mysql"},
{"sibling compose service must not collapse with the previous one", "app-1425-redis", "app-1425-redis"},
{"compose default naming stays distinct", "project-web-1", "project-web-1"},
{"name without separators", "single", "single"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := GetServiceName(tc.in); got != tc.want {
t.Errorf("GetServiceName(%q) = %q, want %q", tc.in, got, tc.want)
}
})
}
}