diff --git a/pkg/kubelet/metrics/collectors/log_metrics.go b/pkg/kubelet/metrics/collectors/log_metrics.go index 23194106efa..a793429501a 100644 --- a/pkg/kubelet/metrics/collectors/log_metrics.go +++ b/pkg/kubelet/metrics/collectors/log_metrics.go @@ -17,14 +17,13 @@ limitations under the License. package collectors import ( - "github.com/prometheus/client_golang/prometheus" + "k8s.io/component-base/metrics" "k8s.io/klog" - statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" ) var ( - descLogSize = prometheus.NewDesc( + descLogSize = metrics.NewDesc( "kubelet_container_log_filesystem_used_bytes", "Bytes used by the container's logs on the filesystem.", []string{ @@ -33,28 +32,35 @@ var ( "pod", "container", }, nil, + metrics.ALPHA, + "", ) ) type logMetricsCollector struct { + metrics.BaseStableCollector + podStats func() ([]statsapi.PodStats, error) } -// NewLogMetricsCollector implements the prometheus.Collector interface and +// Check if logMetricsCollector implements necessary interface +var _ metrics.StableCollector = &logMetricsCollector{} + +// NewLogMetricsCollector implements the metrics.StableCollector interface and // exposes metrics about container's log volume size. -func NewLogMetricsCollector(podStats func() ([]statsapi.PodStats, error)) prometheus.Collector { +func NewLogMetricsCollector(podStats func() ([]statsapi.PodStats, error)) metrics.StableCollector { return &logMetricsCollector{ podStats: podStats, } } -// Describe implements the prometheus.Collector interface. -func (c *logMetricsCollector) Describe(ch chan<- *prometheus.Desc) { +// DescribeWithStability implements the metrics.StableCollector interface. +func (c *logMetricsCollector) DescribeWithStability(ch chan<- *metrics.Desc) { ch <- descLogSize } -// Collect implements the prometheus.Collector interface. -func (c *logMetricsCollector) Collect(ch chan<- prometheus.Metric) { +// CollectWithStability implements the metrics.StableCollector interface. +func (c *logMetricsCollector) CollectWithStability(ch chan<- metrics.Metric) { podStats, err := c.podStats() if err != nil { klog.Errorf("failed to get pod stats: %v", err) @@ -64,9 +70,9 @@ func (c *logMetricsCollector) Collect(ch chan<- prometheus.Metric) { for _, ps := range podStats { for _, c := range ps.Containers { if c.Logs != nil && c.Logs.UsedBytes != nil { - ch <- prometheus.MustNewConstMetric( + ch <- metrics.NewLazyConstMetric( descLogSize, - prometheus.GaugeValue, + metrics.GaugeValue, float64(*c.Logs.UsedBytes), ps.PodRef.UID, ps.PodRef.Namespace, diff --git a/pkg/kubelet/metrics/collectors/log_metrics_test.go b/pkg/kubelet/metrics/collectors/log_metrics_test.go index 2006973b977..2dcbba4db97 100644 --- a/pkg/kubelet/metrics/collectors/log_metrics_test.go +++ b/pkg/kubelet/metrics/collectors/log_metrics_test.go @@ -25,18 +25,24 @@ import ( ) func TestNoMetricsCollected(t *testing.T) { + // Refresh Desc to share with different registry + descLogSize = descLogSize.GetRawDesc() + collector := &logMetricsCollector{ podStats: func() ([]statsapi.PodStats, error) { return []statsapi.PodStats{}, nil }, } - if err := testutil.CollectAndCompare(collector, strings.NewReader(""), ""); err != nil { + if err := testutil.CustomCollectAndCompare(collector, strings.NewReader(""), ""); err != nil { t.Fatal(err) } } func TestMetricsCollected(t *testing.T) { + // Refresh Desc to share with different registry + descLogSize = descLogSize.GetRawDesc() + size := uint64(18) collector := &logMetricsCollector{ podStats: func() ([]statsapi.PodStats, error) { @@ -60,8 +66,8 @@ func TestMetricsCollected(t *testing.T) { }, } - err := testutil.CollectAndCompare(collector, strings.NewReader(` - # HELP kubelet_container_log_filesystem_used_bytes Bytes used by the container's logs on the filesystem. + err := testutil.CustomCollectAndCompare(collector, strings.NewReader(` + # HELP kubelet_container_log_filesystem_used_bytes [ALPHA] Bytes used by the container's logs on the filesystem. # TYPE kubelet_container_log_filesystem_used_bytes gauge kubelet_container_log_filesystem_used_bytes{container="containerName1",namespace="some-namespace",pod="podName1",uid="UID_some_id"} 18 `), "kubelet_container_log_filesystem_used_bytes") diff --git a/pkg/kubelet/metrics/collectors/volume_stats.go b/pkg/kubelet/metrics/collectors/volume_stats.go index 78e047527c1..1c76a7ca1eb 100644 --- a/pkg/kubelet/metrics/collectors/volume_stats.go +++ b/pkg/kubelet/metrics/collectors/volume_stats.go @@ -17,58 +17,68 @@ limitations under the License. package collectors import ( - "github.com/prometheus/client_golang/prometheus" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/klog" + "k8s.io/component-base/metrics" stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1" - "k8s.io/kubernetes/pkg/kubelet/metrics" + kubeletmetrics "k8s.io/kubernetes/pkg/kubelet/metrics" serverstats "k8s.io/kubernetes/pkg/kubelet/server/stats" ) var ( - volumeStatsCapacityBytesDesc = prometheus.NewDesc( - prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsCapacityBytesKey), + volumeStatsCapacityBytesDesc = metrics.NewDesc( + metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsCapacityBytesKey), "Capacity in bytes of the volume", []string{"namespace", "persistentvolumeclaim"}, nil, + metrics.ALPHA, "", ) - volumeStatsAvailableBytesDesc = prometheus.NewDesc( - prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsAvailableBytesKey), + volumeStatsAvailableBytesDesc = metrics.NewDesc( + metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsAvailableBytesKey), "Number of available bytes in the volume", []string{"namespace", "persistentvolumeclaim"}, nil, + metrics.ALPHA, "", ) - volumeStatsUsedBytesDesc = prometheus.NewDesc( - prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsUsedBytesKey), + volumeStatsUsedBytesDesc = metrics.NewDesc( + metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsUsedBytesKey), "Number of used bytes in the volume", []string{"namespace", "persistentvolumeclaim"}, nil, + metrics.ALPHA, "", ) - volumeStatsInodesDesc = prometheus.NewDesc( - prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsInodesKey), + volumeStatsInodesDesc = metrics.NewDesc( + metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsInodesKey), "Maximum number of inodes in the volume", []string{"namespace", "persistentvolumeclaim"}, nil, + metrics.ALPHA, "", ) - volumeStatsInodesFreeDesc = prometheus.NewDesc( - prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsInodesFreeKey), + volumeStatsInodesFreeDesc = metrics.NewDesc( + metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsInodesFreeKey), "Number of free inodes in the volume", []string{"namespace", "persistentvolumeclaim"}, nil, + metrics.ALPHA, "", ) - volumeStatsInodesUsedDesc = prometheus.NewDesc( - prometheus.BuildFQName("", metrics.KubeletSubsystem, metrics.VolumeStatsInodesUsedKey), + volumeStatsInodesUsedDesc = metrics.NewDesc( + metrics.BuildFQName("", kubeletmetrics.KubeletSubsystem, kubeletmetrics.VolumeStatsInodesUsedKey), "Number of used inodes in the volume", []string{"namespace", "persistentvolumeclaim"}, nil, + metrics.ALPHA, "", ) ) type volumeStatsCollector struct { + metrics.BaseStableCollector + statsProvider serverstats.Provider } -// NewVolumeStatsCollector creates a volume stats prometheus collector. -func NewVolumeStatsCollector(statsProvider serverstats.Provider) prometheus.Collector { +// Check if volumeStatsCollector implements necessary interface +var _ metrics.StableCollector = &volumeStatsCollector{} + +// NewVolumeStatsCollector creates a volume stats metrics.StableCollector. +func NewVolumeStatsCollector(statsProvider serverstats.Provider) metrics.StableCollector { return &volumeStatsCollector{statsProvider: statsProvider} } -// Describe implements the prometheus.Collector interface. -func (collector *volumeStatsCollector) Describe(ch chan<- *prometheus.Desc) { +// DescribeWithStability implements the metrics.StableCollector interface. +func (collector *volumeStatsCollector) DescribeWithStability(ch chan<- *metrics.Desc) { ch <- volumeStatsCapacityBytesDesc ch <- volumeStatsAvailableBytesDesc ch <- volumeStatsUsedBytesDesc @@ -77,20 +87,16 @@ func (collector *volumeStatsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- volumeStatsInodesUsedDesc } -// Collect implements the prometheus.Collector interface. -func (collector *volumeStatsCollector) Collect(ch chan<- prometheus.Metric) { +// CollectWithStability implements the metrics.StableCollector interface. +func (collector *volumeStatsCollector) CollectWithStability(ch chan<- metrics.Metric) { podStats, err := collector.statsProvider.ListPodStats() if err != nil { return } - addGauge := func(desc *prometheus.Desc, pvcRef *stats.PVCReference, v float64, lv ...string) { + addGauge := func(desc *metrics.Desc, pvcRef *stats.PVCReference, v float64, lv ...string) { lv = append([]string{pvcRef.Namespace, pvcRef.Name}, lv...) - metric, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, v, lv...) - if err != nil { - klog.Warningf("Failed to generate metric: %v", err) - return - } - ch <- metric + + ch <- metrics.NewLazyConstMetric(desc, metrics.GaugeValue, v, lv...) } allPVCs := sets.String{} for _, podStat := range podStats { diff --git a/pkg/kubelet/metrics/collectors/volume_stats_test.go b/pkg/kubelet/metrics/collectors/volume_stats_test.go index 43de19d2419..3ff2df51f01 100644 --- a/pkg/kubelet/metrics/collectors/volume_stats_test.go +++ b/pkg/kubelet/metrics/collectors/volume_stats_test.go @@ -34,17 +34,17 @@ func TestVolumeStatsCollector(t *testing.T) { // Fixed metadata on type and help text. We prepend this to every expected // output so we only have to modify a single place when doing adjustments. const metadata = ` - # HELP kubelet_volume_stats_available_bytes Number of available bytes in the volume + # HELP kubelet_volume_stats_available_bytes [ALPHA] Number of available bytes in the volume # TYPE kubelet_volume_stats_available_bytes gauge - # HELP kubelet_volume_stats_capacity_bytes Capacity in bytes of the volume + # HELP kubelet_volume_stats_capacity_bytes [ALPHA] Capacity in bytes of the volume # TYPE kubelet_volume_stats_capacity_bytes gauge - # HELP kubelet_volume_stats_inodes Maximum number of inodes in the volume + # HELP kubelet_volume_stats_inodes [ALPHA] Maximum number of inodes in the volume # TYPE kubelet_volume_stats_inodes gauge - # HELP kubelet_volume_stats_inodes_free Number of free inodes in the volume + # HELP kubelet_volume_stats_inodes_free [ALPHA] Number of free inodes in the volume # TYPE kubelet_volume_stats_inodes_free gauge - # HELP kubelet_volume_stats_inodes_used Number of used inodes in the volume + # HELP kubelet_volume_stats_inodes_used [ALPHA] Number of used inodes in the volume # TYPE kubelet_volume_stats_inodes_used gauge - # HELP kubelet_volume_stats_used_bytes Number of used bytes in the volume + # HELP kubelet_volume_stats_used_bytes [ALPHA] Number of used bytes in the volume # TYPE kubelet_volume_stats_used_bytes gauge ` @@ -132,7 +132,7 @@ func TestVolumeStatsCollector(t *testing.T) { mockStatsProvider := new(statstest.StatsProvider) mockStatsProvider.On("ListPodStats").Return(podStats, nil) mockStatsProvider.On("ListPodStatsAndUpdateCPUNanoCoreUsage").Return(podStats, nil) - if err := testutil.CollectAndCompare(&volumeStatsCollector{statsProvider: mockStatsProvider}, strings.NewReader(want), metrics...); err != nil { + if err := testutil.CustomCollectAndCompare(&volumeStatsCollector{statsProvider: mockStatsProvider}, strings.NewReader(want), metrics...); err != nil { t.Errorf("unexpected collecting result:\n%s", err) } } diff --git a/pkg/kubelet/metrics/metrics.go b/pkg/kubelet/metrics/metrics.go index 3806c47f658..8263c39581f 100644 --- a/pkg/kubelet/metrics/metrics.go +++ b/pkg/kubelet/metrics/metrics.go @@ -499,7 +499,7 @@ var ( var registerMetrics sync.Once // Register registers all metrics. -func Register(containerCache kubecontainer.RuntimeCache, collectors ...metrics.Collector) { +func Register(containerCache kubecontainer.RuntimeCache, collectors ...metrics.StableCollector) { // Register the metrics. registerMetrics.Do(func() { legacyregistry.MustRegister(NodeName) @@ -540,7 +540,7 @@ func Register(containerCache kubecontainer.RuntimeCache, collectors ...metrics.C legacyregistry.MustRegister(ConfigError) } for _, collector := range collectors { - legacyregistry.RawMustRegister(collector) + legacyregistry.CustomMustRegister(collector) } }) } diff --git a/pkg/kubelet/pluginmanager/metrics/metrics.go b/pkg/kubelet/pluginmanager/metrics/metrics.go index a6f357be98b..aabc1f7b146 100644 --- a/pkg/kubelet/pluginmanager/metrics/metrics.go +++ b/pkg/kubelet/pluginmanager/metrics/metrics.go @@ -19,8 +19,8 @@ package metrics import ( "sync" - "github.com/prometheus/client_golang/prometheus" - "k8s.io/klog" + "k8s.io/component-base/metrics" + "k8s.io/component-base/metrics/legacyregistry" "k8s.io/kubernetes/pkg/kubelet/pluginmanager/cache" ) @@ -32,11 +32,13 @@ const ( var ( registerMetrics sync.Once - totalPluginsDesc = prometheus.NewDesc( + totalPluginsDesc = metrics.NewDesc( pluginManagerTotalPlugins, "Number of plugins in Plugin Manager", []string{"socket_path", "state"}, nil, + metrics.ALPHA, + "", ) ) @@ -55,35 +57,33 @@ func (pc pluginCount) add(state, pluginName string) { // Register registers Plugin Manager metrics. func Register(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld) { registerMetrics.Do(func() { - prometheus.MustRegister(&totalPluginsCollector{asw, dsw}) + legacyregistry.CustomMustRegister(&totalPluginsCollector{asw: asw, dsw: dsw}) }) } type totalPluginsCollector struct { + metrics.BaseStableCollector + asw cache.ActualStateOfWorld dsw cache.DesiredStateOfWorld } -var _ prometheus.Collector = &totalPluginsCollector{} +var _ metrics.StableCollector = &totalPluginsCollector{} -// Describe implements the prometheus.Collector interface. -func (c *totalPluginsCollector) Describe(ch chan<- *prometheus.Desc) { +// DescribeWithStability implements the metrics.StableCollector interface. +func (c *totalPluginsCollector) DescribeWithStability(ch chan<- *metrics.Desc) { ch <- totalPluginsDesc } -// Collect implements the prometheus.Collector interface. -func (c *totalPluginsCollector) Collect(ch chan<- prometheus.Metric) { +// CollectWithStability implements the metrics.StableCollector interface. +func (c *totalPluginsCollector) CollectWithStability(ch chan<- metrics.Metric) { for stateName, pluginCount := range c.getPluginCount() { for socketPath, count := range pluginCount { - metric, err := prometheus.NewConstMetric(totalPluginsDesc, - prometheus.GaugeValue, + ch <- metrics.NewLazyConstMetric(totalPluginsDesc, + metrics.GaugeValue, float64(count), socketPath, stateName) - if err != nil { - klog.Warningf("Failed to create metric : %v", err) - } - ch <- metric } } } diff --git a/pkg/kubelet/pluginmanager/metrics/metrics_test.go b/pkg/kubelet/pluginmanager/metrics/metrics_test.go index 1f18eb95581..ed52653a47e 100644 --- a/pkg/kubelet/pluginmanager/metrics/metrics_test.go +++ b/pkg/kubelet/pluginmanager/metrics/metrics_test.go @@ -42,7 +42,7 @@ func TestMetricCollection(t *testing.T) { t.Fatalf("AddOrUpdatePlugin failed. Expected: Actual: <%v>", err) } - metricCollector := &totalPluginsCollector{asw, dsw} + metricCollector := &totalPluginsCollector{asw: asw, dsw: dsw} // Check if getPluginCount returns correct data count := metricCollector.getPluginCount() diff --git a/pkg/kubelet/volumemanager/metrics/metrics.go b/pkg/kubelet/volumemanager/metrics/metrics.go index 86f800b0bc4..e9e4bd04fb6 100644 --- a/pkg/kubelet/volumemanager/metrics/metrics.go +++ b/pkg/kubelet/volumemanager/metrics/metrics.go @@ -17,11 +17,10 @@ limitations under the License. package metrics import ( - "k8s.io/component-base/metrics/legacyregistry" "sync" - "github.com/prometheus/client_golang/prometheus" - "k8s.io/klog" + "k8s.io/component-base/metrics" + "k8s.io/component-base/metrics/legacyregistry" "k8s.io/kubernetes/pkg/kubelet/volumemanager/cache" "k8s.io/kubernetes/pkg/volume" volumeutil "k8s.io/kubernetes/pkg/volume/util" @@ -37,11 +36,12 @@ const ( var ( registerMetrics sync.Once - totalVolumesDesc = prometheus.NewDesc( + totalVolumesDesc = metrics.NewDesc( volumeManagerTotalVolumes, "Number of volumes in Volume Manager", []string{"plugin_name", "state"}, nil, + metrics.ALPHA, "", ) ) @@ -60,36 +60,34 @@ func (v volumeCount) add(state, plugin string) { // Register registers Volume Manager metrics. func Register(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld, pluginMgr *volume.VolumePluginMgr) { registerMetrics.Do(func() { - legacyregistry.RawMustRegister(&totalVolumesCollector{asw, dsw, pluginMgr}) + legacyregistry.CustomMustRegister(&totalVolumesCollector{asw: asw, dsw: dsw, pluginMgr: pluginMgr}) }) } type totalVolumesCollector struct { + metrics.BaseStableCollector + asw cache.ActualStateOfWorld dsw cache.DesiredStateOfWorld pluginMgr *volume.VolumePluginMgr } -var _ prometheus.Collector = &totalVolumesCollector{} +var _ metrics.StableCollector = &totalVolumesCollector{} -// Describe implements the prometheus.Collector interface. -func (c *totalVolumesCollector) Describe(ch chan<- *prometheus.Desc) { +// DescribeWithStability implements the metrics.StableCollector interface. +func (c *totalVolumesCollector) DescribeWithStability(ch chan<- *metrics.Desc) { ch <- totalVolumesDesc } -// Collect implements the prometheus.Collector interface. -func (c *totalVolumesCollector) Collect(ch chan<- prometheus.Metric) { +// CollectWithStability implements the metrics.StableCollector interface. +func (c *totalVolumesCollector) CollectWithStability(ch chan<- metrics.Metric) { for stateName, pluginCount := range c.getVolumeCount() { for pluginName, count := range pluginCount { - metric, err := prometheus.NewConstMetric(totalVolumesDesc, - prometheus.GaugeValue, + ch <- metrics.NewLazyConstMetric(totalVolumesDesc, + metrics.GaugeValue, float64(count), pluginName, stateName) - if err != nil { - klog.Warningf("Failed to create metric : %v", err) - } - ch <- metric } } } diff --git a/pkg/kubelet/volumemanager/metrics/metrics_test.go b/pkg/kubelet/volumemanager/metrics/metrics_test.go index 45e57dedf7d..3c630d0061c 100644 --- a/pkg/kubelet/volumemanager/metrics/metrics_test.go +++ b/pkg/kubelet/volumemanager/metrics/metrics_test.go @@ -83,7 +83,7 @@ func TestMetricCollection(t *testing.T) { t.Fatalf("AddPodToVolume failed. Expected: Actual: <%v>", err) } - metricCollector := &totalVolumesCollector{asw, dsw, volumePluginMgr} + metricCollector := &totalVolumesCollector{asw: asw, dsw: dsw, pluginMgr: volumePluginMgr} // Check if getVolumeCount returns correct data count := metricCollector.getVolumeCount()