github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/ndm-exporter/collector/static.go (about)

     1  /*
     2  Copyright 2019 The OpenEBS Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package collector
    18  
    19  import (
    20  	"sync"
    21  
    22  	"github.com/openebs/node-disk-manager/db/kubernetes"
    23  	"github.com/openebs/node-disk-manager/pkg/metrics/static"
    24  
    25  	"github.com/prometheus/client_golang/prometheus"
    26  	"k8s.io/klog/v2"
    27  )
    28  
    29  // StaticMetricCollector contains the metrics, concurrency handler and client to get the
    30  // static metrics
    31  type StaticMetricCollector struct {
    32  	// Client is the k8s client which will be used to interface with etcd
    33  	Client kubernetes.Client
    34  
    35  	// concurrency handling
    36  	sync.Mutex
    37  	requestInProgress bool
    38  
    39  	// all the exposed metrics
    40  	metrics *static.Metrics
    41  }
    42  
    43  // NewStaticMetricCollector creates a new instance of StaticMetricCollector which
    44  // implements Collector interface
    45  func NewStaticMetricCollector(c kubernetes.Client) prometheus.Collector {
    46  	klog.V(2).Infof("Static Metric Collector initialized")
    47  	return &StaticMetricCollector{
    48  		Client:  c,
    49  		metrics: static.NewMetrics(),
    50  	}
    51  }
    52  
    53  // setRequestProgressToFalse is used to set the progress flag, when a request is
    54  // processed or errored
    55  func (mc *StaticMetricCollector) setRequestProgressToFalse() {
    56  	mc.Lock()
    57  	mc.requestInProgress = false
    58  	mc.Unlock()
    59  }
    60  
    61  // Describe is the implementation of Describe in prometheus.Collector
    62  func (mc *StaticMetricCollector) Describe(ch chan<- *prometheus.Desc) {
    63  	for _, col := range mc.metrics.Collectors() {
    64  		col.Describe(ch)
    65  	}
    66  }
    67  
    68  // Collect is the implementation of Collect in prometheus.Collector
    69  func (mc *StaticMetricCollector) Collect(ch chan<- prometheus.Metric) {
    70  
    71  	klog.V(4).Info("Starting to collect metrics for a request")
    72  
    73  	// when a second request comes, and the first one is already in progress,
    74  	// ignore/reject the second request
    75  	mc.Lock()
    76  	if mc.requestInProgress {
    77  		klog.V(4).Info("Another request already in progress.")
    78  		mc.metrics.IncRejectRequestCounter()
    79  		mc.Unlock()
    80  		return
    81  	}
    82  
    83  	mc.requestInProgress = true
    84  	mc.Unlock()
    85  
    86  	// once a request is processed, set the progress flag to false
    87  	defer mc.setRequestProgressToFalse()
    88  
    89  	klog.V(4).Info("Setting client for this request.")
    90  
    91  	// set the client each time
    92  	if err := mc.Client.InitClient(); err != nil {
    93  		klog.Errorf("error setting client. %v", err)
    94  		mc.metrics.IncErrorRequestCounter()
    95  		mc.collectErrors(ch)
    96  		return
    97  	}
    98  
    99  	// get list of blockdevices from etcd
   100  	blockDevices, err := mc.Client.ListBlockDevice()
   101  	if err != nil {
   102  		mc.metrics.IncErrorRequestCounter()
   103  		mc.collectErrors(ch)
   104  		return
   105  	}
   106  
   107  	klog.V(4).Info("Metric data fetched from etcd")
   108  
   109  	// set the metric data into the respective fields
   110  	mc.metrics.SetMetrics(blockDevices)
   111  
   112  	klog.V(4).Info("Prometheus metrics is set and initializing collection.")
   113  
   114  	// collect each metric
   115  	for _, col := range mc.metrics.Collectors() {
   116  		col.Collect(ch)
   117  	}
   118  }
   119  
   120  // collectErrors collects only the error metrics and set it on the channel
   121  func (mc *StaticMetricCollector) collectErrors(ch chan<- prometheus.Metric) {
   122  	for _, col := range mc.metrics.ErrorCollectors() {
   123  		col.Collect(ch)
   124  	}
   125  }