proxy/pkg/metrics/prometheus_exporter.go (96 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package metrics import ( "fmt" "github.com/go-chassis/go-chassis/v2/pkg/metrics" "github.com/go-chassis/openlog" "github.com/prometheus/client_golang/prometheus" "runtime" "sync" ) //PrometheusExporter struct has attributes for prometheus data type PrometheusExporter struct { gaugesMutex sync.RWMutex countersMutex sync.RWMutex summaryMutex sync.RWMutex registry *prometheus.Registry gauges map[string]*prometheus.GaugeVec counters map[string]*prometheus.CounterVec summary map[string]*prometheus.SummaryVec } // PrometheusMesherSinker is the struct for prometheus configuration parameters type PrometheusMesherSinker struct { PromRegistry prometheus.Registerer //Prometheus registry } var ( //DefaultPrometheusExporter stores value of default prometheus exporter type DefaultPrometheusExporter = GetPrometheusExporter() //DefaultPrometheusSinker stores value of default prometheus exporter type DefaultPrometheusSinker *PrometheusMesherSinker ) //GetPrometheusExporter returns default prometheus exporter func GetPrometheusExporter() *PrometheusExporter { //use go chassis registry var promRegistry = metrics.GetSystemPrometheusRegistry() prometheus.DefaultGatherer = promRegistry prometheus.DefaultRegisterer = promRegistry return &PrometheusExporter{ registry: promRegistry, gauges: make(map[string]*prometheus.GaugeVec), counters: make(map[string]*prometheus.CounterVec), summary: make(map[string]*prometheus.SummaryVec), summaryMutex: sync.RWMutex{}, gaugesMutex: sync.RWMutex{}, countersMutex: sync.RWMutex{}, } } //Count function returns count func (s *PrometheusExporter) Count(name string, labelNames []string, labels prometheus.Labels) { s.countersMutex.RLock() cv, ok := s.counters[name] s.countersMutex.RUnlock() if !ok { cv = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: name, Help: name, }, labelNames) s.registry.MustRegister(cv) s.countersMutex.Lock() s.counters[name] = cv defer s.countersMutex.Unlock() } cv.With(labels).Add(1) } //Gauge function func (s *PrometheusExporter) Gauge(name string, val float64, labelNames []string, labels prometheus.Labels) { defer recoverPanic(name) s.gaugesMutex.RLock() g, ok := s.gauges[name] s.gaugesMutex.RUnlock() if !ok { g = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: name, Help: name, }, labelNames) s.registry.MustRegister(g) s.gaugesMutex.Lock() s.gauges[name] = g defer s.gaugesMutex.Unlock() } g.With(labels).Set(val) } //Summary function func (s *PrometheusExporter) Summary(name string, val float64, labelNames []string, labels prometheus.Labels) { defer recoverPanic(name) s.summaryMutex.RLock() sm, ok := s.summary[name] s.summaryMutex.RUnlock() if !ok { sm = prometheus.NewSummaryVec(prometheus.SummaryOpts{ Name: name, Help: name, }, labelNames) s.registry.MustRegister(sm) s.summaryMutex.Lock() s.summary[name] = sm defer s.summaryMutex.Unlock() } sm.With(labels).Observe(val) } func recoverPanic(metricName string) { if r := recover(); r != nil { pc := make([]uintptr, 10) runtime.Callers(1, pc) openlog.Warn(fmt.Sprintf("panics while registering metric [%s] to prometheus %s", metricName, r)) } }