2
0

pvmetrics.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. package metrics
  2. import (
  3. "github.com/opencost/opencost/core/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. pvUID := string(pv.UID)
  36. if _, disabled := disabledMetrics["kube_persistentvolume_status_phase"]; !disabled {
  37. phase := pv.Status.Phase
  38. if phase != "" {
  39. phases := []struct {
  40. v bool
  41. n string
  42. }{
  43. {phase == v1.VolumePending, string(v1.VolumePending)},
  44. {phase == v1.VolumeAvailable, string(v1.VolumeAvailable)},
  45. {phase == v1.VolumeBound, string(v1.VolumeBound)},
  46. {phase == v1.VolumeReleased, string(v1.VolumeReleased)},
  47. {phase == v1.VolumeFailed, string(v1.VolumeFailed)},
  48. }
  49. for _, p := range phases {
  50. ch <- newKubePVStatusPhaseMetric("kube_persistentvolume_status_phase", pv.Name, pvUID, p.n, boolFloat64(p.v))
  51. }
  52. }
  53. }
  54. if _, disabled := disabledMetrics["kube_persistentvolume_capacity_bytes"]; !disabled {
  55. storage := pv.Spec.Capacity[v1.ResourceStorage]
  56. m := newKubePVCapacityBytesMetric("kube_persistentvolume_capacity_bytes", pv.Name, pvUID, float64(storage.Value()))
  57. ch <- m
  58. }
  59. if _, disabled := disabledMetrics["kubecost_pv_info"]; !disabled {
  60. storageClass := pv.Spec.StorageClassName
  61. providerID := pv.Name
  62. // if a more accurate provider ID is available, use that
  63. if pv.Spec.CSI != nil && pv.Spec.CSI.VolumeHandle != "" {
  64. providerID = pv.Spec.CSI.VolumeHandle
  65. }
  66. m := newKubecostPVInfoMetric("kubecost_pv_info", pv.Name, pvUID, storageClass, providerID, float64(1))
  67. ch <- m
  68. }
  69. }
  70. }
  71. //--------------------------------------------------------------------------
  72. // KubePVCapacityBytesMetric
  73. //--------------------------------------------------------------------------
  74. // KubePVCapacityBytesMetric is a prometheus.Metric
  75. type KubePVCapacityBytesMetric struct {
  76. fqName string
  77. help string
  78. pv string
  79. value float64
  80. uid string
  81. }
  82. // Creates a new KubePVCapacityBytesMetric, implementation of prometheus.Metric
  83. func newKubePVCapacityBytesMetric(fqname, pv, uid string, value float64) KubePVCapacityBytesMetric {
  84. return KubePVCapacityBytesMetric{
  85. fqName: fqname,
  86. help: "kube_persistentvolume_capacity_bytes pv storage capacity in bytes",
  87. pv: pv,
  88. value: value,
  89. uid: uid,
  90. }
  91. }
  92. // Desc returns the descriptor for the Metric. This method idempotently
  93. // returns the same descriptor throughout the lifetime of the Metric.
  94. func (kpcrr KubePVCapacityBytesMetric) Desc() *prometheus.Desc {
  95. l := prometheus.Labels{
  96. "persistentvolume": kpcrr.pv,
  97. "uid": kpcrr.uid,
  98. }
  99. return prometheus.NewDesc(kpcrr.fqName, kpcrr.help, []string{}, l)
  100. }
  101. // Write encodes the Metric into a "Metric" Protocol Buffer data
  102. // transmission object.
  103. func (kpcrr KubePVCapacityBytesMetric) Write(m *dto.Metric) error {
  104. m.Gauge = &dto.Gauge{
  105. Value: &kpcrr.value,
  106. }
  107. m.Label = []*dto.LabelPair{
  108. {
  109. Name: toStringPtr("persistentvolume"),
  110. Value: &kpcrr.pv,
  111. },
  112. {
  113. Name: toStringPtr("uid"),
  114. Value: &kpcrr.uid,
  115. },
  116. }
  117. return nil
  118. }
  119. //--------------------------------------------------------------------------
  120. // KubePVStatusPhaseMetric
  121. //--------------------------------------------------------------------------
  122. // KubePVStatusPhaseMetric is a prometheus.Metric
  123. type KubePVStatusPhaseMetric struct {
  124. fqName string
  125. help string
  126. pv string
  127. phase string
  128. value float64
  129. uid string
  130. }
  131. // Creates a new KubePVStatusPhaseMetric, implementation of prometheus.Metric
  132. func newKubePVStatusPhaseMetric(fqname, pv, uid, phase string, value float64) KubePVStatusPhaseMetric {
  133. return KubePVStatusPhaseMetric{
  134. fqName: fqname,
  135. help: "kube_persistentvolume_status_phase pv status phase",
  136. pv: pv,
  137. phase: phase,
  138. value: value,
  139. uid: uid,
  140. }
  141. }
  142. // Desc returns the descriptor for the Metric. This method idempotently
  143. // returns the same descriptor throughout the lifetime of the Metric.
  144. func (kpcrr KubePVStatusPhaseMetric) Desc() *prometheus.Desc {
  145. l := prometheus.Labels{
  146. "persistentvolume": kpcrr.pv,
  147. "phase": kpcrr.phase,
  148. "uid": kpcrr.uid,
  149. }
  150. return prometheus.NewDesc(kpcrr.fqName, kpcrr.help, []string{}, l)
  151. }
  152. // Write encodes the Metric into a "Metric" Protocol Buffer data
  153. // transmission object.
  154. func (kpcrr KubePVStatusPhaseMetric) Write(m *dto.Metric) error {
  155. m.Gauge = &dto.Gauge{
  156. Value: &kpcrr.value,
  157. }
  158. m.Label = []*dto.LabelPair{
  159. {
  160. Name: toStringPtr("persistentvolume"),
  161. Value: &kpcrr.pv,
  162. },
  163. {
  164. Name: toStringPtr("phase"),
  165. Value: &kpcrr.phase,
  166. },
  167. {
  168. Name: toStringPtr("uid"),
  169. Value: &kpcrr.uid,
  170. },
  171. }
  172. return nil
  173. }
  174. // --------------------------------------------------------------------------
  175. //
  176. // KubecostPVInfoMetric
  177. //
  178. // --------------------------------------------------------------------------
  179. // KubecostPVInfoMetric is a prometheus.Metric
  180. type KubecostPVInfoMetric struct {
  181. fqName string
  182. help string
  183. pv string
  184. storageClass string
  185. value float64
  186. providerId string
  187. uid string
  188. }
  189. // Creates a new newKubecostPVInfoMetric, implementation of prometheus.Metric
  190. func newKubecostPVInfoMetric(fqname, pv, uid, storageClass, providerID string, value float64) KubecostPVInfoMetric {
  191. return KubecostPVInfoMetric{
  192. fqName: fqname,
  193. help: "kubecost_pv_info pv info",
  194. pv: pv,
  195. storageClass: storageClass,
  196. value: value,
  197. providerId: providerID,
  198. uid: uid,
  199. }
  200. }
  201. // Desc returns the descriptor for the Metric. This method idempotently
  202. // returns the same descriptor throughout the lifetime of the Metric.
  203. func (kpvim KubecostPVInfoMetric) Desc() *prometheus.Desc {
  204. l := prometheus.Labels{
  205. "persistentvolume": kpvim.pv,
  206. "storageclass": kpvim.storageClass,
  207. "provider_id": kpvim.providerId,
  208. "uid": kpvim.uid,
  209. }
  210. return prometheus.NewDesc(kpvim.fqName, kpvim.help, []string{}, l)
  211. }
  212. // Write encodes the Metric into a "Metric" Protocol Buffer data
  213. // transmission object.
  214. func (kpvim KubecostPVInfoMetric) Write(m *dto.Metric) error {
  215. m.Gauge = &dto.Gauge{
  216. Value: &kpvim.value,
  217. }
  218. m.Label = []*dto.LabelPair{
  219. {
  220. Name: toStringPtr("persistentvolume"),
  221. Value: &kpvim.pv,
  222. },
  223. {
  224. Name: toStringPtr("storageclass"),
  225. Value: &kpvim.storageClass,
  226. },
  227. {
  228. Name: toStringPtr("provider_id"),
  229. Value: &kpvim.providerId,
  230. },
  231. {
  232. Name: toStringPtr("uid"),
  233. Value: &kpvim.uid,
  234. },
  235. }
  236. return nil
  237. }