@@ -459,7 +459,7 @@ func TestPush_SystemMetricsFailure_StillPushesDbMetrics(t *testing.T) {
459459 setupNetCollectorMocks (mocks .netcollector )
460460 setupStorageCollectorMocks (mocks .storagecollector )
461461 mocks .collector .On ("Collect" , testCred ).
462- Return (domainmetrics.PostgreSQLDatabaseMetrics {ConnectionsTotal : 5 }, nil )
462+ Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true , ConnectionsTotal : 5 }, nil )
463463 mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .MatchedBy (func (p domainmetrics.MetricPayload ) bool {
464464 hasNetwork := false
465465 hasDb := false
@@ -469,7 +469,8 @@ func TestPush_SystemMetricsFailure_StillPushesDbMetrics(t *testing.T) {
469469 hasNetwork = true
470470 }
471471 if ms .Type == domainmetrics .MetricTypePostgreSQLDatabase {
472- hasDb = true
472+ dbMetrics := ms .Metrics .(domainmetrics.PostgreSQLDatabaseMetrics )
473+ hasDb = dbMetrics .Up
473474 }
474475 if ms .Type == domainmetrics .MetricTypeStorage {
475476 hasStorage = true
@@ -486,7 +487,7 @@ func TestPush_SystemMetricsFailure_StillPushesDbMetrics(t *testing.T) {
486487}
487488
488489// Push Tests - Partial Collection (system succeeds, db fails)
489- func TestPush_DatabaseMetricsFailure_StillPushesSystemMetrics (t * testing.T ) {
490+ func TestPush_DatabaseMetricsFailure_StillPushesSystemMetricsAndDbWithUpFalse (t * testing.T ) {
490491 mp , mocks := setupTestMetricsPusher ()
491492 testCred := credential.Credential {Host : "localhost" , DataDirectory : "/var/lib/postgresql" }
492493 collectErr := errors .New ("connection refused" )
@@ -501,6 +502,7 @@ func TestPush_DatabaseMetricsFailure_StillPushesSystemMetrics(t *testing.T) {
501502 hasSys := false
502503 hasNetwork := false
503504 hasStorage := false
505+ hasDbWithUpFalse := false
504506 for _ , ms := range p .MetricSets {
505507 if ms .Type == domainmetrics .MetricTypeSystem {
506508 hasSys = true
@@ -511,8 +513,12 @@ func TestPush_DatabaseMetricsFailure_StillPushesSystemMetrics(t *testing.T) {
511513 if ms .Type == domainmetrics .MetricTypeStorage {
512514 hasStorage = true
513515 }
516+ if ms .Type == domainmetrics .MetricTypePostgreSQLDatabase {
517+ dbMetrics := ms .Metrics .(domainmetrics.PostgreSQLDatabaseMetrics )
518+ hasDbWithUpFalse = ! dbMetrics .Up
519+ }
514520 }
515- return hasSys && hasNetwork && hasStorage
521+ return hasSys && hasNetwork && hasStorage && hasDbWithUpFalse
516522 })).Return (nil )
517523
518524 err := mp .Push (testCred )
@@ -522,8 +528,8 @@ func TestPush_DatabaseMetricsFailure_StillPushesSystemMetrics(t *testing.T) {
522528 mocks .apiserver .AssertExpectations (t )
523529}
524530
525- // Push Tests - All Collections Fail
526- func TestPush_AllCollectionsFail (t * testing.T ) {
531+ // Push Tests - All Collections Fail — still pushes postgresql.database with up=false
532+ func TestPush_AllCollectionsFail_StillPushesDbWithUpFalse (t * testing.T ) {
527533 mp , mocks := setupTestMetricsPusher ()
528534 testCred := credential.Credential {Host : "localhost" , DataDirectory : "/var/lib/postgresql" }
529535
@@ -536,12 +542,22 @@ func TestPush_AllCollectionsFail(t *testing.T) {
536542 Return (nil , errors .New ("storage failed" ))
537543 mocks .collector .On ("Collect" , testCred ).
538544 Return (domainmetrics.PostgreSQLDatabaseMetrics {}, errors .New ("connection refused" ))
545+ mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .MatchedBy (func (p domainmetrics.MetricPayload ) bool {
546+ if len (p .MetricSets ) != 1 {
547+ return false
548+ }
549+ ms := p .MetricSets [0 ]
550+ if ms .Type != domainmetrics .MetricTypePostgreSQLDatabase {
551+ return false
552+ }
553+ dbMetrics := ms .Metrics .(domainmetrics.PostgreSQLDatabaseMetrics )
554+ return ! dbMetrics .Up
555+ })).Return (nil )
539556
540557 err := mp .Push (testCred )
541558
542- assert .Error (t , err )
543- assert .Contains (t , err .Error (), "all metrics collection failed" )
544- mocks .apiserver .AssertNotCalled (t , "PushMetrics" )
559+ assert .NoError (t , err )
560+ mocks .apiserver .AssertExpectations (t )
545561}
546562
547563func TestPush_APIServerPushFailure (t * testing.T ) {
@@ -554,7 +570,7 @@ func TestPush_APIServerPushFailure(t *testing.T) {
554570 setupNetCollectorMocks (mocks .netcollector )
555571 setupStorageCollectorMocks (mocks .storagecollector )
556572 mocks .collector .On ("Collect" , testCred ).
557- Return (domainmetrics.PostgreSQLDatabaseMetrics {ConnectionsTotal : 5 }, nil )
573+ Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true , ConnectionsTotal : 5 }, nil )
558574 mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .Anything ).
559575 Return (pushErr )
560576
@@ -579,6 +595,7 @@ func TestPush_Success_ValidatesPayloadSchema(t *testing.T) {
579595 setupStorageCollectorMocks (mocks .storagecollector )
580596 mocks .collector .On ("Collect" , testCred ).
581597 Return (domainmetrics.PostgreSQLDatabaseMetrics {
598+ Up : true ,
582599 ConnectionsTotal : 10 ,
583600 MaxConnections : 100 ,
584601 CacheHitRatio : 95.5 ,
@@ -653,6 +670,9 @@ func TestPush_Success_ValidatesPayloadSchema(t *testing.T) {
653670 }
654671
655672 // Check database metrics values
673+ if ! dbMetrics .Up {
674+ return false
675+ }
656676 if dbMetrics .ConnectionsTotal != 10 {
657677 return false
658678 }
@@ -695,7 +715,7 @@ func TestPush_ContextPropagation(t *testing.T) {
695715 setupNetCollectorMocks (mocks .netcollector )
696716 setupStorageCollectorMocks (mocks .storagecollector )
697717 mocks .collector .On ("Collect" , testCred ).
698- Return (domainmetrics.PostgreSQLDatabaseMetrics {}, nil )
718+ Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true }, nil )
699719 mocks .apiserver .On ("PushMetrics" , mock .MatchedBy (func (ctx context.Context ) bool {
700720 return ctx != nil
701721 }), mock .Anything ).
@@ -742,7 +762,7 @@ func TestPush_CredentialPassedCorrectly(t *testing.T) {
742762 c .Port == testCred .Port &&
743763 c .Username == testCred .Username &&
744764 c .Dialect == testCred .Dialect
745- })).Return (domainmetrics.PostgreSQLDatabaseMetrics {}, nil )
765+ })).Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true }, nil )
746766 mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .Anything ).
747767 Return (nil )
748768
@@ -793,6 +813,59 @@ func setupStorageCollectorMocks(collector *MockStorageCollector) {
793813 }, nil )
794814}
795815
816+ // Verifies database down sends up=false with zero metrics
817+ func TestPush_DatabaseDown_SendsUpFalseWithZeroMetrics (t * testing.T ) {
818+ mp , mocks := setupTestMetricsPusher ()
819+ testCred := credential.Credential {Host : "localhost" , DataDirectory : "/var/lib/postgresql" }
820+
821+ mocks .agentstate .On ("GetAgentID" ).Return ("agent-123" )
822+ setupSysCollectorMocks (mocks .syscollector )
823+ setupNetCollectorMocks (mocks .netcollector )
824+ setupStorageCollectorMocks (mocks .storagecollector )
825+ mocks .collector .On ("Collect" , testCred ).
826+ Return (domainmetrics.PostgreSQLDatabaseMetrics {}, errors .New ("connection refused" ))
827+ mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .MatchedBy (func (p domainmetrics.MetricPayload ) bool {
828+ for _ , ms := range p .MetricSets {
829+ if ms .Type == domainmetrics .MetricTypePostgreSQLDatabase {
830+ dbMetrics := ms .Metrics .(domainmetrics.PostgreSQLDatabaseMetrics )
831+ // up must be false
832+ if dbMetrics .Up {
833+ return false
834+ }
835+ // all other fields must be zero
836+ if dbMetrics .ConnectionsTotal != 0 {
837+ return false
838+ }
839+ if dbMetrics .MaxConnections != 0 {
840+ return false
841+ }
842+ if dbMetrics .CacheHitRatio != 0 {
843+ return false
844+ }
845+ if dbMetrics .TransactionsPerSecond != 0 {
846+ return false
847+ }
848+ if dbMetrics .CommittedTxPerSecond != 0 {
849+ return false
850+ }
851+ if dbMetrics .BlocksReadPerSecond != 0 {
852+ return false
853+ }
854+ if dbMetrics .ReplicationLagSeconds != 0 {
855+ return false
856+ }
857+ return true
858+ }
859+ }
860+ return false // postgresql.database metric set must be present
861+ })).Return (nil )
862+
863+ err := mp .Push (testCred )
864+
865+ assert .NoError (t , err )
866+ mocks .apiserver .AssertExpectations (t )
867+ }
868+
796869// Verifies storage metrics are included in the payload
797870func TestPush_IncludesStorageMetrics (t * testing.T ) {
798871 mp , mocks := setupTestMetricsPusher ()
@@ -803,7 +876,7 @@ func TestPush_IncludesStorageMetrics(t *testing.T) {
803876 setupNetCollectorMocks (mocks .netcollector )
804877 setupStorageCollectorMocks (mocks .storagecollector )
805878 mocks .collector .On ("Collect" , testCred ).
806- Return (domainmetrics.PostgreSQLDatabaseMetrics {}, nil )
879+ Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true }, nil )
807880 mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .MatchedBy (func (p domainmetrics.MetricPayload ) bool {
808881 hasStorage := false
809882 for _ , ms := range p .MetricSets {
@@ -832,7 +905,7 @@ func TestPush_StorageMetricsFailure_StillPushesOtherMetrics(t *testing.T) {
832905 mocks .storagecollector .On ("Collect" , mock .Anything ).
833906 Return (nil , errors .New ("storage collection failed" ))
834907 mocks .collector .On ("Collect" , testCred ).
835- Return (domainmetrics.PostgreSQLDatabaseMetrics {}, nil )
908+ Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true }, nil )
836909 mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .MatchedBy (func (p domainmetrics.MetricPayload ) bool {
837910 hasSys := false
838911 hasNet := false
@@ -876,7 +949,7 @@ func TestPush_StorageMetricsMultipleMounts(t *testing.T) {
876949 },
877950 }, nil )
878951 mocks .collector .On ("Collect" , testCred ).
879- Return (domainmetrics.PostgreSQLDatabaseMetrics {}, nil )
952+ Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true }, nil )
880953 mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .MatchedBy (func (p domainmetrics.MetricPayload ) bool {
881954 storageCount := 0
882955 for _ , ms := range p .MetricSets {
@@ -913,7 +986,7 @@ func TestPush_StorageMetricsWithAttributes(t *testing.T) {
913986 },
914987 }, nil )
915988 mocks .collector .On ("Collect" , testCred ).
916- Return (domainmetrics.PostgreSQLDatabaseMetrics {}, nil )
989+ Return (domainmetrics.PostgreSQLDatabaseMetrics {Up : true }, nil )
917990 mocks .apiserver .On ("PushMetrics" , mock .Anything , mock .MatchedBy (func (p domainmetrics.MetricPayload ) bool {
918991 for _ , ms := range p .MetricSets {
919992 if ms .Type == domainmetrics .MetricTypeStorage {
0 commit comments