...

Source file src/github.com/chaos-mesh/chaos-mesh/controllers/metrics/metrics.go

Documentation: github.com/chaos-mesh/chaos-mesh/controllers/metrics

     1  // Copyright 2020 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package metrics
    15  
    16  import (
    17  	"context"
    18  	"reflect"
    19  
    20  	"github.com/prometheus/client_golang/prometheus"
    21  	ctrl "sigs.k8s.io/controller-runtime"
    22  	"sigs.k8s.io/controller-runtime/pkg/cache"
    23  
    24  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    25  	"github.com/chaos-mesh/chaos-mesh/pkg/apiserver/utils"
    26  )
    27  
    28  var log = ctrl.Log.WithName("metrics-collector")
    29  
    30  // ChaosCollector implements prometheus.Collector interface
    31  type ChaosCollector struct {
    32  	store               cache.Cache
    33  	experimentStatus    *prometheus.GaugeVec
    34  	SidecarTemplates    prometheus.Gauge
    35  	ConfigTemplates     *prometheus.GaugeVec
    36  	InjectionConfigs    *prometheus.GaugeVec
    37  	TemplateNotExist    *prometheus.CounterVec
    38  	TemplateLoadError   prometheus.Counter
    39  	ConfigNameDuplicate *prometheus.CounterVec
    40  	InjectRequired      *prometheus.CounterVec
    41  	Injections          *prometheus.CounterVec
    42  }
    43  
    44  // NewChaosCollector initializes metrics and collector
    45  func NewChaosCollector(store cache.Cache, registerer prometheus.Registerer) *ChaosCollector {
    46  	c := &ChaosCollector{
    47  		store: store,
    48  		experimentStatus: prometheus.NewGaugeVec(prometheus.GaugeOpts{
    49  			Name: "chaos_mesh_experiments",
    50  			Help: "Total number of chaos experiments and their phases",
    51  		}, []string{"namespace", "kind", "phase"}),
    52  		SidecarTemplates: prometheus.NewGauge(prometheus.GaugeOpts{
    53  			Name: "chaos_mesh_templates",
    54  			Help: "Total number of injection templates",
    55  		}),
    56  		ConfigTemplates: prometheus.NewGaugeVec(prometheus.GaugeOpts{
    57  			Name: "chaos_mesh_config_templates",
    58  			Help: "Total number of config templates",
    59  		}, []string{"namespace", "template"}),
    60  		InjectionConfigs: prometheus.NewGaugeVec(prometheus.GaugeOpts{
    61  			Name: "chaos_mesh_injection_configs",
    62  			Help: "Total number of injection configs",
    63  		}, []string{"namespace", "template"}),
    64  		TemplateNotExist: prometheus.NewCounterVec(prometheus.CounterOpts{
    65  			Name: "chaos_mesh_template_not_exist_total",
    66  			Help: "Total number of template not exist error",
    67  		}, []string{"namespace", "template"}),
    68  		ConfigNameDuplicate: prometheus.NewCounterVec(prometheus.CounterOpts{
    69  			Name: "chaos_mesh_config_name_duplicate_total",
    70  			Help: "Total number of config name duplication error",
    71  		}, []string{"namespace", "config"}),
    72  		TemplateLoadError: prometheus.NewCounter(prometheus.CounterOpts{
    73  			Name: "chaos_mesh_template_load_failed_total",
    74  			Help: "Total number of failures when rendering config args to template",
    75  		}),
    76  		InjectRequired: prometheus.NewCounterVec(prometheus.CounterOpts{
    77  			Name: "chaos_mesh_inject_required_total",
    78  			Help: "Total number of injections required",
    79  		}, []string{"namespace", "config"}),
    80  		Injections: prometheus.NewCounterVec(prometheus.CounterOpts{
    81  			Name: "chaos_mesh_injections_total",
    82  			Help: "Total number of sidecar injections performed on the webhook",
    83  		}, []string{"namespace", "config"}),
    84  	}
    85  	registerer.MustRegister(c)
    86  	return c
    87  }
    88  
    89  // Describe implements the prometheus.Collector interface.
    90  func (c *ChaosCollector) Describe(ch chan<- *prometheus.Desc) {
    91  	c.experimentStatus.Describe(ch)
    92  	c.SidecarTemplates.Describe(ch)
    93  	c.ConfigTemplates.Describe(ch)
    94  	c.InjectionConfigs.Describe(ch)
    95  	c.TemplateNotExist.Describe(ch)
    96  	c.ConfigNameDuplicate.Describe(ch)
    97  	c.TemplateLoadError.Describe(ch)
    98  	c.InjectRequired.Describe(ch)
    99  	c.Injections.Describe(ch)
   100  }
   101  
   102  // Collect implements the prometheus.Collector interface.
   103  func (c *ChaosCollector) Collect(ch chan<- prometheus.Metric) {
   104  	c.collect()
   105  	c.SidecarTemplates.Collect(ch)
   106  	c.ConfigTemplates.Collect(ch)
   107  	c.InjectionConfigs.Collect(ch)
   108  	c.TemplateNotExist.Collect(ch)
   109  	c.ConfigNameDuplicate.Collect(ch)
   110  	c.TemplateLoadError.Collect(ch)
   111  	c.InjectRequired.Collect(ch)
   112  	c.Injections.Collect(ch)
   113  	c.experimentStatus.Collect(ch)
   114  }
   115  
   116  func (c *ChaosCollector) collect() {
   117  	// TODO(yeya24) if there is an error in List
   118  	// the experiment status will be lost
   119  	c.experimentStatus.Reset()
   120  
   121  	for kind, obj := range v1alpha1.AllKinds() {
   122  		expCache := map[string]map[string]int{}
   123  		if err := c.store.List(context.TODO(), obj.ChaosList); err != nil {
   124  			log.Error(err, "failed to list chaos", "kind", kind)
   125  			return
   126  		}
   127  
   128  		items := reflect.ValueOf(obj.ChaosList).Elem().FieldByName("Items")
   129  		for i := 0; i < items.Len(); i++ {
   130  			item := items.Index(i).Addr().Interface().(v1alpha1.InnerObject)
   131  			if _, ok := expCache[item.GetChaos().Namespace]; !ok {
   132  				// There is only 4 supported phases
   133  				expCache[item.GetChaos().Namespace] = make(map[string]int, 4)
   134  			}
   135  			expCache[item.GetChaos().Namespace][string(utils.GetChaosState(item))]++
   136  		}
   137  
   138  		for ns, v := range expCache {
   139  			for phase, count := range v {
   140  				c.experimentStatus.WithLabelValues(ns, kind, phase).Set(float64(count))
   141  			}
   142  		}
   143  	}
   144  }
   145