github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/promutil/registry.go (about) 1 // Copyright 2022 PingCAP, Inc. 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 promutil 15 16 import ( 17 "sync" 18 19 frameModel "github.com/pingcap/tiflow/engine/framework/model" 20 "github.com/prometheus/client_golang/prometheus" 21 "github.com/prometheus/client_golang/prometheus/collectors" 22 dto "github.com/prometheus/client_model/go" 23 ) 24 25 var _ prometheus.Gatherer = globalMetricGatherer 26 27 // NOTICE: we don't use prometheus.DefaultRegistry in case of incorrect usage of a 28 // non-wrapped metric by app(user) 29 var ( 30 globalMetricRegistry = NewRegistry() 31 globalMetricGatherer prometheus.Gatherer = globalMetricRegistry 32 ) 33 34 func init() { 35 globalMetricRegistry.MustRegister(systemID, collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})) 36 globalMetricRegistry.MustRegister(systemID, collectors.NewGoCollector( 37 collectors.WithGoCollections(collectors.GoRuntimeMemStatsCollection|collectors.GoRuntimeMetricsCollection))) 38 } 39 40 // Registry is used for registering metric 41 type Registry struct { 42 mu sync.Mutex 43 registry *prometheus.Registry 44 45 // collectorByWorker is for cleaning all collectors for specific worker(jobmaster/worker) 46 collectorByWorker map[frameModel.WorkerID][]prometheus.Collector 47 } 48 49 // NewRegistry return a new Registry 50 func NewRegistry() *Registry { 51 return &Registry{ 52 registry: prometheus.NewRegistry(), 53 collectorByWorker: make(map[frameModel.WorkerID][]prometheus.Collector), 54 } 55 } 56 57 // MustRegister registers the provided Collector of the specified worker 58 func (r *Registry) MustRegister(workerID frameModel.WorkerID, c prometheus.Collector) { 59 if c == nil { 60 return 61 } 62 r.mu.Lock() 63 defer r.mu.Unlock() 64 65 r.registry.MustRegister(c) 66 67 var ( 68 cls []prometheus.Collector 69 exists bool 70 ) 71 cls, exists = r.collectorByWorker[workerID] 72 if !exists { 73 cls = make([]prometheus.Collector, 0) 74 } 75 cls = append(cls, c) 76 r.collectorByWorker[workerID] = cls 77 } 78 79 // Unregister unregisters all Collectors of the specified worker 80 func (r *Registry) Unregister(workerID frameModel.WorkerID) { 81 r.mu.Lock() 82 defer r.mu.Unlock() 83 84 cls, exists := r.collectorByWorker[workerID] 85 if exists { 86 for _, collector := range cls { 87 r.registry.Unregister(collector) 88 } 89 delete(r.collectorByWorker, workerID) 90 } 91 } 92 93 // Gather implements Gatherer interface 94 func (r *Registry) Gather() ([]*dto.MetricFamily, error) { 95 // NOT NEED lock here. prometheus.Registry has thread-safe methods 96 return r.registry.Gather() 97 } 98 99 // AutoRegisterFactory uses inner Factory to create metrics and register metrics 100 // to Registry with id. Panic if it can't register successfully. 101 type AutoRegisterFactory struct { 102 inner Factory 103 r *Registry 104 // ID identify the worker(jobmaster/worker) the factory owns 105 // It's used to unregister all collectors when worker exits normally or commits suicide 106 id frameModel.WorkerID 107 } 108 109 // NewAutoRegisterFactory creates an AutoRegisterFactory. 110 func NewAutoRegisterFactory(f Factory, r *Registry, id frameModel.WorkerID) Factory { 111 return &AutoRegisterFactory{ 112 inner: f, 113 r: r, 114 id: id, 115 } 116 } 117 118 // NewCounter implements Factory.NewCounter. 119 func (f *AutoRegisterFactory) NewCounter(opts prometheus.CounterOpts) prometheus.Counter { 120 c := f.inner.NewCounter(opts) 121 f.r.MustRegister(f.id, c) 122 return c 123 } 124 125 // NewCounterVec implements Factory.NewCounterVec. 126 func (f *AutoRegisterFactory) NewCounterVec(opts prometheus.CounterOpts, labelNames []string) *prometheus.CounterVec { 127 c := f.inner.NewCounterVec(opts, labelNames) 128 f.r.MustRegister(f.id, c) 129 return c 130 } 131 132 // NewGauge implements Factory.NewGauge. 133 func (f *AutoRegisterFactory) NewGauge(opts prometheus.GaugeOpts) prometheus.Gauge { 134 c := f.inner.NewGauge(opts) 135 f.r.MustRegister(f.id, c) 136 return c 137 } 138 139 // NewGaugeVec implements Factory.NewGaugeVec. 140 func (f *AutoRegisterFactory) NewGaugeVec(opts prometheus.GaugeOpts, labelNames []string) *prometheus.GaugeVec { 141 c := f.inner.NewGaugeVec(opts, labelNames) 142 f.r.MustRegister(f.id, c) 143 return c 144 } 145 146 // NewHistogram implements Factory.NewHistogram. 147 func (f *AutoRegisterFactory) NewHistogram(opts prometheus.HistogramOpts) prometheus.Histogram { 148 c := f.inner.NewHistogram(opts) 149 f.r.MustRegister(f.id, c) 150 return c 151 } 152 153 // NewHistogramVec implements Factory.NewHistogramVec. 154 func (f *AutoRegisterFactory) NewHistogramVec(opts prometheus.HistogramOpts, labelNames []string) *prometheus.HistogramVec { 155 c := f.inner.NewHistogramVec(opts, labelNames) 156 f.r.MustRegister(f.id, c) 157 return c 158 } 159 160 // RegOnlyRegister can Register collectors but can't Unregister. It's only used in tests. 161 type RegOnlyRegister struct { 162 r prometheus.Registerer 163 } 164 165 // NewOnlyRegRegister creates an RegOnlyRegister. 166 func NewOnlyRegRegister(r prometheus.Registerer) prometheus.Registerer { 167 return &RegOnlyRegister{r} 168 } 169 170 // Register implements prometheus.Registerer. 171 func (o RegOnlyRegister) Register(collector prometheus.Collector) error { 172 return o.r.Register(collector) 173 } 174 175 // MustRegister implements prometheus.Registerer. 176 func (o RegOnlyRegister) MustRegister(collector ...prometheus.Collector) { 177 o.r.MustRegister(collector...) 178 } 179 180 // Unregister implements prometheus.Registerer. 181 func (o RegOnlyRegister) Unregister(collector prometheus.Collector) bool { 182 return false 183 } 184 185 // UnregOnlyRegister can Unregister collectors but can't Register. It's used to 186 // protect the global registry. 187 type UnregOnlyRegister struct { 188 r prometheus.Registerer 189 } 190 191 // NewOnlyUnregRegister creates an UnregOnlyRegister. 192 func NewOnlyUnregRegister(r prometheus.Registerer) prometheus.Registerer { 193 return &UnregOnlyRegister{r} 194 } 195 196 // Register implements prometheus.Registerer. 197 func (o UnregOnlyRegister) Register(collector prometheus.Collector) error { 198 return nil 199 } 200 201 // MustRegister implements prometheus.Registerer. 202 func (o UnregOnlyRegister) MustRegister(collector ...prometheus.Collector) {} 203 204 // Unregister implements prometheus.Registerer. 205 func (o UnregOnlyRegister) Unregister(collector prometheus.Collector) bool { 206 return o.r.Unregister(collector) 207 }