github.com/cilium/cilium@v1.16.2/pkg/hive/health/metrics_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package health 5 6 import ( 7 "context" 8 "testing" 9 10 "github.com/cilium/hive" 11 "github.com/cilium/hive/cell" 12 "github.com/cilium/hive/hivetest" 13 "github.com/cilium/hive/job" 14 "github.com/cilium/statedb" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 18 "github.com/cilium/cilium/pkg/hive/health/types" 19 ) 20 21 func Test_Metrics(t *testing.T) { 22 var db *statedb.DB 23 var table statedb.Table[types.Status] 24 resChan := make(chan map[types.Level]uint64) 25 // Using upstream hive here to avoid import cycles and be able to inject the right metric 26 // publishing func for the test. 27 h := hive.New( 28 statedb.Cell, 29 job.Cell, 30 31 cell.ProvidePrivate(newTablesPrivate), 32 cell.Provide( 33 newHealthV2Provider, 34 statedb.RWTable[types.Status].ToTable, 35 ), 36 cell.Provide(func(lc cell.Lifecycle, p types.Provider, jr job.Registry) job.Group { 37 h := p.ForModule(cell.FullModuleID{"test"}) 38 jg := jr.NewGroup(h) 39 lc.Append(jg) 40 return jg 41 }), 42 43 cell.Module("health-metrics-test", "hive module health metrics test", 44 cell.Provide(newMetrics), 45 cell.Invoke(func(p metricPublisherParams) { 46 // Writes the updates to a chan to synchronise with the test. 47 publish := func(stats map[types.Level]uint64) { 48 resChan <- stats 49 } 50 51 p.JobGroup.Add(job.OneShot("module-status-metrics", 52 func(ctx context.Context, health cell.Health) error { 53 return publishJob(ctx, p, publish) 54 })) 55 }), 56 57 // Generate some test module health data 58 cell.Invoke(func(db_ *statedb.DB, table_ statedb.RWTable[types.Status]) { 59 db = db_ 60 table = table_ 61 txn := db_.WriteTxn(table_) 62 _, _, err := table_.Insert(txn, types.Status{ 63 ID: types.Identifier{ 64 Module: cell.FullModuleID{"test"}, 65 }, 66 Level: types.LevelDegraded, 67 }) 68 assert.NoError(t, err) 69 _, _, err = table_.Insert(txn, types.Status{ 70 ID: types.Identifier{ 71 Module: cell.FullModuleID{"test2"}, 72 }, 73 Level: types.LevelOK, 74 }) 75 assert.NoError(t, err) 76 txn.Commit() 77 }), 78 ), 79 ) 80 require.NotNil(t, h) 81 82 tlog := hivetest.Logger(t) 83 err := h.Start(tlog, context.TODO()) 84 require.NoError(t, err) 85 86 t.Cleanup(func() { 87 err = h.Stop(tlog, context.TODO()) 88 require.NoError(t, err) 89 }) 90 91 // Metrics as they would be published 92 resMetrics := <-resChan 93 it := table.All(db.ReadTxn()) 94 ok, degraded, stopped := count(it) 95 96 assert.Equal(t, resMetrics[types.LevelOK], ok) 97 assert.Greater(t, resMetrics[types.LevelOK], uint64(1)) 98 assert.Equal(t, resMetrics[types.LevelDegraded], degraded) 99 assert.Equal(t, resMetrics[types.LevelDegraded], uint64(1)) 100 assert.Equal(t, resMetrics[types.LevelStopped], stopped) 101 } 102 103 func count(it statedb.Iterator[types.Status]) (ok uint64, degraded uint64, stopped uint64) { 104 for obj, _, hasMore := it.Next(); hasMore; obj, _, hasMore = it.Next() { 105 switch obj.Level { 106 case types.LevelOK: 107 ok++ 108 case types.LevelDegraded: 109 degraded++ 110 case types.LevelStopped: 111 stopped++ 112 } 113 } 114 return 115 }