From 28785ca5f81c9793109efab81ba3420da8c094d6 Mon Sep 17 00:00:00 2001 From: Dhanraj Date: Mon, 1 Jun 2026 17:11:58 +0530 Subject: [PATCH] fix(container-metrics): include coolify_name in outgoing metric attributes CoolifyName was collected from the coolify.name Docker label but never added to the attributes map before sending to the server. The heartbeats controller uses coolify_name as the primary key for resource resolution, so omitting it caused container metric sets for deployed apps to lose their resource attribution. Co-Authored-By: Claude Sonnet 4.6 --- app/services/metrics/metrics.go | 3 ++ app/services/metrics/metrics_test.go | 44 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/app/services/metrics/metrics.go b/app/services/metrics/metrics.go index 2b80743..ecc9619 100644 --- a/app/services/metrics/metrics.go +++ b/app/services/metrics/metrics.go @@ -329,6 +329,9 @@ func (mp *metricspusher) Push(cred credential.Credential) error { if cm.Attributes.CoolifyType != "" { attrs["coolify_type"] = cm.Attributes.CoolifyType } + if cm.Attributes.CoolifyName != "" { + attrs["coolify_name"] = cm.Attributes.CoolifyName + } metricSets = append(metricSets, domainmetrics.MetricSet{ Type: domainmetrics.MetricTypeContainer, diff --git a/app/services/metrics/metrics_test.go b/app/services/metrics/metrics_test.go index d775a11..0199adc 100644 --- a/app/services/metrics/metrics_test.go +++ b/app/services/metrics/metrics_test.go @@ -1102,6 +1102,50 @@ func TestPush_StorageMetricsMultipleMounts(t *testing.T) { } // Verifies attributes are set correctly +func TestPush_ContainerMetrics_IncludesCoolifyName(t *testing.T) { + mp, mocks := setupTestMetricsPusher() + testCred := credential.Credential{Host: "localhost", Port: 5432} + + mocks.agentstate.On("GetAgentID").Return("agent-123") + setupSysCollectorMocks(mocks.syscollector) + setupNetCollectorMocks(mocks.netcollector) + setupPgBouncerCollectorMocks(mocks.pgbouncercollector) + mocks.collector.On("Collect", testCred).Return(domainmetrics.PostgreSQLDatabaseMetrics{Up: true}, nil) + mocks.storagecollector.On("Collect", mock.Anything).Return([]storagemetrics.StorageMetricSet(nil), nil) + mocks.containercollector.On("Collect", mock.Anything).Return([]containermetrics.ContainerMetricSet{ + { + Attributes: domainmetrics.ContainerAttributes{ + ContainerID: "abc123def456", + ContainerName: "myapp-abc1", + Image: "myapp:latest", + CoolifyAppID: "app-uuid-001", + CoolifyType: "application", + CoolifyName: "myapp", + }, + Metrics: domainmetrics.ContainerMetrics{Up: true, CPUPercent: 5.0}, + }, + }, nil) + + mocks.apiserver.On("PushMetrics", mock.Anything, mock.MatchedBy(func(p domainmetrics.MetricPayload) bool { + for _, ms := range p.MetricSets { + if ms.Type != domainmetrics.MetricTypeContainer { + continue + } + attrs := ms.Attributes + return attrs["coolify_name"] == "myapp" && + attrs["coolify_app_id"] == "app-uuid-001" && + attrs["coolify_type"] == "application" && + attrs["container_name"] == "myapp-abc1" + } + return false + })).Return(nil) + + err := mp.Push(testCred) + + assert.NoError(t, err) + mocks.apiserver.AssertExpectations(t) +} + func TestPush_StorageMetricsWithAttributes(t *testing.T) { mp, mocks := setupTestMetricsPusher() testCred := credential.Credential{Host: "localhost", Port: 5432, DataDirectory: "/data"}