@@ -285,7 +285,8 @@ func TestPowerCollector(t *testing.T) {
285
285
mockMonitor .On ("Snapshot" ).Return (testData , nil )
286
286
287
287
// Create collector
288
- collector := NewPowerCollector (mockMonitor , "test-node" , logger , metrics .MetricsLevelNode | metrics .MetricsLevelProcess | metrics .MetricsLevelContainer | metrics .MetricsLevelVM | metrics .MetricsLevelPod )
288
+ allLevels := metrics .MetricsLevelNode | metrics .MetricsLevelProcess | metrics .MetricsLevelContainer | metrics .MetricsLevelVM | metrics .MetricsLevelPod
289
+ collector := NewPowerCollector (mockMonitor , "test-node" , logger , allLevels )
289
290
290
291
// Trigger update to ensure descriptors are created
291
292
mockMonitor .TriggerUpdate ()
@@ -860,3 +861,197 @@ func TestPowerCollector_MetricsLevelFiltering(t *testing.T) {
860
861
})
861
862
}
862
863
}
864
+
865
+ func TestTerminatedContainerExport (t * testing.T ) {
866
+ logger := slog .New (slog .NewTextHandler (os .Stderr , & slog.HandlerOptions {Level : slog .LevelError }))
867
+ mockMonitor := NewMockPowerMonitor ()
868
+
869
+ packageZone := device .NewMockRaplZone ("package" , 0 , "/sys/class/powercap/intel-rapl/intel-rapl:0" , 1000 )
870
+
871
+ testSnapshot := & monitor.Snapshot {
872
+ Timestamp : time .Now (),
873
+ Node : & monitor.Node {
874
+ Zones : monitor.NodeZoneUsageMap {
875
+ packageZone : monitor.NodeUsage {
876
+ EnergyTotal : 1000 * device .Joule ,
877
+ Power : 10 * device .Watt ,
878
+ },
879
+ },
880
+ },
881
+ Processes : monitor.Processes {},
882
+ Containers : monitor.Containers {
883
+ "running-container" : & monitor.Container {
884
+ ID : "running-container" ,
885
+ Name : "running-cont" ,
886
+ Runtime : resource .DockerRuntime ,
887
+ Zones : monitor.ZoneUsageMap {
888
+ packageZone : monitor.Usage {
889
+ EnergyTotal : 150 * device .Joule ,
890
+ Power : 15 * device .Watt ,
891
+ },
892
+ },
893
+ },
894
+ },
895
+ TerminatedContainers : monitor.Containers {
896
+ "terminated-container" : & monitor.Container {
897
+ ID : "terminated-container" ,
898
+ Name : "terminated-cont" ,
899
+ Runtime : resource .PodmanRuntime ,
900
+ Zones : monitor.ZoneUsageMap {
901
+ packageZone : monitor.Usage {
902
+ EnergyTotal : 300 * device .Joule ,
903
+ Power : 30 * device .Watt ,
904
+ },
905
+ },
906
+ },
907
+ },
908
+ VirtualMachines : monitor.VirtualMachines {},
909
+ Pods : monitor.Pods {},
910
+ }
911
+
912
+ mockMonitor .On ("Snapshot" ).Return (testSnapshot , nil )
913
+
914
+ allLevels := metrics .MetricsLevelNode | metrics .MetricsLevelProcess | metrics .MetricsLevelContainer | metrics .MetricsLevelVM | metrics .MetricsLevelPod
915
+ collector := NewPowerCollector (mockMonitor , "test-node" , logger , allLevels )
916
+
917
+ registry := prometheus .NewRegistry ()
918
+ registry .MustRegister (collector )
919
+
920
+ mockMonitor .TriggerUpdate ()
921
+ time .Sleep (10 * time .Millisecond )
922
+
923
+ t .Run ("Terminated Container Metrics Export" , func (t * testing.T ) {
924
+ // Test running container metrics
925
+ assertMetricLabelValues (t , registry , "kepler_container_cpu_joules_total" ,
926
+ map [string ]string {"container_id" : "running-container" , "state" : "running" }, 150.0 )
927
+ assertMetricLabelValues (t , registry , "kepler_container_cpu_watts" ,
928
+ map [string ]string {"container_id" : "running-container" , "state" : "running" }, 15.0 )
929
+
930
+ // Test terminated container metrics
931
+ assertMetricLabelValues (t , registry , "kepler_container_cpu_joules_total" ,
932
+ map [string ]string {"container_id" : "terminated-container" , "state" : "terminated" }, 300.0 )
933
+ assertMetricLabelValues (t , registry , "kepler_container_cpu_watts" ,
934
+ map [string ]string {"container_id" : "terminated-container" , "state" : "terminated" }, 30.0 )
935
+
936
+ // Test additional labels for running container
937
+ assertMetricLabelValues (t , registry , "kepler_container_cpu_joules_total" ,
938
+ map [string ]string {"container_id" : "running-container" , "container_name" : "running-cont" , "runtime" : "docker" }, 150.0 )
939
+
940
+ // Test additional labels for terminated container
941
+ assertMetricLabelValues (t , registry , "kepler_container_cpu_joules_total" ,
942
+ map [string ]string {"container_id" : "terminated-container" , "container_name" : "terminated-cont" , "runtime" : "podman" }, 300.0 )
943
+ })
944
+
945
+ t .Run ("Container State Labels" , func (t * testing.T ) {
946
+ // Verify that the state label exists and has correct values
947
+ assertMetricExists (t , registry , "kepler_container_cpu_joules_total" ,
948
+ map [string ]string {"state" : "running" })
949
+ assertMetricExists (t , registry , "kepler_container_cpu_joules_total" ,
950
+ map [string ]string {"state" : "terminated" })
951
+
952
+ // Also verify for watts metrics
953
+ assertMetricExists (t , registry , "kepler_container_cpu_watts" ,
954
+ map [string ]string {"state" : "running" })
955
+ assertMetricExists (t , registry , "kepler_container_cpu_watts" ,
956
+ map [string ]string {"state" : "terminated" })
957
+ })
958
+
959
+ mockMonitor .AssertExpectations (t )
960
+ }
961
+
962
+ func TestTerminatedVMExport (t * testing.T ) {
963
+ logger := slog .New (slog .NewTextHandler (os .Stderr , & slog.HandlerOptions {Level : slog .LevelError }))
964
+ mockMonitor := NewMockPowerMonitor ()
965
+
966
+ packageZone := device .NewMockRaplZone ("package" , 0 , "/sys/class/powercap/intel-rapl/intel-rapl:0" , 1000 )
967
+
968
+ testSnapshot := & monitor.Snapshot {
969
+ Timestamp : time .Now (),
970
+ Node : & monitor.Node {
971
+ Zones : monitor.NodeZoneUsageMap {
972
+ packageZone : monitor.NodeUsage {
973
+ EnergyTotal : 1000 * device .Joule ,
974
+ Power : 10 * device .Watt ,
975
+ },
976
+ },
977
+ },
978
+ Processes : monitor.Processes {},
979
+ Containers : monitor.Containers {},
980
+ VirtualMachines : monitor.VirtualMachines {
981
+ "running-vm" : & monitor.VirtualMachine {
982
+ ID : "running-vm" ,
983
+ Name : "running-virtual-machine" ,
984
+ Hypervisor : resource .KVMHypervisor ,
985
+ Zones : monitor.ZoneUsageMap {
986
+ packageZone : monitor.Usage {
987
+ EnergyTotal : 250 * device .Joule ,
988
+ Power : 25 * device .Watt ,
989
+ },
990
+ },
991
+ },
992
+ },
993
+ TerminatedVirtualMachines : monitor.VirtualMachines {
994
+ "terminated-vm" : & monitor.VirtualMachine {
995
+ ID : "terminated-vm" ,
996
+ Name : "terminated-virtual-machine" ,
997
+ Hypervisor : resource .KVMHypervisor ,
998
+ Zones : monitor.ZoneUsageMap {
999
+ packageZone : monitor.Usage {
1000
+ EnergyTotal : 400 * device .Joule ,
1001
+ Power : 40 * device .Watt ,
1002
+ },
1003
+ },
1004
+ },
1005
+ },
1006
+ Pods : monitor.Pods {},
1007
+ }
1008
+
1009
+ mockMonitor .On ("Snapshot" ).Return (testSnapshot , nil )
1010
+
1011
+ allLevels := metrics .MetricsLevelNode | metrics .MetricsLevelProcess | metrics .MetricsLevelContainer | metrics .MetricsLevelVM | metrics .MetricsLevelPod
1012
+ collector := NewPowerCollector (mockMonitor , "test-node" , logger , allLevels )
1013
+
1014
+ registry := prometheus .NewRegistry ()
1015
+ registry .MustRegister (collector )
1016
+
1017
+ mockMonitor .TriggerUpdate ()
1018
+ time .Sleep (10 * time .Millisecond )
1019
+
1020
+ t .Run ("Terminated VM Metrics Export" , func (t * testing.T ) {
1021
+ // Test running VM metrics
1022
+ assertMetricLabelValues (t , registry , "kepler_vm_cpu_joules_total" ,
1023
+ map [string ]string {"vm_id" : "running-vm" , "state" : "running" }, 250.0 )
1024
+ assertMetricLabelValues (t , registry , "kepler_vm_cpu_watts" ,
1025
+ map [string ]string {"vm_id" : "running-vm" , "state" : "running" }, 25.0 )
1026
+
1027
+ // Test terminated VM metrics
1028
+ assertMetricLabelValues (t , registry , "kepler_vm_cpu_joules_total" ,
1029
+ map [string ]string {"vm_id" : "terminated-vm" , "state" : "terminated" }, 400.0 )
1030
+ assertMetricLabelValues (t , registry , "kepler_vm_cpu_watts" ,
1031
+ map [string ]string {"vm_id" : "terminated-vm" , "state" : "terminated" }, 40.0 )
1032
+
1033
+ // Test additional labels for running VM
1034
+ assertMetricLabelValues (t , registry , "kepler_vm_cpu_joules_total" ,
1035
+ map [string ]string {"vm_id" : "running-vm" , "vm_name" : "running-virtual-machine" , "hypervisor" : "kvm" }, 250.0 )
1036
+
1037
+ // Test additional labels for terminated VM
1038
+ assertMetricLabelValues (t , registry , "kepler_vm_cpu_joules_total" ,
1039
+ map [string ]string {"vm_id" : "terminated-vm" , "vm_name" : "terminated-virtual-machine" , "hypervisor" : "kvm" }, 400.0 )
1040
+ })
1041
+
1042
+ t .Run ("VM State Labels" , func (t * testing.T ) {
1043
+ // Verify that the state label exists and has correct values
1044
+ assertMetricExists (t , registry , "kepler_vm_cpu_joules_total" ,
1045
+ map [string ]string {"state" : "running" })
1046
+ assertMetricExists (t , registry , "kepler_vm_cpu_joules_total" ,
1047
+ map [string ]string {"state" : "terminated" })
1048
+
1049
+ // Also verify for watts metrics
1050
+ assertMetricExists (t , registry , "kepler_vm_cpu_watts" ,
1051
+ map [string ]string {"state" : "running" })
1052
+ assertMetricExists (t , registry , "kepler_vm_cpu_watts" ,
1053
+ map [string ]string {"state" : "terminated" })
1054
+ })
1055
+
1056
+ mockMonitor .AssertExpectations (t )
1057
+ }
0 commit comments