1
2
3
4
5
6
7
8
9
10
11
12
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
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
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
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
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
118
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
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