github.com/kubewharf/katalyst-core@v0.5.3/pkg/metrics/metrics-pool/otel_prom_metrics_mux.go (about) 1 /* 2 Copyright 2022 The Katalyst 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 metrics_pool 18 19 import ( 20 "context" 21 "fmt" 22 "net/http" 23 "sync" 24 "time" 25 26 "k8s.io/apimachinery/pkg/util/wait" 27 28 "github.com/kubewharf/katalyst-core/pkg/config/generic" 29 "github.com/kubewharf/katalyst-core/pkg/metrics" 30 "github.com/kubewharf/katalyst-core/pkg/util/general" 31 ) 32 33 type PrometheusMetricOptions struct { 34 Path metrics.PrometheusMetricPathName 35 } 36 37 // openTelemetryPrometheusMetricsEmitterPool is a metrics emitter mux for metrics.openTelemetryPrometheusMetricsEmitter. 38 type openTelemetryPrometheusMetricsEmitterPool struct { 39 sync.Mutex 40 genericConf *generic.MetricsConfiguration 41 42 mux *http.ServeMux 43 emitters map[metrics.PrometheusMetricPathName]metrics.MetricEmitter 44 started map[metrics.PrometheusMetricPathName]bool 45 } 46 47 var _ MetricsEmitterPool = &openTelemetryPrometheusMetricsEmitterPool{} 48 49 func NewOpenTelemetryPrometheusMetricsEmitterPool(genericConf *generic.MetricsConfiguration, mux *http.ServeMux) (MetricsEmitterPool, error) { 50 m := &openTelemetryPrometheusMetricsEmitterPool{ 51 mux: mux, 52 genericConf: genericConf, 53 emitters: make(map[metrics.PrometheusMetricPathName]metrics.MetricEmitter), 54 started: make(map[metrics.PrometheusMetricPathName]bool), 55 } 56 57 if _, err := m.GetMetricsEmitter(PrometheusMetricOptions{ 58 Path: metrics.PrometheusMetricPathNameDefault, 59 }); err != nil { 60 return nil, fmt.Errorf("init default emitter err: %v", err) 61 } 62 63 return m, nil 64 } 65 66 // GetDefaultMetricsEmitter returns metrics emitter with default path 67 func (m *openTelemetryPrometheusMetricsEmitterPool) GetDefaultMetricsEmitter() metrics.MetricEmitter { 68 m.Lock() 69 defer m.Unlock() 70 return m.emitters[metrics.PrometheusMetricPathNameDefault] 71 } 72 73 // SetDefaultMetricsEmitter is not supported by openTelemetryPrometheusMetricsEmitterPool 74 func (m *openTelemetryPrometheusMetricsEmitterPool) SetDefaultMetricsEmitter(_ metrics.MetricEmitter) { 75 } 76 77 // GetMetricsEmitter get a prometheus metrics emitter which is exposed to an input path. 78 func (m *openTelemetryPrometheusMetricsEmitterPool) GetMetricsEmitter(para interface{}) (metrics.MetricEmitter, error) { 79 m.Lock() 80 defer m.Unlock() 81 82 options, ok := para.(PrometheusMetricOptions) 83 if !ok { 84 return metrics.DummyMetrics{}, fmt.Errorf("failed to transform %v to path", para) 85 } 86 87 pathName := options.Path 88 if _, ok := m.emitters[pathName]; !ok { 89 e, err := metrics.NewOpenTelemetryPrometheusMetricsEmitter(m.genericConf, pathName, m.mux) 90 if err != nil { 91 return nil, err 92 } 93 m.emitters[pathName] = e 94 general.Infof("add path %s to metric emitter", pathName) 95 } 96 m.started[pathName] = false 97 return m.emitters[pathName], nil 98 } 99 100 func (m *openTelemetryPrometheusMetricsEmitterPool) Run(ctx context.Context) { 101 go wait.Until(func() { 102 m.Lock() 103 defer m.Unlock() 104 105 for pathName := range m.emitters { 106 if !m.started[pathName] { 107 m.emitters[pathName].Run(ctx) 108 m.started[pathName] = true 109 } 110 } 111 }, time.Minute, ctx.Done()) 112 }