pvmetrics.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package metrics
  2. import (
  3. "github.com/opencost/opencost/pkg/clustercache"
  4. "github.com/prometheus/client_golang/prometheus"
  5. dto "github.com/prometheus/client_model/go"
  6. v1 "k8s.io/api/core/v1"
  7. )
  8. //--------------------------------------------------------------------------
  9. // KubePVCollector
  10. //--------------------------------------------------------------------------
  11. // KubePVCollector is a prometheus collector that generates PV metrics
  12. type KubePVCollector struct {
  13. KubeClusterCache clustercache.ClusterCache
  14. metricsConfig MetricsConfig
  15. }
  16. // Describe sends the super-set of all possible descriptors of metrics
  17. // collected by this Collector.
  18. func (kpvcb KubePVCollector) Describe(ch chan<- *prometheus.Desc) {
  19. disabledMetrics := kpvcb.metricsConfig.GetDisabledMetricsMap()
  20. if _, disabled := disabledMetrics["kube_persistentvolume_capacity_bytes"]; !disabled {
  21. ch <- prometheus.NewDesc("kube_persistentvolume_capacity_bytes", "The pv storage capacity in bytes", []string{}, nil)
  22. }
  23. if _, disabled := disabledMetrics["kube_persistentvolume_status_phase"]; !disabled {
  24. 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)
  25. }
  26. if _, disabled := disabledMetrics["kubecost_pv_info"]; !disabled {
  27. ch <- prometheus.NewDesc("kubecost_pv_info", "The pv information", []string{}, nil)
  28. }
  29. }
  30. // Collect is called by the Prometheus registry when collecting metrics.
  31. func (kpvcb KubePVCollector) Collect(ch chan<- prometheus.Metric) {
  32. pvs := kpvcb.KubeClusterCache.GetAllPersistentVolumes()
  33. disabledMetrics := kpvcb.metricsConfig.GetDisabledMetricsMap()
  34. for _, pv := range pvs {
  35. if _, disabled := disabledMetrics["kube_persistentvolume_status_phase"]; !disabled {
  36. phase := pv.Status.Phase
  37. if phase != "" {
  38. phases := []struct {
  39. v bool
  40. n string
  41. }{
  42. {phase == v1.VolumePending, string(v1.VolumePending)},
  43. {phase == v1.VolumeAvailable, string(v1.VolumeAvailable)},
  44. {phase == v1.VolumeBound, string(v1.VolumeBound)},
  45. {phase == v1.VolumeReleased, string(v1.VolumeReleased)},
  46. {phase == v1.VolumeFailed, string(v1.VolumeFailed)},
  47. }
  48. for _, p := range phases {
  49. ch <- newKubePVStatusPhaseMetric("kube_persistentvolume_status_phase", pv.Name, p.n, boolFloat64(p.v))
  50. }
  51. }
  52. }
  53. if _, disabled := disabledMetrics["kube_persistentvolume_capacity_bytes"]; !disabled {
  54. storage := pv.Spec.Capacity[v1.ResourceStorage]
  55. m := newKubePVCapacityBytesMetric("kube_persistentvolume_capacity_bytes", pv.Name, float64(storage.Value()))
  56. ch <- m
  57. }
  58. if _, disabled := disabledMetrics["kubecost_pv_info"]; !disabled {
  59. storageClass := pv.Spec.StorageClassName
  60. providerID := pv.Name
  61. // if a more accurate provider ID is available, use that
  62. if pv.Spec.CSI != nil && pv.Spec.CSI.VolumeHandle != "" {
  63. providerID = pv.Spec.CSI.VolumeHandle
  64. }
  65. m := newKubecostPVInfoMetric("kubecost_pv_info", pv.Name, storageClass, providerID, float64(1))
  66. ch <- m
  67. }
  68. }
  69. }
  70. //--------------------------------------------------------------------------
  71. // KubePVCapacityBytesMetric
  72. //--------------------------------------------------------------------------
  73. // KubePVCapacityBytesMetric is a prometheus.Metric
  74. type KubePVCapacityBytesMetric struct {
  75. fqName string
  76. help string
  77. pv string
  78. value float64
  79. }
  80. // Creates a new KubePVCapacityBytesMetric, implementation of prometheus.Metric
  81. func newKubePVCapacityBytesMetric(fqname, pv string, value float64) KubePVCapacityBytesMetric {
  82. return KubePVCapacityBytesMetric{
  83. fqName: fqname,
  84. help: "kube_persistentvolume_capacity_bytes pv storage capacity in bytes",
  85. pv: pv,
  86. value: value,
  87. }
  88. }
  89. // Desc returns the descriptor for the Metric. This method idempotently
  90. // returns the same descriptor throughout the lifetime of the Metric.
  91. func (kpcrr KubePVCapacityBytesMetric) Desc() *prometheus.Desc {
  92. l := prometheus.Labels{
  93. "persistentvolume": kpcrr.pv,
  94. }
  95. return prometheus.NewDesc(kpcrr.fqName, kpcrr.help, []string{}, l)
  96. }
  97. // Write encodes the Metric into a "Metric" Protocol Buffer data
  98. // transmission object.
  99. func (kpcrr KubePVCapacityBytesMetric) Write(m *dto.Metric) error {
  100. m.Gauge = &dto.Gauge{
  101. Value: &kpcrr.value,
  102. }
  103. m.Label = []*dto.LabelPair{
  104. {
  105. Name: toStringPtr("persistentvolume"),
  106. Value: &kpcrr.pv,
  107. },
  108. }
  109. return nil
  110. }
  111. //--------------------------------------------------------------------------
  112. // KubePVStatusPhaseMetric
  113. //--------------------------------------------------------------------------
  114. // KubePVStatusPhaseMetric is a prometheus.Metric
  115. type KubePVStatusPhaseMetric struct {
  116. fqName string
  117. help string
  118. pv string
  119. phase string
  120. value float64
  121. }
  122. // Creates a new KubePVCapacityBytesMetric, implementation of prometheus.Metric
  123. func newKubePVStatusPhaseMetric(fqname, pv, phase string, value float64) KubePVStatusPhaseMetric {
  124. return KubePVStatusPhaseMetric{
  125. fqName: fqname,
  126. help: "kube_persistentvolume_status_phase pv status phase",
  127. pv: pv,
  128. phase: phase,
  129. value: value,
  130. }
  131. }
  132. // Desc returns the descriptor for the Metric. This method idempotently
  133. // returns the same descriptor throughout the lifetime of the Metric.
  134. func (kpcrr KubePVStatusPhaseMetric) Desc() *prometheus.Desc {
  135. l := prometheus.Labels{
  136. "persistentvolume": kpcrr.pv,
  137. "phase": kpcrr.phase,
  138. }
  139. return prometheus.NewDesc(kpcrr.fqName, kpcrr.help, []string{}, l)
  140. }
  141. // Write encodes the Metric into a "Metric" Protocol Buffer data
  142. // transmission object.
  143. func (kpcrr KubePVStatusPhaseMetric) Write(m *dto.Metric) error {
  144. m.Gauge = &dto.Gauge{
  145. Value: &kpcrr.value,
  146. }
  147. m.Label = []*dto.LabelPair{
  148. {
  149. Name: toStringPtr("persistentvolume"),
  150. Value: &kpcrr.pv,
  151. },
  152. {
  153. Name: toStringPtr("phase"),
  154. Value: &kpcrr.phase,
  155. },
  156. }
  157. return nil
  158. }
  159. // --------------------------------------------------------------------------
  160. //
  161. // KubecostPVInfoMetric
  162. //
  163. // --------------------------------------------------------------------------
  164. // KubecostPVInfoMetric is a prometheus.Metric
  165. type KubecostPVInfoMetric struct {
  166. fqName string
  167. help string
  168. pv string
  169. storageClass string
  170. value float64
  171. providerId string
  172. }
  173. // Creates a new newKubecostPVInfoMetric, implementation of prometheus.Metric
  174. func newKubecostPVInfoMetric(fqname, pv, storageClass, providerID string, value float64) KubecostPVInfoMetric {
  175. return KubecostPVInfoMetric{
  176. fqName: fqname,
  177. help: "kubecost_pv_info pv info",
  178. pv: pv,
  179. storageClass: storageClass,
  180. value: value,
  181. providerId: providerID,
  182. }
  183. }
  184. // Desc returns the descriptor for the Metric. This method idempotently
  185. // returns the same descriptor throughout the lifetime of the Metric.
  186. func (kpvim KubecostPVInfoMetric) Desc() *prometheus.Desc {
  187. l := prometheus.Labels{
  188. "persistentvolume": kpvim.pv,
  189. "storageclass": kpvim.storageClass,
  190. "provider_id": kpvim.providerId,
  191. }
  192. return prometheus.NewDesc(kpvim.fqName, kpvim.help, []string{}, l)
  193. }
  194. // Write encodes the Metric into a "Metric" Protocol Buffer data
  195. // transmission object.
  196. func (kpvim KubecostPVInfoMetric) Write(m *dto.Metric) error {
  197. m.Gauge = &dto.Gauge{
  198. Value: &kpvim.value,
  199. }
  200. m.Label = []*dto.LabelPair{
  201. {
  202. Name: toStringPtr("persistentvolume"),
  203. Value: &kpvim.pv,
  204. },
  205. {
  206. Name: toStringPtr("storageclass"),
  207. Value: &kpvim.storageClass,
  208. },
  209. {
  210. Name: toStringPtr("provider_id"),
  211. Value: &kpvim.providerId,
  212. },
  213. }
  214. return nil
  215. }