collector.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package metric
  2. import (
  3. "maps"
  4. "sort"
  5. "time"
  6. "github.com/opencost/opencost/modules/collector-source/pkg/metric/aggregator"
  7. "github.com/opencost/opencost/modules/collector-source/pkg/util"
  8. )
  9. // MetricCollectorID is a unique identifier for a specific metric collector instance. We
  10. // use this identifier to register and unregister metric instances from the metrics metric
  11. // instead of the metric name and aggregation type to allow selectable cardinality (via Labels)
  12. // across multiple instances of the same aggregation type and metric name.
  13. type MetricCollectorID string
  14. const (
  15. PVPricePerGiBHourID MetricCollectorID = "PVPricePerGiBHour"
  16. PVUsedAverageID MetricCollectorID = "PVUsedAverage"
  17. PVUsedMaxID MetricCollectorID = "PVUsedMax"
  18. PVCInfoID MetricCollectorID = "PVCInfo"
  19. PVActiveMinutesID MetricCollectorID = "PVActiveMinutes"
  20. LocalStorageUsedActiveMinutesID MetricCollectorID = "LocalStorageUsedCost"
  21. LocalStorageUsedAverageID MetricCollectorID = "LocalStorageUsedAverage"
  22. LocalStorageUsedMaxID MetricCollectorID = "LocalStorageUsedMax"
  23. LocalStorageBytesID MetricCollectorID = "LocalStorageBytesID"
  24. LocalStorageActiveMinutesID MetricCollectorID = "LocalStorageActiveMinutes"
  25. NodeCPUCoresCapacityID MetricCollectorID = "NodeCPUCoresCapacity"
  26. NodeCPUCoresAllocatableID MetricCollectorID = "NodeCPUCoresAllocatable"
  27. NodeRAMBytesCapacityID MetricCollectorID = "NodeRAMBytesCapacity"
  28. NodeRAMBytesAllocatableID MetricCollectorID = "NodeRAMBytesAllocatable"
  29. NodeGPUCountID MetricCollectorID = "NodeGPUCount"
  30. NodeLabelsID MetricCollectorID = "NodeLabels"
  31. NodeActiveMinutesID MetricCollectorID = "NodeActiveMinutes"
  32. NodeCPUModeTotalID MetricCollectorID = "NodeCPUModeTotal"
  33. NodeRAMSystemUsageAverageID MetricCollectorID = "NodeRAMSystemUsageAverage"
  34. NodeRAMUserUsageAverageID MetricCollectorID = "NodeRAMUserUsageAverage"
  35. LBPricePerHourID MetricCollectorID = "LBPricePerHour"
  36. LBActiveMinutesID MetricCollectorID = "LBActiveMinutes"
  37. ClusterManagementDurationID MetricCollectorID = "ClusterManagementDuration"
  38. ClusterManagementPricePerHourID MetricCollectorID = "ClusterManagementPricePerHour"
  39. PodActiveMinutesID MetricCollectorID = "PodActiveMinutes"
  40. RAMBytesAllocatedID MetricCollectorID = "RAMBytesAllocated"
  41. RAMRequestsID MetricCollectorID = "RAMRequests"
  42. RAMUsageAverageID MetricCollectorID = "RAMUsageAverage"
  43. RAMUsageMaxID MetricCollectorID = "RAMUsageMax"
  44. CPUCoresAllocatedID MetricCollectorID = "CPUCoresAllocated"
  45. CPURequestsID MetricCollectorID = "CPURequestsID"
  46. CPUUsageAverageID MetricCollectorID = "CPUUsageAverage"
  47. CPUUsageMaxID MetricCollectorID = "CPUUsageMax"
  48. GPUsRequestedID MetricCollectorID = "GPUsRequested"
  49. GPUsUsageAverageID MetricCollectorID = "GPUsUsageAverage"
  50. GPUsUsageMaxID MetricCollectorID = "GPUsUsageMax"
  51. GPUsAllocatedID MetricCollectorID = "GPUsAllocated"
  52. IsGPUSharedID MetricCollectorID = "IsGPUShared"
  53. GPUInfoID MetricCollectorID = "GPUInfo"
  54. NodeCPUPricePerHourID MetricCollectorID = "NodeCPUPricePerHour"
  55. NodeRAMPricePerGiBHourID MetricCollectorID = "NodeRAMPricePerGiBHour"
  56. NodeGPUPricePerHourID MetricCollectorID = "NodeGPUPricePerHour"
  57. NodeIsSpotID MetricCollectorID = "NodeIsSpot"
  58. PodPVCAllocationID MetricCollectorID = "PodPVCAllocation"
  59. PVCBytesRequestedID MetricCollectorID = "PVCBytesRequested"
  60. PVBytesID MetricCollectorID = "PVBytesID"
  61. PVInfoID MetricCollectorID = "PVInfo"
  62. NetZoneGiBID MetricCollectorID = "NetZoneGiB"
  63. NetZonePricePerGiBID MetricCollectorID = "NetZonePricePerGiB"
  64. NetRegionGiBID MetricCollectorID = "NetRegionGiB"
  65. NetRegionPricePerGiBID MetricCollectorID = "NetRegionPricePerGiB"
  66. NetInternetGiBID MetricCollectorID = "NetInternetGiB"
  67. NetInternetPricePerGiBID MetricCollectorID = "NetInternetPricePerGiB"
  68. NetInternetServiceGiBID MetricCollectorID = "NetInternetServiceGiB"
  69. NetTransferBytesID MetricCollectorID = "NetTransferBytes"
  70. NetZoneIngressGiBID MetricCollectorID = "NetZoneIngressGiB"
  71. NetRegionIngressGiBID MetricCollectorID = "NetRegionIngressGiB"
  72. NetInternetIngressGiBID MetricCollectorID = "NetInternetIngressGiB"
  73. NetInternetServiceIngressGiBID MetricCollectorID = "NetInternetServiceIngressGiB"
  74. NetReceiveBytesID MetricCollectorID = "NetReceiveBytes"
  75. NamespaceLabelsID MetricCollectorID = "NamespaceLabels"
  76. NamespaceAnnotationsID MetricCollectorID = "NamespaceAnnotations"
  77. PodLabelsID MetricCollectorID = "PodLabels"
  78. PodAnnotationsID MetricCollectorID = "PodAnnotations"
  79. ServiceLabelsID MetricCollectorID = "ServiceLabels"
  80. DeploymentLabelsID MetricCollectorID = "DeploymentLabels"
  81. StatefulSetLabelsID MetricCollectorID = "StatefulSetLabels"
  82. DaemonSetLabelsID MetricCollectorID = "DaemonSetLabels"
  83. JobLabelsID MetricCollectorID = "JobLabels"
  84. PodsWithReplicaSetOwnerID MetricCollectorID = "PodsWithReplicaSetOwner"
  85. ReplicaSetsWithoutOwnersID MetricCollectorID = "ReplicaSetsWithoutOwners"
  86. ReplicaSetsWithRolloutID MetricCollectorID = "ReplicaSetsWithRollout"
  87. )
  88. // MetricCollector is a data structure that represents a specific MetricCollector metric instance that contains its own breakdown
  89. // of stored metrics by a specific label set.
  90. type MetricCollector struct {
  91. id MetricCollectorID // ie: RAMUsageAverage
  92. metricName string // ie: container_memory_working_set_bytes
  93. labels []string
  94. aggregatorFactory aggregator.MetricAggregatorFactory
  95. metrics map[uint64]aggregator.MetricAggregator // map[Hash(labelValues)] = aggregator
  96. filter func(map[string]string) bool
  97. }
  98. // NewMetricCollector creates a new MetricCollector instance with a unique identifier. The metric name is the specific
  99. // name of the collected metric that will be used to query the
  100. func NewMetricCollector(id MetricCollectorID, metricName string, labels []string, aggregatorFactory aggregator.MetricAggregatorFactory, fn func(map[string]string) bool) *MetricCollector {
  101. return &MetricCollector{
  102. id: id,
  103. metricName: metricName,
  104. labels: labels,
  105. aggregatorFactory: aggregatorFactory,
  106. metrics: make(map[uint64]aggregator.MetricAggregator),
  107. filter: fn,
  108. }
  109. }
  110. func (mi *MetricCollector) Update(labels map[string]string, value float64, timestamp time.Time, additionalInfo map[string]string) {
  111. if mi.filter != nil && !mi.filter(labels) {
  112. return
  113. }
  114. labelValues := make([]string, len(mi.labels))
  115. for i, key := range mi.labels {
  116. labelValues[i] = labels[key]
  117. }
  118. key := util.Hash(labelValues)
  119. if mi.metrics[key] == nil {
  120. mi.metrics[key] = mi.aggregatorFactory(
  121. util.MetricNameFor(mi.metricName, mi.labels, labelValues), labelValues)
  122. }
  123. mi.metrics[key].Update(value, timestamp, additionalInfo)
  124. }
  125. func (mi *MetricCollector) Get() []*aggregator.MetricResult {
  126. results := make([]*aggregator.MetricResult, 0, len(mi.metrics))
  127. for _, metric := range mi.metrics {
  128. labels := util.ToMap(mi.labels, metric.LabelValues())
  129. maps.Copy(labels, metric.AdditionInfo())
  130. mr := &aggregator.MetricResult{
  131. Name: metric.Name(),
  132. MetricLabels: labels,
  133. Values: metric.Value(),
  134. }
  135. results = append(results, mr)
  136. }
  137. sort.Slice(results, func(i, j int) bool {
  138. return results[i].Name < results[j].Name
  139. })
  140. return results
  141. }
  142. func (mi *MetricCollector) Labels() []string {
  143. return mi.labels
  144. }