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  }