Browse Source

addressing code comments and emitting a new metrics called kubecost_pv_info and also making unknown and local storage class constants

Signed-off-by: Alan Rodrigues <alanr5691@yahoo.com>
Alan Rodrigues 3 years ago
parent
commit
1b4941ee3d
3 changed files with 73 additions and 6 deletions
  1. 5 5
      pkg/costmodel/cluster.go
  2. 7 1
      pkg/kubecost/asset.go
  3. 61 0
      pkg/metrics/pvmetrics.go

+ 5 - 5
pkg/costmodel/cluster.go

@@ -157,7 +157,7 @@ func ClusterDisks(client prometheus.Client, provider cloud.Provider, start, end
 	queryPVCost := fmt.Sprintf(`avg(avg_over_time(pv_hourly_cost[%s])) by (%s, persistentvolume,provider_id)`, durStr, env.GetPromClusterLabel())
 	queryPVSize := fmt.Sprintf(`avg(avg_over_time(kube_persistentvolume_capacity_bytes[%s])) by (%s, persistentvolume)`, durStr, env.GetPromClusterLabel())
 	queryActiveMins := fmt.Sprintf(`count(pv_hourly_cost) by (%s, persistentvolume)[%s:%dm]`, env.GetPromClusterLabel(), durStr, minsPerResolution)
-	queryPVStorageClass := fmt.Sprintf(`avg(avg_over_time(kube_persistentvolumeclaim_info[%s])) by (%s, volumename, storageclass)`, durStr, env.GetPromClusterLabel())
+	queryPVStorageClass := fmt.Sprintf(`avg(avg_over_time(kubecost_pv_info[%s])) by (%s, persistentvolume, storageclass)`, durStr, env.GetPromClusterLabel())
 
 	queryLocalStorageCost := fmt.Sprintf(`sum_over_time(sum(container_fs_limit_bytes{device!="tmpfs", id="/"}) by (instance, %s)[%s:%dm]) / 1024 / 1024 / 1024 * %f * %f`, env.GetPromClusterLabel(), durStr, minsPerResolution, hourlyToCumulative, costPerGBHr)
 	queryLocalStorageUsedCost := fmt.Sprintf(`sum_over_time(sum(container_fs_usage_bytes{device!="tmpfs", id="/"}) by (instance, %s)[%s:%dm]) / 1024 / 1024 / 1024 * %f * %f`, env.GetPromClusterLabel(), durStr, minsPerResolution, hourlyToCumulative, costPerGBHr)
@@ -215,7 +215,7 @@ func ClusterDisks(client prometheus.Client, provider cloud.Provider, start, end
 		diskMap[key].Cost += cost
 
 		//Assigning explicitly the storage class of local storage to local
-		diskMap[key].StorageClass = "Local"
+		diskMap[key].StorageClass = kubecost.LocalStorageClass
 	}
 
 	for _, result := range resLocalStorageUsedCost {
@@ -312,7 +312,7 @@ func ClusterDisks(client prometheus.Client, provider cloud.Provider, start, end
 			cluster = env.GetClusterID()
 		}
 
-		name, _ := result.GetString("volumename")
+		name, _ := result.GetString("persistentvolume")
 
 		key := DiskIdentifier{cluster, name}
 		if _, ok := diskMap[key]; !ok {
@@ -327,7 +327,7 @@ func ClusterDisks(client prometheus.Client, provider cloud.Provider, start, end
 		storageClass, err := result.GetString("storageclass")
 
 		if err != nil {
-			diskMap[key].StorageClass = "Unknown"
+			diskMap[key].StorageClass = kubecost.UnknownStorageClass
 		} else {
 			diskMap[key].StorageClass = storageClass
 		}
@@ -344,7 +344,7 @@ func ClusterDisks(client prometheus.Client, provider cloud.Provider, start, end
 
 		// Explicitly specify unknown storage class for disk whose information is unavailable in prometheus metrics of kube_persistentvolumeclaim_info
 		if disk.StorageClass == "" {
-			disk.StorageClass = "Unknown"
+			disk.StorageClass = kubecost.UnknownStorageClass
 		}
 	}
 

+ 7 - 1
pkg/kubecost/asset.go

@@ -15,6 +15,12 @@ import (
 // E.g. if aggregating on Cluster, Assets in the AssetSet where Asset has no cluster will be grouped under key "__undefined__"
 const UndefinedKey = "__undefined__"
 
+// LocalStorageClass is used to assign storage class of local disks.
+const LocalStorageClass = "__local__"
+
+// UnknownStorageClass is used to assign storage class of persistent volume whose information is unable to be traced.
+const UnknownStorageClass = "__unknown__"
+
 // Asset defines an entity within a cluster that has a defined cost over a
 // given period of time.
 type Asset interface {
@@ -1256,7 +1262,7 @@ func (d *Disk) add(that *Disk) {
 
 	d.ByteHours += that.ByteHours
 
-	if that.StorageClass != "" && that.StorageClass != "Unknown" {
+	if that.StorageClass != "" && that.StorageClass != UnknownStorageClass {
 		d.StorageClass = that.StorageClass
 	}
 }

+ 61 - 0
pkg/metrics/pvmetrics.go

@@ -28,6 +28,9 @@ func (kpvcb KubePVCollector) Describe(ch chan<- *prometheus.Desc) {
 	if _, disabled := disabledMetrics["kube_persistentvolume_status_phase"]; !disabled {
 		ch <- prometheus.NewDesc("kube_persistentvolume_status_phase", "The phase indicates if a volume is available, bound to a claim, or released by a claim.", []string{}, nil)
 	}
+	if _, disabled := disabledMetrics["kubecost_pv_info"]; !disabled {
+		ch <- prometheus.NewDesc("kubecost_pv_info", "The pv information", []string{}, nil)
+	}
 }
 
 // Collect is called by the Prometheus registry when collecting metrics.
@@ -59,7 +62,12 @@ func (kpvcb KubePVCollector) Collect(ch chan<- prometheus.Metric) {
 		if _, disabled := disabledMetrics["kube_persistentvolume_capacity_bytes"]; !disabled {
 			storage := pv.Spec.Capacity[v1.ResourceStorage]
 			m := newKubePVCapacityBytesMetric("kube_persistentvolume_capacity_bytes", pv.Name, float64(storage.Value()))
+			ch <- m
+		}
 
+		if _, disabled := disabledMetrics["kubecost_pv_info"]; !disabled {
+			storageClass := pv.Spec.StorageClassName
+			m := newKubecostPVInfoMetric("kubecost_pv_info", pv.Name, storageClass, float64(1))
 			ch <- m
 		}
 	}
@@ -165,3 +173,56 @@ func (kpcrr KubePVStatusPhaseMetric) Write(m *dto.Metric) error {
 	}
 	return nil
 }
+
+//--------------------------------------------------------------------------
+//  KubecostPVInfoMetric
+//--------------------------------------------------------------------------
+// KubecostPVInfoMetric is a prometheus.Metric
+type KubecostPVInfoMetric struct {
+	fqName       string
+	help         string
+	pv           string
+	storageClass string
+	value        float64
+}
+
+// Creates a new newKubecostPVInfoMetric, implementation of prometheus.Metric
+func newKubecostPVInfoMetric(fqname, pv, storageClass string, value float64) KubecostPVInfoMetric {
+	return KubecostPVInfoMetric{
+		fqName:       fqname,
+		help:         "kubecost_pv_info pv info",
+		pv:           pv,
+		storageClass: storageClass,
+		value:        value,
+	}
+}
+
+// Desc returns the descriptor for the Metric. This method idempotently
+// returns the same descriptor throughout the lifetime of the Metric.
+func (kpvim KubecostPVInfoMetric) Desc() *prometheus.Desc {
+	l := prometheus.Labels{
+		"persistentvolume": kpvim.pv,
+		"storageclass":     kpvim.storageClass,
+	}
+	return prometheus.NewDesc(kpvim.fqName, kpvim.help, []string{}, l)
+}
+
+// Write encodes the Metric into a "Metric" Protocol Buffer data
+// transmission object.
+func (kpvim KubecostPVInfoMetric) Write(m *dto.Metric) error {
+	m.Gauge = &dto.Gauge{
+		Value: &kpvim.value,
+	}
+
+	m.Label = []*dto.LabelPair{
+		{
+			Name:  toStringPtr("persistentvolume"),
+			Value: &kpvim.pv,
+		},
+		{
+			Name:  toStringPtr("storageclass"),
+			Value: &kpvim.storageClass,
+		},
+	}
+	return nil
+}